isodoc 1.6.7.1 → 1.7.3

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