isodoc 1.5.3 → 1.6.2

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +1 -1
  3. data/.rubocop.yml +6 -4
  4. data/Gemfile +2 -2
  5. data/bin/rspec +1 -2
  6. data/isodoc.gemspec +11 -11
  7. data/lib/isodoc-yaml/i18n-ar.yaml +152 -0
  8. data/lib/isodoc-yaml/i18n-de.yaml +149 -0
  9. data/lib/isodoc-yaml/i18n-es.yaml +151 -0
  10. data/lib/isodoc-yaml/i18n-ru.yaml +154 -0
  11. data/lib/isodoc/base_style/all.css +7 -0
  12. data/lib/isodoc/base_style/metanorma_word.css +7 -0
  13. data/lib/isodoc/base_style/metanorma_word.scss +8 -0
  14. data/lib/isodoc/base_style/reset.css +7 -0
  15. data/lib/isodoc/base_style/reset.scss +9 -0
  16. data/lib/isodoc/base_style/scripts.html +187 -0
  17. data/lib/isodoc/class_utils.rb +6 -5
  18. data/lib/isodoc/common.rb +2 -0
  19. data/lib/isodoc/convert.rb +30 -17
  20. data/lib/isodoc/css.rb +42 -28
  21. data/lib/isodoc/function/blocks.rb +25 -4
  22. data/lib/isodoc/function/blocks_example_note.rb +2 -2
  23. data/lib/isodoc/function/cleanup.rb +1 -2
  24. data/lib/isodoc/function/form.rb +51 -0
  25. data/lib/isodoc/function/inline.rb +32 -10
  26. data/lib/isodoc/function/references.rb +55 -42
  27. data/lib/isodoc/function/table.rb +1 -0
  28. data/lib/isodoc/function/to_word_html.rb +29 -27
  29. data/lib/isodoc/function/utils.rb +41 -38
  30. data/lib/isodoc/gem_tasks.rb +30 -31
  31. data/lib/isodoc/html_convert.rb +6 -4
  32. data/lib/isodoc/html_function/form.rb +62 -0
  33. data/lib/isodoc/html_function/postprocess.rb +35 -76
  34. data/lib/isodoc/html_function/postprocess_footnotes.rb +59 -0
  35. data/lib/isodoc/i18n.rb +33 -31
  36. data/lib/isodoc/pdf_convert.rb +1 -3
  37. data/lib/isodoc/presentation_function/block.rb +26 -11
  38. data/lib/isodoc/presentation_function/inline.rb +60 -111
  39. data/lib/isodoc/presentation_function/math.rb +84 -0
  40. data/lib/isodoc/presentation_xml_convert.rb +2 -1
  41. data/lib/isodoc/version.rb +1 -1
  42. data/lib/isodoc/word_function/body.rb +28 -24
  43. data/lib/isodoc/word_function/footnotes.rb +22 -15
  44. data/lib/isodoc/word_function/inline.rb +6 -0
  45. data/lib/isodoc/word_function/postprocess.rb +16 -6
  46. data/lib/isodoc/xref.rb +10 -11
  47. data/lib/isodoc/xref/xref_counter.rb +31 -15
  48. data/lib/isodoc/xref/xref_gen.rb +28 -22
  49. data/lib/isodoc/xref/xref_sect_gen.rb +22 -20
  50. data/lib/isodoc/xslfo_convert.rb +36 -25
  51. data/spec/assets/html_override.css +1 -0
  52. data/spec/assets/word_override.css +1 -0
  53. data/spec/isodoc/blocks_spec.rb +2599 -2503
  54. data/spec/isodoc/cleanup_spec.rb +1107 -1109
  55. data/spec/isodoc/footnotes_spec.rb +1 -16
  56. data/spec/isodoc/form_spec.rb +156 -0
  57. data/spec/isodoc/i18n_spec.rb +984 -972
  58. data/spec/isodoc/inline_spec.rb +984 -920
  59. data/spec/isodoc/lists_spec.rb +316 -315
  60. data/spec/isodoc/postproc_spec.rb +1692 -1538
  61. data/spec/isodoc/presentation_xml_spec.rb +345 -338
  62. data/spec/isodoc/ref_spec.rb +718 -723
  63. data/spec/isodoc/section_spec.rb +910 -902
  64. data/spec/isodoc/table_spec.rb +566 -556
  65. data/spec/isodoc/terms_spec.rb +252 -256
  66. data/spec/isodoc/xref_spec.rb +3040 -2985
  67. data/spec/isodoc/xslfo_convert_spec.rb +39 -0
  68. data/spec/spec_helper.rb +30 -29
  69. metadata +80 -69
  70. data/.rubocop.ribose.yml +0 -65
  71. data/.rubocop.tb.yml +0 -650
@@ -0,0 +1,84 @@
1
+ require "twitter_cldr"
2
+ require "bigdecimal"
3
+
4
+ module IsoDoc
5
+ class PresentationXMLConvert < ::IsoDoc::Convert
6
+ MATHML = { "m" => "http://www.w3.org/1998/Math/MathML" }.freeze
7
+
8
+ def mathml(docxml)
9
+ locale = twitter_cldr_localiser
10
+ docxml.xpath("//m:math", MATHML).each do |f|
11
+ mathml1(f, locale)
12
+ end
13
+ end
14
+
15
+ # symbols is merged into
16
+ # TwitterCldr::DataReaders::NumberDataReader.new(locale).symbols
17
+ def localize_maths(node, locale)
18
+ node.xpath(".//m:mn", MATHML).each do |x|
19
+ num = BigDecimal(x.text)
20
+ precision = /\./.match?(x.text) ? x.text.sub(/^.*\./, "").size : 0
21
+ x.children = localized_number(num, locale, precision)
22
+ end
23
+ end
24
+
25
+ # By itself twitter-cldr does not support fraction part digits grouping
26
+ # and custom delimeter, will decorate fraction part manually
27
+ def localized_number(num, locale, precision)
28
+ localized = localized_number1(num, locale, precision)
29
+ twitter_cldr_reader_symbols = twitter_cldr_reader(locale)
30
+ return localized unless twitter_cldr_reader_symbols[:decimal]
31
+
32
+ integer, fraction = localized.split(twitter_cldr_reader_symbols[:decimal])
33
+ return localized if fraction.nil? || fraction.length.zero?
34
+
35
+ [integer, decorate_fraction_part(fraction, locale)]
36
+ .join(twitter_cldr_reader_symbols[:decimal])
37
+ end
38
+
39
+ def localized_number1(num, locale, precision)
40
+ if precision.zero?
41
+ num.localize(locale).to_s
42
+ else
43
+ num.localize(locale).to_decimal.to_s(precision: precision)
44
+ end
45
+ end
46
+
47
+ def decorate_fraction_part(fract, locale)
48
+ result = []
49
+ twitter_cldr_reader_symbols = twitter_cldr_reader(locale)
50
+ fract = fract.slice(0..(twitter_cldr_reader_symbols[:precision] || -1))
51
+ fr_group_digits = twitter_cldr_reader_symbols[:fraction_group_digits] || 1
52
+ until fract.empty?
53
+ result.push(fract.slice!(0, fr_group_digits))
54
+ end
55
+ result.join(twitter_cldr_reader_symbols[:fraction_group].to_s)
56
+ end
57
+
58
+ def twitter_cldr_localiser_symbols
59
+ {}
60
+ end
61
+
62
+ def twitter_cldr_reader(locale)
63
+ num = TwitterCldr::DataReaders::NumberDataReader.new(locale)
64
+ num.symbols.merge!(twitter_cldr_localiser_symbols)
65
+ end
66
+
67
+ def twitter_cldr_localiser
68
+ locale = TwitterCldr.supported_locale?(@lang.to_sym) ? @lang.to_sym : :en
69
+ twitter_cldr_reader(locale)
70
+ locale
71
+ end
72
+
73
+ def mathml1(node, locale)
74
+ localize_maths(node, locale)
75
+ return unless node.elements.size == 1 && node.elements.first.name == "mn"
76
+
77
+ if node.parent.name == "stem"
78
+ node.parent.replace(node.at("./m:mn", MATHML).children)
79
+ else
80
+ node.replace(node.at("./m:mn", MATHML).children)
81
+ end
82
+ end
83
+ end
84
+ end
@@ -1,5 +1,6 @@
1
1
  require_relative "presentation_function/block"
2
2
  require_relative "presentation_function/inline"
3
+ require_relative "presentation_function/math"
3
4
  require_relative "presentation_function/section"
4
5
  require_relative "presentation_function/bibdata"
5
6
 
@@ -59,7 +60,7 @@ module IsoDoc
59
60
  variant docxml
60
61
  end
61
62
 
62
- def postprocess(result, filename, dir)
63
+ def postprocess(result, filename, _dir)
63
64
  toXML(result, filename)
64
65
  @files_to_delete.each { |f| FileUtils.rm_rf f }
65
66
  end
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "1.5.3".freeze
2
+ VERSION = "1.6.2".freeze
3
3
  end
@@ -1,5 +1,5 @@
1
- require_relative "./table.rb"
2
- require_relative "./inline.rb"
1
+ require_relative "./table"
2
+ require_relative "./inline"
3
3
 
4
4
  module IsoDoc::WordFunction
5
5
  module Body
@@ -71,8 +71,8 @@ module IsoDoc::WordFunction
71
71
  node.xpath(ns("./note")).each { |n| parse(n, out) }
72
72
  end
73
73
 
74
- WORD_DT_ATTRS = {class: @note ? "Note" : nil, align: "left",
75
- style: "margin-left:0pt;text-align:left;"}.freeze
74
+ WORD_DT_ATTRS = { class: @note ? "Note" : nil, align: "left",
75
+ style: "margin-left:0pt;text-align:left;" }.freeze
76
76
 
77
77
  def dt_parse(dt, term)
78
78
  term.p **attr_code(WORD_DT_ATTRS) do |p|
@@ -102,6 +102,7 @@ module IsoDoc::WordFunction
102
102
 
103
103
  def dl_parse_notes(node, v)
104
104
  return if node.elements.reject { |n| dt_dd? n }.empty?
105
+
105
106
  v.tr do |tr|
106
107
  tr.td **{ colspan: 2 } do |td|
107
108
  node.elements.reject { |n| dt_dd? n }.each { |n| parse(n, td) }
@@ -109,19 +110,19 @@ module IsoDoc::WordFunction
109
110
  end
110
111
  end
111
112
 
112
- def figure_get_or_make_dl(t)
113
- dl = t.at(".//table[@class = 'dl']")
113
+ def figure_get_or_make_dl(node)
114
+ dl = node.at(".//table[@class = 'dl']")
114
115
  if dl.nil?
115
- t.add_child("<p><b>#{@i18n.key}</b></p><table class='dl'></table>")
116
- dl = t.at(".//table[@class = 'dl']")
116
+ node.add_child("<p><b>#{@i18n.key}</b></p><table class='dl'></table>")
117
+ dl = node.at(".//table[@class = 'dl']")
117
118
  end
118
119
  dl
119
120
  end
120
121
 
121
- def figure_aside_process(f, aside, key)
122
+ def figure_aside_process(fig, aside, key)
122
123
  # get rid of footnote link, it is in diagram
123
- f&.at("./a[@class='TableFootnoteRef']")&.remove
124
- fnref = f.at(".//span[@class='TableFootnoteRef']/..")
124
+ fig&.at("./a[@class='TableFootnoteRef']")&.remove
125
+ fnref = fig.at(".//span[@class='TableFootnoteRef']/..")
125
126
  tr = key.add_child("<tr></tr>").first
126
127
  dt = tr.add_child("<td valign='top' align='left'></td>").first
127
128
  dd = tr.add_child("<td valign='top'></td>").first
@@ -174,31 +175,32 @@ module IsoDoc::WordFunction
174
175
  attrs[:align] = node["align"] unless node["align"] == "justify"
175
176
  attrs[:style] += "text-align:#{node['align']};"
176
177
  end
177
- attrs[:style] += "#{keep_style(node)}"
178
+ attrs[:style] += keep_style(node).to_s
178
179
  attrs[:style] = nil if attrs[:style].empty?
179
180
  attrs
180
181
  end
181
182
 
182
183
  def example_table_attr(node)
183
184
  super.merge({
184
- style: "mso-table-lspace:15.0cm;margin-left:423.0pt;"\
185
- "mso-table-rspace:15.0cm;margin-right:423.0pt;"\
186
- "mso-table-anchor-horizontal:column;"\
187
- "mso-table-overlap:never;border-collapse:collapse;"\
188
- "#{keep_style(node)}"
189
- })
185
+ style: "mso-table-lspace:15.0cm;margin-left:423.0pt;"\
186
+ "mso-table-rspace:15.0cm;margin-right:423.0pt;"\
187
+ "mso-table-anchor-horizontal:column;"\
188
+ "mso-table-overlap:never;border-collapse:collapse;"\
189
+ "#{keep_style(node)}",
190
+ })
190
191
  end
191
192
 
192
- def formula_where(dl, out)
193
- return unless dl
193
+ def formula_where(deflist, out)
194
+ return unless deflist
195
+
194
196
  out.p { |p| p << @i18n.where }
195
- parse(dl, out)
197
+ parse(deflist, out)
196
198
  out.parent.at("./table")["class"] = "formula_dl"
197
199
  end
198
200
 
199
201
  def formula_parse1(node, out)
200
202
  out.div **attr_code(class: "formula") do |div|
201
- div.p do |p|
203
+ div.p do |_p|
202
204
  parse(node.at(ns("./stem")), div)
203
205
  insert_tab(div, 1)
204
206
  if lbl = node&.at(ns("./name"))&.text
@@ -209,7 +211,7 @@ module IsoDoc::WordFunction
209
211
  end
210
212
 
211
213
  def li_parse(node, out)
212
- out.li **attr_code(id: node["id"]) do |li|
214
+ out.li **attr_code(id: node["id"]) do |li|
213
215
  if node["uncheckedcheckbox"] == "true"
214
216
  li << '<span class="zzMoveToFollowing">&#x2610; </span>'
215
217
  elsif node["checkedcheckbox"] == "true"
@@ -220,7 +222,9 @@ module IsoDoc::WordFunction
220
222
  end
221
223
 
222
224
  def suffix_url(url)
223
- return url if %r{^http[s]?://}.match(url)
225
+ return url if %r{^https?://}.match?(url)
226
+ return url unless File.extname(url).empty?
227
+
224
228
  url.sub(/#{File.extname(url)}$/, ".doc")
225
229
  end
226
230
  end
@@ -2,7 +2,7 @@ module IsoDoc::WordFunction
2
2
  module Footnotes
3
3
  def bookmarkid
4
4
  ret = "X"
5
- until !@bookmarks_allocated[ret] do
5
+ until !@bookmarks_allocated[ret]
6
6
  ret = Random.rand(1000000000)
7
7
  end
8
8
  @bookmarks_allocated[ret] = true
@@ -11,6 +11,7 @@ module IsoDoc::WordFunction
11
11
 
12
12
  def footnotes(div)
13
13
  return if @footnotes.empty?
14
+
14
15
  @footnotes.each { |fn| div.parent << fn }
15
16
  end
16
17
 
@@ -52,6 +53,7 @@ module IsoDoc::WordFunction
52
53
  def get_table_ancestor_id(node)
53
54
  table = node.ancestors("table") || node.ancestors("figure")
54
55
  return UUIDTools::UUID.random_create.to_s if table.empty?
56
+
55
57
  table.last["id"]
56
58
  end
57
59
 
@@ -61,30 +63,34 @@ module IsoDoc::WordFunction
61
63
  make_table_footnote_link(out, tid + fn, fn)
62
64
  # do not output footnote text if we have already seen it for this table
63
65
  return if @seen_footnote.include?(tid + fn)
66
+
64
67
  @in_footnote = true
65
68
  out.aside { |a| a << make_table_footnote_text(node, tid + fn, fn) }
66
69
  @in_footnote = false
67
70
  @seen_footnote << (tid + fn)
68
71
  end
69
72
 
70
- def seen_footnote_parse(node, out, fn)
71
- out.span **{style: "mso-element:field-begin"}
72
- out << " NOTEREF _Ref#{@fn_bookmarks[fn]} \\f \\h"
73
- out.span **{style: "mso-element:field-separator"}
74
- out.span **{class: "MsoFootnoteReference"} do |s|
75
- s << fn
73
+ def seen_footnote_parse(_node, out, footnote)
74
+ out.span **{ style: "mso-element:field-begin" }
75
+ out << " NOTEREF _Ref#{@fn_bookmarks[footnote]} \\f \\h"
76
+ out.span **{ style: "mso-element:field-separator" }
77
+ out.span **{ class: "MsoFootnoteReference" } do |s|
78
+ s << footnote
76
79
  end
77
- out.span **{style: "mso-element:field-end"}
80
+ out.span **{ style: "mso-element:field-end" }
78
81
  end
79
82
 
80
83
  def footnote_parse(node, out)
81
84
  return table_footnote_parse(node, out) if (@in_table || @in_figure) &&
82
- !node.ancestors.map {|m| m.name }.include?("name")
85
+ !node.ancestors.map { |m| m.name }.include?("name")
86
+
83
87
  fn = node["reference"] || UUIDTools::UUID.random_create.to_s
84
88
  return seen_footnote_parse(node, out, fn) if @seen_footnote.include?(fn)
89
+
85
90
  @fn_bookmarks[fn] = bookmarkid
86
- out.span **{style: "mso-bookmark:_Ref#{@fn_bookmarks[fn]}"} do |s|
87
- s.a **{ "class": "FootnoteRef", "epub:type": "footnote", href: "#ftn#{fn}" } do |a|
91
+ out.span **{ style: "mso-bookmark:_Ref#{@fn_bookmarks[fn]}" } do |s|
92
+ s.a **{ "class": "FootnoteRef", "epub:type": "footnote",
93
+ href: "#ftn#{fn}" } do |a|
88
94
  a.sup { |sup| sup << fn }
89
95
  end
90
96
  end
@@ -94,12 +100,13 @@ module IsoDoc::WordFunction
94
100
  @seen_footnote << fn
95
101
  end
96
102
 
97
- def make_footnote(node, fn)
98
- return if @seen_footnote.include?(fn)
103
+ def make_footnote(node, footnote)
104
+ return if @seen_footnote.include?(footnote)
105
+
99
106
  @in_footnote = true
100
- @footnotes << make_generic_footnote_text(node, fn)
107
+ @footnotes << make_generic_footnote_text(node, footnote)
101
108
  @in_footnote = false
102
- @seen_footnote << fn
109
+ @seen_footnote << footnote
103
110
  end
104
111
  end
105
112
  end
@@ -22,6 +22,12 @@ module IsoDoc::WordFunction
22
22
  end
23
23
  end
24
24
 
25
+ def svg_parse(node, out)
26
+ svg = Base64.strict_encode64(node.to_xml)
27
+ r = node.replace("<img src='data:image/svg+xml;base64,#{svg}' mimetype='image/svg+xml'/>").first
28
+ image_parse(r, out, nil)
29
+ end
30
+
25
31
  def imgsrc(node)
26
32
  ret = svg_to_emf(node) and return ret
27
33
  return node["src"] unless %r{^data:}.match node["src"]
@@ -37,17 +37,27 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
37
37
 
38
38
  def toWord(result, filename, dir, header)
39
39
  result = from_xhtml(word_cleanup(to_xhtml(result)))
40
- unless @landscapestyle.empty?
41
- @wordstylesheet&.open
42
- @wordstylesheet&.write(@landscapestyle)
43
- @wordstylesheet&.close
44
- end
40
+ @wordstylesheet = wordstylesheet_update
45
41
  Html2Doc.process(result, filename: filename, stylesheet: @wordstylesheet&.path,
46
42
  header_file: header&.path, dir: dir,
47
43
  asciimathdelims: [@openmathdelim, @closemathdelim],
48
44
  liststyles: { ul: @ulstyle, ol: @olstyle })
49
45
  header&.unlink
50
- @wordstylesheet&.unlink
46
+ @wordstylesheet&.unlink if @wordstylesheet&.is_a?(Tempfile)
47
+ end
48
+
49
+ def wordstylesheet_update()
50
+ return if @wordstylesheet.nil?
51
+ f = File.open(@wordstylesheet.path, "a")
52
+ @landscapestyle.empty? or f.write(@landscapestyle)
53
+ if @wordstylesheet_override && @wordstylesheet
54
+ f.write(@wordstylesheet_override.read)
55
+ @wordstylesheet_override.close
56
+ elsif @wordstylesheet_override && !@wordstylesheet
57
+ @wordstylesheet = @wordstylesheet_override
58
+ end
59
+ f.close
60
+ @wordstylesheet
51
61
  end
52
62
 
53
63
  def word_admonition_images(docxml)
data/lib/isodoc/xref.rb CHANGED
@@ -11,7 +11,7 @@ module IsoDoc
11
11
  include XrefGen::Blocks
12
12
  include XrefGen::Sections
13
13
 
14
- def initialize(lang, script, klass, i18n, options = {})
14
+ def initialize(lang, script, klass, i18n, options = {})
15
15
  @anchors = {}
16
16
  @lang = lang
17
17
  @script = script
@@ -28,13 +28,12 @@ module IsoDoc
28
28
 
29
29
  def anchor(id, lbl, warning = true)
30
30
  return nil if id.nil? || id.empty?
31
- unless @anchors[id]
32
- if warning
33
- @seen ||= Seen_Anchor.instance
34
- @seen.seen(id) or warn "No label has been processed for ID #{id}"
35
- @seen.add(id)
36
- return "[#{id}]"
37
- end
31
+
32
+ if warning && !@anchors[id]
33
+ @seen ||= Seen_Anchor.instance
34
+ @seen.seen(id) or warn "No label has been processed for ID #{id}"
35
+ @seen.add(id)
36
+ return "[#{id}]"
38
37
  end
39
38
  @anchors.dig(id, lbl)
40
39
  end
@@ -49,15 +48,15 @@ module IsoDoc
49
48
  note_anchor_names(docxml.xpath(ns(SECTIONS_XPATH)))
50
49
  example_anchor_names(docxml.xpath(ns(SECTIONS_XPATH)))
51
50
  list_anchor_names(docxml.xpath(ns(SECTIONS_XPATH)))
52
- bookmark_anchor_names(docxml.xpath(ns(SECTIONS_XPATH)))
51
+ bookmark_anchor_names(docxml)
53
52
  end
54
53
 
55
54
  def ns(xpath)
56
55
  Common::ns(xpath)
57
56
  end
58
57
 
59
- def l10n(a, lang = @lang, script = @script)
60
- @i18n.l10n(a, lang, script)
58
+ def l10n(text, lang = @lang, script = @script)
59
+ @i18n.l10n(text, lang, script)
61
60
  end
62
61
  end
63
62
  end
@@ -2,16 +2,17 @@ require "roman-numerals"
2
2
 
3
3
  module IsoDoc::XrefGen
4
4
  class Counter
5
- def initialize(num = 0, opts = {numerals: :arabic})
5
+ def initialize(num = 0, opts = { numerals: :arabic })
6
6
  @num = num
7
7
  @letter = ""
8
8
  @subseq = ""
9
9
  @letter_override = nil
10
10
  @number_override = nil
11
11
  @style = opts[:numerals]
12
+ @skip_i = opts[:skip_i]
12
13
  @base = ""
13
14
  if num.is_a? String
14
- if /^\d+$/.match(num)
15
+ if /^\d+$/.match?(num)
15
16
  @num = num.to_i
16
17
  else
17
18
  @num = nil
@@ -34,7 +35,7 @@ module IsoDoc::XrefGen
34
35
  @base = b
35
36
  else
36
37
  @letter_override = node["number"]
37
- @letter = @letter_override if /^[a-zA-Z]$/.match(@letter_override)
38
+ @letter = @letter_override if /^[a-zA-Z]$/.match?(@letter_override)
38
39
  end
39
40
  end
40
41
  end
@@ -64,7 +65,7 @@ module IsoDoc::XrefGen
64
65
  @letter_override = node["number"]
65
66
  /^(?<b>.*?)(?<n>\d*)(?<a>[a-zA-Z])$/ =~ node["number"]
66
67
  if blank?(a)
67
- if /^\d+$/.match(node["number"])
68
+ if /^\d+$/.match?(node["number"])
68
69
  @letter_override = @letter = ""
69
70
  @number_override = @num = node["number"].to_i
70
71
  else
@@ -80,32 +81,46 @@ module IsoDoc::XrefGen
80
81
  @number_override = @num = n.to_i unless n.empty?
81
82
  end
82
83
  else
83
- @letter = (@letter.ord + 1).chr.to_s
84
+ increment_letter
85
+ end
86
+ end
87
+
88
+ def increment_letter
89
+ case @letter
90
+ when "Z"
91
+ @letter = "@"
92
+ @base = @base.empty? ? "A" : @base[0..-2] + (@base[-1].ord + 1).chr.to_s
93
+ when "z"
94
+ @letter = "`"
95
+ @base = @base.empty? ? "a" : @base[0..-2] + (@base[-1].ord + 1).chr.to_s
84
96
  end
97
+ @letter = (@letter.ord + 1).chr.to_s
98
+ @skip_i && %w(i I).include?(@letter) and
99
+ @letter = (@letter.ord + 1).chr.to_s
85
100
  end
86
101
 
87
- def blank?(x)
88
- x.nil? || x.empty?
102
+ def blank?(str)
103
+ str.nil? || str.empty?
89
104
  end
90
105
 
91
106
  def increment(node)
92
107
  return self if node["unnumbered"]
108
+
93
109
  @letter_override = nil
94
110
  @number_override = nil
95
- if node["subsequence"] != @subseq && !(blank?(node["subsequence"]) && blank?(@subseq))
111
+ if node["subsequence"] != @subseq &&
112
+ !(blank?(node["subsequence"]) && blank?(@subseq))
96
113
  new_subseq_increment(node)
97
- elsif @letter.empty?
98
- sequence_increment(node)
99
- else
100
- subsequence_increment(node)
114
+ elsif @letter.empty? then sequence_increment(node)
115
+ else subsequence_increment(node)
101
116
  end
102
117
  self
103
118
  end
104
119
 
105
120
  def print
106
121
  num = @number_override || @num
107
- num_out = @style == :roman && !num.nil? ? RomanNumerals.to_roman(num) : num
108
- "#{@base}#{num_out}#{@letter_override || @letter}"
122
+ out = @style == :roman && !num.nil? ? RomanNumerals.to_roman(num) : num
123
+ "#{@base}#{out}#{@letter_override || @letter}"
109
124
  end
110
125
 
111
126
  def ol_type(list, depth)
@@ -115,7 +130,8 @@ module IsoDoc::XrefGen
115
130
  return :alphabet_upper if [4, 9].include? depth
116
131
  return :roman if [3, 8].include? depth
117
132
  return :roman_upper if [5, 10].include? depth
118
- return :arabic
133
+
134
+ :arabic
119
135
  end
120
136
 
121
137
  def listlabel(list, depth)