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.
Files changed (186) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.document +4 -0
  4. data/.gitignore +10 -0
  5. data/.rspec +3 -0
  6. data/.simplecov +4 -0
  7. data/.travis.yml +17 -0
  8. data/.yardopts +2 -0
  9. data/AGPL +662 -0
  10. data/BSDL +29 -0
  11. data/Gemfile +42 -0
  12. data/Guardfile +14 -0
  13. data/README.md +32 -76
  14. data/Rakefile +60 -0
  15. data/citeproc-ruby.gemspec +46 -0
  16. data/cucumber.yml +1 -0
  17. data/features/bibliography.feature +25 -0
  18. data/features/name_options.feature +37 -0
  19. data/features/names.feature +192 -0
  20. data/features/renderer.feature +74 -0
  21. data/features/sort.feature +50 -0
  22. data/features/step_definitions/renderer.rb +80 -0
  23. data/features/support/env.rb +33 -0
  24. data/features/support/hooks.rb +10 -0
  25. data/lib/citeproc/ruby.rb +32 -0
  26. data/lib/citeproc/ruby/engine.rb +122 -0
  27. data/lib/citeproc/ruby/format.rb +303 -0
  28. data/lib/citeproc/ruby/formats/default.rb +25 -0
  29. data/lib/citeproc/ruby/formats/html.rb +221 -0
  30. data/lib/citeproc/ruby/renderer.rb +140 -0
  31. data/lib/citeproc/ruby/renderer/choose.rb +106 -0
  32. data/lib/citeproc/ruby/renderer/date.rb +90 -0
  33. data/lib/citeproc/ruby/renderer/format.rb +129 -0
  34. data/lib/citeproc/ruby/renderer/group.rb +34 -0
  35. data/lib/citeproc/ruby/renderer/history.rb +40 -0
  36. data/lib/citeproc/ruby/renderer/label.rb +66 -0
  37. data/lib/citeproc/ruby/renderer/layout.rb +20 -0
  38. data/lib/citeproc/ruby/renderer/locale.rb +26 -0
  39. data/lib/citeproc/ruby/renderer/macro.rb +20 -0
  40. data/lib/citeproc/ruby/renderer/names.rb +401 -0
  41. data/lib/citeproc/ruby/renderer/number.rb +41 -0
  42. data/lib/citeproc/ruby/renderer/observer.rb +44 -0
  43. data/lib/citeproc/ruby/renderer/state.rb +96 -0
  44. data/lib/citeproc/ruby/renderer/text.rb +62 -0
  45. data/lib/citeproc/ruby/sort.rb +82 -0
  46. data/lib/citeproc/ruby/version.rb +5 -0
  47. data/spec/citeproc/ruby/engine_spec.rb +94 -0
  48. data/spec/citeproc/ruby/formats/default_spec.rb +159 -0
  49. data/spec/citeproc/ruby/formats/html_spec.rb +162 -0
  50. data/spec/citeproc/ruby/renderer/choose_spec.rb +293 -0
  51. data/spec/citeproc/ruby/renderer/date_spec.rb +173 -0
  52. data/spec/citeproc/ruby/renderer/group_spec.rb +88 -0
  53. data/spec/citeproc/ruby/renderer/history_spec.rb +38 -0
  54. data/spec/citeproc/ruby/renderer/label_spec.rb +225 -0
  55. data/spec/citeproc/ruby/renderer/layout_spec.rb +41 -0
  56. data/spec/citeproc/ruby/renderer/macro_spec.rb +31 -0
  57. data/spec/citeproc/ruby/renderer/names_spec.rb +396 -0
  58. data/spec/citeproc/ruby/renderer/number_spec.rb +120 -0
  59. data/spec/citeproc/ruby/renderer/text_spec.rb +120 -0
  60. data/spec/citeproc/ruby/renderer_spec.rb +65 -0
  61. data/spec/fixtures/items.rb +80 -0
  62. data/{resource/locale → spec/fixtures/locales}/locales-en-US.xml +2 -11
  63. data/{resource/locale → spec/fixtures/locales}/locales-fr-FR.xml +77 -66
  64. data/{resource/style → spec/fixtures/styles}/apa.csl +5 -5
  65. data/spec/spec_helper.rb +67 -14
  66. metadata +121 -211
  67. data/lib/citeproc.rb +0 -100
  68. data/lib/citeproc/bibliography.rb +0 -57
  69. data/lib/citeproc/data.rb +0 -149
  70. data/lib/citeproc/date.rb +0 -133
  71. data/lib/citeproc/formatter.rb +0 -38
  72. data/lib/citeproc/item.rb +0 -53
  73. data/lib/citeproc/name.rb +0 -284
  74. data/lib/citeproc/processor.rb +0 -166
  75. data/lib/citeproc/selector.rb +0 -61
  76. data/lib/citeproc/variable.rb +0 -82
  77. data/lib/citeproc/version.rb +0 -3
  78. data/lib/csl/locale.rb +0 -223
  79. data/lib/csl/node.rb +0 -72
  80. data/lib/csl/nodes.rb +0 -1418
  81. data/lib/csl/renderer.rb +0 -88
  82. data/lib/csl/sort.rb +0 -61
  83. data/lib/csl/style.rb +0 -110
  84. data/lib/csl/term.rb +0 -124
  85. data/lib/extensions/core.rb +0 -43
  86. data/lib/plugins/filters/bibtex.rb +0 -12
  87. data/lib/plugins/formats/default.rb +0 -134
  88. data/lib/plugins/formats/html.rb +0 -67
  89. data/lib/support/attributes.rb +0 -99
  90. data/lib/support/compatibility.rb +0 -83
  91. data/lib/support/tree.rb +0 -80
  92. data/resource/locale/locales-af-ZA.xml +0 -305
  93. data/resource/locale/locales-ar-AR.xml +0 -306
  94. data/resource/locale/locales-bg-BG.xml +0 -305
  95. data/resource/locale/locales-ca-AD.xml +0 -305
  96. data/resource/locale/locales-cs-CZ.xml +0 -305
  97. data/resource/locale/locales-da-DK.xml +0 -305
  98. data/resource/locale/locales-de-AT.xml +0 -304
  99. data/resource/locale/locales-de-CH.xml +0 -304
  100. data/resource/locale/locales-de-DE.xml +0 -332
  101. data/resource/locale/locales-el-GR.xml +0 -305
  102. data/resource/locale/locales-en-GB.xml +0 -304
  103. data/resource/locale/locales-es-ES.xml +0 -305
  104. data/resource/locale/locales-et-EE.xml +0 -304
  105. data/resource/locale/locales-eu.xml +0 -305
  106. data/resource/locale/locales-fa-IR.xml +0 -304
  107. data/resource/locale/locales-fi-FI.xml +0 -304
  108. data/resource/locale/locales-fr-CA.xml +0 -306
  109. data/resource/locale/locales-he-IL.xml +0 -304
  110. data/resource/locale/locales-hu-HU.xml +0 -305
  111. data/resource/locale/locales-is-IS.xml +0 -304
  112. data/resource/locale/locales-it-IT.xml +0 -305
  113. data/resource/locale/locales-ja-JP.xml +0 -305
  114. data/resource/locale/locales-kh-KH.xml +0 -303
  115. data/resource/locale/locales-km-KH.xml +0 -304
  116. data/resource/locale/locales-ko-KR.xml +0 -305
  117. data/resource/locale/locales-mn-MN.xml +0 -306
  118. data/resource/locale/locales-nb-NO.xml +0 -304
  119. data/resource/locale/locales-nl-NL.xml +0 -304
  120. data/resource/locale/locales-nn-NO.xml +0 -304
  121. data/resource/locale/locales-pl-PL.xml +0 -305
  122. data/resource/locale/locales-pt-BR.xml +0 -304
  123. data/resource/locale/locales-pt-PT.xml +0 -305
  124. data/resource/locale/locales-ro-RO.xml +0 -305
  125. data/resource/locale/locales-ru-RU.xml +0 -306
  126. data/resource/locale/locales-sk-SK.xml +0 -304
  127. data/resource/locale/locales-sl-SI.xml +0 -305
  128. data/resource/locale/locales-sr-RS.xml +0 -305
  129. data/resource/locale/locales-sv-SE.xml +0 -305
  130. data/resource/locale/locales-th-TH.xml +0 -304
  131. data/resource/locale/locales-tr-TR.xml +0 -305
  132. data/resource/locale/locales-uk-UA.xml +0 -306
  133. data/resource/locale/locales-vi-VN.xml +0 -305
  134. data/resource/locale/locales-zh-CN.xml +0 -304
  135. data/resource/locale/locales-zh-TW.xml +0 -305
  136. data/resource/schema/csl-categories.rnc +0 -39
  137. data/resource/schema/csl-data.rnc +0 -98
  138. data/resource/schema/csl-terms.rnc +0 -106
  139. data/resource/schema/csl-types.rnc +0 -39
  140. data/resource/schema/csl-variables.rnc +0 -182
  141. data/resource/schema/csl.rnc +0 -941
  142. data/resource/style/bibtex.csl +0 -177
  143. data/resource/style/chicago-annotated-bibliography.csl +0 -513
  144. data/resource/style/chicago-author-date-basque.csl +0 -707
  145. data/resource/style/chicago-author-date-de.csl +0 -394
  146. data/resource/style/chicago-author-date-listing.csl +0 -434
  147. data/resource/style/chicago-author-date.csl +0 -425
  148. data/resource/style/chicago-dated-note-biblio-no-ibid.csl +0 -472
  149. data/resource/style/chicago-fullnote-bibliography-bb.csl +0 -928
  150. data/resource/style/chicago-fullnote-bibliography-delimiter-fixes.csl +0 -972
  151. data/resource/style/chicago-fullnote-bibliography-no-ibid-delimiter-fixes.csl +0 -963
  152. data/resource/style/chicago-fullnote-bibliography-no-ibid.csl +0 -785
  153. data/resource/style/chicago-fullnote-bibliography.csl +0 -803
  154. data/resource/style/chicago-library-list.csl +0 -511
  155. data/resource/style/chicago-note-biblio-no-ibid.csl +0 -514
  156. data/resource/style/chicago-note-bibliography.csl +0 -530
  157. data/resource/style/chicago-note.csl +0 -388
  158. data/resource/style/chicago-quick-copy.csl +0 -685
  159. data/resource/style/ieee.csl +0 -299
  160. data/resource/style/mla-notes.csl +0 -796
  161. data/resource/style/mla-underline.csl +0 -175
  162. data/resource/style/mla-url.csl +0 -214
  163. data/resource/style/mla.csl +0 -394
  164. data/resource/style/vancouver-brackets.csl +0 -256
  165. data/resource/style/vancouver-superscript-bracket-only-year.csl +0 -165
  166. data/resource/style/vancouver-superscript.csl +0 -256
  167. data/resource/style/vancouver.csl +0 -256
  168. data/spec/citeproc/bibliography_spec.rb +0 -45
  169. data/spec/citeproc/citeproc_spec.rb +0 -80
  170. data/spec/citeproc/date_spec.rb +0 -89
  171. data/spec/citeproc/formatter_spec.rb +0 -101
  172. data/spec/citeproc/item_spec.rb +0 -71
  173. data/spec/citeproc/name_spec.rb +0 -30
  174. data/spec/citeproc/processor_spec.rb +0 -61
  175. data/spec/citeproc/selector_spec.rb +0 -82
  176. data/spec/citeproc/variable_spec.rb +0 -69
  177. data/spec/csl/locale_spec.rb +0 -208
  178. data/spec/csl/node_spec.rb +0 -25
  179. data/spec/csl/nodes_spec.rb +0 -145
  180. data/spec/csl/style_spec.rb +0 -62
  181. data/spec/csl/term_spec.rb +0 -56
  182. data/spec/fixtures/dates.yaml +0 -80
  183. data/spec/fixtures/names.yaml +0 -115
  184. data/spec/fixtures/nodes.yaml +0 -245
  185. data/spec/support/attributes_spec.rb +0 -39
  186. 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
+ '&amp;' => '&',
13
+ '&gt;' => '>',
14
+ '&lt;' => '<'
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/, '& ' => '&amp; ', '< ' => '&lt; ')
146
+ output.gsub!(/\s>/, ' &gt;')
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