Class: CiteProc::Ruby::Renderer

Inherits:
Object
  • Object
show all
Defined in:
lib/citeproc/ruby/renderer.rb,
lib/citeproc/ruby/renderer/date.rb,
lib/citeproc/ruby/renderer/text.rb,
lib/citeproc/ruby/renderer/group.rb,
lib/citeproc/ruby/renderer/label.rb,
lib/citeproc/ruby/renderer/macro.rb,
lib/citeproc/ruby/renderer/names.rb,
lib/citeproc/ruby/renderer/state.rb,
lib/citeproc/ruby/renderer/choose.rb,
lib/citeproc/ruby/renderer/format.rb,
lib/citeproc/ruby/renderer/layout.rb,
lib/citeproc/ruby/renderer/locale.rb,
lib/citeproc/ruby/renderer/number.rb,
lib/citeproc/ruby/renderer/history.rb,
lib/citeproc/ruby/renderer/observer.rb

Defined Under Namespace

Classes: History, ItemObserver, State

Constant Summary collapse

PAGE_RANGE_PATTERN =
/\b([[:alpha:]]*)(\d+)([[:alpha:]]*)\s*[–-]+\s*([[:alpha:]]*)(\d+)([[:alpha:]]*)\b/

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options_or_engine = nil) ⇒ Renderer

Returns a new instance of Renderer.



10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/citeproc/ruby/renderer.rb', line 10

def initialize(options_or_engine = nil)
  @state = State.new

  case options_or_engine
  when Engine
    @engine = options_or_engine
  when Hash
    locale, format = options_or_engine.values_at(:locale, :format)
    @locale = locale.is_a?(CSL::Locale) ? locale : CSL::Locale.load(locale)
    @format = Format.load(format)
  end
end

Instance Attribute Details

#engineObject

Returns the value of attribute engine.



8
9
10
# File 'lib/citeproc/ruby/renderer.rb', line 8

def engine
  @engine
end

#stateObject (readonly)

Returns the value of attribute state.



6
7
8
# File 'lib/citeproc/ruby/renderer.rb', line 6

def state
  @state
end

Instance Method Details

#abbreviate(*arguments) ⇒ Object Also known as: abbrev



23
24
25
26
# File 'lib/citeproc/ruby/renderer.rb', line 23

def abbreviate(*arguments)
  return unless engine
  engine.abbreviate(*arguments)
end

#allow_locale_overrides?Boolean

Returns:

  • (Boolean)


29
30
31
32
# File 'lib/citeproc/ruby/renderer.rb', line 29

def allow_locale_overrides?
  return false unless engine
  engine.options[:allow_locale_overrides]
end

#bibliography_mode?Boolean

Returns:

  • (Boolean)


9
10
11
# File 'lib/citeproc/ruby/renderer/state.rb', line 9

def bibliography_mode?
  state.mode == 'bibliography'
end

#citation_mode?Boolean

Returns:

  • (Boolean)


5
6
7
# File 'lib/citeproc/ruby/renderer/state.rb', line 5

def citation_mode?
  state.mode == 'citation'
end

#completely_substitute?(names) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/citeproc/ruby/renderer/names.rb', line 117

def completely_substitute?(names)
  # Substitution applies only to the first names
  # node being rendered!
  return false if state.rendered_names?

  state.store_authors! names
  previous_names = state.previous_authors

  return false unless previous_names

  names == previous_names[0]
end

#concat(string, suffix) ⇒ String

Concatenates two strings, making sure that squeezable characters are not duplicated between string and suffix.

Parameters:

  • string (String)
  • suffix (String)

Returns:

  • (String)

    new string consisting of string and suffix



34
35
36
# File 'lib/citeproc/ruby/renderer/format.rb', line 34

def concat(string, suffix)
  format.concat(string, suffix)
end

#count_names(names, node) ⇒ Object



93
94
95
96
97
98
99
100
101
# File 'lib/citeproc/ruby/renderer/names.rb', line 93

def count_names(names, node)
  names.reduce(0) do |count, (_, ns)|
    if node.truncate?(ns)
      count + node.truncate(ns).length
    else
      count + ns.length
    end
  end
end

#evaluates?(item, node) ⇒ Boolean

Evaluates the conditions of the passed-in Choose::Block against the passed-in CitationItem using the Block’s matcher.

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Style::Choose::Block)

Returns:

  • (Boolean)

    whether or not the node’s conditions are true for the passed-in item



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/citeproc/ruby/renderer/choose.rb', line 39

def evaluates?(item, node)

  # subtle: else-nodes have no conditions. since the default
  # matcher :all? returns true for an empty list we do not
  # need to check for an else node specifically.

  # return true if node.nodename == 'else'

  node.conditions.send(node.matcher) do |type, matcher, values|
    case type
    when :disambiguate
      false # TODO not implemented yet

    when :'is-numeric'
      evaluates_condition? matcher, values do |value|
        v = item.data.unobservable_read_attribute(value)
        v.respond_to?(:numeric?) && v.numeric?
      end

    when :'is-uncertain-date'
      evaluates_condition? matcher, values do |value|
        v = item.data.unobservable_read_attribute(value)
        v.respond_to?(:uncertain?) && v.uncertain?
      end


    when :locator
      locator = item.locator.to_s.tr(' ', '-')

      evaluates_condition? matcher, values do |value|
        value.to_s == locator
      end

    when :position
      false # TODO not implemented yet

    when :type
      type = item.data.unobservable_read_attribute(:type).to_s

      evaluates_condition? matcher, values do |value|
        value.to_s == type
      end

    when :variable
      evaluates_condition? matcher, values do |value|
        item.data.attribute?(value)
      end

    else
      fail "unknown condition type: #{type}"
    end
  end
end

#evaluates_condition?(matcher, values, &condition) ⇒ Boolean

Evaluates the passed-in block for each value in values, negating the result if the value is prefixed with ‘not:’

Returns:

  • (Boolean)


95
96
97
98
99
100
101
102
# File 'lib/citeproc/ruby/renderer/choose.rb', line 95

def evaluates_condition?(matcher, values, &condition)
  values.send(matcher) do |value|
    value, negate = value.split(/^not:/, 2).reverse
    result = condition.call(value)

    negate ? !result : result
  end
end

#formatObject



8
9
10
# File 'lib/citeproc/ruby/renderer/format.rb', line 8

def format
 @format ||= Format.load
end

#format!(string, node) ⇒ Object

Applies the current format on the string using the node’s formatting options.



18
19
20
# File 'lib/citeproc/ruby/renderer/format.rb', line 18

def format!(string, node)
  format.apply(string, node, locale)
end

#format=(format) ⇒ Object



12
13
14
# File 'lib/citeproc/ruby/renderer/format.rb', line 12

def format=(format)
  @format = Format.load(format)
end

#format_page_range(pages, format) ⇒ Object

Formats pages accoring to format. Valid formats are:

  • “chicago”: page ranges are abbreviated according to the Chicago Manual of Style rules.

  • “expanded”: Abbreviated page ranges are expanded to their non-abbreviated form: 42-45, 321-328, 2787-2816.

  • “minimal”: All digits repeated in the second number are left out: 42-45, 321-8, 2787-816.

Parameters:

  • pages (String)

    to be formatted

  • format (String)

    to use for formatting



56
57
58
59
# File 'lib/citeproc/ruby/renderer/format.rb', line 56

def format_page_range(pages, format)
  return if pages.nil?
  format_page_range!(pages.dup, format)
end

#format_page_range!(pages, format) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/citeproc/ruby/renderer/format.rb', line 61

def format_page_range!(pages, format)
  return if pages.nil?
  return pages if pages.empty?

  dash = translate('page-range-delimiter') || '' # en-dash

  pages.gsub! PAGE_RANGE_PATTERN do
    affixes, f, t = [$1, $3, $4, $6], $2, $5

    # When there are affixes or no format was
    # specified we skip this part. As a result,
    # only the delimiter will be replaced!

    if affixes.all?(&:empty?) && !format.nil?

      dim = f.length
      delta = dim - t.length

      if delta >= 0
        t.prepend f[0, delta] unless delta.zero?

        if format == 'chicago'
          changes = dim - f.chars.zip(t.chars).
            take_while { |a,b| a == b }.length if dim == 4

          format = case
            when dim < 3
              'expanded'
            when dim == 4 && changes > 2
              'expanded'
            when f[-2, 2] == '00'
              'expanded'
            when f[-2] == '0'
              'minimal'
            else
              'minimal-two'
            end
        end

        case format
        when 'expanded'
          # nothing to do
        when 'minimal'
          t = t.each_char.drop_while.with_index { |c, i| c == f[i] }.join('')
        when 'minimal-two'
          if dim > 2
            t = t.each_char.drop_while.with_index { |c, i|
              c == f[i] && dim - i > 2
            }.join('')
          end
        else
          raise ArgumentError, "unknown page range format: #{format}"
        end
      end
    end

    affixes.zip([f, dash, t]).flatten.compact.join('')
  end

  pages
end

#individually_substitute!(names) ⇒ Object



130
131
# File 'lib/citeproc/ruby/renderer/names.rb', line 130

def individually_substitute!(names)
end

#join(list, delimiter = nil) ⇒ Object



22
23
24
# File 'lib/citeproc/ruby/renderer/format.rb', line 22

def join(list, delimiter = nil)
  format.join(list, delimiter)
end

#localeObject



6
7
8
# File 'lib/citeproc/ruby/renderer/locale.rb', line 6

def locale
  @locale ||= CSL::Locale.load
end

#locale=(locale) ⇒ Object



10
11
12
# File 'lib/citeproc/ruby/renderer/locale.rb', line 10

def locale=(locale)
  @locale = CSL::Locale.load(locale)
end

#ordinalize(number, options = {}) ⇒ String

Returns number as an ordinal.

Returns:

  • (String)

    number as an ordinal



19
20
21
# File 'lib/citeproc/ruby/renderer/locale.rb', line 19

def ordinalize(number, options = {})
  locale.ordinalize(number, options)
end

#render(item, node) ⇒ String

Returns the rendered and formatted string.

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Node)

Returns:

  • (String)

    the rendered and formatted string

Raises:

  • (ArgumentError)


37
38
39
40
41
42
43
44
45
46
47
# File 'lib/citeproc/ruby/renderer.rb', line 37

def render(item, node)
  raise ArgumentError, "no CSL node: #{node.inspect}" unless
    node.respond_to?(:nodename)

  specialize = "render_#{node.nodename.tr('-', '_')}"

  raise ArgumentError, "#{specialize} not implemented" unless
    respond_to?(specialize, true)

  format! send(specialize, item, node), node
end

#render_bibliography(item, node) ⇒ String

Returns the rendered and formatted string.

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Style::Bibliography)

Returns:

  • (String)

    the rendered and formatted string



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/citeproc/ruby/renderer.rb', line 77

def render_bibliography(item, node)
  state.store! item, node

  if allow_locale_overrides? && item.language != locale.language
    begin
      new_locale = CSL::Locale.load(item.language)

      unless new_locale.nil?
        original_locale, @locale = @locale, new_locale
      end
    rescue ParseError
      # locale not found
    end
  end

  result = render item, node.layout

ensure
  unless original_locale.nil?
    @locale = original_locale
  end

  state.clear! result
end

#render_block(item, node) ⇒ String

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Style::Choose::Block)

Returns:

  • (String)


22
23
24
25
26
27
28
# File 'lib/citeproc/ruby/renderer/choose.rb', line 22

def render_block(item, node)
  return '' unless node.has_children?

  join node.each_child.map { |child|
    render item, child
  }
end

#render_choose(item, node) ⇒ String

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Style::Choose)

Returns:

  • (String)


9
10
11
12
13
14
15
16
17
# File 'lib/citeproc/ruby/renderer/choose.rb', line 9

def render_choose(item, node)
  return '' unless node.has_children?

  node.each_child do |child|
    return render_block(item, child) if evaluates?(item, child)
  end

  '' # no block was rendered
end

#render_citation(data, node) ⇒ String

Returns the rendered and formatted string.

Parameters:

  • data (CiteProc::CitationData)
  • node (CSL::Style::Citation)

Returns:

  • (String)

    the rendered and formatted string



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/citeproc/ruby/renderer.rb', line 52

def render_citation(data, node)
  state.store! data, node

  citations = join data.map { |item|
    render_single_citation item, node.layout
  }, node.layout.delimiter || ''

  result = format! citations, node.layout
ensure
  state.clear! result
end

#render_date(item, node) ⇒ String

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Node)

Returns:

  • (String)

Raises:

  • RenderingError



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/citeproc/ruby/renderer/date.rb', line 10

def render_date(item, node)
  return '' unless node.has_variable?

  date = item.data[node.variable]
  return '' if date.nil? || date.empty?

  return date.to_s if date.literal?

  # TODO date-ranges

  if node.localized?
    localized_node = locale.date.detect { |d| d.form == node.form } or
      raise RenderingError, "no localized date for form #{node.form} found"

    delimiter, filter = node.delimiter, node.parts_filter

    parts = localized_node.parts.select do |part|
      filter.include? part.name
    end
  else
    parts, delimiter = node.parts, node.delimiter
  end

  parts.map { |part|
    render date, part
  }.reject(&:empty?).join(delimiter)
end

#render_date_part(date, node) ⇒ String

Parameters:

  • date (CiteProc::Date)
  • node (CSL::Style::DatePart, CSL::Locale::DatePart)

Returns:

  • (String)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/citeproc/ruby/renderer/date.rb', line 41

def render_date_part(date, node)
  case
  when node.day?
    case
    when date.day.nil?
      ''
    when node.form == 'ordinal'
      if date.day > 1 && locale.limit_day_ordinals?
        date.day.to_s
      else
        ordinalize date.day
      end
    when node.form == 'numeric-leading-zeros'
      '%02d' % date.day
    else
      date.day.to_s
    end

  when node.month?
    case
    when date.season?
      translate(('season-%02d' % date.season), node.attributes_for(:form))
    when date.month.nil?
      ''
    when node.numeric?
      date.month.to_s
    when node.numeric_leading_zeros?
      '%02d' % date.month
    else
      translate(('month-%02d' % date.month), node.attributes_for(:form))
    end

  when node.year?
    year = date.year
    year = year % 100 if node.short?

    if date.ad?
      year = year.to_s
      year << translate(:ad) if date.ad?
    elsif date.bc?
      year = (-1*year).to_s
      year << translate(:bc) if date.bc?
    else
      year = year.to_s
    end

    year

  else
    ''
  end
end

#render_group(item, node) ⇒ String

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Style::Group)

Returns:

  • (String)


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/citeproc/ruby/renderer/group.rb', line 9

def render_group(item, node)
  return '' unless node.has_children?

  observer = ItemObserver.new(item.data)
  observer.start

  begin
    rendition = node.each_child.map { |child|
      render item, child
    }.reject(&:empty?)

    rendition = join(rendition, node.delimiter)

  ensure
    observer.stop
  end

  return '' if observer.skip?

  rendition
end

#render_individual_name(name, node, position = 1) ⇒ String

Parameters:

  • names (CiteProc::Name)
  • node (CSL::Style::Name)
  • position (Fixnum) (defaults to: 1)

Returns:

  • (String)


230
231
232
233
234
235
236
237
238
239
240
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
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/citeproc/ruby/renderer/names.rb', line 230

def render_individual_name(name, node, position = 1)
  if name.personal?
    name = name.dup

    # TODO move parts of the formatting logic here
    # because name parts may include particles etc.


    # Strip away some unusual characters to normalize
    # sort order for names.
    if sort_mode?
      name.family = name.family.to_s.gsub(/[\[\]]|^\W+/, '')
    end

    name.options.merge! node.name_options
    name.sort_order! node.name_as_sort_order_at?(position)

    name.initialize_without_hyphen! if node.initialize_without_hyphen?

    if style && style.demote_particle?
      name.options[:'demote-non-dropping-particle'] = style.demote_particle
    end

    # Strip away (hyphenated) particles in sort mode!
    if sort_mode? && name.demote_particle?
      name.family = name.family.to_s.sub(/^[[:lower:]]+[\s-]/, '')
    end

    node.name_part.each do |part|
      case part[:name]
      when 'family'
        if !name.particle? || name.demote_particle?
          name.family = format!(name.family, part)
        else
          name.family = format!("#{name.particle} #{name.family}", part)
          name.particle = nil
        end

        # Name suffix must be enclosed by family-part
        # suffix in display order!
        if name.has_suffix? && !name.sort_order? && part.attribute?(:suffix)
          comma = name.comma_suffix? ? name.comma : ' '
          suffix = part[:suffix]

          name.family.chomp! suffix
          name.family.concat "#{comma}#{name.suffix}#{suffix}"
          name.suffix = nil
        end

      when 'given'
        if name.dropping_particle?
          name.given = format!("#{name.initials} #{name.dropping_particle}", part)
          name.dropping_particle = nil
        else
          name.given = format!(name.initials, part)
        end

        # Demoted particles must be enclosed by
        # given-part affixes in sort order!
        if name.particle? && name.demote_particle? &&
          name.sort_order? && part.attribute?(:suffix)

          suffix = part[:suffix]

          name.given.chomp! suffix
          name.given.concat " #{name.particle}#{suffix}"

          name.particle = nil
        end

      end
    end

  end

  format! name.format, node
end

#render_label(item, node, variable = node.variable) ⇒ String

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Style::Label)
  • variable (String) (defaults to: node.variable)

Returns:

  • (String)


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/citeproc/ruby/renderer/label.rb', line 11

def render_label(item, node, variable = node.variable)
  return '' if variable.nil? || variable.empty?

  case
  when node.page?
    value, name = item.read_attribute(:page) || item.data.unobservable_read_attribute(:page).to_s, :page

    format_page_range!(value, node.page_range_format)

  when node.locator?

    # Subtle: when there is no locator we also look
    # in item.data; there should be no locator there
    # either but the read access will be noticed by
    # observers (if any).
    value, name = item.locator || item.data.unobservable_read_attribute(:locator), item.label || 'page'

  when node.names_label?

    # We handle the editortranslator special case
    # by fetching editors since we can assume
    # that both are present and identical!
    if variable == :editortranslator
      value, name = item.data.unobservable_read_attribute(:editor), variable.to_s
    else
      value, name = item.data.unobservable_read_attribute(variable), variable.to_s
    end

  else
    value, name = item.data.unobservable_read_attribute(variable), node.term
  end

  return '' if value.nil? || value.respond_to?(:empty?) && value.empty?

  options = node.attributes_for :form

  options[:plural] = case
    when node.always_pluralize?
      true
    when node.never_pluralize?
      false
    when node.number_of_pages?, node.number_of_volumes?
      value.to_i > 1
    when value.respond_to?(:plural?)
      value.plural?
    else
      CiteProc::Number.pluralize?(value.to_s)
    end

  translate name, options
end

#render_name(names, node) ⇒ String

Formats one or more names according to the configuration of the passed-in node. Returns the formatted name(s) as a string.

Parameters:

  • names (CiteProc::Names)
  • node (CSL::Style::Name)

Returns:

  • (String)


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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/citeproc/ruby/renderer/names.rb', line 140

def render_name(names, node)

  # TODO handle subsequent citation rules

  delimiter = node.delimiter

  connector = node.connector
  connector = translate('and') if connector == 'text'

  # Add spaces around connector
  connector = " #{connector} " unless connector.nil?

  rendered_names =
    case
    when node.truncate?(names)
      truncated = node.truncate(names)

      return '' if truncated.empty?

      if node.delimiter_precedes_last?(truncated)
        connector = join [delimiter, connector].compact
      end

      if node.ellipsis? && names.length - truncated.length > 1
        join [
          join(truncated.map.with_index { |name, idx|
            render_individual_name name, node, idx + 1
          }, delimiter),

          render_individual_name(names[-1], node, truncated.length + 1)

        ], node.ellipsis

      else
        others = node.et_al ?
          format!(translate(node.et_al[:term]), node.et_al) :
          translate('et-al')

        connector = node.delimiter_precedes_et_al?(truncated) ?
          delimiter : ' '

        join [
          join(truncated.map.with_index { |name, idx|
            render_individual_name name, node, idx + 1
          }, delimiter),

          others

        ], connector

      end

    when names.length < 3
      if node.delimiter_precedes_last?(names)
        connector = [delimiter, connector].compact.join('').squeeze(' ')
      end

      join names.map.with_index { |name, idx|
        render_individual_name name, node, idx + 1
      }, connector || delimiter

    else
      if node.delimiter_precedes_last?(names)
        connector = [delimiter, connector].compact.join('').squeeze(' ')
      end

      join [
        join(names[0...-1].map.with_index { |name, idx|
          render_individual_name name, node, idx + 1
        }, delimiter),

        render_individual_name(names[-1], node, names.length)

      ], connector || delimiter
    end


  if substitute_subsequent_authors_completely? &&
    completely_substitute?(rendered_names)

    rendered_names = state.node.subsequent_author_substitute
  end

  format! rendered_names, node
end

#render_names(item, node) ⇒ String

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Style::Names)

Returns:

  • (String)


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/citeproc/ruby/renderer/names.rb', line 9

def render_names(item, node)
  return '' unless node.has_variable?

  names = node.variable.split(/\s+/).map do |role|
    [role.to_sym, item.data[role]]
  end

  suppressed = names.reject! { |n| item.suppressed? n[0] }

  names.reject! { |n| n[1].nil? || n[1].empty? }

  if names.empty?
    # We also return when the list is empty because
    # of a suppression, because we do not want to
    # substitute suppressed items!
    return '' unless suppressed.nil? && node.has_substitute?

    rendered_names = render_substitute item, node.substitute

    if substitute_subsequent_authors_completely? &&
      completely_substitute?(rendered_names)

      rendered_names = state.node.subsequent_author_substitute
    end

    rendered_names

  else

    resolve_editor_translator_exception! names

    # Pick the names node that will be used for
    # formatting; if we are currently in substiution
    # mode, the node that is being substituted for
    # will take precedence if the current node is
    # a descendant of it.
    #
    # This makes sure that nodes in macros do not
    # use the original names node.
    #
    # When the current node has children the names
    # will not be substituted either.
    if substitution_mode? && !node.has_children? &&
      node.ancestors.include?(state.substitute)

      names_node = state.substitute

    else
      names_node = node
    end

    name = name_node_for(names_node)

    return count_names(names, name).to_s if name.count?

    names.map! do |role, ns|
      if names_node.has_label?
        label = render_label item, names_node.label, role
        label = format! label, names_node.label

        rendered_names = render_name(ns, name)

        if rendered_names.empty?
          rendered_names
        else
          if names_node.prefix_label?
            concat label, rendered_names
          else
            concat rendered_names, label
          end
        end

      else
        render_name ns, name
      end
    end

    join names, names_node.delimiter(state.node)
  end

ensure
  state.rendered_names!
end

#render_number(item, node) ⇒ String

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Style::Number)

Returns:

  • (String)


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/citeproc/ruby/renderer/number.rb', line 9

def render_number(item, node)
  return '' unless node.has_variable?

  variable = item.data[node.variable]
  return variable.to_s unless variable && variable.numeric?

  numbers = variable.tokenize

  case
  when node.ordinal? || node.long_ordinal?
    options = node.attributes_for :form
    # TODO lookup term of variable to check gender

    numbers.map! do |num|
      num =~ /^\d+$/ ? ordinalize(num, options) : num
    end

  when node.roman?
    numbers.map! do |num|
      num =~ /^\d+$/ ? romanize(num) : num
    end

  else
					# nothing
  end

				numbers.join('')
end

#render_single_citation(item, node) ⇒ String

Returns the rendered and string.

Parameters:

  • data (CiteProc::CitationItem)
  • node (CSL::Style::Layout)

Returns:

  • (String)

    the rendered and string



67
68
69
70
71
72
# File 'lib/citeproc/ruby/renderer.rb', line 67

def render_single_citation(item, node)
  # TODO author_only
  item.suppress! 'author' if item.suppress_author?

  join [item.prefix, render_layout(item, node), item.suffix].compact
end

#render_sort(a, b, node, key) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/citeproc/ruby/renderer.rb', line 102

def render_sort(a, b, node, key)
  state.store! nil, key

  original_format = @format
  @format = Formats::Sort.new

  if a.is_a?(CiteProc::Names)
    [render_name(a, node), render_name(b, node)]

  else
    # We need to clear any items that are suppressed
    # because they were used as substitutes during
    # rendering for sorting purposes!
    a_rendered = render a.cite, node
    a.suppressed.clear

    b_rendered = render b.cite, node
    b.suppressed.clear

    [a_rendered, b_rendered]
  end

ensure
  @format = original_format
  state.clear!
end

#render_substitute(item, node) ⇒ String

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Style::Substitute)

Returns:

  • (String)


311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
# File 'lib/citeproc/ruby/renderer/names.rb', line 311

def render_substitute(item, node)
  return '' unless node.has_children?

  if substitution_mode?
    saved_substitute = state.substitute
  end

  state.substitute! node.parent
  observer = ItemObserver.new(item.data)

  node.each_child do |child|
    observer.start

    begin
      string = render(item, child)

      unless string.empty?
        # Variables rendered as substitutes
        # must be suppressed during the remainder
        # of the rendering process!
        item.suppress!(*observer.accessed)

        # Report a read-access using the substitution string
        # for the name variable being substituted, or the first
        # name variable (if there are more than one).
        variable = node.parent.variable[/\w+/]
        item.data.simulate_read_attribute variable, string

        return string # break out of each loop!
      end

    ensure
      observer.stop
      observer.clear!
    end

  end

  '' # no substitute was rendered
ensure
  state.clear_substitute! saved_substitute
end

#render_text(item, node) ⇒ String

Parameters:

  • item (CiteProc::CitationItem)
  • node (CSL::Style::Text)

Returns:

  • (String)


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/citeproc/ruby/renderer/text.rb', line 9

def render_text(item, node)
  case
  when node.has_variable?

    if node.variable == 'locator'

      # Subtle: when there is no locator we also look
      # in item.data; there should be no locator there
      # either but the read access will be noticed by
      # observers (if any).
      text = item.locator || item.data[:locator].to_s

    else
      text = item.data.variable(node.variable, node.variable_options).to_s

      # Check for abbreviations or short-form fallbacks!
      context, was_short_form = node.variable.split(/-short$/, 2)

      if !was_short_form.nil? || node[:form] == 'short'
        if text.empty? && context != node.variable
          text = item.data.variable(context, node.variable_options).to_s
        end

        text = abbreviate(context, text) || text
      end
    end


    case
    when node.variable == 'page'
      format_page_range!(text, node.page_range_format)

    when node.variable == 'page-first' && text.empty?
      text = item.data[:'page'].to_s[/\d+/].to_s

    end

    text

  when node.has_macro?
    render item, node.macro

  when node.has_term?
    translate node[:term], node.attributes_for(:plural, :form)

  else
    node.value.to_s
  end
end

#romanize(number) ⇒ String

Returns the roman numeral of number.

Returns:

  • (String)

    the roman numeral of number



40
41
42
# File 'lib/citeproc/ruby/renderer/format.rb', line 40

def romanize(number)
	CiteProc::Number.romanize(number)
end

#sort_mode?Boolean

Returns:

  • (Boolean)


13
14
15
# File 'lib/citeproc/ruby/renderer/state.rb', line 13

def sort_mode?
  state.mode == 'key'
end

#styleObject



21
22
23
24
25
26
# File 'lib/citeproc/ruby/renderer/state.rb', line 21

def style
  return unless state.node && !state.node.root? &&
    state.node.root.is_a?(CSL::Style)

  state.node.root
end

#substitute_subsequent_authors?Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/citeproc/ruby/renderer/names.rb', line 103

def substitute_subsequent_authors?
  bibliography_mode? && state.node.substitute_subsequent_authors?
end

#substitute_subsequent_authors_completely?Boolean

Returns:

  • (Boolean)


107
108
109
110
# File 'lib/citeproc/ruby/renderer/names.rb', line 107

def substitute_subsequent_authors_completely?
  substitute_subsequent_authors? &&
    state.node.substitute_subsequent_authors_completely?
end

#substitute_subsequent_authors_individually?Boolean

Returns:

  • (Boolean)


112
113
114
115
# File 'lib/citeproc/ruby/renderer/names.rb', line 112

def substitute_subsequent_authors_individually?
  substitute_subsequent_authors? &&
    state.node.substitute_subsequent_authors_individually?
end

#substitution_mode?Boolean

Returns:

  • (Boolean)


17
18
19
# File 'lib/citeproc/ruby/renderer/state.rb', line 17

def substitution_mode?
  !state.substitute.nil?
end

#translate(name, options = {}) ⇒ Object



14
15
16
# File 'lib/citeproc/ruby/renderer/locale.rb', line 14

def translate(name, options = {})
  locale.translate(name, options)
end