isodoc 1.6.3 → 1.6.7.1

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +2 -12
  3. data/.hound.yml +3 -1
  4. data/.rubocop.yml +4 -6
  5. data/isodoc.gemspec +3 -2
  6. data/lib/isodoc-yaml/i18n-en.yaml +1 -0
  7. data/lib/isodoc-yaml/i18n-fr.yaml +1 -0
  8. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
  9. data/lib/isodoc.rb +0 -2
  10. data/lib/isodoc/convert.rb +7 -1
  11. data/lib/isodoc/function/blocks.rb +5 -4
  12. data/lib/isodoc/function/cleanup.rb +52 -43
  13. data/lib/isodoc/function/inline.rb +7 -7
  14. data/lib/isodoc/function/references.rb +33 -52
  15. data/lib/isodoc/function/section.rb +28 -16
  16. data/lib/isodoc/function/table.rb +21 -22
  17. data/lib/isodoc/function/terms.rb +6 -7
  18. data/lib/isodoc/function/to_word_html.rb +6 -3
  19. data/lib/isodoc/function/utils.rb +181 -163
  20. data/lib/isodoc/gem_tasks.rb +8 -9
  21. data/lib/isodoc/headlesshtml_convert.rb +8 -7
  22. data/lib/isodoc/html_convert.rb +5 -1
  23. data/lib/isodoc/html_function/comments.rb +14 -12
  24. data/lib/isodoc/html_function/footnotes.rb +14 -7
  25. data/lib/isodoc/html_function/html.rb +30 -26
  26. data/lib/isodoc/html_function/postprocess.rb +191 -182
  27. data/lib/isodoc/html_function/sectionsplit.rb +230 -0
  28. data/lib/isodoc/metadata.rb +22 -20
  29. data/lib/isodoc/metadata_contributor.rb +31 -28
  30. data/lib/isodoc/pdf_convert.rb +11 -13
  31. data/lib/isodoc/presentation_function/bibdata.rb +50 -22
  32. data/lib/isodoc/presentation_function/inline.rb +20 -15
  33. data/lib/isodoc/presentation_function/section.rb +38 -1
  34. data/lib/isodoc/presentation_xml_convert.rb +2 -0
  35. data/lib/isodoc/version.rb +1 -1
  36. data/lib/isodoc/word_function/postprocess.rb +50 -36
  37. data/lib/isodoc/xref.rb +2 -0
  38. data/lib/isodoc/xref/xref_gen_seq.rb +60 -35
  39. data/lib/isodoc/xref/xref_sect_gen.rb +4 -4
  40. data/spec/assets/scripts_override.html +3 -0
  41. data/spec/isodoc/blocks_spec.rb +373 -685
  42. data/spec/isodoc/cleanup_spec.rb +40 -42
  43. data/spec/isodoc/i18n_spec.rb +694 -821
  44. data/spec/isodoc/inline_spec.rb +482 -328
  45. data/spec/isodoc/metadata_spec.rb +384 -379
  46. data/spec/isodoc/postproc_spec.rb +163 -55
  47. data/spec/isodoc/presentation_xml_spec.rb +355 -278
  48. data/spec/isodoc/ref_spec.rb +5 -5
  49. data/spec/isodoc/section_spec.rb +216 -199
  50. data/spec/isodoc/sectionsplit_spec.rb +190 -0
  51. data/spec/isodoc/table_spec.rb +41 -42
  52. data/spec/isodoc/terms_spec.rb +84 -84
  53. data/spec/isodoc/xref_spec.rb +974 -932
  54. metadata +22 -5
@@ -1,11 +1,10 @@
1
- require_relative "html_function/comments.rb"
2
- require_relative "html_function/footnotes.rb"
3
- require_relative "html_function/html.rb"
1
+ require_relative "html_function/comments"
2
+ require_relative "html_function/footnotes"
3
+ require_relative "html_function/html"
4
4
  require "metanorma"
5
5
 
6
6
  module IsoDoc
7
7
  class PdfConvert < ::IsoDoc::Convert
8
-
9
8
  include HtmlFunction::Comments
10
9
  include HtmlFunction::Footnotes
11
10
  include HtmlFunction::Html
@@ -13,6 +12,8 @@ module IsoDoc
13
12
  def initialize(options)
14
13
  @standardstylesheet = nil
15
14
  super
15
+ @format = :pdf
16
+ @suffix = "pdf"
16
17
  @scripts = @scripts_pdf if @scripts_pdf
17
18
  @maxwidth = 500
18
19
  @maxheight = 800
@@ -22,22 +23,19 @@ module IsoDoc
22
23
  "_pdfimages"
23
24
  end
24
25
 
25
- def initialize(options)
26
- @format = :pdf
27
- @suffix = "pdf"
28
- super
29
- end
30
-
31
26
  def convert(input_filename, file = nil, debug = false, output_filename = nil)
32
27
  file = File.read(input_filename, encoding: "utf-8") if file.nil?
33
28
  @openmathdelim, @closemathdelim = extract_delims(file)
34
29
  docxml, filename, dir = convert_init(file, input_filename, debug)
35
30
  result = convert1(docxml, filename, dir)
36
31
  return result if debug
37
- postprocess(result, filename + ".tmp.html", dir)
32
+
33
+ postprocess(result, "#{filename}.tmp.html", dir)
38
34
  FileUtils.rm_rf dir
39
- ::Metanorma::Output::Pdf.new.convert("#{filename}.tmp.html",
40
- output_filename || "#{filename}.#{@suffix}")
35
+ ::Metanorma::Output::Pdf.new.convert(
36
+ "#{filename}.tmp.html",
37
+ output_filename || "#{filename}.#{@suffix}",
38
+ )
41
39
  FileUtils.rm_rf ["#{filename}.tmp.html", tmpimagedir]
42
40
  end
43
41
 
@@ -1,13 +1,40 @@
1
1
  module IsoDoc
2
2
  class PresentationXMLConvert < ::IsoDoc::Convert
3
3
  def bibdata(docxml)
4
+ docid_prefixes(docxml)
4
5
  a = bibdata_current(docxml) or return
6
+ address_precompose(a)
5
7
  bibdata_i18n(a)
6
8
  a.next =
7
9
  "<localized-strings>#{i8n_name(trim_hash(@i18n.get), '').join('')}"\
8
10
  "</localized-strings>"
9
11
  end
10
12
 
13
+ def docid_prefixes(docxml)
14
+ docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
15
+ i.children = @xrefs.klass.docid_prefix(i["type"], i.text)
16
+ end
17
+ end
18
+
19
+ def address_precompose(bib)
20
+ bib.xpath(ns("//bibdata//address")).each do |b|
21
+ next if b.at(ns("./formattedAddress"))
22
+
23
+ x = address_precompose1(b)
24
+ b.children = "<formattedAddress>#{x}</formattedAddress>"
25
+ end
26
+ end
27
+
28
+ def address_precompose1(addr)
29
+ ret = []
30
+ addr.xpath(ns("./street")).each { |s| ret << s.children.to_xml }
31
+ a = addr.at(ns("./city")) and ret << a.children.to_xml
32
+ addr.xpath(ns("./state")).each { |s| ret << s.children.to_xml }
33
+ a = addr.at(ns("./country")) and ret << a.children.to_xml
34
+ a = addr.at(ns("./postcode")) and ret[-1] += " #{a.children.to_xml}"
35
+ ret.join("<br/>")
36
+ end
37
+
11
38
  def bibdata_current(docxml)
12
39
  a = docxml.at(ns("//bibdata")) or return
13
40
  a.xpath(ns("./language")).each do |l|
@@ -35,27 +62,28 @@ module IsoDoc
35
62
  x.next.children = hash[x.text]
36
63
  end
37
64
 
38
- def i18n_tag(k, v)
39
- "<localized-string key='#{k}' language='#{@lang}'>#{v}</localized-string>"
65
+ def i18n_tag(key, value)
66
+ "<localized-string key='#{key}' language='#{@lang}'>#{value}"\
67
+ "</localized-string>"
40
68
  end
41
69
 
42
- def i18n_safe(k)
43
- k.to_s.gsub(/\s|\./, "_")
70
+ def i18n_safe(key)
71
+ key.to_s.gsub(/\s|\./, "_")
44
72
  end
45
73
 
46
- def i8n_name(h, pref)
47
- if h.is_a? Hash then i8n_name1(h, pref)
48
- elsif h.is_a? Array
49
- h.reject { |a| blank?(a) }.each_with_object([])
74
+ def i8n_name(hash, pref)
75
+ if hash.is_a? Hash then i8n_name1(hash, pref)
76
+ elsif hash.is_a? Array
77
+ hash.reject { |a| blank?(a) }.each_with_object([])
50
78
  .with_index do |(v1, g), i|
51
79
  i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
52
80
  end
53
- else [i18n_tag(pref, h)]
81
+ else [i18n_tag(pref, hash)]
54
82
  end
55
83
  end
56
84
 
57
- def i8n_name1(h, pref)
58
- h.reject { |k, v| blank?(v) }.each_with_object([]) do |(k, v), g|
85
+ def i8n_name1(hash, pref)
86
+ hash.reject { |_k, v| blank?(v) }.each_with_object([]) do |(k, v), g|
59
87
  if v.is_a? Hash then i8n_name(v, i18n_safe(k)).each { |x| g << x }
60
88
  elsif v.is_a? Array
61
89
  v.reject { |a| blank?(a) }.each_with_index do |v1, i|
@@ -68,28 +96,28 @@ module IsoDoc
68
96
  end
69
97
 
70
98
  # https://stackoverflow.com/a/31822406
71
- def blank?(v)
72
- v.nil? || v.respond_to?(:empty?) && v.empty?
99
+ def blank?(elem)
100
+ elem.nil? || elem.respond_to?(:empty?) && elem.empty?
73
101
  end
74
102
 
75
- def trim_hash(h)
103
+ def trim_hash(hash)
76
104
  loop do
77
- h_new = trim_hash1(h)
78
- break h if h==h_new
105
+ h_new = trim_hash1(hash)
106
+ break hash if hash == h_new
79
107
 
80
- h = h_new
108
+ hash = h_new
81
109
  end
82
110
  end
83
111
 
84
- def trim_hash1(h)
85
- return h unless h.is_a? Hash
112
+ def trim_hash1(hash)
113
+ return hash unless hash.is_a? Hash
86
114
 
87
- h.each_with_object({}) do |(k, v), g|
115
+ hash.each_with_object({}) do |(k, v), g|
88
116
  next if blank?(v)
89
117
 
90
- g[k] = if v.is_a? Hash then trim_hash1(h[k])
118
+ g[k] = if v.is_a? Hash then trim_hash1(hash[k])
91
119
  elsif v.is_a? Array
92
- h[k].map { |a| trim_hash1(a) }.reject { |a| blank?(a) }
120
+ hash[k].map { |a| trim_hash1(a) }.reject { |a| blank?(a) }
93
121
  else
94
122
  v
95
123
  end
@@ -9,8 +9,8 @@ module IsoDoc
9
9
  return @xrefs.anchor(node["bibitemid"], :xref) || "???"
10
10
  elsif node["target"] && node["droploc"]
11
11
  return @xrefs.anchor(node["target"], :value) ||
12
- @xrefs.anchor(node["target"], :label) ||
13
- @xrefs.anchor(node["target"], :xref) || "???"
12
+ @xrefs.anchor(node["target"], :label) ||
13
+ @xrefs.anchor(node["target"], :xref) || "???"
14
14
  elsif node["target"] && !/.#./.match(node["target"])
15
15
  linkend = anchor_linkend1(node)
16
16
  end
@@ -33,6 +33,10 @@ module IsoDoc
33
33
  return linkend&.downcase if node["case"] == "lowercase"
34
34
  return linkend if linkend[0, 1].match?(/\p{Upper}/)
35
35
 
36
+ capitalise_xref1(node, linkend)
37
+ end
38
+
39
+ def capitalise_xref1(node, linkend)
36
40
  prec = nearest_block_parent(node).xpath("./descendant-or-self::text()") &
37
41
  node.xpath("./preceding::text()")
38
42
  if prec.empty? || /(?!<[^.].)\.\s+$/.match(prec.map(&:text).join)
@@ -43,8 +47,8 @@ module IsoDoc
43
47
 
44
48
  def nearest_block_parent(node)
45
49
  until %w(p title td th name formula li dt dd sourcecode pre)
46
- .include?(node.name)
47
- node = node.parent
50
+ .include?(node.name)
51
+ node = node.parent
48
52
  end
49
53
  node
50
54
  end
@@ -90,7 +94,7 @@ module IsoDoc
90
94
  ret
91
95
  end
92
96
 
93
- def eref_localities0(ref, _i, target, delim, node)
97
+ def eref_localities0(ref, _idx, target, delim, node)
94
98
  if ref["type"] == "whole" then l10n("#{delim} #{@i18n.wholeoftext}")
95
99
  else
96
100
  eref_localities1(target, ref["type"], ref.at(ns("./referenceFrom")),
@@ -99,24 +103,24 @@ module IsoDoc
99
103
  end
100
104
 
101
105
  # TODO: move to localization file
102
- def eref_localities1_zh(_target, type, from, to, node, delim)
106
+ def eref_localities1_zh(_target, type, from, upto, node, delim)
103
107
  ret = "#{delim} 第#{from.text}" if from
104
- ret += "&ndash;#{to.text}" if to
108
+ ret += "&ndash;#{upto.text}" if upto
105
109
  loc = (@i18n.locality[type] || type.sub(/^locality:/, "").capitalize)
106
110
  ret += " #{loc}" unless node["droploc"] == "true"
107
111
  ret
108
112
  end
109
113
 
110
114
  # TODO: move to localization file
111
- def eref_localities1(target, type, from, to, delim, node, lang = "en")
115
+ def eref_localities1(target, type, from, upto, delim, node, lang = "en")
112
116
  return "" if type == "anchor"
113
117
 
114
118
  lang == "zh" and
115
- return l10n(eref_localities1_zh(target, type, from, to, node, delim))
119
+ return l10n(eref_localities1_zh(target, type, from, upto, node, delim))
116
120
  ret = delim
117
121
  ret += eref_locality_populate(type, node)
118
122
  ret += " #{from.text}" if from
119
- ret += "&ndash;#{to.text}" if to
123
+ ret += "&ndash;#{upto.text}" if upto
120
124
  l10n(ret)
121
125
  end
122
126
 
@@ -161,11 +165,12 @@ module IsoDoc
161
165
  content = node.first_element_child.children.reject do |c|
162
166
  %w{locality localityStack}.include? c.name
163
167
  end.select { |c| !c.text? || /\S/.match(c) }
164
- if node.replace content.empty?
165
- @i18n.term_defined_in.sub(/%/, node.first_element_child.to_xml)
166
- else
167
- "<em>#{node.children.to_xml}</em>"
168
- end
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)
169
174
  end
170
175
 
171
176
  def variant(docxml)
@@ -44,10 +44,47 @@ module IsoDoc
44
44
  prefix_name(elem, "", "#{lbl}#{clausedelim}", "name")
45
45
  end
46
46
 
47
- def references(docxml); end
47
+ def references(docxml)
48
+ end
49
+
50
+ def docid_prefixes(docxml)
51
+ docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
52
+ i.children = @xrefs.klass.docid_prefix(i["type"], i.text)
53
+ end
54
+ end
48
55
 
49
56
  def index(docxml)
50
57
  docxml.xpath(ns("//index | //index-xref | //indexsect")).each(&:remove)
51
58
  end
59
+
60
+ def display_order_at(docxml, xpath, idx)
61
+ return idx unless c = docxml.at(ns(xpath))
62
+
63
+ idx += 1
64
+ c["displayorder"] = idx
65
+ idx
66
+ end
67
+
68
+ def display_order_xpath(docxml, xpath, idx)
69
+ docxml.xpath(ns(xpath)).each do |c|
70
+ idx += 1
71
+ c["displayorder"] = idx
72
+ end
73
+ idx
74
+ end
75
+
76
+ def display_order(docxml)
77
+ i = 0
78
+ i = display_order_xpath(docxml, "//preface/*", i)
79
+ i = display_order_at(docxml, "//clause[@type = 'scope']", i)
80
+ i = display_order_at(docxml, @xrefs.klass.norm_ref_xpath, i)
81
+ i = display_order_at(docxml, "//sections/terms | "\
82
+ "//sections/clause[descendant::terms]", i)
83
+ i = display_order_at(docxml, "//sections/definitions", i)
84
+ i = display_order_xpath(docxml, @xrefs.klass.middle_clause(docxml), i)
85
+ i = display_order_xpath(docxml, "//annex", i)
86
+ i = display_order_xpath(docxml, @xrefs.klass.bibliography_xpath, i)
87
+ display_order_xpath(docxml, "//indexsect", i)
88
+ end
52
89
  end
53
90
  end
@@ -22,12 +22,14 @@ module IsoDoc
22
22
 
23
23
  def conversions(docxml)
24
24
  bibdata docxml
25
+ @xrefs.parse docxml
25
26
  section docxml
26
27
  block docxml
27
28
  inline docxml
28
29
  end
29
30
 
30
31
  def section(docxml)
32
+ display_order docxml
31
33
  clause docxml
32
34
  annex docxml
33
35
  term docxml
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "1.6.3".freeze
2
+ VERSION = "1.6.7.1".freeze
3
3
  end
@@ -1,17 +1,17 @@
1
1
  require "fileutils"
2
- require_relative "./postprocess_cover.rb"
2
+ require_relative "./postprocess_cover"
3
3
 
4
4
  module IsoDoc::WordFunction
5
5
  module Postprocess
6
6
  # add namespaces for Word fragments
7
7
  WORD_NOKOHEAD = <<~HERE.freeze
8
- <!DOCTYPE html SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
9
- <html xmlns="http://www.w3.org/1999/xhtml"
10
- xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"
11
- xmlns:w="urn:schemas-microsoft-com:office:word"
12
- xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
13
- <head> <title></title> <meta charset="UTF-8" /> </head>
14
- <body> </body> </html>
8
+ <!DOCTYPE html SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
9
+ <html xmlns="http://www.w3.org/1999/xhtml"
10
+ xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"
11
+ xmlns:w="urn:schemas-microsoft-com:office:word"
12
+ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
13
+ <head> <title></title> <meta charset="UTF-8" /> </head>
14
+ <body> </body> </html>
15
15
  HERE
16
16
 
17
17
  def to_word_xhtml_fragment(xml)
@@ -22,7 +22,8 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
22
22
  def table_note_cleanup(docxml)
23
23
  super
24
24
  # preempt html2doc putting MsoNormal there
25
- docxml.xpath("//p[not(self::*[@class])][ancestor::*[@class = 'Note']]").each do |p|
25
+ docxml.xpath("//p[not(self::*[@class])][ancestor::*[@class = 'Note']]")
26
+ .each do |p|
26
27
  p["class"] = "Note"
27
28
  end
28
29
  end
@@ -38,16 +39,21 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
38
39
  def toWord(result, filename, dir, header)
39
40
  result = from_xhtml(word_cleanup(to_xhtml(result)))
40
41
  @wordstylesheet = wordstylesheet_update
41
- Html2Doc.process(result, filename: filename, stylesheet: @wordstylesheet&.path,
42
- header_file: header&.path, dir: dir,
43
- asciimathdelims: [@openmathdelim, @closemathdelim],
44
- liststyles: { ul: @ulstyle, ol: @olstyle })
42
+ Html2Doc.process(
43
+ result,
44
+ filename: filename,
45
+ stylesheet: @wordstylesheet&.path,
46
+ header_file: header&.path, dir: dir,
47
+ asciimathdelims: [@openmathdelim, @closemathdelim],
48
+ liststyles: { ul: @ulstyle, ol: @olstyle }
49
+ )
45
50
  header&.unlink
46
- @wordstylesheet&.unlink if @wordstylesheet&.is_a?(Tempfile)
51
+ @wordstylesheet.unlink if @wordstylesheet.is_a?(Tempfile)
47
52
  end
48
53
 
49
- def wordstylesheet_update()
54
+ def wordstylesheet_update
50
55
  return if @wordstylesheet.nil?
56
+
51
57
  f = File.open(@wordstylesheet.path, "a")
52
58
  @landscapestyle.empty? or f.write(@landscapestyle)
53
59
  if @wordstylesheet_override && @wordstylesheet
@@ -62,7 +68,8 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
62
68
 
63
69
  def word_admonition_images(docxml)
64
70
  docxml.xpath("//div[@class = 'Admonition']//img").each do |i|
65
- i["width"], i["height"] = Html2Doc.image_resize(i, image_localfile(i), @maxheight, 300)
71
+ i["width"], i["height"] =
72
+ Html2Doc.image_resize(i, image_localfile(i), @maxheight, 300)
66
73
  end
67
74
  end
68
75
 
@@ -88,21 +95,23 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
88
95
  cells2d = {}
89
96
  docxml.xpath("//table[colgroup]").each do |t|
90
97
  w = colgroup_widths(t)
91
- t.xpath(".//tr").each_with_index { |tr, r| cells2d[r] = {} }
98
+ t.xpath(".//tr").each_with_index { |_tr, r| cells2d[r] = {} }
92
99
  t.xpath(".//tr").each_with_index do |tr, r|
93
- tr.xpath("./td | ./th").each_with_index do |td, i|
100
+ tr.xpath("./td | ./th").each_with_index do |td, _i|
94
101
  x = 0
95
102
  rs = td&.attr("rowspan")&.to_i || 1
96
103
  cs = td&.attr("colspan")&.to_i || 1
97
- while cells2d[r][x] do
98
- x += 1
104
+ while cells2d[r][x]
105
+ x += 1
99
106
  end
100
- for y2 in r..(r + rs - 1)
101
- for x2 in x..(x + cs - 1)
107
+ (r..(r + rs - 1)).each do |y2|
108
+ (x..(x + cs - 1)).each do |x2|
102
109
  cells2d[y2][x2] = 1
103
110
  end
104
111
  end
105
- width = (x..(x+cs-1)).each_with_object({width: 0}) { |z, m| m[:width] += w[z] }
112
+ width = (x..(x + cs - 1)).each_with_object({ width: 0 }) do |z, m|
113
+ m[:width] += w[z]
114
+ end
106
115
  td["width"] = "#{width[:width]}%"
107
116
  x += cs
108
117
  end
@@ -111,8 +120,8 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
111
120
  end
112
121
 
113
122
  # assume percentages
114
- def colgroup_widths(t)
115
- t.xpath("./colgroup/col").each_with_object([]) do |c, m|
123
+ def colgroup_widths(table)
124
+ table.xpath("./colgroup/col").each_with_object([]) do |c, m|
116
125
  m << c["width"].sub(/%$/, "").to_f
117
126
  end
118
127
  end
@@ -127,12 +136,13 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
127
136
 
128
137
  def style_update(node, css)
129
138
  return unless node
130
- node["style"] = node["style"] ? node["style"].sub(/;?$/, ";#{css}") : css
139
+
140
+ node["style"] = node["style"] ? node["style"].sub(/;?$/, ";#{css}") : css
131
141
  end
132
142
 
133
143
  def word_image_caption(docxml)
134
- docxml.xpath("//p[@class = 'FigureTitle' or @class = 'SourceTitle']").
135
- each do |t|
144
+ docxml.xpath("//p[@class = 'FigureTitle' or @class = 'SourceTitle']")
145
+ .each do |t|
136
146
  if t&.previous_element&.name == "img"
137
147
  img = t.previous_element
138
148
  t.previous_element.swap("<p class=\'figure\'>#{img.to_xml}</p>")
@@ -150,7 +160,8 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
150
160
  xpath.each do |list|
151
161
  (list.xpath(".//li") - list.xpath(".//ol//li | .//ul//li")).each do |l|
152
162
  l.xpath("./p | ./div | ./table").each_with_index do |p, i|
153
- next if i == 0
163
+ next if i.zero?
164
+
154
165
  p.wrap(%{<div class="ListContLevel#{lvl}"/>})
155
166
  end
156
167
  list_add(l.xpath(".//ul") - l.xpath(".//ul//ul | .//ol//ul"), lvl + 1)
@@ -162,20 +173,21 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
162
173
  def word_table_align(docxml)
163
174
  docxml.xpath("//td[@align]/p | //th[@align]/p").each do |p|
164
175
  next if p["align"]
165
- style_update(p, "text-align: #{p.parent["align"]}")
176
+
177
+ style_update(p, "text-align: #{p.parent['align']}")
166
178
  end
167
179
  end
168
180
 
169
181
  def word_table_separator(docxml)
170
182
  docxml.xpath("//p[@class = 'TableTitle']").each do |t|
171
183
  next unless t.children.empty?
184
+
172
185
  t["style"] = t["style"].sub(/;?$/, ";font-size:0pt;")
173
186
  t.children = "&nbsp;"
174
187
  end
175
188
  end
176
189
 
177
- def word_annex_cleanup(docxml)
178
- end
190
+ def word_annex_cleanup(docxml); end
179
191
 
180
192
  def word_example_cleanup(docxml)
181
193
  docxml.xpath("//div[@class = 'example']//p[not(@class)]").each do |p|
@@ -194,19 +206,21 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
194
206
  docxml.xpath("//div[p/br]").each do |d|
195
207
  /^WordSection\d+_\d+$/.match(d["class"]) or next
196
208
  d.elements[0].name == "p" && !d.elements[0].elements.empty? or next
197
- d.elements[0].elements[0].name == "br" && d.elements[0].elements[0]["style"] ==
198
- "mso-special-character:line-break;page-break-before:always" or next
209
+ d.elements[0].elements[0].name == "br" &&
210
+ d.elements[0].elements[0]["style"] ==
211
+ "mso-special-character:line-break;page-break-before:always" or next
199
212
  d.elements[0].remove
200
213
  end
201
214
  end
202
215
 
203
216
  def word_footnote_format(docxml)
204
- # the content is in a[@epub:type = 'footnote']//sup, but in Word,
217
+ # the content is in a[@epub:type = 'footnote']//sup, but in Word,
205
218
  # we need to inject content around the autonumbered footnote reference
206
219
  docxml.xpath("//a[@epub:type = 'footnote']").each do |x|
207
220
  footnote_reference_format(x)
208
221
  end
209
- docxml.xpath("//a[@class = 'TableFootnoteRef'] | //span[@class = 'TableFootnoteRef']").each do |x|
222
+ docxml.xpath("//a[@class = 'TableFootnoteRef'] | "\
223
+ "//span[@class = 'TableFootnoteRef']").each do |x|
210
224
  table_footnote_reference_format(x)
211
225
  end
212
226
  docxml