class AsciidoctorBibtex::Processor
Class used through utility method to hold data about citations for current document, and run the different steps to add the citations and bibliography
Public Class Methods
# File lib/asciidoctor-bibtex/processor.rb, line 51 def initialize(bibfile, links = false, style = 'ieee', locale = 'en-US', numeric_in_appearance_order = false, output = :asciidoc, throw_on_unknown = false, custom_citation_template: '[$id]') raise "File '#{bibfile}' is not found" unless FileTest.file? bibfile bibtex = BibTeX.open bibfile, filter: [LatexFilter] @biblio = bibtex @links = links @numeric_in_appearance_order = numeric_in_appearance_order @style = style @locale = locale @citations = [] @filenames = Set.new @output = output @throw_on_unknown = throw_on_unknown @bibtex_ob = '[' @bibtex_cb = ']' match = custom_citation_template.match(/^(.+?)\$id(.+)$/) unless match.nil? @bibtex_ob = match[1] @bibtex_cb = match[2] end if (output != :latex) && (output != :bibtex) && (output != :biblatex) @citeproc = CiteProc::Processor.new style: @style, format: :html, locale: @locale @citeproc.import @biblio.to_citeproc end end
Public Instance Methods
Build the asciidoc text for a single bibliography item
# File lib/asciidoctor-bibtex/processor.rb, line 154 def build_bibitem_text(key) begin if @biblio[key].nil? puts "Unknown reference: #{key}" cptext = key else cptext = @citeproc.render :bibliography, id: key cptext = cptext.first end rescue Exception => e puts "Failed to render #{key}: #{e}" cptext = key end StringUtils.html_to_asciidoc(cptext) end
Build bibliography text for a given reference
# File lib/asciidoctor-bibtex/processor.rb, line 171 def build_bibliography_item(key, index = 0) index += 1 result = '' begin cptext = if @biblio[key].nil? nil else @citeproc.render :bibliography, id: key end rescue Exception => e puts "Failed to render #{key}: #{e}" end result << "[[#{key}]]" if @links if StyleUtils.is_numeric? @style result << "#{@bibtex_ob}#{index}#{@bibtex_cb} " end if cptext.nil? return result + key else result << cptext.first end StringUtils.html_to_asciidoc(result) end
Build the bibliography list just as bibtex.
Return an array of texts representing an asciidoc list.
# File lib/asciidoctor-bibtex/processor.rb, line 140 def build_bibliography_list result = [] @citations.each_with_index do |ref, index| result << build_bibliography_item(ref, index) result << '' end result end
Build the complete citation text for given citation macro
# File lib/asciidoctor-bibtex/processor.rb, line 199 def build_citation_text(macro) if (@output == :latex) || (@output == :bibtex) || (@output == :biblatex) result = '+++' macro.items.each do |cite| # NOTE: xelatex does not support "\citenp", so we output all # references as "cite" here unless we're using biblatex. result << '\\' << if @output == :biblatex if macro.type == 'citenp' 'textcite' else 'parencite' end else 'cite' end result << '[p. ' << cite.locator << ']' if cite.locator != '' result << '{' << cite.key.to_s << '},' end result = result[0..-2] if result[-1] == ',' result << '+++' result else result = '' if StyleUtils.is_numeric? @style ob = "+#{@bibtex_ob}+" cb = "+#{@bibtex_cb}+" separator = ',' elsif macro.type == 'cite' ob = '(' cb = ')' separator = ';' else ob = '' cb = '' separator = ';' end macro.items.each_with_index do |cite, index| # before all items apart from the first, insert appropriate separator result << "#{separator} " unless index.zero? # @links requires adding hyperlink to reference result << "<<#{cite.key}," if @links # if found, insert reference information if @biblio[cite.key].nil? if @throw_on_unknown raise "Unknown reference: #{cite.key}" else puts "Unknown reference: #{cite.key}" cite_text = cite.key.to_s end else cite_text = citation_text(macro, cite) end result << StringUtils.html_to_asciidoc(cite_text) result << '>>' if @links end if StyleUtils.is_numeric?(@style) && !@links result = StringUtils.combine_consecutive_numbers(result) end include_pretext result, macro, ob, cb end end
Generate a raw citation text for a single citation item
# File lib/asciidoctor-bibtex/processor.rb, line 301 def citation_text(macro, cite) if StyleUtils.is_numeric? @style cite_text = (@citations.index(cite.key) + 1).to_s cite_text << format_locator(cite) else # We generate the citation without locator using citeproc, then strip # the surrounding braces, finally add the locator and add braces for # `citenp`. cite_text = @citeproc.render :citation, id: cite.key cite_text = cite_text.gsub('(', '') cite_text = cite_text.gsub(')', '') cite_text += format_locator(cite) year = @biblio[cite.key].year if !year.nil? && macro.type == 'citenp' segs = cite_text.partition(year.to_s) head = segs[0].gsub(', ', ' ') tail = segs[1..-1].join cite_text = "#{head}(#{tail})" end # finally escape some special chars cite_text = cite_text.gsub(',', ',') if @links # replace comma end cite_text end
Finalize citation macro processing and build internal citation list.
As this function being called, processor will clean up the list of citation keys to form a correct ordered citation list.
# File lib/asciidoctor-bibtex/processor.rb, line 95 def finalize_macro_processing @citations = @citations.uniq(&:to_s) # only keep the first occurance return if StyleUtils.is_numeric?(@style) && @numeric_in_appearance_order @citations = @citations.sort_by do |ref| bibitem = @biblio[ref] if bibitem.nil? [ref] else # extract the reference, and uppercase. # Remove { } from grouped names for sorting. author = bibitem.author author = bibitem.editor if author.nil? year = bibitem.year sortable = CitationUtils.author_chicago(author).map { |s| s.upcase.delete '{}' } sortable << year if year sortable end end nil end
Format locator with pp/p as appropriate
# File lib/asciidoctor-bibtex/processor.rb, line 268 def format_locator(cite) result = '' unless cite.locator.empty? result << ',' unless StyleUtils.is_numeric? @style result << ' ' # use p.x for single numerical page and pp.x for all others. This will # produce pp. 1 seq for complex locators, which is the correct behavior. result << if @style.include? 'chicago' cite.locator elsif /^\d+$/ =~ cite.locator "p. #{cite.locator}" else "pp. #{cite.locator}" end end result end
# File lib/asciidoctor-bibtex/processor.rb, line 287 def include_pretext(result, macro, ob, cb) pretext = macro.pretext pretext += ' ' unless pretext.empty? # add space after any content if StyleUtils.is_numeric? @style "#{pretext}#{ob}#{result}#{cb}" elsif macro.type == 'cite' "#{ob}#{pretext}#{result}#{cb}" else "#{pretext}#{result}" end end
Scan a line and process citation macros.
As this function being called iteratively on the lines of the document, processor will build a list of all citation keys in the same order as they appear in the original document.
# File lib/asciidoctor-bibtex/processor.rb, line 85 def process_citation_macros(line) CitationMacro.extract_macros(line).each do |citation| @citations += citation.items.collect(&:key) end end
Replace bibitem macros with rendered bibitem.
Return new text with all macros replaced.
# File lib/asciidoctor-bibtex/processor.rb, line 130 def replace_bibitem_macros(line) BibitemMacro.extract_macros(line).each do |item| line = line.gsub(item.text, build_bibitem_text(item.key)) end line end
Replace citation macros with corresponding citation texts.
Return new text with all macros replaced.
# File lib/asciidoctor-bibtex/processor.rb, line 120 def replace_citation_macros(line) CitationMacro.extract_macros(line).each do |citation| line = line.gsub(citation.text, build_citation_text(citation)) end line end