isodoc 1.0.24 → 1.0.29

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +14 -4
  3. data/.github/workflows/ubuntu.yml +19 -5
  4. data/.github/workflows/windows.yml +14 -4
  5. data/isodoc.gemspec +1 -1
  6. data/lib/isodoc-yaml/i18n-en.yaml +3 -1
  7. data/lib/isodoc-yaml/i18n-fr.yaml +3 -1
  8. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +3 -1
  9. data/lib/isodoc/convert.rb +1 -0
  10. data/lib/isodoc/function/blocks.rb +43 -49
  11. data/lib/isodoc/function/{blocks_example.rb → blocks_example_note.rb} +57 -2
  12. data/lib/isodoc/function/cleanup.rb +16 -2
  13. data/lib/isodoc/function/i18n.rb +1 -0
  14. data/lib/isodoc/function/inline.rb +79 -77
  15. data/lib/isodoc/function/inline_simple.rb +72 -0
  16. data/lib/isodoc/function/lists.rb +12 -6
  17. data/lib/isodoc/function/references.rb +51 -39
  18. data/lib/isodoc/function/reqt.rb +13 -4
  19. data/lib/isodoc/function/section.rb +19 -8
  20. data/lib/isodoc/function/table.rb +3 -4
  21. data/lib/isodoc/function/terms.rb +1 -1
  22. data/lib/isodoc/function/to_word_html.rb +23 -13
  23. data/lib/isodoc/function/utils.rb +13 -6
  24. data/lib/isodoc/function/xref_counter.rb +43 -9
  25. data/lib/isodoc/function/xref_gen.rb +2 -1
  26. data/lib/isodoc/function/xref_gen_seq.rb +11 -10
  27. data/lib/isodoc/function/xref_sect_gen.rb +24 -24
  28. data/lib/isodoc/headlesshtml_convert.rb +5 -0
  29. data/lib/isodoc/html_convert.rb +5 -0
  30. data/lib/isodoc/html_function/footnotes.rb +3 -3
  31. data/lib/isodoc/html_function/html.rb +16 -1
  32. data/lib/isodoc/html_function/postprocess.rb +6 -5
  33. data/lib/isodoc/metadata.rb +10 -3
  34. data/lib/isodoc/metadata_date.rb +19 -7
  35. data/lib/isodoc/pdf_convert.rb +5 -0
  36. data/lib/isodoc/version.rb +1 -1
  37. data/lib/isodoc/word_convert.rb +5 -0
  38. data/lib/isodoc/word_function/body.rb +13 -51
  39. data/lib/isodoc/word_function/footnotes.rb +3 -3
  40. data/lib/isodoc/word_function/inline.rb +75 -0
  41. data/lib/isodoc/word_function/postprocess.rb +13 -2
  42. data/lib/isodoc/word_function/table.rb +3 -3
  43. data/lib/isodoc/xslfo_convert.rb +5 -0
  44. data/spec/assets/i18n.yaml +4 -1
  45. data/spec/assets/odf.emf +0 -0
  46. data/spec/assets/odf.svg +4 -0
  47. data/spec/assets/odf1.svg +4 -0
  48. data/spec/isodoc/blocks_spec.rb +274 -51
  49. data/spec/isodoc/cleanup_spec.rb +317 -25
  50. data/spec/isodoc/footnotes_spec.rb +20 -5
  51. data/spec/isodoc/i18n_spec.rb +12 -12
  52. data/spec/isodoc/inline_spec.rb +299 -4
  53. data/spec/isodoc/lists_spec.rb +8 -8
  54. data/spec/isodoc/metadata_spec.rb +112 -3
  55. data/spec/isodoc/postproc_spec.rb +39 -21
  56. data/spec/isodoc/ref_spec.rb +121 -52
  57. data/spec/isodoc/section_spec.rb +236 -207
  58. data/spec/isodoc/table_spec.rb +28 -28
  59. data/spec/isodoc/terms_spec.rb +57 -13
  60. data/spec/isodoc/xref_spec.rb +218 -71
  61. metadata +10 -5
@@ -14,6 +14,11 @@ module IsoDoc
14
14
  "_headlessimages"
15
15
  end
16
16
 
17
+ def initialize(options)
18
+ @format = :html
19
+ super
20
+ end
21
+
17
22
  def convert(filename, file = nil, debug = false)
18
23
  file = File.read(filename, encoding: "utf-8") if file.nil?
19
24
  @openmathdelim, @closemathdelim = extract_delims(file)
@@ -14,6 +14,11 @@ module IsoDoc
14
14
  "_htmlimages"
15
15
  end
16
16
 
17
+ def initialize(options)
18
+ @format = :html
19
+ super
20
+ end
21
+
17
22
  def convert(filename, file = nil, debug = false)
18
23
  ret = super
19
24
  Dir.exists?(tmpimagedir) and Dir["#{tmpimagedir}/*"].empty? and
@@ -48,7 +48,7 @@ module IsoDoc::HtmlFunction
48
48
  end
49
49
 
50
50
  def table_footnote_parse(node, out)
51
- fn = node["reference"]
51
+ fn = node["reference"] || UUIDTools::UUID.random_create.to_s
52
52
  tid = get_table_ancestor_id(node)
53
53
  make_table_footnote_link(out, tid + fn, fn)
54
54
  # do not output footnote text if we have already seen it for this table
@@ -64,8 +64,8 @@ module IsoDoc::HtmlFunction
64
64
  def footnote_parse(node, out)
65
65
  return table_footnote_parse(node, out) if (@in_table || @in_figure) &&
66
66
  !node.ancestors.map {|m| m.name }.include?("name")
67
- fn = node["reference"]
68
- attrs = { "epub:type": "footnote", rel: "footnote", href: "#fn:#{fn}" }
67
+ fn = node["reference"] || UUIDTools::UUID.random_create.to_s
68
+ attrs = { class: "FootnoteRef", href: "#fn:#{fn}" }
69
69
  out.a **attrs do |a|
70
70
  a.sup { |sup| sup << fn }
71
71
  end
@@ -3,6 +3,18 @@ require "base64"
3
3
 
4
4
  module IsoDoc::HtmlFunction
5
5
  module Html
6
+ def convert1(docxml, filename, dir)
7
+ anchor_names docxml
8
+ noko do |xml|
9
+ xml.html **{ lang: "#{@lang}" } do |html|
10
+ info docxml, nil
11
+ populate_css()
12
+ html.head { |head| define_head head, filename, dir }
13
+ make_body(html, docxml)
14
+ end
15
+ end.join("\n")
16
+ end
17
+
6
18
  def make_body1(body, _docxml)
7
19
  body.div **{ class: "title-section" } do |div1|
8
20
  div1.p { |p| p << "&nbsp;" } # placeholder
@@ -90,12 +102,15 @@ module IsoDoc::HtmlFunction
90
102
  def sourcecode_parse(node, out)
91
103
  name = node.at(ns("./name"))
92
104
  class1 = "prettyprint #{sourcecodelang(node&.at(ns('./@lang'))&.value)}"
93
- out.pre **attr_code(id: node["id"], class: class1) do |div|
105
+ out.pre **sourcecode_attrs(node).merge(class: class1) do |div|
94
106
  @sourcecode = true
95
107
  node.children.each { |n| parse(n, div) unless n.name == "name" }
96
108
  @sourcecode = false
97
109
  end
98
110
  sourcecode_name_parse(node, out, name)
99
111
  end
112
+
113
+ def table_long_strings_cleanup(docxml)
114
+ end
100
115
  end
101
116
  end
@@ -108,7 +108,7 @@ module IsoDoc::HtmlFunction
108
108
  idx = docxml.at("//div[@id = 'toc']") or return docxml
109
109
  toc = "<ul>"
110
110
  path = toclevel_classes.map do |l|
111
- "//main//#{l}[not(@class = 'TermNum')][not(@class = 'noTOC')][not(text())]"
111
+ "//main//#{l}[not(@class = 'TermNum')][not(@class = 'noTOC')][text()]"
112
112
  end
113
113
  docxml.xpath(path.join(" | ")).each_with_index do |h, tocidx|
114
114
  h["id"] ||= "toc#{tocidx}"
@@ -159,7 +159,8 @@ module IsoDoc::HtmlFunction
159
159
  def inject_script(doc)
160
160
  return doc unless @scripts
161
161
  scripts = File.read(@scripts, encoding: "UTF-8")
162
- doc.sub("</body>", scripts + "\n</body>")
162
+ a = doc.split(%r{</body>})
163
+ a[0] + scripts + "</body>" + a[1]
163
164
  end
164
165
 
165
166
  def update_footnote_filter(fn, x, i, seen)
@@ -178,7 +179,7 @@ module IsoDoc::HtmlFunction
178
179
  def html_footnote_filter(docxml)
179
180
  seen = {}
180
181
  i = 1
181
- docxml.xpath('//a[@epub:type = "footnote"]').each do |x|
182
+ docxml.xpath('//a[@class = "FootnoteRef"]').each do |x|
182
183
  fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
183
184
  i, seen = update_footnote_filter(fn, x, i, seen)
184
185
  end
@@ -187,7 +188,7 @@ module IsoDoc::HtmlFunction
187
188
 
188
189
  def footnote_backlinks(docxml)
189
190
  seen = {}
190
- docxml.xpath('//a[@epub:type = "footnote"]').each_with_index do |x, i|
191
+ docxml.xpath('//a[@class = "FootnoteRef"]').each_with_index do |x, i|
191
192
  seen[x["href"]] and next or seen[x["href"]] = true
192
193
  fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
193
194
  xdup = x.dup
@@ -200,7 +201,7 @@ module IsoDoc::HtmlFunction
200
201
  end
201
202
 
202
203
  def footnote_format(docxml)
203
- docxml.xpath("//a[@epub:type = 'footnote']/sup").each do |x|
204
+ docxml.xpath("//a[@class = 'FootnoteRef']/sup").each do |x|
204
205
  footnote_reference_format(x)
205
206
  end
206
207
  docxml.xpath("//a[@class = 'TableFootnoteRef'] | "\
@@ -3,7 +3,8 @@ require_relative "./metadata_date"
3
3
  module IsoDoc
4
4
  class Metadata
5
5
  DATETYPES = %w{published accessed created implemented obsoleted confirmed
6
- updated issued received transmitted copied unchanged circulated}.freeze
6
+ updated issued received transmitted copied unchanged circulated vote-started
7
+ vote-ended}.freeze
7
8
 
8
9
  def ns(xpath)
9
10
  Common::ns(xpath)
@@ -15,7 +16,7 @@ module IsoDoc
15
16
 
16
17
  def initialize(lang, script, labels)
17
18
  @metadata = {}
18
- DATETYPES.each { |w| @metadata["#{w}date".to_sym] = "XXX" }
19
+ DATETYPES.each { |w| @metadata["#{w.gsub(/-/, "_")}date".to_sym] = "XXX" }
19
20
  @lang = lang
20
21
  @script = script
21
22
  @c = HTMLEntities.new
@@ -84,7 +85,7 @@ module IsoDoc
84
85
 
85
86
  def bibdate(isoxml, _out)
86
87
  isoxml.xpath(ns("//bibdata/date")).each do |d|
87
- set("#{d['type']}date".to_sym, Common::date_range(d))
88
+ set("#{d['type'].gsub(/-/, "_")}date".to_sym, Common::date_range(d))
88
89
  end
89
90
  end
90
91
 
@@ -217,5 +218,11 @@ module IsoDoc
217
218
  a = xml.at(ns("//bibdata/uri[@type = 'pdf']")) and set(:pdf, a.text)
218
219
  a = xml.at(ns("//bibdata/uri[@type = 'doc']")) and set(:doc, a.text)
219
220
  end
221
+
222
+ def keywords(isoxml, _out)
223
+ ret = []
224
+ isoxml.xpath(ns("//bibdata/keyword")).each { |kw| ret << kw.text }
225
+ set(:keywords, ret)
226
+ end
220
227
  end
221
228
  end
@@ -14,14 +14,26 @@ module IsoDoc
14
14
  "10": @labels["month_october"],
15
15
  "11": @labels["month_november"],
16
16
  "12": @labels["month_december"],
17
- }
17
+ }
18
18
  end
19
19
 
20
- def monthyr(isodate)
21
- m = /(?<yr>\d\d\d\d)-(?<mo>\d\d)/.match isodate
22
- return isodate unless m && m[:yr] && m[:mo]
23
- IsoDoc::Function::I18n::l10n("#{months[m[:mo].to_sym]} #{m[:yr]}",
24
- @lang, @script)
25
- end
20
+ def monthyr(isodate)
21
+ m = /(?<yr>\d\d\d\d)-(?<mo>\d\d)/.match isodate
22
+ return isodate unless m && m[:yr] && m[:mo]
23
+ IsoDoc::Function::I18n::l10n("#{months[m[:mo].to_sym]} #{m[:yr]}",
24
+ @lang, @script)
25
+ end
26
+
27
+ def MMMddyyyy(isodate)
28
+ return nil if isodate.nil?
29
+ arr = isodate.split("-")
30
+ date = if arr.size == 1 and (/^\d+$/.match isodate)
31
+ Date.new(*arr.map(&:to_i)).strftime("%Y")
32
+ elsif arr.size == 2
33
+ Date.new(*arr.map(&:to_i)).strftime("%B %Y")
34
+ else
35
+ Date.parse(isodate).strftime("%B %d, %Y")
36
+ end
37
+ end
26
38
  end
27
39
  end
@@ -22,6 +22,11 @@ module IsoDoc
22
22
  "_pdfimages"
23
23
  end
24
24
 
25
+ def initialize(options)
26
+ @format = :pdf
27
+ super
28
+ end
29
+
25
30
  def convert(filename, file = nil, debug = false)
26
31
  file = File.read(filename, encoding: "utf-8") if file.nil?
27
32
  @openmathdelim, @closemathdelim = extract_delims(file)
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "1.0.24".freeze
2
+ VERSION = "1.0.29".freeze
3
3
  end
@@ -30,6 +30,11 @@ module IsoDoc
30
30
  include WordFunction::Body
31
31
  include WordFunction::Postprocess
32
32
 
33
+ def initialize(options)
34
+ @format = :doc
35
+ super
36
+ end
37
+
33
38
  def convert(filename, file = nil, debug = false)
34
39
  ret = super
35
40
  FileUtils.rm_rf tmpimagedir
@@ -1,4 +1,5 @@
1
1
  require_relative "./table.rb"
2
+ require_relative "./inline.rb"
2
3
 
3
4
  module IsoDoc::WordFunction
4
5
  module Body
@@ -69,28 +70,6 @@ module IsoDoc::WordFunction
69
70
  node.xpath(ns("./note")).each { |n| parse(n, out) }
70
71
  end
71
72
 
72
- def section_break(body)
73
- body.p do |p|
74
- p.br **{ clear: "all", class: "section" }
75
- end
76
- end
77
-
78
- def page_break(out)
79
- out.p do |p|
80
- p.br **{ clear: "all",
81
- style: "mso-special-character:line-break;"\
82
- "page-break-before:always" }
83
- end
84
- end
85
-
86
- def pagebreak_parse(node, out)
87
- return page_break(out) if node["orientation"].nil?
88
- out.p do |p|
89
- p.br **{clear: "all", class: "section",
90
- orientation: node["orientation"] }
91
- end
92
- end
93
-
94
73
  WORD_DT_ATTRS = {class: @note ? "Note" : nil, align: "left",
95
74
  style: "margin-left:0pt;text-align:left;"}.freeze
96
75
 
@@ -174,7 +153,7 @@ module IsoDoc::WordFunction
174
153
  end
175
154
 
176
155
  def termnote_parse(node, out)
177
- out.div **{ class: "Note" } do |div|
156
+ out.div **note_attrs(node) do |div|
178
157
  first = node.first_element_child
179
158
  div.p **{ class: "Note" } do |p|
180
159
  anchor = get_anchors[node['id']]
@@ -185,45 +164,23 @@ module IsoDoc::WordFunction
185
164
  end
186
165
 
187
166
  def para_attrs(node)
188
- attrs = { class: para_class(node), id: node["id"] }
167
+ attrs = { class: para_class(node), id: node["id"], style: "" }
189
168
  unless node["align"].nil?
190
169
  attrs[:align] = node["align"] unless node["align"] == "justify"
191
- attrs[:style] = "text-align:#{node['align']}"
170
+ attrs[:style] += "text-align:#{node['align']};"
192
171
  end
172
+ attrs[:style] += "#{keep_style(node)}"
173
+ attrs[:style] = nil if attrs[:style].empty?
193
174
  attrs
194
175
  end
195
176
 
196
- def imgsrc(uri)
197
- return uri unless %r{^data:image/}.match uri
198
- save_dataimage(uri)
199
- end
200
-
201
- def image_parse(node, out, caption)
202
- attrs = { src: imgsrc(node["src"]),
203
- height: node["height"],
204
- alt: node["alt"],
205
- title: node["title"],
206
- width: node["width"] }
207
- if node["height"] == "auto" || node["width"] == "auto"
208
- attrs[:height] = nil
209
- attrs[:width] = nil
210
- end
211
- out.img **attr_code(attrs)
212
- image_title_parse(out, caption)
213
- end
214
-
215
- def xref_parse(node, out)
216
- target = /#/.match(node["target"]) ? node["target"].sub(/#/, ".doc#") :
217
- "##{node["target"]}"
218
- out.a(**{ "href": target }) { |l| l << get_linkend(node) }
219
- end
220
-
221
177
  def example_table_attr(node)
222
178
  super.merge({
223
179
  style: "mso-table-lspace:15.0cm;margin-left:423.0pt;"\
224
180
  "mso-table-rspace:15.0cm;margin-right:423.0pt;"\
225
181
  "mso-table-anchor-horizontal:column;"\
226
- "mso-table-overlap:never;border-collapse:collapse;"
182
+ "mso-table-overlap:never;border-collapse:collapse;"\
183
+ "#{keep_style(node)}"
227
184
  })
228
185
  end
229
186
 
@@ -244,5 +201,10 @@ module IsoDoc::WordFunction
244
201
  node.children.each { |n| parse(n, li) }
245
202
  end
246
203
  end
204
+
205
+ def suffix_url(url)
206
+ return url if %r{^http[s]?://}.match(url)
207
+ url.sub(/#{File.extname(url)}$/, ".doc")
208
+ end
247
209
  end
248
210
  end
@@ -56,7 +56,7 @@ module IsoDoc::WordFunction
56
56
  end
57
57
 
58
58
  def table_footnote_parse(node, out)
59
- fn = node["reference"]
59
+ fn = node["reference"] || UUIDTools::UUID.random_create.to_s
60
60
  tid = get_table_ancestor_id(node)
61
61
  make_table_footnote_link(out, tid + fn, fn)
62
62
  # do not output footnote text if we have already seen it for this table
@@ -80,11 +80,11 @@ module IsoDoc::WordFunction
80
80
  def footnote_parse(node, out)
81
81
  return table_footnote_parse(node, out) if (@in_table || @in_figure) &&
82
82
  !node.ancestors.map {|m| m.name }.include?("name")
83
- fn = node["reference"]
83
+ fn = node["reference"] || UUIDTools::UUID.random_create.to_s
84
84
  return seen_footnote_parse(node, out, fn) if @seen_footnote.include?(fn)
85
85
  @fn_bookmarks[fn] = bookmarkid
86
86
  out.span **{style: "mso-bookmark:_Ref#{@fn_bookmarks[fn]}"} do |s|
87
- s.a **{ "epub:type": "footnote", href: "#ftn#{fn}" } do |a|
87
+ s.a **{ "class": "FootnoteRef", "epub:type": "footnote", href: "#ftn#{fn}" } do |a|
88
88
  a.sup { |sup| sup << fn }
89
89
  end
90
90
  end
@@ -0,0 +1,75 @@
1
+ module IsoDoc::WordFunction
2
+ module Body
3
+ def section_break(body)
4
+ body.p do |p|
5
+ p.br **{ clear: "all", class: "section" }
6
+ end
7
+ end
8
+
9
+ def page_break(out)
10
+ out.p do |p|
11
+ p.br **{ clear: "all",
12
+ style: "mso-special-character:line-break;"\
13
+ "page-break-before:always" }
14
+ end
15
+ end
16
+
17
+ def pagebreak_parse(node, out)
18
+ return page_break(out) if node["orientation"].nil?
19
+ out.p do |p|
20
+ p.br **{clear: "all", class: "section",
21
+ orientation: node["orientation"] }
22
+ end
23
+ end
24
+
25
+ def imgsrc(node)
26
+ ret = svg_to_emf(node) and return ret
27
+ return node["src"] unless %r{^data:image/}.match node["src"]
28
+ save_dataimage(node["src"])
29
+ end
30
+
31
+ def image_parse(node, out, caption)
32
+ attrs = { src: imgsrc(node),
33
+ height: node["height"],
34
+ alt: node["alt"],
35
+ title: node["title"],
36
+ width: node["width"] }
37
+ out.img **attr_code(attrs)
38
+ image_title_parse(out, caption)
39
+ end
40
+
41
+ def svg_to_emf_filename(uri)
42
+ File.join(File.dirname(uri), File.basename(uri, ".*")) + ".emf"
43
+ end
44
+
45
+ def svg_to_emf(node)
46
+ return unless node["mimetype"] == "image/svg+xml"
47
+ uri = node["src"]
48
+ %r{^data:image/}.match(uri) and uri = save_dataimage(uri)
49
+ ret = svg_to_emf_filename(uri)
50
+ File.exists?(ret) and return ret
51
+ exe = inkscape_installed? or return nil
52
+ system %(#{exe} --export-type="emf" #{uri}) and
53
+ return ret
54
+ nil
55
+ end
56
+
57
+ def inkscape_installed?
58
+ cmd = "inkscape"
59
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
60
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
61
+ exts.each do |ext|
62
+ exe = File.join(path, "#{cmd}#{ext}")
63
+ return exe if File.executable?(exe) && !File.directory?(exe)
64
+ end
65
+ end
66
+ nil
67
+ end
68
+
69
+ def xref_parse(node, out)
70
+ target = /#/.match(node["target"]) ? node["target"].sub(/#/, ".doc#") :
71
+ "##{node["target"]}"
72
+ out.a(**{ "href": target }) { |l| l << get_linkend(node) }
73
+ end
74
+ end
75
+ end
@@ -39,7 +39,6 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
39
39
  end
40
40
 
41
41
  def toWord(result, filename, dir, header)
42
- #result = populate_template(result, :word)
43
42
  result = from_xhtml(word_cleanup(to_xhtml(result)))
44
43
  unless @landscapestyle.empty?
45
44
  @wordstylesheet&.open
@@ -196,6 +195,8 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
196
195
  @landscapestyle = ""
197
196
  word_section_breaks1(docxml, "WordSection2")
198
197
  word_section_breaks1(docxml, "WordSection3")
198
+ word_remove_pb_before_annex(docxml)
199
+ docxml.xpath("//br[@orientation]").each { |br| br.delete("orientation") }
199
200
  end
200
201
 
201
202
  def word_section_breaks1(docxml, sect)
@@ -203,7 +204,6 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
203
204
  each_with_index do |br, i|
204
205
  @landscapestyle += "\ndiv.#{sect}_#{i} {page:#{sect}"\
205
206
  "#{br["orientation"] == "landscape" ? "L" : "P"};}\n"
206
- br.delete("orientation")
207
207
  split_at_section_break(docxml, sect, br, i)
208
208
  end
209
209
  end
@@ -219,6 +219,17 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
219
219
  end
220
220
  end
221
221
 
222
+ # applies for <div class="WordSectionN_M"><p><pagebreak/></p>...
223
+ def word_remove_pb_before_annex(docxml)
224
+ docxml.xpath("//div[p/br]").each do |d|
225
+ /^WordSection\d+_\d+$/.match(d["class"]) or next
226
+ d.elements[0].name == "p" && !d.elements[0].elements.empty? or next
227
+ d.elements[0].elements[0].name == "br" && d.elements[0].elements[0]["style"] ==
228
+ "mso-special-character:line-break;page-break-before:always" or next
229
+ d.elements[0].remove
230
+ end
231
+ end
232
+
222
233
  def word_footnote_format(docxml)
223
234
  # the content is in a[@epub:type = 'footnote']//sup, but in Word,
224
235
  # we need to inject content around the autonumbered footnote reference