citeproc-ruby 0.0.6 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|