isodoc 1.2.6 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +69 -0
  3. data/README.adoc +1 -3
  4. data/isodoc.gemspec +2 -1
  5. data/lib/isodoc-yaml/i18n-en.yaml +56 -0
  6. data/lib/isodoc-yaml/i18n-fr.yaml +64 -7
  7. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
  8. data/lib/isodoc/base_style/all.css +4 -0
  9. data/lib/isodoc/base_style/blocks.scss +2 -2
  10. data/lib/isodoc/base_style/reset.css +4 -0
  11. data/lib/isodoc/base_style/reset.scss +5 -0
  12. data/lib/isodoc/base_style/typography.scss +1 -1
  13. data/lib/isodoc/convert.rb +13 -98
  14. data/lib/isodoc/css.rb +95 -0
  15. data/lib/isodoc/function/inline.rb +0 -33
  16. data/lib/isodoc/function/inline_simple.rb +4 -1
  17. data/lib/isodoc/function/lists.rb +2 -1
  18. data/lib/isodoc/function/references.rb +8 -13
  19. data/lib/isodoc/function/section.rb +1 -1
  20. data/lib/isodoc/function/table.rb +10 -0
  21. data/lib/isodoc/function/to_word_html.rb +2 -2
  22. data/lib/isodoc/gem_tasks.rb +4 -0
  23. data/lib/isodoc/html_function/html.rb +1 -0
  24. data/lib/isodoc/html_function/mathvariant_to_plain.rb +82 -0
  25. data/lib/isodoc/html_function/postprocess.rb +41 -20
  26. data/lib/isodoc/i18n.rb +15 -2
  27. data/lib/isodoc/metadata.rb +28 -109
  28. data/lib/isodoc/metadata_contributor.rb +91 -0
  29. data/lib/isodoc/metadata_date.rb +6 -0
  30. data/lib/isodoc/presentation_function/bibdata.rb +79 -7
  31. data/lib/isodoc/presentation_function/block.rb +14 -9
  32. data/lib/isodoc/presentation_function/inline.rb +126 -22
  33. data/lib/isodoc/presentation_function/section.rb +9 -0
  34. data/lib/isodoc/presentation_xml_convert.rb +5 -0
  35. data/lib/isodoc/version.rb +1 -1
  36. data/lib/isodoc/word_convert.rb +0 -20
  37. data/lib/isodoc/word_function/body.rb +12 -0
  38. data/lib/isodoc/word_function/postprocess.rb +38 -80
  39. data/lib/isodoc/word_function/postprocess_cover.rb +55 -0
  40. data/lib/isodoc/word_function/table.rb +10 -0
  41. data/lib/isodoc/xref.rb +1 -0
  42. data/lib/isodoc/xref/xref_counter.rb +20 -9
  43. data/lib/isodoc/xref/xref_gen.rb +20 -2
  44. data/lib/isodoc/xref/xref_sect_gen.rb +1 -1
  45. data/spec/assets/html.scss +14 -0
  46. data/spec/assets/i18n.yaml +17 -9
  47. data/spec/isodoc/blocks_spec.rb +89 -241
  48. data/spec/isodoc/cleanup_spec.rb +0 -1
  49. data/spec/isodoc/footnotes_spec.rb +4 -5
  50. data/spec/isodoc/i18n_spec.rb +73 -38
  51. data/spec/isodoc/inline_spec.rb +177 -199
  52. data/spec/isodoc/lists_spec.rb +1 -1
  53. data/spec/isodoc/metadata_spec.rb +50 -7
  54. data/spec/isodoc/postproc_spec.rb +472 -11
  55. data/spec/isodoc/presentation_xml_spec.rb +584 -1
  56. data/spec/isodoc/ref_spec.rb +327 -12
  57. data/spec/isodoc/table_spec.rb +28 -0
  58. data/spec/isodoc/xref_spec.rb +162 -17
  59. data/spec/spec_helper.rb +2 -0
  60. metadata +22 -7
  61. data/.github/workflows/macos.yml +0 -42
  62. data/.github/workflows/ubuntu.yml +0 -62
  63. data/.github/workflows/windows.yml +0 -44
@@ -1,3 +1,5 @@
1
+ require "twitter_cldr"
2
+
1
3
  module IsoDoc
2
4
  class PresentationXMLConvert < ::IsoDoc::Convert
3
5
  def prefix_container(container, linkend, _target)
@@ -8,8 +10,8 @@ module IsoDoc
8
10
  if node["citeas"].nil? && node["bibitemid"]
9
11
  return @xrefs.anchor(node["bibitemid"] ,:xref) || "???"
10
12
  elsif node["target"] && node["droploc"]
11
- return @xrefs.anchor(node["target"], :value) ||
12
- @xrefs.anchor(node["target"], :label) ||
13
+ return @xrefs.anchor(node["target"], :value) ||
14
+ @xrefs.anchor(node["target"], :label) ||
13
15
  @xrefs.anchor(node["target"], :xref) || "???"
14
16
  elsif node["target"] && !/.#./.match(node["target"])
15
17
  linkend = anchor_linkend1(node)
@@ -38,7 +40,7 @@ module IsoDoc
38
40
  end
39
41
 
40
42
  def nearest_block_parent(node)
41
- until %w(p title td th name formula
43
+ until %w(p title td th name formula
42
44
  li dt dd sourcecode pre).include?(node.name)
43
45
  node = node.parent
44
46
  end
@@ -51,13 +53,13 @@ module IsoDoc
51
53
  end
52
54
  end
53
55
 
54
- def get_linkend(node)
55
- contents = non_locality_elems(node).select { |c| !c.text? || /\S/.match(c) }
56
+ def get_linkend(n)
57
+ contents = non_locality_elems(n).select { |c| !c.text? || /\S/.match(c) }
56
58
  return unless contents.empty?
57
- link = anchor_linkend(node, docid_l10n(node["target"] || node["citeas"]))
58
- link += eref_localities(node.xpath(ns("./locality | ./localityStack")), link)
59
- non_locality_elems(node).each { |n| n.remove }
60
- node.add_child(link)
59
+ link = anchor_linkend(n, docid_l10n(n["target"] || n["citeas"]))
60
+ link += eref_localities(n.xpath(ns("./locality | ./localityStack")), link)
61
+ non_locality_elems(n).each { |n| n.remove }
62
+ n.add_child(link)
61
63
  end
62
64
  # so not <origin bibitemid="ISO7301" citeas="ISO 7301">
63
65
  # <locality type="section"><reference>3.1</reference></locality></origin>
@@ -104,7 +106,8 @@ module IsoDoc
104
106
  # TODO: move to localization file
105
107
  def eref_localities1(target, type, from, to, delim, lang = "en")
106
108
  return "" if type == "anchor"
107
- return l10n(eref_localities1_zh(target, type, from, to, delim)) if lang == "zh"
109
+ lang == "zh" and
110
+ return l10n(eref_localities1_zh(target, type, from, to, delim))
108
111
  ret = delim
109
112
  loc = @i18n.locality[type] || type.sub(/^locality:/, "").capitalize
110
113
  ret += " #{loc}"
@@ -114,31 +117,132 @@ module IsoDoc
114
117
  end
115
118
 
116
119
  def xref(docxml)
117
- docxml.xpath(ns("//xref")).each do |f|
118
- xref1(f)
119
- end
120
+ docxml.xpath(ns("//xref")).each { |f| xref1(f) }
120
121
  end
121
122
 
122
123
  def eref(docxml)
123
- docxml.xpath(ns("//eref")).each do |f|
124
- xref1(f)
125
- end
124
+ docxml.xpath(ns("//eref")).each { |f| xref1(f) }
126
125
  end
127
126
 
128
127
  def origin(docxml)
129
- docxml.xpath(ns("//origin[not(termref)]")).each do |f|
130
- xref1(f)
131
- end
128
+ docxml.xpath(ns("//origin[not(termref)]")).each { |f| xref1(f) }
132
129
  end
133
130
 
134
131
  def quotesource(docxml)
135
- docxml.xpath(ns("//quote/source")).each do |f|
136
- xref1(f)
137
- end
132
+ docxml.xpath(ns("//quote/source")).each { |f| xref1(f) }
138
133
  end
139
134
 
140
135
  def xref1(f)
141
136
  get_linkend(f)
142
137
  end
138
+
139
+ def concept(docxml)
140
+ docxml.xpath(ns("//concept")).each { |f| concept1(f) }
141
+ end
142
+
143
+ def concept1(node)
144
+ content = node.first_element_child.children.select do |c|
145
+ !%w{locality localityStack}.include? c.name
146
+ end.select { |c| !c.text? || /\S/.match(c) }
147
+ node.replace content.empty? ?
148
+ @i18n.term_defined_in.sub(/%/, node.first_element_child.to_xml) :
149
+ "<em>#{node.children.to_xml}</em>"
150
+ end
151
+
152
+
153
+ MATHML = { "m" => "http://www.w3.org/1998/Math/MathML" }.freeze
154
+
155
+ def mathml(docxml)
156
+ locale = twitter_cldr_localiser()
157
+ docxml.xpath("//m:math", MATHML).each do |f|
158
+ mathml1(f, locale)
159
+ end
160
+ end
161
+
162
+ # symbols is merged into
163
+ # TwitterCldr::DataReaders::NumberDataReader.new(locale).symbols
164
+ def localize_maths(f, locale)
165
+ f.xpath(".//m:mn", MATHML).each do |x|
166
+ num = /\./.match(x.text) ? x.text.to_f : x.text.to_i
167
+ precision = /\./.match(x.text) ? x.text.sub(/^.*\./, "").size : 0
168
+ x.children = localized_number(num, locale, precision)
169
+ end
170
+ end
171
+
172
+ # By itself twiiter cldr does not support fraction part digits grouping
173
+ # and custom delimeter, will decorate fraction part manually
174
+ def localized_number(num, locale, precision)
175
+ localized = precision == 0 ? num.localize(locale).to_s :
176
+ num.localize(locale).to_decimal.to_s(:precision => precision)
177
+ twitter_cldr_reader_symbols = twitter_cldr_reader(locale)
178
+ return localized unless twitter_cldr_reader_symbols[:decimal]
179
+ integer, fraction = localized.split(twitter_cldr_reader_symbols[:decimal])
180
+ return localized if fraction.nil? || fraction.length.zero?
181
+ [integer, decorate_fraction_part(fraction, locale)].
182
+ join(twitter_cldr_reader_symbols[:decimal])
183
+ end
184
+
185
+ def decorate_fraction_part(fract, locale)
186
+ result = []
187
+ twitter_cldr_reader_symbols = twitter_cldr_reader(locale)
188
+ fract = fract.slice(0..(twitter_cldr_reader_symbols[:precision] || -1))
189
+ fr_group_digits = twitter_cldr_reader_symbols[:fraction_group_digits] || 1
190
+ until fract.empty?
191
+ result.push(fract.slice!(0, fr_group_digits))
192
+ end
193
+ result.join(twitter_cldr_reader_symbols[:fraction_group].to_s)
194
+ end
195
+
196
+ def twitter_cldr_localiser_symbols
197
+ {}
198
+ end
199
+
200
+ def twitter_cldr_reader(locale)
201
+ num = TwitterCldr::DataReaders::NumberDataReader.new(locale)
202
+ num.symbols.merge!(twitter_cldr_localiser_symbols)
203
+ end
204
+
205
+ def twitter_cldr_localiser()
206
+ locale = TwitterCldr.supported_locale?(@lang.to_sym) ? @lang.to_sym : :en
207
+ twitter_cldr_reader(locale)
208
+ locale
209
+ end
210
+
211
+ def mathml1(f, locale)
212
+ localize_maths(f, locale)
213
+ return unless f.elements.size == 1 && f.elements.first.name == "mn"
214
+ f.replace(f.at("./m:mn", MATHML).children)
215
+ end
216
+
217
+ def variant(docxml)
218
+ docxml.xpath(ns("//variant")).each { |f| variant1(f) }
219
+ docxml.xpath(ns("//variant[@remove = 'true']")).each { |f| f.remove }
220
+ docxml.xpath(ns("//variant")).each do |v|
221
+ next unless v&.next&.name == "variant"
222
+ v.next = "/"
223
+ end
224
+ docxml.xpath(ns("//variant")).each { |f| f.replace(f.children) }
225
+ end
226
+
227
+ def variant1(node)
228
+ if (!node["lang"] || node["lang"] == @lang) &&
229
+ (!node["script"] || node["script"] == @script)
230
+ elsif found_matching_variant_sibling(node)
231
+ node["remove"] = "true"
232
+ else
233
+ #return unless !node.at("./preceding-sibling::xmlns:variant")
234
+ end
235
+ end
236
+
237
+ def found_matching_variant_sibling(node)
238
+ prev = node.xpath("./preceding-sibling::xmlns:variant")
239
+ foll = node.xpath("./following-sibling::xmlns:variant")
240
+ found = false
241
+ (prev + foll).each do |n|
242
+ found = true if n["lang"] == @lang &&
243
+ (!n["script"] || n["script"] == @script)
244
+ end
245
+ found
246
+ end
143
247
  end
144
248
  end
@@ -42,5 +42,14 @@ module IsoDoc
42
42
  lbl = @xrefs.get[f["id"]][:label] or return
43
43
  prefix_name(f, "", "#{lbl}#{clausedelim}", "name")
44
44
  end
45
+
46
+ def references(docxml)
47
+ end
48
+
49
+ def index(docxml)
50
+ docxml.xpath(ns("//index | //index-xref")).each do |f|
51
+ f.remove
52
+ end
53
+ end
45
54
  end
46
55
  end
@@ -30,6 +30,8 @@ module IsoDoc
30
30
  clause docxml
31
31
  annex docxml
32
32
  term docxml
33
+ references docxml
34
+ index docxml
33
35
  end
34
36
 
35
37
  def block(docxml)
@@ -51,7 +53,10 @@ module IsoDoc
51
53
  xref docxml
52
54
  eref docxml
53
55
  origin docxml
56
+ concept docxml
54
57
  quotesource docxml
58
+ mathml docxml
59
+ variant docxml
55
60
  end
56
61
 
57
62
  def postprocess(result, filename, dir)
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "1.2.6".freeze
2
+ VERSION = "1.4.0".freeze
3
3
  end
@@ -4,26 +4,6 @@ require_relative "word_function/body.rb"
4
4
  require_relative "word_function/postprocess.rb"
5
5
 
6
6
  module IsoDoc
7
-
8
- =begin
9
- module WordConvertModule
10
- # http://tech.tulentsev.com/2012/02/ruby-how-to-override-class-method-with-a-module/
11
- # https://www.ruby-forum.com/topic/148303
12
- #
13
- # The following is ugly indeed, but the only way I can split module override methods
14
- # across files
15
- def self.included base
16
- base.class_eval do
17
-
18
- eval File.open(File.join(File.dirname(__FILE__),"wordconvertmodule.rb")).read
19
- eval File.open(File.join(File.dirname(__FILE__),"comments.rb")).read
20
- eval File.open(File.join(File.dirname(__FILE__),"footnotes.rb")).read
21
- eval File.open(File.join(File.dirname(__FILE__),"postprocess.rb")).read
22
- end
23
- end
24
- end
25
- =end
26
-
27
7
  class WordConvert < ::IsoDoc::Convert
28
8
  include WordFunction::Comments
29
9
  include WordFunction::Footnotes
@@ -196,6 +196,18 @@ module IsoDoc::WordFunction
196
196
  out.parent.at("./table")["class"] = "formula_dl"
197
197
  end
198
198
 
199
+ def formula_parse1(node, out)
200
+ out.div **attr_code(class: "formula") do |div|
201
+ div.p do |p|
202
+ parse(node.at(ns("./stem")), div)
203
+ insert_tab(div, 1)
204
+ if lbl = node&.at(ns("./name"))&.text
205
+ div << "(#{lbl})"
206
+ end
207
+ end
208
+ end
209
+ end
210
+
199
211
  def li_parse(node, out)
200
212
  out.li **attr_code(id: node["id"]) do |li|
201
213
  if node["uncheckedcheckbox"] == "true"
@@ -5,11 +5,9 @@ module IsoDoc::WordFunction
5
5
  module Postprocess
6
6
  # add namespaces for Word fragments
7
7
  WORD_NOKOHEAD = <<~HERE.freeze
8
- <!DOCTYPE html SYSTEM
9
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
8
+ <!DOCTYPE html SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
10
9
  <html xmlns="http://www.w3.org/1999/xhtml"
11
- xmlns:v="urn:schemas-microsoft-com:vml"
12
- xmlns:o="urn:schemas-microsoft-com:office:office"
10
+ xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"
13
11
  xmlns:w="urn:schemas-microsoft-com:office:word"
14
12
  xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
15
13
  <head> <title></title> <meta charset="UTF-8" /> </head>
@@ -18,15 +16,13 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
18
16
 
19
17
  def to_word_xhtml_fragment(xml)
20
18
  doc = ::Nokogiri::XML.parse(WORD_NOKOHEAD)
21
- fragment = ::Nokogiri::XML::DocumentFragment.new(doc, xml, doc.root)
22
- fragment
19
+ ::Nokogiri::XML::DocumentFragment.new(doc, xml, doc.root)
23
20
  end
24
21
 
25
22
  def table_note_cleanup(docxml)
26
23
  super
27
24
  # preempt html2doc putting MsoNormal there
28
- docxml.xpath("//p[not(self::*[@class])]"\
29
- "[ancestor::*[@class = 'Note']]").each do |p|
25
+ docxml.xpath("//p[not(self::*[@class])][ancestor::*[@class = 'Note']]").each do |p|
30
26
  p["class"] = "Note"
31
27
  end
32
28
  end
@@ -56,8 +52,7 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
56
52
 
57
53
  def word_admonition_images(docxml)
58
54
  docxml.xpath("//div[@class = 'Admonition']//img").each do |i|
59
- i["width"], i["height"] =
60
- Html2Doc.image_resize(i, image_localfile(i), @maxheight, 300)
55
+ i["width"], i["height"] = Html2Doc.image_resize(i, image_localfile(i), @maxheight, 300)
61
56
  end
62
57
  end
63
58
 
@@ -65,6 +60,7 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
65
60
  word_annex_cleanup(docxml)
66
61
  word_preface(docxml)
67
62
  word_nested_tables(docxml)
63
+ word_colgroup(docxml)
68
64
  word_table_align(docxml)
69
65
  word_table_separator(docxml)
70
66
  word_admonition_images(docxml)
@@ -78,28 +74,44 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
78
74
  docxml
79
75
  end
80
76
 
81
- def word_nested_tables(docxml)
82
- docxml.xpath("//table").each do |t|
83
- t.xpath(".//table").reverse.each do |tt|
84
- t.next = tt.remove
77
+ def word_colgroup(docxml)
78
+ cells2d = {}
79
+ docxml.xpath("//table[colgroup]").each do |t|
80
+ w = colgroup_widths(t)
81
+ t.xpath(".//tr").each_with_index { |tr, r| cells2d[r] = {} }
82
+ t.xpath(".//tr").each_with_index do |tr, r|
83
+ tr.xpath("./td | ./th").each_with_index do |td, i|
84
+ x = 0
85
+ rs = td&.attr("rowspan")&.to_i || 1
86
+ cs = td&.attr("colspan")&.to_i || 1
87
+ while cells2d[r][x] do
88
+ x += 1
89
+ end
90
+ for y2 in r..(r + rs - 1)
91
+ for x2 in x..(x + cs - 1)
92
+ cells2d[y2][x2] = 1
93
+ end
94
+ end
95
+ width = (x..(x+cs-1)).each_with_object({width: 0}) { |z, m| m[:width] += w[z] }
96
+ td["width"] = "#{width[:width]}%"
97
+ x += cs
98
+ end
85
99
  end
86
100
  end
87
101
  end
88
102
 
89
- def authority_cleanup1(docxml, klass)
90
- dest = docxml.at("//div[@id = 'boilerplate-#{klass}-destination']")
91
- auth = docxml.at("//div[@id = 'boilerplate-#{klass}' or @class = 'boilerplate-#{klass}']")
92
- auth&.xpath(".//h1[not(text())] | .//h2[not(text())]")&.each { |h| h.remove }
93
- auth&.xpath(".//h1 | .//h2")&.each do |h|
94
- h.name = "p"
95
- h["class"] = "TitlePageSubhead"
103
+ # assume percentages
104
+ def colgroup_widths(t)
105
+ t.xpath("./colgroup/col").each_with_object([]) do |c, m|
106
+ m << c["width"].sub(/%$/, "").to_f
96
107
  end
97
- dest and auth and dest.replace(auth.remove)
98
108
  end
99
109
 
100
- def authority_cleanup(docxml)
101
- %w(copyright license legal feedback).each do |t|
102
- authority_cleanup1(docxml, t)
110
+ def word_nested_tables(docxml)
111
+ docxml.xpath("//table").each do |t|
112
+ t.xpath(".//table").reverse.each do |tt|
113
+ t.next = tt.remove
114
+ end
103
115
  end
104
116
  end
105
117
 
@@ -144,19 +156,6 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
144
156
  end
145
157
  end
146
158
 
147
- =begin
148
- EMPTY_PARA = "<p style='margin-top:0cm;margin-right:0cm;"\
149
- "margin-bottom:0cm;margin-left:0.0pt;margin-bottom:.0001pt;"\
150
- "line-height:1.0pt;mso-line-height-rule:exactly'>"\
151
- "<span lang=EN-GB style='display:none;mso-hide:all'>&nbsp;</span></p>"
152
-
153
- def table_after_table(docxml)
154
- docxml.xpath("//table[following-sibling::*[1]/self::table]").each do |t|
155
- t.add_next_sibling(EMPTY_PARA)
156
- end
157
- end
158
- =end
159
-
160
159
  def word_table_separator(docxml)
161
160
  docxml.xpath("//p[@class = 'TableTitle']").each do |t|
162
161
  next unless t.children.empty?
@@ -180,46 +179,6 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
180
179
  end
181
180
  end
182
181
 
183
- def generate_header(filename, _dir)
184
- return nil unless @header
185
- template = IsoDoc::Common.liquid(File.read(@header, encoding: "UTF-8"))
186
- meta = @meta.get
187
- meta[:filename] = filename
188
- params = meta.map { |k, v| [k.to_s, v] }.to_h
189
- Tempfile.open(%w(header html), :encoding => "utf-8") do |f|
190
- f.write(template.render(params))
191
- f
192
- end
193
- end
194
-
195
- def word_section_breaks(docxml)
196
- @landscapestyle = ""
197
- word_section_breaks1(docxml, "WordSection2")
198
- word_section_breaks1(docxml, "WordSection3")
199
- word_remove_pb_before_annex(docxml)
200
- docxml.xpath("//br[@orientation]").each { |br| br.delete("orientation") }
201
- end
202
-
203
- def word_section_breaks1(docxml, sect)
204
- docxml.xpath("//div[@class = '#{sect}']//br[@orientation]").reverse.
205
- each_with_index do |br, i|
206
- @landscapestyle += "\ndiv.#{sect}_#{i} {page:#{sect}"\
207
- "#{br["orientation"] == "landscape" ? "L" : "P"};}\n"
208
- split_at_section_break(docxml, sect, br, i)
209
- end
210
- end
211
-
212
- def split_at_section_break(docxml, sect, br, i)
213
- move = br.parent.xpath("following::node()") &
214
- br.document.xpath("//div[@class = '#{sect}']//*")
215
- ins = docxml.at("//div[@class = '#{sect}']").
216
- after("<div class='#{sect}_#{i}'/>").next_element
217
- move.each do |m|
218
- next if m.at("./ancestor::div[@class = '#{sect}_#{i}']")
219
- ins << m.remove
220
- end
221
- end
222
-
223
182
  # applies for <div class="WordSectionN_M"><p><pagebreak/></p>...
224
183
  def word_remove_pb_before_annex(docxml)
225
184
  docxml.xpath("//div[p/br]").each do |d|
@@ -237,8 +196,7 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
237
196
  docxml.xpath("//a[@epub:type = 'footnote']").each do |x|
238
197
  footnote_reference_format(x)
239
198
  end
240
- docxml.xpath("//a[@class = 'TableFootnoteRef'] | "\
241
- "//span[@class = 'TableFootnoteRef']").each do |x|
199
+ docxml.xpath("//a[@class = 'TableFootnoteRef'] | //span[@class = 'TableFootnoteRef']").each do |x|
242
200
  table_footnote_reference_format(x)
243
201
  end
244
202
  docxml