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,41 @@
1
+ module CiteProc
2
+ module Ruby
3
+
4
+ class Renderer
5
+
6
+ # @param item [CiteProc::CitationItem]
7
+ # @param node [CSL::Style::Number]
8
+ # @return [String]
9
+ def render_number(item, node)
10
+ return '' unless node.has_variable?
11
+
12
+ variable = item.data[node.variable]
13
+ return variable.to_s unless variable && variable.numeric?
14
+
15
+ numbers = variable.tokenize
16
+
17
+ case
18
+ when node.ordinal? || node.long_ordinal?
19
+ options = node.attributes_for :form
20
+ # TODO lookup term of variable to check gender
21
+
22
+ numbers.map! do |num|
23
+ num =~ /^\d+$/ ? ordinalize(num, options) : num
24
+ end
25
+
26
+ when node.roman?
27
+ numbers.map! do |num|
28
+ num =~ /^\d+$/ ? romanize(num) : num
29
+ end
30
+
31
+ else
32
+ # nothing
33
+ end
34
+
35
+ numbers.join('')
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,44 @@
1
+ module CiteProc
2
+ module Ruby
3
+
4
+ class Renderer
5
+
6
+ class ItemObserver
7
+ attr_accessor :history, :item
8
+
9
+ def initialize(item, history = {})
10
+ @item, @history = item, history
11
+ end
12
+
13
+ def start
14
+ item.add_observer(self)
15
+ self
16
+ end
17
+
18
+ def stop
19
+ item.delete_observer(self)
20
+ self
21
+ end
22
+
23
+ def update(method, key, value)
24
+ history[key] = value if method == :read
25
+ end
26
+
27
+ def skip?
28
+ !history.empty? && history.values.all?(&:nil?)
29
+ end
30
+
31
+ def accessed
32
+ history.select { |key, value| !value.nil? }.keys
33
+ end
34
+
35
+ def clear!
36
+ history.clear
37
+ self
38
+ end
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,96 @@
1
+ module CiteProc
2
+ module Ruby
3
+ class Renderer
4
+
5
+ def citation_mode?
6
+ state.mode == 'citation'
7
+ end
8
+
9
+ def bibliography_mode?
10
+ state.mode == 'bibliography'
11
+ end
12
+
13
+ def sort_mode?
14
+ state.mode == 'key'
15
+ end
16
+
17
+ def substitution_mode?
18
+ !state.substitute.nil?
19
+ end
20
+
21
+ def style
22
+ return unless state.node && !state.node.root? &&
23
+ state.node.root.is_a?(CSL::Style)
24
+
25
+ state.node.root
26
+ end
27
+
28
+ class State
29
+ include Observable
30
+
31
+ attr_reader :history, :node, :item, :authors, :substitute
32
+
33
+ def initialize
34
+ @history, @authors = History.new(self, 3), []
35
+ end
36
+
37
+ def store!(item, node)
38
+ @item, @node = item, node
39
+ ensure
40
+ changed
41
+ end
42
+
43
+ def store_authors!(authors)
44
+ @authors << authors
45
+ ensure
46
+ changed
47
+ end
48
+
49
+ def clear!(result = nil)
50
+ memories = conserve(result)
51
+ @item, @node, @substitute, @authors, @names = nil, nil, nil, [], nil
52
+ ensure
53
+ changed
54
+ notify_observers :clear!, memories.delete(:mode), memories
55
+ end
56
+
57
+ def mode
58
+ node && node.nodename
59
+ end
60
+
61
+ def substitute!(names)
62
+ @substitute = names
63
+ end
64
+
65
+ def clear_substitute!(backup = nil)
66
+ @substitute = backup
67
+ end
68
+
69
+ def previous_authors
70
+ past = history.recall(mode)
71
+ return unless past && !past.empty?
72
+
73
+ past[:authors]
74
+ end
75
+
76
+ def rendered_names?
77
+ @names
78
+ end
79
+
80
+ def rendered_names!
81
+ @names = true
82
+ end
83
+
84
+ def conserve(result = nil)
85
+ {
86
+ :mode => mode,
87
+ :item => item,
88
+ :authors => authors,
89
+ :result => result
90
+ }
91
+ end
92
+ end
93
+
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,62 @@
1
+ module CiteProc
2
+ module Ruby
3
+
4
+ class Renderer
5
+
6
+ # @param item [CiteProc::CitationItem]
7
+ # @param node [CSL::Style::Text]
8
+ # @return [String]
9
+ def render_text(item, node)
10
+ case
11
+ when node.has_variable?
12
+
13
+ if node.variable == 'locator'
14
+
15
+ # Subtle: when there is no locator we also look
16
+ # in item.data; there should be no locator there
17
+ # either but the read access will be noticed by
18
+ # observers (if any).
19
+ text = item.locator || item.data[:locator].to_s
20
+
21
+ else
22
+ text = item.data.variable(node.variable, node.variable_options).to_s
23
+
24
+ # Check for abbreviations or short-form fallbacks!
25
+ context, was_short_form = node.variable.split(/-short/, 2)
26
+
27
+ if was_short_form || node[:form] == 'short'
28
+ if text.empty?
29
+ text = item.data.variable(context, node.variable_options).to_s
30
+ end
31
+
32
+ text = abbreviate(context, text) || text
33
+ end
34
+ end
35
+
36
+
37
+ case
38
+ when node.variable == 'page'
39
+ format_page_range!(text, node.page_range_format)
40
+
41
+ when node.variable == 'page-first' && text.empty?
42
+ text = item.data[:'page'].to_s[/\d+/].to_s
43
+
44
+ end
45
+
46
+ text
47
+
48
+ when node.has_macro?
49
+ render item, node.macro
50
+
51
+ when node.has_term?
52
+ translate node[:term], node.attributes_for(:plural, :form)
53
+
54
+ else
55
+ node.value.to_s
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,82 @@
1
+ module CiteProc
2
+ module Ruby
3
+
4
+ module SortItems
5
+
6
+ def sort!(items, keys)
7
+ return itmes unless !keys.nil? && !keys.empty?
8
+
9
+ # TODO refactor
10
+ if items.is_a?(CitationData)
11
+ items.sort! do |a, b|
12
+ compare_items_by_keys(a.data, b.data, keys)
13
+ end
14
+ else
15
+ items.sort! do |a, b|
16
+ compare_items_by_keys(a, b, keys)
17
+ end
18
+ end
19
+ end
20
+
21
+ # @returns [-1, 0, 1, nil]
22
+ def compare_items_by_keys(a, b, keys)
23
+ result = 0
24
+
25
+ keys.each do |key|
26
+ result = compare_items_by_key(a, b, key)
27
+ return result unless result.zero?
28
+ end
29
+
30
+ result
31
+ end
32
+
33
+ # @returns [-1, 0, 1, nil]
34
+ def compare_items_by_key(a, b, key)
35
+ if key.macro?
36
+ result = compare_items(*renderer.render_sort(a, b, key.macro, key))
37
+
38
+ else
39
+ va, vb = a[key.variable], b[key.variable]
40
+
41
+ # Return early if one side is nil. In this
42
+ # case ascending/descending is irrelevant!
43
+ return 1 if va.nil? || va.empty?
44
+ return -1 if vb.nil? || va.empty?
45
+
46
+ result = case CiteProc::Variable.types[key.variable]
47
+ when :names
48
+ node = CSL::Style::Name.new(key.name_options)
49
+ node.all_names_as_sort_order!
50
+
51
+ compare_items(*renderer.render_sort(va, vb, node, key))
52
+
53
+ when :date
54
+ va <=> vb
55
+ when :number
56
+ va <=> vb
57
+ else
58
+ compare_items(va, vb)
59
+ end
60
+ end
61
+
62
+ result = -result unless key.ascending?
63
+ result
64
+ end
65
+
66
+ def compare_items(a, b)
67
+ if sort_case_sensitively?
68
+ a <=> b
69
+ else
70
+ a.to_s.downcase <=> b.to_s.downcase
71
+ end
72
+ end
73
+
74
+ def sort_case_sensitively?
75
+ return false unless processor && processor.options
76
+ processor.options[:sort_case_sensitively]
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,5 @@
1
+ module CiteProc
2
+ module Ruby
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
@@ -0,0 +1,94 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'spec_helper'
4
+
5
+ module CiteProc
6
+ module Ruby
7
+
8
+ describe 'The CiteProc-Ruby Engine' do
9
+ let(:cp) { CiteProc::Processor.new :style => 'apa', :format => 'text' }
10
+ let(:engine) { cp.engine }
11
+
12
+ it 'registers itself as "citeproc-ruby"' do
13
+ CiteProc::Engine.available.should include('citeproc-ruby')
14
+ end
15
+
16
+ it 'is the default engine' do
17
+ CiteProc::Engine.default.should equal(CiteProc::Ruby::Engine)
18
+ engine.should be_a(CiteProc::Ruby::Engine)
19
+ end
20
+
21
+ describe '#bibliography' do
22
+
23
+ describe 'when there are no items in the processor' do
24
+ it 'returns an empty bibliography for any selector' do
25
+ cp.bibliography().should be_empty
26
+ cp.bibliography(:all => {}).should be_empty
27
+ cp.bibliography(:none => {}).should be_empty
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ describe '#render' do
34
+
35
+ describe 'when there are no items in the processor' do
36
+ end
37
+
38
+ describe 'when there are items in the processor' do
39
+ before(:each) do
40
+ cp << items(:grammatology).data
41
+ cp << items(:knuth1968).data
42
+ cp << items(:difference).data
43
+ end
44
+
45
+ it 'renders the reference for the given id' do
46
+ cp.render(:bibliography, :id => 'grammatology').should == ['Derrida, J. (1976). Of Grammatology (corrected ed.). Baltimore: Johns Hopkins University Press.']
47
+ cp.render(:citation, :id => 'grammatology', :locator => '3-4').should == '(Derrida, 1976, pp. 3-4)'
48
+ cp.render(:bibliography, :id => 'knuth1968').should == ['Knuth, D. (1968). The art of computer programming (Vol. 1). Boston: Addison-Wesley.']
49
+
50
+ node = cp.engine.style.macros['author']
51
+ (node > 'names' > 'name')[:initialize] = 'false'
52
+
53
+ cp.engine.format = 'html'
54
+ cp.render(:bibliography, :id => 'knuth1968').should == ['Knuth, Donald. (1968). <i>The art of computer programming</i> (Vol. 1). Boston: Addison-Wesley.']
55
+
56
+ cp.render(:citation, :id => 'knuth1968', :locator => '23').should == '(Knuth, 1968, p. 23)'
57
+ end
58
+
59
+ it 'overrides locales if the processor option is set' do
60
+ cp.render(:bibliography, :id => 'difference').should == ['Derrida, J. (1967). L’écriture et la différence (1st ed.). Paris: Éditions du Seuil.']
61
+
62
+ cp.options[:allow_locale_overrides] = true
63
+ cp.render(:bibliography, :id => 'difference').should == ['Derrida, J. (1967). L’écriture et la différence (1ʳᵉ éd.). Paris: Éditions du Seuil.']
64
+ end
65
+ end
66
+ end
67
+
68
+ describe '#process' do
69
+ describe 'when there are no items in the processor' do
70
+ end
71
+
72
+ describe 'when there are items in the processor' do
73
+ before(:each) do
74
+ cp << items(:grammatology).data
75
+ cp << items(:knuth1968).data
76
+ end
77
+
78
+ it 'renders the citation for the given id' do
79
+ cp.process(:id => 'knuth1968', :locator => '23').should == '(Knuth, 1968, p. 23)'
80
+ end
81
+
82
+ it 'combines and sorts multiple cite items' do
83
+ cp.process([
84
+ {:id => 'knuth1968', :locator => '23'},
85
+ {:id => 'grammatology', :locator => '11-14'}
86
+ ]).should == '(Derrida, 1976, pp. 11-14; Knuth, 1968, p. 23)'
87
+ end
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,159 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module CiteProc
6
+ module Ruby
7
+
8
+ describe 'Formats::Text#apply' do
9
+ let(:format) { Format.load 'text' }
10
+ let(:node) { CSL::Style::Text.new }
11
+
12
+ it 'returns an empty string if input is nil' do
13
+ format.apply(nil, node).should == ''
14
+ end
15
+
16
+ it 'returns the string unchanged if empty' do
17
+ input = ''
18
+ format.apply(input, node).should be_equal(input)
19
+ input.should == ''
20
+ end
21
+
22
+ it 'returns the string unchanged if node is nil' do
23
+ input = 'foo'
24
+ format.apply(input, nil).should be_equal(input)
25
+ input.should == 'foo'
26
+ end
27
+
28
+ it 'supports localized quotes' do
29
+ locale = double(:locale)
30
+ locale.stub(:punctuation_in_quotes?).and_return(true)
31
+ locale.stub(:quote).and_return('bar')
32
+
33
+ node[:quotes] = true
34
+
35
+ format.apply('foo', node, locale).should == 'bar'
36
+ end
37
+
38
+ it 'disregards localized closing quotes when squeezing affixes' do
39
+ locale = double(:locale)
40
+ locale.stub(:punctuation_in_quotes?).and_return(true)
41
+ locale.stub(:quote) { |t| '"' << t << '"' }
42
+ locale.stub(:t) { |t| t == 'close-quote' ? '"' : "'" }
43
+
44
+ node[:quotes] = true
45
+ node[:suffix] = '.'
46
+
47
+ format.apply('foo', node, locale).should == '"foo."'
48
+ format.apply("'foo'", node, locale).should == "\"'foo.'\""
49
+ end
50
+
51
+ describe 'text-case formats' do
52
+ it 'supports lowercase' do
53
+ node[:'text-case'] = 'lowercase'
54
+ format.apply('Foo BAR', node).should == 'foo bar'
55
+ end
56
+
57
+ it 'supports lowercase for non-ascii letters' do
58
+ node[:'text-case'] = 'lowercase'
59
+ format.apply('SCHÖN!', node).should == 'schön!'
60
+ end
61
+
62
+ it 'supports uppercase' do
63
+ node[:'text-case'] = 'uppercase'
64
+ format.apply('Foo BAR', node).should == 'FOO BAR'
65
+ end
66
+
67
+ it 'supports uppercase for non-ascii letters' do
68
+ node[:'text-case'] = 'uppercase'
69
+ format.apply('schön!', node).should == 'SCHÖN!'
70
+ end
71
+
72
+ it 'does not alter the original string' do
73
+ node[:'text-case'] = 'lowercase'
74
+ input = 'fooBar'
75
+
76
+ format.apply(input, node).should == 'foobar'
77
+ input.should == 'fooBar'
78
+ end
79
+
80
+ it 'supports capitalize-first' do
81
+ node[:'text-case'] = 'capitalize-first'
82
+
83
+ format.apply('foo bar', node).should == 'Foo bar'
84
+ format.apply('Foo bar', node).should == 'Foo bar'
85
+ format.apply('!foo bar', node).should == '!Foo bar'
86
+ format.apply('én foo bar', node).should == 'Én foo bar'
87
+ end
88
+
89
+ it 'supports capitalize-all' do
90
+ node[:'text-case'] = 'capitalize-all'
91
+
92
+ format.apply('foo bar', node).should == 'Foo Bar'
93
+ format.apply('!foo bar', node).should == '!Foo Bar'
94
+ format.apply('én foo bar', node).should == 'Én Foo Bar'
95
+ end
96
+
97
+ it 'supports sentence case' do
98
+ node[:'text-case'] = 'sentence'
99
+
100
+ format.apply('FOO bar', node).should == 'Foo bar'
101
+ format.apply('foo Bar BAR', node).should == 'Foo Bar Bar'
102
+ format.apply('én Foo bar', node).should == 'Én Foo bar'
103
+ end
104
+
105
+ it 'supports title case' do
106
+ node[:'text-case'] = 'title'
107
+
108
+ format.apply('The adventures of Huckleberry Finn', node).should == 'The Adventures of Huckleberry Finn'
109
+ format.apply("This IS a pen that is a smith pencil", node).should == 'This IS a Pen That Is a Smith Pencil'
110
+ #format.apply('of mice and men', node).should == 'Of Mice And Men'
111
+ end
112
+ end
113
+
114
+ describe 'strip-periods' do
115
+ before { node[:'strip-periods'] = true }
116
+
117
+ it 'strips all periods from the output' do
118
+ format.apply('hello there...! how.are.you?', node).should == 'hello there! howareyou?'
119
+ format.apply('foo bar!', node).should == 'foo bar!'
120
+ end
121
+
122
+ it 'does not strip periods from affixes' do
123
+ node[:prefix] = '...('
124
+ node[:suffix] = ').'
125
+
126
+ format.apply('foo.bar.', node).should == '...(foobar).'
127
+ end
128
+ end
129
+
130
+ describe 'affixes' do
131
+ it 'are added after text formats have been applied' do
132
+ node[:prefix] = 'foo'
133
+ node[:suffix] = 'ooo'
134
+ node[:'text-case'] = 'uppercase'
135
+
136
+ format.apply('ooo', node).should == 'fooOOOooo'
137
+ end
138
+
139
+ it 'drop squeezable characters at start/end' do
140
+ node[:suffix] = ' '
141
+
142
+ format.apply('foo', node).should == 'foo '
143
+ format.apply('foo ', node).should == 'foo '
144
+
145
+ node[:suffix] = '. '
146
+ format.apply('foo', node).should == 'foo. '
147
+ format.apply('foo.', node).should == 'foo. '
148
+ format.apply('foo?', node).should == 'foo? '
149
+
150
+ node[:prefix] = '.'
151
+ format.apply('foo', node).should == '.foo. '
152
+ format.apply('.foo', node).should == '.foo. '
153
+ format.apply(',foo', node).should == '.,foo. '
154
+ end
155
+ end
156
+ end
157
+
158
+ end
159
+ end