# encoding: utf-8 =begin * Name: SiSU ** Description: documents, structuring, processing, publishing, search *** system environment, resource control and configuration details ** Author: Ralph Amissah <ralph@amissah.com> <ralph.amissah@gmail.com> ** Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Ralph Amissah, All Rights Reserved. ** License: GPL 3 or later: SiSU, a framework for document structuring, publishing and search Copyright (C) Ralph Amissah This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. If you have Internet connection, the latest version of the GPL should be available at these locations: <http://www.fsf.org/licensing/licenses/gpl.html> <http://www.gnu.org/licenses/gpl.html> <http://www.sisudoc.org/sisu/en/manifest/gpl.fsf.html> ** SiSU uses: * Standard SiSU markup syntax, * Standard SiSU meta-markup syntax, and the * Standard SiSU object citation numbering and system ** Hompages: <http://www.jus.uio.no/sisu> <http://www.sisudoc.org> ** Git <http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=summary> <http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=blob;f=lib/sisu/ao_appendices.rb;hb=HEAD> =end module SiSU_AO_Appendices class Glossary def initialize(md,data) @md,@data=md,data end def glossary_extraction glossary=[] glossaryflag=false code_flag=false flag_code_curly=:not_code_curly flag_code_tics=:not_code_tics @data=@data.select do |t_o| if t_o =~/^code\{/ flag_code_curly=:code_curly elsif t_o =~/^\}code/ flag_code_curly=:not_code_curly elsif t_o =~/^``` code/ flag_code_tics=:code_tics elsif flag_code_tics ==:code_tics \ and t_o =~/^```/ flag_code_tics=:not_code_tics end code_flag=if flag_code_curly==:code_curly \ or flag_code_tics==:code_tics true else false end unless code_flag if @md.flag_glossary if t_o =~/^1~!glossary/ glossaryflag = true next elsif t_o =~/^:?[B-D]~/ next elsif t_o =~/^:?[B-D1]~/ glossaryflag = false t_o elsif glossaryflag if t_o !~/\A%+ / glossary << t_o next else t_o end else t_o end else t_o end else t_o end end.compact [@data,glossary] end end class Bibliography def initialize(md,data) @md,@data=md,data end def sort_bibliography_array_by_deemed_author_year_title(bib) if bib bib.compact.sort_by do |c| [c[:deemed_author],c[:ymd],c[:title]] end end end def citation_in_prepared_bibliography(cite) @cite=cite def generic { is: nil, # :book, :article, :magazine, :newspaper, :blog, :other author_raw: nil, author: nil, author_arr: nil, editor_raw: nil, editor: nil, editor_arr: nil, title: nil, subtitle: nil, fulltitle: nil, language: nil, trans: nil, src: nil, journal: nil, in: nil, volume: nil, edition: nil, year: nil, place: nil, publisher: nil, url: nil, pages: nil, note: nil, #format: nil, #consider list of fields arranged with markup short_name: nil, id: nil, } end def citation_metadata type=:generic if type citation=generic citeblock=@cite.split("\n") citeblock.select do |meta| case meta when /^((?:au|author):\s+)\S+/ #req citation[:author_raw]=/^#{$1}(.+)/.match(meta)[1] when /^((?:ti|title):\s+)\S+/ #req citation[:title]=/^#{$1}(.+)/.match(meta)[1] when /^((?:st|subtitle):\s+)\S+/ citation[:subtitle]=/^#{$1}(.+)/.match(meta)[1] when /^((?:lng|language):\s+)\S+/ citation[:language]=/^#{$1}(.+)/.match(meta)[1] when /^((?:edr?|editor):\s+)\S+/ citation[:editor_raw]=/^#{$1}(.+)/.match(meta)[1] when /^((?:tr|trans(:?lator)?):\s+)\S+/ citation[:editor_raw]=/^#{$1}(.+)/.match(meta)[1] when /^((?:pb|publisher):\s+)\S+/ citation[:publisher]=/^#{$1}(.+)/.match(meta)[1] when /^((?:edn|edition):\s+)\S+/ citation[:edition]=/^#{$1}(.+)/.match(meta)[1] when /^((?:yr|year):\s+)\S+/ #req? citation[:year]=/^#{$1}(.+)/.match(meta)[1] when /^((?:pl|publisher_state):\s+)\S+/ citation[:place]=/^#{$1}(.+)/.match(meta)[1] when /^((?:jo|journal):\s+)\S+/ #req? citation[:journal]=/^#{$1}(.+)/.match(meta)[1] when /^((?:vol?|volume):\s+)\S+/ citation[:volume]=/^#{$1}(.+)/.match(meta)[1] when /^((?:in):\s+)\S+/ citation[:in]=/^#{$1}(.+)/.match(meta)[1] when /^((?:src):\s+)\S+/ citation[:src]=/^#{$1}(.+)/.match(meta)[1] when /^((?:pg|pages?):\s+)\S+/ citation[:pages]=/^#{$1}(.+)/.match(meta)[1] when /^(url:\s+)\S+/ citation[:url]=/^#{$1}(.+)/.match(meta)[1] when /^(note:\s+)\S+/ citation[:note]=/^#{$1}(.+)/.match(meta)[1] when /^((?:sn|shortname):\s+)\S+/ # substitution: (/#{id}/,"#{sn}") citation[:short_name]=/^#{$1}(.+)/.match(meta)[1] when /^(id:\s+)\S+/ # substitution: (/#{id}/,"#{sn}") citation[:id]=/^#{$1}(.+)/.match(meta)[1] end end if citation[:subtitle] citation[:fulltitle] = citation[:title] \ + ' - ' \ + citation[:subtitle] else citation[:fulltitle] = citation[:title] end if citation[:author_raw] citation[:author_arr]=citation[:author_raw].split(/;\s*/) citation[:author]=citation[:author_arr].map do |author| author.gsub(/(.+?),\s+(.+)/,'\2 \1').strip end.join(', ').strip end if citation[:editor_raw] citation[:editor_arr]=citation[:editor_raw].split(/;\s*/) citation[:editor]=citation[:editor_arr].map do |editor| editor.gsub(/(.+?),\s+(.+)/,'\2 \1').strip end.join(', ').strip end citation[:ymd]=if not citation[:year] =~/^[0-9]{4}/ '9999' else citation[:year] end citation[:deemed_author]=if not citation[:author_raw] \ and citation[:editor_raw] citation[:editor_arr][0] elsif citation[:author_raw] citation[:author_arr][0] else SiSU_Utils::CodeMarker.new(__LINE__,__FILE__,:fuchsia). warn('Citation needs an author or editor, title: "' \ + citation[:title] + '"') '000' end unless citation[:short_name] citation[:short_name]=%{#{citation[:author]}, "#{citation[:title]}" (#{citation[:date]})} end end citation end self end def biblio_format def generic(c) cite=%{#{c[:author]}. /{"#{c[:fulltitle]}".}/} cite=(c[:journal]) \ ? cite + %{ #{c[:journal]},} : cite cite=(c[:source]) \ ? cite + %{ #{c[:source]},} : cite cite=(c[:in]) \ ? cite + %{ in #{c[:in]},} : cite cite=(c[:volume]) \ ? cite + %{ #{c[:volume]},} : cite cite=(c[:trans]) \ ? cite + %{ trans. #{c[:trans]},} : cite cite=(c[:editor]) \ ? cite + %{ ed. #{c[:editor]},} : cite cite=(c[:place]) \ ? cite + %{ #{c[:place]},} : cite cite=(c[:publisher]) \ ? cite + %{ #{c[:publisher]},} : cite cite=(c[:year]) \ ? cite + %{ (#{c[:year]})} : cite cite=(c[:pages]) \ ? cite + %{ #{c[:pages]}} : cite cite=(c[:url]) \ ? cite + %{ #{c[:url]}} : cite cite=(c[:note]) \ ? cite + %{ #{c[:note]}} : cite cite end def generic_editor(c) cite=%{#{c[:editor]} ed. /{"#{c[:fulltitle]}".}/} cite=(c[:journal]) \ ? cite + %{ #{c[:journal]}, } : cite cite=(c[:source]) \ ? cite + %{ #{c[:source]}, } : cite cite=(c[:in]) \ ? cite + %{ in #{c[:in]},} : cite cite=(c[:volume]) \ ? cite + %{ #{c[:volume]},} : cite cite=(c[:trans]) \ ? cite + %{ trans. #{c[:trans]},} : cite cite=(c[:place]) \ ? cite + %{ #{c[:place]},} : cite cite=(c[:publisher]) \ ? cite + %{ #{c[:publisher]}} : cite cite=(c[:year]) \ ? cite + %{ (#{c[:year]})} : cite cite=(c[:pages]) \ ? cite + %{ #{c[:pages]}} : cite cite=(c[:url]) \ ? cite + %{ #{c[:url]}} : cite cite=(c[:note]) \ ? cite + %{ #{c[:note]}} : cite cite end self end def biblio_make(cite) if cite[:author] biblio_format.generic(cite) elsif cite[:editor] biblio_format.generic_editor(cite) else biblio_format.generic(cite) end end def biblio_extraction bibliography=[] biblioflag=false code_flag=false flag_code_curly=:not_code_curly flag_code_tics=:not_code_tics @data=@data.select do |t_o| if t_o =~/^code\{/ flag_code_curly=:code_curly elsif t_o =~/^\}code/ flag_code_curly=:not_code_curly elsif t_o =~/^``` code/ flag_code_tics=:code_tics elsif flag_code_tics ==:code_tics \ and t_o =~/^```/ flag_code_tics=:not_code_tics end code_flag=if flag_code_curly==:code_curly \ or flag_code_tics==:code_tics true else false end unless code_flag if @md.flag_auto_biblio if t_o =~/^1~!biblio(?:graphy)?/ biblioflag = true t_o elsif t_o =~/^:?[B-D1]~/ biblioflag = false t_o elsif biblioflag if t_o !~/\A%+ / bibliography << citation_in_prepared_bibliography(t_o).citation_metadata next else t_o end else t_o end elsif @md.flag_biblio if t_o =~/^1~!biblio(?:graphy)?/ biblioflag = true next elsif t_o =~/^:?[B-D]~/ next elsif t_o =~/^:?[B-D1]~/ biblioflag = false t_o elsif biblioflag if t_o !~/\A%+ / bibliography << t_o next else t_o end else t_o end else t_o end else t_o end end.compact if @md.flag_auto_biblio \ and bibliography.length > 0 data_new=[] bib=sort_bibliography_array_by_deemed_author_year_title(bibliography) biblio_done=[] @data.select do |t_o| if t_o =~/^1~!biblio(?:graphy)?/ bib.each do |c| d=c d.store(:obj, biblio_make(c)) biblio_done << d #biblio_done << { obj: biblio_make(c), id: c[:id] } end else data_new << t_o end end @data=data_new end [@data,biblio_done] end end class Citations def initialize(md='',data='') @md,@data=md,data #@biblio=[] end def songsheet tuned_file,citations=citations_scan(@data) [tuned_file,citations] end def sort_bibliography_array_by_author_year(bib) bib.sort_by do |c| [c[:author_raw],c[:year]] #[c[:author_arr][0],c[:year],c[:title]] end end def citations_regex def pages_pattern %r{(?:[,.:]?\s+(?:p{1,2}\.?\s+)?(?:\d+--?\d+)[,.]?\s+)?} end def editor_pattern %r{(?<editor>(?:editor|edited by)\s+.+?)} end def year_pattern %r{[(\[]?(?<year>\d{4})[\])]?[.,]?} end def authors_year_title_publication_editor_pages /(?<authors>.+?)\s+#{year_pattern}\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})\s+#{editor_pattern}#{pages_pattern}/m # note ed. is usually edition rather than editor end def authors_title_publication_year_editor_pages /(?<authors>.+?)\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})\s+#{year_pattern}\s+#{editor_pattern}#{pages_pattern}/m # note ed. is usually edition rather than editor end def authors_title_publication_editor_year_pages ### /(?<authors>.+?)\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})\s+ed.\s+#{editor_pattern}#{year_pattern}#{pages_pattern}/m # note ed. is usually edition rather than editor end def authors_title_publication_editor_pages_year ### /(?<authors>.+?)\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})\s+#{editor_pattern}#{pages_pattern}#{year_pattern}/m # note ed. is usually edition rather than editor end def authors_year_title_publication_pages /(?<authors>.+?)\s+#{year_pattern}\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})[,.;]?#{pages_pattern}/m end def authors_title_publication_year_pages /(?<authors>.+?)\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})\s+#{year_pattern}\s+#{pages_pattern}/m end def authors_title_publication_pages_year ### /(?<authors>.+?)\s+"(?<title>.+?)"\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})#{pages_pattern}#{year_pattern}/m end def authors_year_publication_pages /(?<authors>.+?)\s+#{year_pattern}\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})#{pages_pattern}/m end def authors_publication_year_pages /(?<authors>.+?)\s+(?:#{Mx[:fa_italics_o]}|#{Mx[:srcrgx_italics_o]})(?<publication>.+?)(?:#{Mx[:fa_italics_c]}|#{Mx[:srcrgx_italics_c]})[,.;]?\s+(?<publisher>.+?)?#{year_pattern}#{pages_pattern}[.;]?/m end self end def authors?(citations) citations.each.map do |b| if b =~ /^.+\s+::.+?:$/ c=/^(?<citation>.+?)\s+::(?<shortref>.+?):$/.match(b) { citation: c[:citation], shortref: c[:shortref], c[:shortref].to_s => c[:citation] } else { citation: b } end end end def long_and_short_ref?(citations) #could be useful, keep ... ectract shortref citations.each.map do |b| if b =~ /^.+\s+::.+?:$/ c=/^(?<citation>.+?)\s+::(?<shortref>.+?):$/.match(b) { citation: c[:citation], shortref: c[:shortref], c[:shortref].to_s => c[:citation] } else { citation: b } end end end def citation_detail(citations) #could be useful, keep ... extract shortref bibahash=[] number=0 missed=0 citations.select do |b| z=if b =~citations_regex.authors_year_title_publication_editor_pages c=citations_regex.authors_year_title_publication_editor_pages.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], editor: c[:editor], } elsif b =~citations_regex.authors_title_publication_year_editor_pages c=citations_regex.authors_title_publication_year_editor_pages.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], editor: c[:editor], } elsif b =~citations_regex.authors_title_publication_editor_year_pages c=citations_regex.authors_title_publication_editor_year_pages.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], editor: c[:editor], } elsif b =~citations_regex.authors_title_publication_editor_pages_year c=citations_regex.authors_title_publication_editor_pages_year.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], editor: c[:editor], } elsif b =~citations_regex.authors_year_title_publication_pages c=citations_regex.authors_year_title_publication_pages.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], } elsif b =~citations_regex.authors_title_publication_year_pages c=citations_regex.authors_title_publication_year_pages.match(b) { is: :article, author_raw: c[:authors], year: c[:year], title: c[:title], publication: c[:publication], } elsif b =~citations_regex.authors_year_publication_pages c=citations_regex.authors_year_publication_pages.match(b) { is: :book, author_raw: c[:authors], year: c[:year], publication: c[:publication], } elsif b =~citations_regex.authors_publication_year_pages c=citations_regex.authors_publication_year_pages.match(b) { is: :book, author_raw: c[:authors], year: c[:year], publication: c[:publication], } else b end if not z.is_a?(NilClass) \ and z.is_a?(Hash) \ and z[:author_raw].length > 0 z[:author_arr]=z[:author_raw].split(/;\s*/) z[:author]=z[:author_arr].map do |author| author.gsub(/(.+?),\s+(.+)/,'\2 \1').strip end.join(', ').strip if @md.opt.act[:verbose_plus][:set]==:on \ || @md.opt.act[:maintenance][:set]==:on number +=1 if z.is_a?(Hash) missed +=1 if z.is_a?(String) (z.is_a?(Hash)) \ ? (p '[' + number.to_s + '] ' + z.to_s) : (p '<' + missed.to_s + '> ' + z.to_s) end end bibahash << z if z.is_a?(Hash) end bibahash=sort_bibliography_array_by_author_year(bibahash.compact) bibahash end def citations_scan(data) citations=[] #short_ref=[] tuned_file = data.compact.select do |dob| if dob.is !=:meta \ && dob.is !=:comment \ && dob.is !=:code \ && dob.is !=:table if dob.obj =~/\.:.+?:\./ citations << dob.obj.scan(/\.:\s*(.+?)\s*:\./m) #short_ref << dob.obj.scan(/\.:\s+(.+?)\s+::([^:]+)::\./m) #look at later ##short_ref << dob.obj.scan(/\.:\s+(.+?)\s+::(.+?)::\./m) #look at later #short_ref << dob.obj.scan(/\.:\s*(.+?)\s*(::(.+?):)?:\./m) #look at later citations=citations.flatten.compact dob.obj=dob.obj. #remove citations delimiter & helpers from text gsub(/\.:|:\./,'') end end dob if dob.is_a?(Object) end #bib=long_and_short_ref?(citations) #could be useful, keep ... extract shortref citations=citation_detail(citations) [tuned_file,citations] end end end __END__