isodoc 1.6.7.1 → 1.7.3

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/isodoc.gemspec +1 -1
  3. data/lib/isodoc-yaml/i18n-ar.yaml +19 -25
  4. data/lib/isodoc-yaml/i18n-de.yaml +1 -0
  5. data/lib/isodoc-yaml/i18n-en.yaml +1 -0
  6. data/lib/isodoc-yaml/i18n-es.yaml +1 -0
  7. data/lib/isodoc-yaml/i18n-fr.yaml +1 -0
  8. data/lib/isodoc-yaml/i18n-ru.yaml +1 -0
  9. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
  10. data/lib/isodoc.rb +1 -0
  11. data/lib/isodoc/convert.rb +1 -1
  12. data/lib/isodoc/css.rb +3 -3
  13. data/lib/isodoc/function/blocks.rb +180 -168
  14. data/lib/isodoc/function/form.rb +39 -36
  15. data/lib/isodoc/function/inline.rb +5 -1
  16. data/lib/isodoc/function/reqt.rb +91 -85
  17. data/lib/isodoc/function/to_word_html.rb +207 -204
  18. data/lib/isodoc/html_convert.rb +0 -4
  19. data/lib/isodoc/html_function/form.rb +48 -45
  20. data/lib/isodoc/html_function/html.rb +2 -0
  21. data/lib/isodoc/html_function/postprocess.rb +9 -4
  22. data/lib/isodoc/presentation_function/block.rb +7 -4
  23. data/lib/isodoc/presentation_function/inline.rb +29 -12
  24. data/lib/isodoc/presentation_function/section.rb +1 -2
  25. data/lib/isodoc/presentation_xml_convert.rb +2 -2
  26. data/lib/isodoc/version.rb +1 -1
  27. data/lib/isodoc/xref.rb +8 -7
  28. data/lib/isodoc/xref/xref_anchor.rb +45 -44
  29. data/lib/isodoc/xref/xref_counter.rb +113 -103
  30. data/lib/isodoc/xref/xref_gen.rb +39 -11
  31. data/lib/metanorma/output.rb +7 -0
  32. data/lib/metanorma/output/base.rb +13 -0
  33. data/lib/metanorma/output/utils.rb +17 -0
  34. data/lib/metanorma/output/xslfo.rb +21 -0
  35. data/spec/assets/outputtest/a.xml +66 -0
  36. data/spec/assets/outputtest/iso.international-standard.xsl +3011 -0
  37. data/spec/isodoc/blocks_spec.rb +358 -243
  38. data/spec/isodoc/form_spec.rb +94 -90
  39. data/spec/isodoc/inline_spec.rb +413 -234
  40. data/spec/isodoc/postproc_spec.rb +70 -27
  41. data/spec/isodoc/terms_spec.rb +2 -2
  42. data/spec/isodoc/xref_spec.rb +274 -652
  43. metadata +8 -18
  44. data/lib/isodoc/html_function/sectionsplit.rb +0 -230
  45. data/spec/isodoc/sectionsplit_spec.rb +0 -190
@@ -2,7 +2,6 @@ require_relative "html_function/comments"
2
2
  require_relative "html_function/footnotes"
3
3
  require_relative "html_function/html"
4
4
  require_relative "html_function/postprocess"
5
- require_relative "html_function/sectionsplit"
6
5
  require_relative "html_function/form"
7
6
 
8
7
  module IsoDoc
@@ -24,9 +23,6 @@ module IsoDoc
24
23
  end
25
24
 
26
25
  def convert(filename, file = nil, debug = false, output_filename = nil)
27
- @sectionsplit and
28
- return sectionsplit_convert(filename, file, debug, output_filename)
29
-
30
26
  ret = super
31
27
  Dir.exists?(tmpimagedir) and Dir["#{tmpimagedir}/*"].empty? and
32
28
  FileUtils.rm_r tmpimagedir
@@ -1,61 +1,64 @@
1
- module IsoDoc::HtmlFunction
2
- module Form
3
- def form_parse(node, out)
4
- out.form **attr_code(id: node["id"], name: node["name"],
5
- action: node["action"]) do |div|
6
- node.children.each do |n|
7
- parse(n, div)
1
+ module IsoDoc
2
+ module HtmlFunction
3
+ module Form
4
+ def form_parse(node, out)
5
+ out.form **attr_code(id: node["id"], name: node["name"],
6
+ class: node["class"],
7
+ action: node["action"]) do |div|
8
+ node.children.each do |n|
9
+ parse(n, div)
10
+ end
8
11
  end
9
12
  end
10
- end
11
13
 
12
- def input_parse(node, out)
13
- out.input nil, **attr_code(
14
- id: node["id"], name: node["name"], type: node["type"],
15
- value: node["value"], disabled: node["disabled"],
16
- readonly: node["readonly"], checked: node["checked"],
17
- maxlength: node["maxlength"], minlength: node["minlength"]
18
- )
19
- end
14
+ def input_parse(node, out)
15
+ out.input nil, **attr_code(
16
+ id: node["id"], name: node["name"], type: node["type"],
17
+ value: node["value"], disabled: node["disabled"],
18
+ readonly: node["readonly"], checked: node["checked"],
19
+ maxlength: node["maxlength"], minlength: node["minlength"]
20
+ )
21
+ end
20
22
 
21
- def select_parse(node, out)
22
- selected = node.at(ns("./option[@value = '#{node['value']}']"))
23
- selected and selected["selected"] = true
24
- out.select **attr_code(
25
- id: node["id"], name: node["name"], size: node["size"],
26
- disabled: node["disabled"], multiple: node["multiple"]
27
- ) do |div|
28
- node.children.each do |n|
29
- parse(n, div)
23
+ def select_parse(node, out)
24
+ selected = node.at(ns("./option[@value = '#{node['value']}']"))
25
+ selected and selected["selected"] = true
26
+ out.select **attr_code(
27
+ id: node["id"], name: node["name"], size: node["size"],
28
+ disabled: node["disabled"], multiple: node["multiple"]
29
+ ) do |div|
30
+ node.children.each do |n|
31
+ parse(n, div)
32
+ end
30
33
  end
31
34
  end
32
- end
33
35
 
34
- def label_parse(node, out)
35
- out.label **attr_code(for: node["for"]) do |div|
36
- node.children.each do |n|
37
- parse(n, div)
36
+ def label_parse(node, out)
37
+ out.label **attr_code(for: node["for"]) do |div|
38
+ node.children.each do |n|
39
+ parse(n, div)
40
+ end
38
41
  end
39
42
  end
40
- end
41
43
 
42
- def option_parse(node, out)
43
- out.option **attr_code(
44
- disabled: node["disabled"], selected: node["selected"],
45
- value: node["value"]
46
- ) do |o|
47
- node.children.each do |n|
48
- parse(n, o)
44
+ def option_parse(node, out)
45
+ out.option **attr_code(
46
+ disabled: node["disabled"], selected: node["selected"],
47
+ value: node["value"]
48
+ ) do |o|
49
+ node.children.each do |n|
50
+ parse(n, o)
51
+ end
49
52
  end
50
53
  end
51
- end
52
54
 
53
- def textarea_parse(node, out)
54
- out.textarea **attr_code(
55
- id: node["id"], name: node["name"], rows: node["rows"],
56
- cols: node["cols"]
57
- ) do |div|
58
- node["value"] and div << node["value"]
55
+ def textarea_parse(node, out)
56
+ out.textarea **attr_code(
57
+ id: node["id"], name: node["name"], rows: node["rows"],
58
+ cols: node["cols"]
59
+ ) do |div|
60
+ node["value"] and div << node["value"]
61
+ end
59
62
  end
60
63
  end
61
64
  end
@@ -74,6 +74,8 @@ module IsoDoc::HtmlFunction
74
74
  end
75
75
 
76
76
  def html_button
77
+ return "" if @bare
78
+
77
79
  '<button onclick="topFunction()" id="myBtn" '\
78
80
  'title="Go to top">Top</button>'.freeze
79
81
  end
@@ -19,7 +19,6 @@ module IsoDoc
19
19
 
20
20
  def toHTML(result, filename)
21
21
  result = from_xhtml(html_cleanup(to_xhtml(result)))
22
- # result = populate_template(result, :html)
23
22
  result = from_xhtml(move_images(to_xhtml(result)))
24
23
  result = html5(script_cdata(inject_script(result)))
25
24
  File.open(filename, "w:UTF-8") { |f| f.write(result) }
@@ -33,7 +32,14 @@ module IsoDoc
33
32
  def html_cleanup(html)
34
33
  html = term_header(html_footnote_filter(html_preface(htmlstyle(html))))
35
34
  html = footnote_format(footnote_backlinks(html_toc(html)))
36
- mathml(html_list_clean(html))
35
+ mathml(html_list_clean(remove_placeholder_paras(html)))
36
+ end
37
+
38
+ def remove_placeholder_paras(html)
39
+ %w(title-section prefatory-section).each do |s|
40
+ html&.at("//div[@class = '#{s}']/p[last()]")&.remove
41
+ end
42
+ html
37
43
  end
38
44
 
39
45
  def html_list_clean(html)
@@ -68,6 +74,7 @@ module IsoDoc
68
74
  head = docxml.at("//*[local-name() = 'head']")
69
75
  head << htmlstylesheet(@htmlstylesheet)
70
76
  s = htmlstylesheet(@htmlstylesheet_override) and head << s
77
+ @bare and head << "<style>body {margin-left: 2em; margin-right: 2em;}</style>"
71
78
  docxml
72
79
  end
73
80
 
@@ -99,7 +106,6 @@ module IsoDoc
99
106
  def html_cover(docxml)
100
107
  doc = to_xhtml_fragment(File.read(@htmlcoverpage, encoding: "UTF-8"))
101
108
  d = docxml.at('//div[@class="title-section"]')
102
- # d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
103
109
  d.children.first.add_previous_sibling(
104
110
  populate_template(doc.to_xml(encoding: "US-ASCII"), :html),
105
111
  )
@@ -108,7 +114,6 @@ module IsoDoc
108
114
  def html_intro(docxml)
109
115
  doc = to_xhtml_fragment(File.read(@htmlintropage, encoding: "UTF-8"))
110
116
  d = docxml.at('//div[@class="prefatory-section"]')
111
- # d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
112
117
  d.children.first.add_previous_sibling(
113
118
  populate_template(doc.to_xml(encoding: "US-ASCII"), :html),
114
119
  )
@@ -19,12 +19,15 @@ module IsoDoc
19
19
  end
20
20
  end
21
21
 
22
- def svg_extract(f)
23
- return unless %r{^data:image/svg\+xml;base64,}.match?(f["src"])
22
+ def svg_extract(elem)
23
+ return unless %r{^data:image/svg\+xml;base64,}.match?(elem["src"])
24
24
 
25
- svg = Base64.strict_decode64(f["src"]
25
+ svg = Base64.strict_decode64(elem["src"]
26
26
  .sub(%r{^data:image/svg\+xml;base64,}, ""))
27
- f.replace(svg.sub(/<\?xml[^>]*>/, ""))
27
+ x = Nokogiri::XML.fragment(svg.sub(/<\?xml[^>]*>/, "")) do |config|
28
+ config.huge
29
+ end
30
+ elem.replace(x)
28
31
  end
29
32
 
30
33
  def figure1(f)
@@ -129,10 +129,8 @@ module IsoDoc
129
129
 
130
130
  loc = @i18n.locality[type] || type.sub(/^locality:/, "")
131
131
  loc = case node["case"]
132
- when "capital" then loc.capitalize
133
132
  when "lowercase" then loc.downcase
134
- else
135
- loc.capitalize
133
+ else loc.capitalize
136
134
  end
137
135
  " #{loc}"
138
136
  end
@@ -162,15 +160,34 @@ module IsoDoc
162
160
  end
163
161
 
164
162
  def concept1(node)
165
- content = node.first_element_child.children.reject do |c|
166
- %w{locality localityStack}.include? c.name
167
- end.select { |c| !c.text? || /\S/.match(c) }
168
- n = if content.empty?
169
- @i18n.term_defined_in.sub(/%/, node.first_element_child.to_xml)
170
- else
171
- "<em>#{node.children.to_xml}</em>"
172
- end
173
- node.replace(n)
163
+ xref = node&.at(ns("./xref/@target"))&.text or
164
+ return concept_render(node, node["ital"] || "true",
165
+ node["ref"] || "true")
166
+ if node.at(ns("//definitions//dt[@id = '#{xref}']"))
167
+ concept_render(node, node["ital"] || "false", node["ref"] || "false")
168
+ else concept_render(node, node["ital"] || "true", node["ref"] || "true")
169
+ end
170
+ end
171
+
172
+ def concept_render(node, ital, ref)
173
+ node&.at(ns("./refterm"))&.remove
174
+ r = node.at(ns("./renderterm"))
175
+ r&.next = " " if node.at(ns("./xref | ./eref | ./termref")) && ref != "false"
176
+ if ital == "true" then r&.name = "em"
177
+ else r&.replace(r&.children)
178
+ end
179
+ concept1_ref(node, ref)
180
+ node.replace(node.children)
181
+ end
182
+
183
+ def concept1_ref(node, ref)
184
+ r = node.at(ns("./xref | ./eref | ./termref")) or return
185
+ return r.remove if ref == "false"
186
+
187
+ if non_locality_elems(r).select { |c| !c.text? || /\S/.match(c) }.empty?
188
+ r.replace(@i18n.term_defined_in.sub(/%/, r.to_xml))
189
+ else r.replace("[#{r.to_xml}]")
190
+ end
174
191
  end
175
192
 
176
193
  def variant(docxml)
@@ -44,8 +44,7 @@ module IsoDoc
44
44
  prefix_name(elem, "", "#{lbl}#{clausedelim}", "name")
45
45
  end
46
46
 
47
- def references(docxml)
48
- end
47
+ def references(docxml); end
49
48
 
50
49
  def docid_prefixes(docxml)
51
50
  docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
@@ -29,12 +29,12 @@ module IsoDoc
29
29
  end
30
30
 
31
31
  def section(docxml)
32
- display_order docxml
33
32
  clause docxml
34
33
  annex docxml
35
34
  term docxml
36
35
  references docxml
37
36
  index docxml
37
+ display_order docxml
38
38
  end
39
39
 
40
40
  def block(docxml)
@@ -53,10 +53,10 @@ module IsoDoc
53
53
  end
54
54
 
55
55
  def inline(docxml)
56
+ concept docxml
56
57
  xref docxml
57
58
  eref docxml
58
59
  origin docxml
59
- concept docxml
60
60
  quotesource docxml
61
61
  mathml docxml
62
62
  variant docxml
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "1.6.7.1".freeze
2
+ VERSION = "1.7.3".freeze
3
3
  end
data/lib/isodoc/xref.rb CHANGED
@@ -28,16 +28,16 @@ module IsoDoc
28
28
  @anchors
29
29
  end
30
30
 
31
- def anchor(id, lbl, warning = true)
32
- return nil if id.nil? || id.empty?
31
+ def anchor(ident, lbl, warning = true)
32
+ return nil if ident.nil? || ident.empty?
33
33
 
34
- if warning && !@anchors[id]
34
+ if warning && !@anchors[ident]
35
35
  @seen ||= Seen_Anchor.instance
36
- @seen.seen(id) or warn "No label has been processed for ID #{id}"
37
- @seen.add(id)
38
- return "[#{id}]"
36
+ @seen.seen(ident) or warn "No label has been processed for ID #{ident}"
37
+ @seen.add(ident)
38
+ return "[#{ident}]"
39
39
  end
40
- @anchors.dig(id, lbl)
40
+ @anchors.dig(ident, lbl)
41
41
  end
42
42
 
43
43
  # extract names for all anchors, xref and label
@@ -50,6 +50,7 @@ module IsoDoc
50
50
  note_anchor_names(docxml.xpath(ns(SECTIONS_XPATH)))
51
51
  example_anchor_names(docxml.xpath(ns(SECTIONS_XPATH)))
52
52
  list_anchor_names(docxml.xpath(ns(SECTIONS_XPATH)))
53
+ deflist_anchor_names(docxml.xpath(ns(SECTIONS_XPATH)))
53
54
  bookmark_anchor_names(docxml)
54
55
  end
55
56
 
@@ -1,61 +1,62 @@
1
1
  require "singleton"
2
2
 
3
- module IsoDoc::XrefGen
4
- module Anchor
5
- class Seen_Anchor
6
- include Singleton
3
+ module IsoDoc
4
+ module XrefGen
5
+ module Anchor
6
+ class Seen_Anchor
7
+ include Singleton
8
+
9
+ def initialize
10
+ @seen = {}
11
+ end
12
+
13
+ def seen(elem)
14
+ @seen.has_key?(elem)
15
+ end
16
+
17
+ def add(elem)
18
+ @seen[elem] = true
19
+ end
20
+ end
7
21
 
8
22
  def initialize
9
- @seen = {}
23
+ @anchors = {}
10
24
  end
11
25
 
12
- def seen(x)
13
- @seen.has_key?(x)
26
+ def get_anchors
27
+ @anchors
14
28
  end
15
29
 
16
- def add(x)
17
- @seen[x] = true
30
+ def anchor_struct_label(lbl, elem)
31
+ case elem
32
+ when @labels["appendix"] then l10n("#{elem} #{lbl}")
33
+ else
34
+ lbl.to_s
35
+ end
18
36
  end
19
- end
20
-
21
- def initialize()
22
- @anchors = {}
23
- end
24
-
25
- def get_anchors
26
- @anchors
27
- end
28
37
 
29
- def anchor_struct_label(lbl, elem)
30
- case elem
31
- when @labels["appendix"] then l10n("#{elem} #{lbl}")
32
- else
33
- lbl.to_s
38
+ def anchor_struct_xref(lbl, elem)
39
+ l10n("#{elem} #{anchor_struct_value(lbl, elem)}")
34
40
  end
35
- end
36
-
37
- def anchor_struct_xref(lbl, elem)
38
- l10n("#{elem} #{anchor_struct_value(lbl, elem)}")
39
- end
40
41
 
41
- def anchor_struct_value(lbl, elem)
42
- case elem
43
- when @labels["formula"] then "(#{lbl})"
44
- when @labels["inequality"] then "(#{lbl})"
45
- else
46
- lbl
42
+ def anchor_struct_value(lbl, elem)
43
+ case elem
44
+ when @labels["formula"], @labels["inequality"] then "(#{lbl})"
45
+ else
46
+ lbl
47
+ end
47
48
  end
48
- end
49
49
 
50
- def anchor_struct(lbl, container, elem, type, unnumbered = false)
51
- ret = {}
52
- ret[:label] = unnumbered == "true" ? nil : anchor_struct_label(lbl, elem)
53
- ret[:xref] = anchor_struct_xref(unnumbered == "true" ? "(??)" : lbl, elem)
54
- ret[:xref].gsub!(/ $/, "")
55
- ret[:container] = @klass.get_clause_id(container) unless container.nil?
56
- ret[:type] = type
57
- ret[:value] = anchor_struct_value(lbl, elem)
58
- ret
50
+ def anchor_struct(lbl, container, elem, type, unnumb = false)
51
+ ret = {}
52
+ ret[:label] = unnumb == "true" ? nil : anchor_struct_label(lbl, elem)
53
+ ret[:xref] = anchor_struct_xref(unnumb == "true" ? "(??)" : lbl, elem)
54
+ ret[:xref].gsub!(/ $/, "")
55
+ ret[:container] = @klass.get_clause_id(container) unless container.nil?
56
+ ret[:type] = type
57
+ ret[:value] = anchor_struct_value(lbl, elem)
58
+ ret
59
+ end
59
60
  end
60
61
  end
61
62
  end
@@ -1,33 +1,37 @@
1
1
  require "roman-numerals"
2
2
 
3
- module IsoDoc::XrefGen
4
- class Counter
5
- def initialize(num = 0, opts = { numerals: :arabic })
6
- @num = num
7
- @letter = ""
8
- @subseq = ""
9
- @letter_override = nil
10
- @number_override = nil
11
- @style = opts[:numerals]
12
- @skip_i = opts[:skip_i]
13
- @base = ""
14
- if num.is_a? String
15
- if /^\d+$/.match?(num)
16
- @num = num.to_i
17
- else
18
- @num = nil
19
- @base = num[0..-2]
20
- @letter = num[-1]
3
+ module IsoDoc
4
+ module XrefGen
5
+ class Counter
6
+ def initialize(num = 0, opts = { numerals: :arabic })
7
+ @num = num
8
+ @letter = ""
9
+ @subseq = ""
10
+ @letter_override = nil
11
+ @number_override = nil
12
+ @style = opts[:numerals]
13
+ @skip_i = opts[:skip_i]
14
+ @base = ""
15
+ if num.is_a? String
16
+ if /^\d+$/.match?(num)
17
+ @num = num.to_i
18
+ else
19
+ @num = nil
20
+ @base = num[0..-2]
21
+ @letter = num[-1]
22
+ end
21
23
  end
22
24
  end
23
- end
24
25
 
25
- def new_subseq_increment(node)
26
- @subseq = node["subsequence"]
27
- @num += 1 unless @num.nil?
28
- @letter = node["subsequence"] ? "a" : ""
29
- @base = ""
30
- if node["number"]
26
+ def new_subseq_increment(node)
27
+ @subseq = node["subsequence"]
28
+ @num += 1 unless @num.nil?
29
+ @letter = node["subsequence"] ? "a" : ""
30
+ @base = ""
31
+ new_subseq_increment1(node) if node["number"]
32
+ end
33
+
34
+ def new_subseq_increment1(node)
31
35
  /^(?<b>.*?)(?<n>\d*)(?<a>[a-zA-Z]*)$/ =~ node["number"]
32
36
  if !n.empty? || !a.empty?
33
37
  @letter_override = @letter = a unless a.empty?
@@ -38,108 +42,114 @@ module IsoDoc::XrefGen
38
42
  @letter = @letter_override if /^[a-zA-Z]$/.match?(@letter_override)
39
43
  end
40
44
  end
41
- end
42
45
 
43
- def sequence_increment(node)
44
- if node["number"]
45
- @base = @letter_override = @number_override = ""
46
- /^(?<b>.*?)(?<n>\d+)$/ =~ node["number"]
47
- if blank?(n)
48
- @num = nil
49
- @base = node["number"][0..-2]
50
- @letter = @letter_override = node["number"][-1]
51
- else
52
- @number_override = @num = n.to_i
53
- @base = b
54
- @letter = ""
46
+ def sequence_increment(node)
47
+ if node["number"]
48
+ @base = @letter_override = @number_override = ""
49
+ /^(?<b>.*?)(?<n>\d+)$/ =~ node["number"]
50
+ if blank?(n)
51
+ @num = nil
52
+ @base = node["number"][0..-2]
53
+ @letter = @letter_override = node["number"][-1]
54
+ else
55
+ @number_override = @num = n.to_i
56
+ @base = b
57
+ @letter = ""
58
+ end
59
+ else @num += 1
55
60
  end
56
- else
57
- @num += 1
58
61
  end
59
- end
60
62
 
61
- def subsequence_increment(node)
62
- if node["number"]
63
+ def subsequence_increment(node)
64
+ return increment_letter unless node["number"]
65
+
63
66
  @base = ""
64
67
  @letter_override = node["number"]
65
68
  /^(?<b>.*?)(?<n>\d*)(?<a>[a-zA-Z])$/ =~ node["number"]
66
- if blank?(a)
67
- if /^\d+$/.match?(node["number"])
68
- @letter_override = @letter = ""
69
- @number_override = @num = node["number"].to_i
70
- else
71
- /^(?<b>.*)(?<a>[a-zA-Z])$/ =~ node["number"]
72
- unless blank?(a)
73
- @letter = @letter_override = a
74
- @base = b
75
- end
76
- end
69
+ if blank?(a) then subsequence_increment_no_letter(node)
77
70
  else
78
71
  @letter_override = @letter = a
79
72
  @base = b
80
73
  @number_override = @num = n.to_i unless n.empty?
81
74
  end
82
- else
83
- increment_letter
84
75
  end
85
- end
86
76
 
87
- def increment_letter
88
- case @letter
89
- when "Z"
90
- @letter = "@"
91
- @base = @base.empty? ? "A" : @base[0..-2] + (@base[-1].ord + 1).chr.to_s
92
- when "z"
93
- @letter = "`"
94
- @base = @base.empty? ? "a" : @base[0..-2] + (@base[-1].ord + 1).chr.to_s
77
+ def subsequence_increment_no_letter(node)
78
+ if /^\d+$/.match?(node["number"])
79
+ @letter_override = @letter = ""
80
+ @number_override = @num = node["number"].to_i
81
+ else
82
+ /^(?<b>.*)(?<a>[a-zA-Z])$/ =~ node["number"]
83
+ unless blank?(a)
84
+ @letter = @letter_override = a
85
+ @base = b
86
+ end
87
+ end
88
+ end
89
+
90
+ def string_inc(str, start)
91
+ return start if str.empty?
92
+
93
+ str[0..-2] + (str[-1].ord + 1).chr.to_s
95
94
  end
96
- @letter = (@letter.ord + 1).chr.to_s
97
- @skip_i && %w(i I).include?(@letter) and
95
+
96
+ def increment_letter
97
+ case @letter
98
+ when "Z"
99
+ @letter = "@"
100
+ @base = string_inc(@base, "A")
101
+ when "z"
102
+ @letter = "`"
103
+ @base = string_inc(@base, "a")
104
+ end
98
105
  @letter = (@letter.ord + 1).chr.to_s
99
- end
106
+ @skip_i && %w(i I).include?(@letter) and
107
+ @letter = (@letter.ord + 1).chr.to_s
108
+ end
100
109
 
101
- def blank?(str)
102
- str.nil? || str.empty?
103
- end
110
+ def blank?(str)
111
+ str.nil? || str.empty?
112
+ end
104
113
 
105
- def increment(node)
106
- return self if node["unnumbered"]
114
+ def increment(node)
115
+ return self if node["unnumbered"]
107
116
 
108
- @letter_override = nil
109
- @number_override = nil
110
- if node["subsequence"] != @subseq &&
111
- !(blank?(node["subsequence"]) && blank?(@subseq))
112
- new_subseq_increment(node)
113
- elsif @letter.empty? then sequence_increment(node)
114
- else subsequence_increment(node)
117
+ @letter_override = nil
118
+ @number_override = nil
119
+ if node["subsequence"] != @subseq &&
120
+ !(blank?(node["subsequence"]) && blank?(@subseq))
121
+ new_subseq_increment(node)
122
+ elsif @letter.empty? then sequence_increment(node)
123
+ else subsequence_increment(node)
124
+ end
125
+ self
115
126
  end
116
- self
117
- end
118
127
 
119
- def print
120
- num = @number_override || @num
121
- out = @style == :roman && !num.nil? ? RomanNumerals.to_roman(num) : num
122
- "#{@base}#{out}#{@letter_override || @letter}"
123
- end
128
+ def print
129
+ num = @number_override || @num
130
+ out = @style == :roman && !num.nil? ? RomanNumerals.to_roman(num) : num
131
+ "#{@base}#{out}#{@letter_override || @letter}"
132
+ end
124
133
 
125
- def ol_type(list, depth)
126
- return list["type"].to_sym if list["type"]
127
- return :arabic if [2, 7].include? depth
128
- return :alphabet if [1, 6].include? depth
129
- return :alphabet_upper if [4, 9].include? depth
130
- return :roman if [3, 8].include? depth
131
- return :roman_upper if [5, 10].include? depth
134
+ def ol_type(list, depth)
135
+ return list["type"].to_sym if list["type"]
136
+ return :arabic if [2, 7].include? depth
137
+ return :alphabet if [1, 6].include? depth
138
+ return :alphabet_upper if [4, 9].include? depth
139
+ return :roman if [3, 8].include? depth
140
+ return :roman_upper if [5, 10].include? depth
132
141
 
133
- :arabic
134
- end
142
+ :arabic
143
+ end
135
144
 
136
- def listlabel(list, depth)
137
- case ol_type(list, depth)
138
- when :arabic then @num.to_s
139
- when :alphabet then (96 + @num).chr.to_s
140
- when :alphabet_upper then (64 + @num).chr.to_s
141
- when :roman then RomanNumerals.to_roman(@num).downcase
142
- when :roman_upper then RomanNumerals.to_roman(@num).upcase
145
+ def listlabel(list, depth)
146
+ case ol_type(list, depth)
147
+ when :arabic then @num.to_s
148
+ when :alphabet then (96 + @num).chr.to_s
149
+ when :alphabet_upper then (64 + @num).chr.to_s
150
+ when :roman then RomanNumerals.to_roman(@num).downcase
151
+ when :roman_upper then RomanNumerals.to_roman(@num).upcase
152
+ end
143
153
  end
144
154
  end
145
155
  end