citeproc-ruby 0.0.6 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.document +4 -0
- data/.gitignore +10 -0
- data/.rspec +3 -0
- data/.simplecov +4 -0
- data/.travis.yml +17 -0
- data/.yardopts +2 -0
- data/AGPL +662 -0
- data/BSDL +29 -0
- data/Gemfile +42 -0
- data/Guardfile +14 -0
- data/README.md +32 -76
- data/Rakefile +60 -0
- data/citeproc-ruby.gemspec +46 -0
- data/cucumber.yml +1 -0
- data/features/bibliography.feature +25 -0
- data/features/name_options.feature +37 -0
- data/features/names.feature +192 -0
- data/features/renderer.feature +74 -0
- data/features/sort.feature +50 -0
- data/features/step_definitions/renderer.rb +80 -0
- data/features/support/env.rb +33 -0
- data/features/support/hooks.rb +10 -0
- data/lib/citeproc/ruby.rb +32 -0
- data/lib/citeproc/ruby/engine.rb +122 -0
- data/lib/citeproc/ruby/format.rb +303 -0
- data/lib/citeproc/ruby/formats/default.rb +25 -0
- data/lib/citeproc/ruby/formats/html.rb +221 -0
- data/lib/citeproc/ruby/renderer.rb +140 -0
- data/lib/citeproc/ruby/renderer/choose.rb +106 -0
- data/lib/citeproc/ruby/renderer/date.rb +90 -0
- data/lib/citeproc/ruby/renderer/format.rb +129 -0
- data/lib/citeproc/ruby/renderer/group.rb +34 -0
- data/lib/citeproc/ruby/renderer/history.rb +40 -0
- data/lib/citeproc/ruby/renderer/label.rb +66 -0
- data/lib/citeproc/ruby/renderer/layout.rb +20 -0
- data/lib/citeproc/ruby/renderer/locale.rb +26 -0
- data/lib/citeproc/ruby/renderer/macro.rb +20 -0
- data/lib/citeproc/ruby/renderer/names.rb +401 -0
- data/lib/citeproc/ruby/renderer/number.rb +41 -0
- data/lib/citeproc/ruby/renderer/observer.rb +44 -0
- data/lib/citeproc/ruby/renderer/state.rb +96 -0
- data/lib/citeproc/ruby/renderer/text.rb +62 -0
- data/lib/citeproc/ruby/sort.rb +82 -0
- data/lib/citeproc/ruby/version.rb +5 -0
- data/spec/citeproc/ruby/engine_spec.rb +94 -0
- data/spec/citeproc/ruby/formats/default_spec.rb +159 -0
- data/spec/citeproc/ruby/formats/html_spec.rb +162 -0
- data/spec/citeproc/ruby/renderer/choose_spec.rb +293 -0
- data/spec/citeproc/ruby/renderer/date_spec.rb +173 -0
- data/spec/citeproc/ruby/renderer/group_spec.rb +88 -0
- data/spec/citeproc/ruby/renderer/history_spec.rb +38 -0
- data/spec/citeproc/ruby/renderer/label_spec.rb +225 -0
- data/spec/citeproc/ruby/renderer/layout_spec.rb +41 -0
- data/spec/citeproc/ruby/renderer/macro_spec.rb +31 -0
- data/spec/citeproc/ruby/renderer/names_spec.rb +396 -0
- data/spec/citeproc/ruby/renderer/number_spec.rb +120 -0
- data/spec/citeproc/ruby/renderer/text_spec.rb +120 -0
- data/spec/citeproc/ruby/renderer_spec.rb +65 -0
- data/spec/fixtures/items.rb +80 -0
- data/{resource/locale → spec/fixtures/locales}/locales-en-US.xml +2 -11
- data/{resource/locale → spec/fixtures/locales}/locales-fr-FR.xml +77 -66
- data/{resource/style → spec/fixtures/styles}/apa.csl +5 -5
- data/spec/spec_helper.rb +67 -14
- metadata +121 -211
- data/lib/citeproc.rb +0 -100
- data/lib/citeproc/bibliography.rb +0 -57
- data/lib/citeproc/data.rb +0 -149
- data/lib/citeproc/date.rb +0 -133
- data/lib/citeproc/formatter.rb +0 -38
- data/lib/citeproc/item.rb +0 -53
- data/lib/citeproc/name.rb +0 -284
- data/lib/citeproc/processor.rb +0 -166
- data/lib/citeproc/selector.rb +0 -61
- data/lib/citeproc/variable.rb +0 -82
- data/lib/citeproc/version.rb +0 -3
- data/lib/csl/locale.rb +0 -223
- data/lib/csl/node.rb +0 -72
- data/lib/csl/nodes.rb +0 -1418
- data/lib/csl/renderer.rb +0 -88
- data/lib/csl/sort.rb +0 -61
- data/lib/csl/style.rb +0 -110
- data/lib/csl/term.rb +0 -124
- data/lib/extensions/core.rb +0 -43
- data/lib/plugins/filters/bibtex.rb +0 -12
- data/lib/plugins/formats/default.rb +0 -134
- data/lib/plugins/formats/html.rb +0 -67
- data/lib/support/attributes.rb +0 -99
- data/lib/support/compatibility.rb +0 -83
- data/lib/support/tree.rb +0 -80
- data/resource/locale/locales-af-ZA.xml +0 -305
- data/resource/locale/locales-ar-AR.xml +0 -306
- data/resource/locale/locales-bg-BG.xml +0 -305
- data/resource/locale/locales-ca-AD.xml +0 -305
- data/resource/locale/locales-cs-CZ.xml +0 -305
- data/resource/locale/locales-da-DK.xml +0 -305
- data/resource/locale/locales-de-AT.xml +0 -304
- data/resource/locale/locales-de-CH.xml +0 -304
- data/resource/locale/locales-de-DE.xml +0 -332
- data/resource/locale/locales-el-GR.xml +0 -305
- data/resource/locale/locales-en-GB.xml +0 -304
- data/resource/locale/locales-es-ES.xml +0 -305
- data/resource/locale/locales-et-EE.xml +0 -304
- data/resource/locale/locales-eu.xml +0 -305
- data/resource/locale/locales-fa-IR.xml +0 -304
- data/resource/locale/locales-fi-FI.xml +0 -304
- data/resource/locale/locales-fr-CA.xml +0 -306
- data/resource/locale/locales-he-IL.xml +0 -304
- data/resource/locale/locales-hu-HU.xml +0 -305
- data/resource/locale/locales-is-IS.xml +0 -304
- data/resource/locale/locales-it-IT.xml +0 -305
- data/resource/locale/locales-ja-JP.xml +0 -305
- data/resource/locale/locales-kh-KH.xml +0 -303
- data/resource/locale/locales-km-KH.xml +0 -304
- data/resource/locale/locales-ko-KR.xml +0 -305
- data/resource/locale/locales-mn-MN.xml +0 -306
- data/resource/locale/locales-nb-NO.xml +0 -304
- data/resource/locale/locales-nl-NL.xml +0 -304
- data/resource/locale/locales-nn-NO.xml +0 -304
- data/resource/locale/locales-pl-PL.xml +0 -305
- data/resource/locale/locales-pt-BR.xml +0 -304
- data/resource/locale/locales-pt-PT.xml +0 -305
- data/resource/locale/locales-ro-RO.xml +0 -305
- data/resource/locale/locales-ru-RU.xml +0 -306
- data/resource/locale/locales-sk-SK.xml +0 -304
- data/resource/locale/locales-sl-SI.xml +0 -305
- data/resource/locale/locales-sr-RS.xml +0 -305
- data/resource/locale/locales-sv-SE.xml +0 -305
- data/resource/locale/locales-th-TH.xml +0 -304
- data/resource/locale/locales-tr-TR.xml +0 -305
- data/resource/locale/locales-uk-UA.xml +0 -306
- data/resource/locale/locales-vi-VN.xml +0 -305
- data/resource/locale/locales-zh-CN.xml +0 -304
- data/resource/locale/locales-zh-TW.xml +0 -305
- data/resource/schema/csl-categories.rnc +0 -39
- data/resource/schema/csl-data.rnc +0 -98
- data/resource/schema/csl-terms.rnc +0 -106
- data/resource/schema/csl-types.rnc +0 -39
- data/resource/schema/csl-variables.rnc +0 -182
- data/resource/schema/csl.rnc +0 -941
- data/resource/style/bibtex.csl +0 -177
- data/resource/style/chicago-annotated-bibliography.csl +0 -513
- data/resource/style/chicago-author-date-basque.csl +0 -707
- data/resource/style/chicago-author-date-de.csl +0 -394
- data/resource/style/chicago-author-date-listing.csl +0 -434
- data/resource/style/chicago-author-date.csl +0 -425
- data/resource/style/chicago-dated-note-biblio-no-ibid.csl +0 -472
- data/resource/style/chicago-fullnote-bibliography-bb.csl +0 -928
- data/resource/style/chicago-fullnote-bibliography-delimiter-fixes.csl +0 -972
- data/resource/style/chicago-fullnote-bibliography-no-ibid-delimiter-fixes.csl +0 -963
- data/resource/style/chicago-fullnote-bibliography-no-ibid.csl +0 -785
- data/resource/style/chicago-fullnote-bibliography.csl +0 -803
- data/resource/style/chicago-library-list.csl +0 -511
- data/resource/style/chicago-note-biblio-no-ibid.csl +0 -514
- data/resource/style/chicago-note-bibliography.csl +0 -530
- data/resource/style/chicago-note.csl +0 -388
- data/resource/style/chicago-quick-copy.csl +0 -685
- data/resource/style/ieee.csl +0 -299
- data/resource/style/mla-notes.csl +0 -796
- data/resource/style/mla-underline.csl +0 -175
- data/resource/style/mla-url.csl +0 -214
- data/resource/style/mla.csl +0 -394
- data/resource/style/vancouver-brackets.csl +0 -256
- data/resource/style/vancouver-superscript-bracket-only-year.csl +0 -165
- data/resource/style/vancouver-superscript.csl +0 -256
- data/resource/style/vancouver.csl +0 -256
- data/spec/citeproc/bibliography_spec.rb +0 -45
- data/spec/citeproc/citeproc_spec.rb +0 -80
- data/spec/citeproc/date_spec.rb +0 -89
- data/spec/citeproc/formatter_spec.rb +0 -101
- data/spec/citeproc/item_spec.rb +0 -71
- data/spec/citeproc/name_spec.rb +0 -30
- data/spec/citeproc/processor_spec.rb +0 -61
- data/spec/citeproc/selector_spec.rb +0 -82
- data/spec/citeproc/variable_spec.rb +0 -69
- data/spec/csl/locale_spec.rb +0 -208
- data/spec/csl/node_spec.rb +0 -25
- data/spec/csl/nodes_spec.rb +0 -145
- data/spec/csl/style_spec.rb +0 -62
- data/spec/csl/term_spec.rb +0 -56
- data/spec/fixtures/dates.yaml +0 -80
- data/spec/fixtures/names.yaml +0 -115
- data/spec/fixtures/nodes.yaml +0 -245
- data/spec/support/attributes_spec.rb +0 -39
- data/spec/support/tree_spec.rb +0 -163
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module CiteProc
|
|
2
|
+
module Ruby
|
|
3
|
+
module Formats
|
|
4
|
+
|
|
5
|
+
class Text < Format
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def finalize!
|
|
10
|
+
super
|
|
11
|
+
output.gsub!(/&(amp|lt|gt);/i, {
|
|
12
|
+
'&' => '&',
|
|
13
|
+
'>' => '>',
|
|
14
|
+
'<' => '<'
|
|
15
|
+
})
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class Debug < Format
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
module CiteProc
|
|
2
|
+
module Ruby
|
|
3
|
+
module Formats
|
|
4
|
+
|
|
5
|
+
class Html < Format
|
|
6
|
+
|
|
7
|
+
@defaults = {
|
|
8
|
+
:css_only => false,
|
|
9
|
+
:italic => 'i', # em
|
|
10
|
+
:bold => 'b', # strong
|
|
11
|
+
:container => 'span', # inner container
|
|
12
|
+
:display => 'div', # display container
|
|
13
|
+
|
|
14
|
+
:bib_container => 'ol',
|
|
15
|
+
:bib_container_class => 'csl-bibliography',
|
|
16
|
+
:bib_entry => 'li',
|
|
17
|
+
:bib_entry_class => 'csl-entry',
|
|
18
|
+
:bib_hanging_indent => '0.5',
|
|
19
|
+
:bib_unit => 'em',
|
|
20
|
+
:bib_indent => ' '
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
attr_reader :defaults
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
attr_reader :config
|
|
28
|
+
|
|
29
|
+
def initialize(config = nil)
|
|
30
|
+
if config.nil?
|
|
31
|
+
@config = Html.defaults.dup
|
|
32
|
+
else
|
|
33
|
+
@config = Html.defaults.merge(config)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def bibliography(bibliography)
|
|
38
|
+
ol, li, indent, unit =
|
|
39
|
+
config.values_at(:bib_container, :bib_entry, :bib_indent, :bib_unit)
|
|
40
|
+
|
|
41
|
+
container_options = {}
|
|
42
|
+
container_options['class'] = config[:bib_container_class]
|
|
43
|
+
|
|
44
|
+
entry_options = {}
|
|
45
|
+
entry_options['class'] = config[:bib_entry_class]
|
|
46
|
+
|
|
47
|
+
entry_options['style'] = {}
|
|
48
|
+
container_options['style'] = {}
|
|
49
|
+
|
|
50
|
+
if bibliography.line_spacing != 1.0
|
|
51
|
+
container_options['style']['line-height'] = bibliography.line_spacing
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
if bibliography.hanging_indent?
|
|
55
|
+
hanging_indent = "#{config[:bib_hanging_indent]}#{bib_unit}"
|
|
56
|
+
|
|
57
|
+
container_options['style']['padding-left'] = hanging_indent
|
|
58
|
+
entry_options['style']['text-indent'] = "-#{hanging_indent}"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if bibliography.entry_spacing != 1.0
|
|
62
|
+
entry_options['style']['margin-bottom'] = "#{bibliography.entry_spacing}#{unit}"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
bibliography.header = opening_tag(ol, container_options)
|
|
66
|
+
bibliography.footer = closing_tag(ol)
|
|
67
|
+
|
|
68
|
+
bibliography.prefix = [indent, opening_tag(li, entry_options)].join('')
|
|
69
|
+
bibliography.suffix = closing_tag(li)
|
|
70
|
+
|
|
71
|
+
bibliography.connector = indent ? "\n" : ''
|
|
72
|
+
bibliography
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def css_only?
|
|
76
|
+
config[:css_only]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def apply_font_style
|
|
80
|
+
if options[:'font-style'] == 'italic' && !css_only?
|
|
81
|
+
output.replace content_tag(config[:italic], output)
|
|
82
|
+
else
|
|
83
|
+
css['font-style'] = options[:'font-style']
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def apply_font_variant
|
|
88
|
+
css['font-variant'] = options[:'font-variant']
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def apply_font_weight
|
|
92
|
+
if options[:'font-weight'] == 'bold' && !css_only?
|
|
93
|
+
output.replace content_tag(config[:bold], output)
|
|
94
|
+
else
|
|
95
|
+
css['font-weight'] = options[:'font-weight']
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def apply_text_decoration
|
|
100
|
+
css['text-decoration'] = options[:'text-decoration']
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def apply_vertical_align
|
|
104
|
+
css['vertical-align'] = options[:'vertical-align']
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def apply_display
|
|
108
|
+
output.replace(
|
|
109
|
+
content_tag(config[:display], output, 'class' => "csl-#{options[:display]}" )
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def prefix
|
|
114
|
+
CSL.encode_xml_text(options[:prefix])
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def suffix
|
|
118
|
+
CSL.encode_xml_text(options[:suffix])
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def escape_quotes?
|
|
122
|
+
true
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def strip(string)
|
|
126
|
+
string.split(/((?:^<[^>]+>)|(?:<[^>]+>))$/, 2)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
protected
|
|
130
|
+
|
|
131
|
+
def css
|
|
132
|
+
@css ||= {}
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def finalize_content!
|
|
136
|
+
super
|
|
137
|
+
output.replace content_tag(config[:container], output, 'style' => css) if @css
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def setup!
|
|
141
|
+
# TODO find a better solution for this (strip tags?)
|
|
142
|
+
# For now make sure not to double encode entities
|
|
143
|
+
# by matching spaces before or after.
|
|
144
|
+
|
|
145
|
+
output.gsub!(/[&<]\s/, '& ' => '& ', '< ' => '< ')
|
|
146
|
+
output.gsub!(/\s>/, ' >')
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def cleanup!
|
|
150
|
+
@css = nil
|
|
151
|
+
super
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
private
|
|
155
|
+
|
|
156
|
+
def content_tag(name, content, options = nil)
|
|
157
|
+
opening_tag(name, options) << content << closing_tag(name)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def style_for(options)
|
|
161
|
+
return unless options && !options.empty?
|
|
162
|
+
options.map { |*kv| kv.join(': ') }.join('; ')
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def attribute_assignments(options)
|
|
166
|
+
return unless options
|
|
167
|
+
|
|
168
|
+
options = options.select { |k, v| !v.nil? }
|
|
169
|
+
|
|
170
|
+
return unless !options.empty?
|
|
171
|
+
|
|
172
|
+
' ' << options.map { |k, v| [k, v.inspect].join('=') }.join(' ')
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def opening_tag(name, options = nil)
|
|
176
|
+
if options && options.key?('style')
|
|
177
|
+
options['style'] = style_for(options['style'])
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
"<#{name}#{attribute_assignments(options)}>"
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def closing_tag(name)
|
|
184
|
+
"</#{name}>"
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
class CiteProcJS < Html
|
|
189
|
+
def initialize
|
|
190
|
+
super(
|
|
191
|
+
:bib_container => 'div',
|
|
192
|
+
:bib_container_class => 'csl-bib-body',
|
|
193
|
+
:bib_entry => 'div',
|
|
194
|
+
:bib_entry_class => 'csl-entry'
|
|
195
|
+
)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def bibliography(bibliography)
|
|
199
|
+
ol, li, indent =
|
|
200
|
+
config.values_at(:bib_container, :bib_entry, :bib_indent)
|
|
201
|
+
|
|
202
|
+
container_options = {}
|
|
203
|
+
container_options['class'] = config[:bib_container_class]
|
|
204
|
+
|
|
205
|
+
entry_options = {}
|
|
206
|
+
entry_options['class'] = config[:bib_entry_class]
|
|
207
|
+
|
|
208
|
+
bibliography.header = opening_tag(ol, container_options)
|
|
209
|
+
bibliography.footer = closing_tag(ol)
|
|
210
|
+
|
|
211
|
+
bibliography.prefix = [indent, opening_tag(li, entry_options)].join('')
|
|
212
|
+
bibliography.suffix = closing_tag(li)
|
|
213
|
+
|
|
214
|
+
bibliography.connector = indent ? "\n" : ''
|
|
215
|
+
bibliography
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
module CiteProc
|
|
2
|
+
module Ruby
|
|
3
|
+
|
|
4
|
+
class Renderer
|
|
5
|
+
|
|
6
|
+
attr_reader :state
|
|
7
|
+
|
|
8
|
+
attr_accessor :engine
|
|
9
|
+
|
|
10
|
+
def initialize(options_or_engine = nil)
|
|
11
|
+
@state = State.new
|
|
12
|
+
|
|
13
|
+
case options_or_engine
|
|
14
|
+
when Engine
|
|
15
|
+
@engine = options_or_engine
|
|
16
|
+
when Hash
|
|
17
|
+
locale, format = options_or_engine.values_at(:locale, :format)
|
|
18
|
+
@locale, @format = CSL::Locale.load(locale), Format.load(format)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def locale
|
|
23
|
+
@locale ||= CSL::Locale.load
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def locale=(new_locale)
|
|
27
|
+
@locale = CSL::Locale.load new_locale
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def abbreviate(*arguments)
|
|
31
|
+
return unless engine
|
|
32
|
+
engine.abbreviate(*arguments)
|
|
33
|
+
end
|
|
34
|
+
alias abbrev abbreviate
|
|
35
|
+
|
|
36
|
+
def allow_locale_overrides?
|
|
37
|
+
return false unless engine
|
|
38
|
+
engine.options[:allow_locale_overrides]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @param item [CiteProc::CitationItem]
|
|
42
|
+
# @param node [CSL::Node]
|
|
43
|
+
# @return [String] the rendered and formatted string
|
|
44
|
+
def render(item, node)
|
|
45
|
+
raise ArgumentError, "no CSL node: #{node.inspect}" unless
|
|
46
|
+
node.respond_to?(:nodename)
|
|
47
|
+
|
|
48
|
+
specialize = "render_#{node.nodename.tr('-', '_')}"
|
|
49
|
+
|
|
50
|
+
raise ArgumentError, "#{specialize} not implemented" unless
|
|
51
|
+
respond_to?(specialize, true)
|
|
52
|
+
|
|
53
|
+
format! send(specialize, item, node), node
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @param data [CiteProc::CitationData]
|
|
57
|
+
# @param node [CSL::Style::Citation]
|
|
58
|
+
# @return [String] the rendered and formatted string
|
|
59
|
+
def render_citation(data, node)
|
|
60
|
+
state.store! data, node
|
|
61
|
+
|
|
62
|
+
citations = join data.map { |item|
|
|
63
|
+
render_single_citation item, node.layout
|
|
64
|
+
}, node.layout.delimiter || ''
|
|
65
|
+
|
|
66
|
+
result = format! citations, node.layout
|
|
67
|
+
ensure
|
|
68
|
+
state.clear! result
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @param data [CiteProc::CitationItem]
|
|
72
|
+
# @param node [CSL::Style::Layout]
|
|
73
|
+
# @return [String] the rendered and string
|
|
74
|
+
def render_single_citation(item, node)
|
|
75
|
+
# TODO author_only
|
|
76
|
+
item.suppress! 'author' if item.suppress_author?
|
|
77
|
+
|
|
78
|
+
join [item.prefix, render_layout(item, node), item.suffix].compact
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @param item [CiteProc::CitationItem]
|
|
82
|
+
# @param node [CSL::Style::Bibliography]
|
|
83
|
+
# @return [String] the rendered and formatted string
|
|
84
|
+
def render_bibliography(item, node)
|
|
85
|
+
state.store! item, node
|
|
86
|
+
|
|
87
|
+
if allow_locale_overrides? && item.language != locale.language
|
|
88
|
+
begin
|
|
89
|
+
new_locale = CSL::Locale.load(item.language)
|
|
90
|
+
|
|
91
|
+
unless new_locale.nil?
|
|
92
|
+
new_locale.merge!(locale)
|
|
93
|
+
original_locale, @locale = @locale, new_locale
|
|
94
|
+
end
|
|
95
|
+
rescue ParseError
|
|
96
|
+
# locale not found
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
result = render item, node.layout
|
|
101
|
+
|
|
102
|
+
ensure
|
|
103
|
+
unless original_locale.nil?
|
|
104
|
+
@locale = original_locale
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
state.clear! result
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def render_sort(a, b, node, key)
|
|
111
|
+
state.store! nil, key
|
|
112
|
+
|
|
113
|
+
original_format = @format
|
|
114
|
+
@format = Formats::Text.new
|
|
115
|
+
|
|
116
|
+
if a.is_a?(CiteProc::Names)
|
|
117
|
+
[render_name(a, node), render_name(b, node)]
|
|
118
|
+
|
|
119
|
+
else
|
|
120
|
+
# We need to clear any items that are suppressed
|
|
121
|
+
# because they were used as substitutes during
|
|
122
|
+
# rendering for sorting purposes!
|
|
123
|
+
a_rendered = render a.cite, node
|
|
124
|
+
a.suppressed.clear
|
|
125
|
+
|
|
126
|
+
b_rendered = render b.cite, node
|
|
127
|
+
b.suppressed.clear
|
|
128
|
+
|
|
129
|
+
[a_rendered, b_rendered]
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
ensure
|
|
133
|
+
@format = original_format
|
|
134
|
+
state.clear!
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
module CiteProc
|
|
2
|
+
module Ruby
|
|
3
|
+
|
|
4
|
+
class Renderer
|
|
5
|
+
|
|
6
|
+
# @param item [CiteProc::CitationItem]
|
|
7
|
+
# @param node [CSL::Style::Choose]
|
|
8
|
+
# @return [String]
|
|
9
|
+
def render_choose(item, node)
|
|
10
|
+
return '' unless node.has_children?
|
|
11
|
+
|
|
12
|
+
node.each_child do |child|
|
|
13
|
+
return render_block(item, child) if evaluates?(item, child)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
'' # no block was rendered
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @param item [CiteProc::CitationItem]
|
|
20
|
+
# @param node [CSL::Style::Choose::Block]
|
|
21
|
+
# @return [String]
|
|
22
|
+
def render_block(item, node)
|
|
23
|
+
return '' unless node.has_children?
|
|
24
|
+
|
|
25
|
+
join node.each_child.map { |child|
|
|
26
|
+
render item, child
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Evaluates the conditions of the passed-in Choose::Block
|
|
32
|
+
# against the passed-in CitationItem using the Block's matcher.
|
|
33
|
+
#
|
|
34
|
+
# @param item [CiteProc::CitationItem]
|
|
35
|
+
# @param node [CSL::Style::Choose::Block]
|
|
36
|
+
#
|
|
37
|
+
# @return [Boolean] whether or not the node's conditions
|
|
38
|
+
# are true for the passed-in item
|
|
39
|
+
def evaluates?(item, node)
|
|
40
|
+
|
|
41
|
+
# subtle: else-nodes have no conditions. since the default
|
|
42
|
+
# matcher :all? returns true for an empty list we do not
|
|
43
|
+
# need to check for an else node specifically.
|
|
44
|
+
|
|
45
|
+
# return true if node.nodename == 'else'
|
|
46
|
+
|
|
47
|
+
node.conditions.send(node.matcher) do |type, matcher, values|
|
|
48
|
+
case type
|
|
49
|
+
when :disambiguate
|
|
50
|
+
false # TODO not implemented yet
|
|
51
|
+
|
|
52
|
+
when :'is-numeric'
|
|
53
|
+
evaluates_condition? matcher, values do |value|
|
|
54
|
+
v = item.data.unobservable_read_attribute(value)
|
|
55
|
+
v.respond_to?(:numeric?) && v.numeric?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
when :'is-uncertain-date'
|
|
59
|
+
evaluates_condition? matcher, values do |value|
|
|
60
|
+
v = item.data.unobservable_read_attribute(value)
|
|
61
|
+
v.respond_to?(:uncertain?) && v.uncertain?
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
when :locator
|
|
66
|
+
locator = item.locator.to_s.tr(' ', '-')
|
|
67
|
+
|
|
68
|
+
evaluates_condition? matcher, values do |value|
|
|
69
|
+
value.to_s == locator
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
when :position
|
|
73
|
+
false # TODO not implemented yet
|
|
74
|
+
|
|
75
|
+
when :type
|
|
76
|
+
type = item.data.unobservable_read_attribute(:type).to_s
|
|
77
|
+
|
|
78
|
+
evaluates_condition? matcher, values do |value|
|
|
79
|
+
value.to_s == type
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
when :variable
|
|
83
|
+
evaluates_condition? matcher, values do |value|
|
|
84
|
+
item.data.attribute?(value)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
else
|
|
88
|
+
fail "unknown condition type: #{type}"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Evaluates the passed-in block for each value in values,
|
|
94
|
+
# negating the result if the value is prefixed with 'not:'
|
|
95
|
+
def evaluates_condition?(matcher, values, &condition)
|
|
96
|
+
values.send(matcher) do |value|
|
|
97
|
+
value, negate = value.split(/^not:/, 2).reverse
|
|
98
|
+
result = condition.call(value)
|
|
99
|
+
|
|
100
|
+
negate ? !result : result
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
end
|
|
106
|
+
end
|