Class: AsciidocBib::Processor

Inherits:
Object
  • Object
show all
Includes:
ProcessorUtils
Defined in:
lib/asciidoc-bib/processor.rb

Overview

Class used through utility method to hold data about citations for current document, and run the different steps to add the citations and bibliography.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ProcessorUtils

#combine_consecutive_numbers

Constructor Details

#initialize(biblio, links, style, numeric_in_appearance_order = false) ⇒ Processor

Returns a new instance of Processor.



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/asciidoc-bib/processor.rb', line 27

def initialize biblio, links, style, numeric_in_appearance_order = false
  @biblio = biblio
  @links = links
  @numeric_in_appearance_order = numeric_in_appearance_order
  @style = style
  @citations = Citations.new
  @filenames = Set.new

  @citeproc = CiteProc::Processor.new style: @style, format: :html
  @citeproc.import @biblio.to_citeproc
end

Instance Attribute Details

#biblioObject (readonly)

The BibTeX instance based on the provided .bib file.



19
20
21
# File 'lib/asciidoc-bib/processor.rb', line 19

def biblio
  @biblio
end

#citationsObject (readonly)

List of citations as read in from the file.



25
26
27
# File 'lib/asciidoc-bib/processor.rb', line 25

def citations
  @citations
end

Flag to indicate if links should be included, as set in options.



21
22
23
# File 'lib/asciidoc-bib/processor.rb', line 21

def links
  @links
end

#styleObject (readonly)

Citation style, as set in options.



23
24
25
# File 'lib/asciidoc-bib/processor.rb', line 23

def style
  @style
end

Class Method Details

.run(options) ⇒ Object

Top-level method to include citations in given asciidoc file.



11
12
13
14
15
16
# File 'lib/asciidoc-bib/processor.rb', line 11

def Processor.run options
  processor = Processor.new BibTeX.open(options.bibfile), options.links, options.style, options.numeric_in_appearance_order?
  processor.read_filenames options.filename
  processor.read_citations 
  processor.add_citations
end

Instance Method Details

#add_citationsObject

Read given text to add cites and biblio to a new file Order is always decided by author surname first with year. If no author present, then use editor field. Links indicates if internal links to be added. Assumes @filenames has been set to list of filenames to process.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/asciidoc-bib/processor.rb', line 72

def add_citations 
  @filenames.each do |curr_file|
    ref_filename = FileHandlers.add_ref(curr_file)
    puts "Writing file:	#{ref_filename}"
    output = File.new(ref_filename, "w")

    IO.foreach(curr_file) do |line|
      begin # catch any errors, and ensure the lines of text are written
        case 
        when line.include?('include::')
          output_include_line output, line
        when line.include?('[bibliography]')
          output_bibliography output
        else
          output_cite_completed_line output, line
        end
      rescue # Any errors, just output the line
        output.puts line
      end
    end

    output.close
  end 
end

#complete_citation(cite_data) ⇒ Object

Return the complete citation text for given cite_data.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/asciidoc-bib/processor.rb', line 133

def complete_citation cite_data
  result = "".dup
  ob, cb = "(", ")"

  cite_data.cites.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.ref}," if @links

    # if found, insert reference information
    unless biblio[cite.ref].nil?
      item = biblio[cite.ref].clone
      cite_text, ob, cb = make_citation item, cite.ref, cite_data, cite
    else
      puts "Unknown reference: #{cite.ref}"
      cite_text = "#{cite.ref}"
    end

    result << cite_text.html_to_asciidoc
    # @links requires finish hyperlink
    result << ">>" if @links
  end

  unless @links
    # combine numeric ranges
    if Styles.is_numeric? @style
      result = combine_consecutive_numbers result
    end
  end

  include_pretext result, cite_data, ob, cb
end

#get_reference(ref) ⇒ Object

Retrieve text for reference in given style.

ref

reference for item to give reference for



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/asciidoc-bib/processor.rb', line 170

def get_reference ref
  result = "".dup
  result << ". " if Styles.is_numeric? @style

  begin
    cptext = @citeproc.render :bibliography, id: ref
  rescue Exception => e
    puts "Failed to render #{id}: #{e}"
  end
  result << "[[#{ref}]]" if @links
  if cptext.nil?
    return result+ref
  else
    result << cptext.first
  end

  return result.html_to_asciidoc
end

#include_pretext(result, cite_data, ob, cb) ⇒ Object

The pretext is the message such as "See" given in the original citation. This method includes the pretext as appropriate, depending on the style and citation type.



225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/asciidoc-bib/processor.rb', line 225

def include_pretext result, cite_data, ob, cb
  pretext = cite_data.pretext
  pretext += ' ' unless pretext.empty? # add space after any content

  if Styles.is_numeric? @style
    "#{pretext}#{ob}#{result}#{cb}"
  elsif cite_data.type == "cite" 
    "#{ob}#{pretext}#{result}#{cb}"
  else 
    "#{pretext}#{result}"
  end
end

#make_citation(item, ref, cite_data, cite) ⇒ Object

Numeric citations are handled by computing the position of the reference in the list of used citations. Other citations are formatted by citeproc.



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/asciidoc-bib/processor.rb', line 241

def make_citation item, ref, cite_data, cite
  if Styles.is_numeric? @style
    cite_text = if @numeric_in_appearance_order
                  "#{@citations.cites_used.index(cite.ref) + 1}"
                else
                  "#{sorted_cites.index(cite.ref) + 1}"
                end
    fc = '['
    lc = ']'
  else
    cite_text = @citeproc.process id: ref, mode: :citation

    fc = cite_text[0,1]
    lc = cite_text[-1,1]
    cite_text = cite_text[1..-2]
  end

  if Styles.is_numeric? @style
    cite_text << "#{page_str(cite)}"
  elsif cite_data.type == "citenp"
    cite_text.gsub!(item.year, "#{fc}#{item.year}#{page_str(cite)}#{lc}")
    cite_text.gsub!(", #{fc}", " #{fc}")
  else 
    cite_text << page_str(cite)
  end

  cite_text.gsub!(",", "&#44;") if @links # replace comma

  return cite_text, fc, lc
end

#output_bibliography(output) ⇒ Object

Output bibliography to given output stream.



98
99
100
101
102
103
104
105
106
107
108
# File 'lib/asciidoc-bib/processor.rb', line 98

def output_bibliography output
  cites = if Styles.is_numeric?(@style) and @numeric_in_appearance_order
            @citations.cites_used 
          else 
            sorted_cites 
          end
  cites.each do |ref|
    output.puts get_reference(ref)
    output.puts
  end
end

#output_cite_completed_line(output, line) ⇒ Object

For each citation in given line, expand into complete citation text before outputting the line



125
126
127
128
129
130
# File 'lib/asciidoc-bib/processor.rb', line 125

def output_cite_completed_line output, line
  @citations.retrieve_citations(line).each do |citation|
    line.gsub!(citation.original, complete_citation(citation))
  end
  output.puts line
end

#output_include_line(output, line) ⇒ Object

Handles a line of text which includes another file. The included file must be redirected to reference the -ref version, the one which includes any expanded citations.



113
114
115
116
117
118
119
120
121
# File 'lib/asciidoc-bib/processor.rb', line 113

def output_include_line output, line
  line.split("include::").drop(1).each do |filetxt|
    ifile = filetxt.partition(/\s|\[/).first
    file = File.expand_path ifile 
    # make sure included file points to the -ref version
    line.gsub!("include::#{ifile}", "include::#{FileHandlers.add_ref(file)}")
  end
  output.puts line
end

#page_str(cite) ⇒ Object

Return page string for given cite.



212
213
214
215
216
217
218
219
220
# File 'lib/asciidoc-bib/processor.rb', line 212

def page_str cite
  result ="".dup 
  unless cite.pages.empty?
    result << "," unless Styles.is_numeric? @style
    result << " #{with_pp(cite.pages)}"
  end

  return result
end

#read_citationsObject

Scans each filename and extracts citations



59
60
61
62
63
64
65
# File 'lib/asciidoc-bib/processor.rb', line 59

def read_citations 
  @filenames.each do |file|
    IO.foreach(file) do |line|
      @citations.add_from_line line
    end
  end 
end

#read_filenames(filename) ⇒ Object

Given an asciidoc filename, reads in all dependent files based on 'include::' statements Leaving a list of files in @filenames



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/asciidoc-bib/processor.rb', line 41

def read_filenames filename
  puts "Reading file: #{filename}"
  files_to_process = [filename]

  begin
    @filenames.add files_to_process.first
    File.new(files_to_process.shift).each_line do |line|
      if line.include?("include::")
        line.split("include::").drop(1).each do |filetxt|
          file = File.expand_path(filetxt.partition(/\s|\[/).first)
          files_to_process << file unless @filenames.include?(file)
        end
      end
    end
  end until files_to_process.empty?
end

#separatorObject

Return the appropriate separator, depending on the current style.



190
191
192
193
194
195
196
# File 'lib/asciidoc-bib/processor.rb', line 190

def separator
  if Styles.is_numeric? @style
    ','
  else
    ';'
  end
end

#sorted_citesObject

Return the list of sorted citations.



273
274
275
# File 'lib/asciidoc-bib/processor.rb', line 273

def sorted_cites
  @citations.sorted_cites @biblio
end

#with_pp(pages) ⇒ Object

Format pages with pp/p as appropriate.



199
200
201
202
203
204
205
206
207
208
209
# File 'lib/asciidoc-bib/processor.rb', line 199

def with_pp pages
  return "".dup if pages.empty?

  if @style.include? "chicago"
    pages
  elsif pages.include? "-"
    "pp.&#160;#{pages}"
  else
    "p.&#160;#{pages}"
  end
end