isodoc 2.4.1 → 2.4.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.
@@ -0,0 +1,114 @@
1
+ module IsoDoc
2
+ class PresentationXMLConvert < ::IsoDoc::Convert
3
+ def sourcehighlighter_css(docxml)
4
+ @sourcehighlighter or return
5
+ ins = docxml.at(ns("//misc-container")) ||
6
+ docxml.at(ns("//bibdata")).after("<misc-container/>").next_element
7
+ ins << "<source-highlighter-css>#{sourcehighlighter_css_file}" \
8
+ "</source-highlighter-css>"
9
+ end
10
+
11
+ def sourcehighlighter_css_file
12
+ File.read(File.join(File.dirname(__FILE__), "..", "base_style",
13
+ "rouge.css"))
14
+ end
15
+
16
+ def sourcehighlighter
17
+ @sourcehighlighter or return
18
+ f = Rouge::Formatters::HTML.new
19
+ opts = { gutter_class: "rouge-gutter", code_class: "rouge-code" }
20
+ { formatter: f,
21
+ formatter_line: Rouge::Formatters::HTMLLineTable.new(f, opts) }
22
+ end
23
+
24
+ def sourcecode(docxml)
25
+ sourcehighlighter_css(docxml)
26
+ @highlighter = sourcehighlighter
27
+ docxml.xpath(ns("//sourcecode")).each do |f|
28
+ sourcecode1(f)
29
+ end
30
+ end
31
+
32
+ def sourcecode1(elem)
33
+ source_highlight(elem)
34
+ source_label(elem)
35
+ end
36
+
37
+ def source_highlight(elem)
38
+ @highlighter or return
39
+ markup = source_remove_markup(elem)
40
+ p = source_lex(elem)
41
+ elem.children = if elem["linenums"] == "true"
42
+ r = sourcecode_table_to_elem(elem, p)
43
+ source_restore_markup_table(r, markup)
44
+ else
45
+ r = @highlighter[:formatter].format(p)
46
+ source_restore_markup(Nokogiri::XML.fragment(r), markup)
47
+ end
48
+ end
49
+
50
+ def source_remove_markup(elem)
51
+ ret = {}
52
+ name = elem.at(ns("./name")) and ret[:name] = name.remove.to_xml
53
+ ret[:ann] = elem.xpath(ns("./annotation")).each(&:remove)
54
+ ret[:call] = elem.xpath(ns("./callout")).each_with_object([]) do |c, m|
55
+ m << { xml: c.remove.to_xml, line: c.line - elem.line }
56
+ end
57
+ ret
58
+ end
59
+
60
+ def source_restore_markup(wrapper, markup)
61
+ ret = source_restore_callouts(wrapper, markup[:call])
62
+ "#{markup[:name]}#{ret}#{markup[:ann]}"
63
+ end
64
+
65
+ def source_restore_markup_table(wrapper, markup)
66
+ source_restore_callouts_table(wrapper, markup[:call])
67
+ ret = to_xml(wrapper)
68
+ "#{markup[:name]}#{ret}#{markup[:ann]}"
69
+ end
70
+
71
+ def source_restore_callouts(code, callouts)
72
+ text = to_xml(code)
73
+ text.split(/[\n\r]/).each_with_index do |c, i|
74
+ while !callouts.empty? && callouts[0][:line] == i
75
+ c.sub!(/\s+$/, " <span class='c'>#{callouts[0][:xml]}</span> ")
76
+ callouts.shift
77
+ end
78
+ end.join("\n")
79
+ end
80
+
81
+ def source_restore_callouts_table(table, callouts)
82
+ table.xpath(".//td[@class = 'rouge-code']/sourcecode")
83
+ .each_with_index do |c, i|
84
+ while !callouts.empty? && callouts[0][:line] == i
85
+ c << " <span class='c'>#{callouts[0][:xml]}</span> "
86
+ callouts.shift
87
+ end
88
+ end
89
+ end
90
+
91
+ def sourcecode_table_to_elem(elem, tokens)
92
+ r = Nokogiri::XML(@highlighter[:formatter_line].format(tokens)).root
93
+ r.xpath(".//td[@class = 'rouge-code']/pre").each do |pre|
94
+ %w(style).each { |n| elem[n] and pre[n] = elem[n] }
95
+ pre.name = "sourcecode"
96
+ pre.children = to_xml(pre.children).sub(/\s+$/, "")
97
+ end
98
+ r
99
+ end
100
+
101
+ def source_lex(elem)
102
+ l = (Rouge::Lexer.find(elem["lang"] || "plaintext") ||
103
+ Rouge::Lexer.find("plaintext"))
104
+ l.lex(@c.decode(elem.children.to_xml))
105
+ end
106
+
107
+ def source_label(elem)
108
+ labelled_ancestor(elem) and return
109
+ lbl = @xrefs.anchor(elem["id"], :label, false) or return
110
+ prefix_name(elem, block_delim,
111
+ l10n("#{lower2cap @i18n.figure} #{lbl}"), "name")
112
+ end
113
+ end
114
+ end
@@ -46,9 +46,8 @@ module IsoDoc
46
46
  end
47
47
 
48
48
  def concept1_linkmention(ref, renderterm, opts)
49
- return unless opts[:linkmention] == "true" &&
50
- !renderterm.nil? && !ref.nil?
51
-
49
+ (opts[:linkmention] == "true" &&
50
+ !renderterm.nil? && !ref.nil?) or return
52
51
  ref2 = ref.clone
53
52
  r2 = renderterm.clone
54
53
  renderterm.replace(ref2).children = r2
@@ -56,16 +55,14 @@ module IsoDoc
56
55
 
57
56
  def concept1_ref(_node, ref, opts)
58
57
  ref.nil? and return
59
- return ref.remove if opts[:ref] == "false"
60
-
58
+ opts[:ref] == "false" and return ref.remove
61
59
  r = concept1_ref_content(ref)
62
60
  ref = r.at("./descendant-or-self::xmlns:xref | " \
63
61
  "./descendant-or-self::xmlns:eref | " \
64
62
  "./descendant-or-self::xmlns:termref")
65
63
  %w(xref eref).include? ref&.name and get_linkend(ref)
66
- if opts[:linkref] == "false" && %w(xref eref).include?(ref&.name)
64
+ opts[:linkref] == "false" && %w(xref eref).include?(ref&.name) and
67
65
  ref.replace(ref.children)
68
- end
69
66
  end
70
67
 
71
68
  def concept1_ref_content(ref)
@@ -97,9 +94,8 @@ module IsoDoc
97
94
 
98
95
  def designation(docxml)
99
96
  docxml.xpath(ns("//term")).each { |t| merge_second_preferred(t) }
100
- docxml.xpath(ns("//preferred | //admitted | //deprecates")).each do |p|
101
- designation1(p)
102
- end
97
+ docxml.xpath(ns("//preferred | //admitted | //deprecates"))
98
+ .each { |p| designation1(p) }
103
99
  end
104
100
 
105
101
  def merge_second_preferred(term)
@@ -112,11 +108,10 @@ module IsoDoc
112
108
  end
113
109
 
114
110
  def merge_second_preferred1(pref, second)
115
- if merge_preferred_eligible?(pref, second)
116
- n1 = pref.at(ns("./expression/name"))
117
- n2 = second.remove.at(ns("./expression/name"))
118
- n1.children = l10n("#{to_xml(n1.children)}; #{Common::to_xml(n2.children)}")
119
- end
111
+ merge_preferred_eligible?(pref, second) or return
112
+ n1 = pref.at(ns("./expression/name"))
113
+ n2 = second.remove.at(ns("./expression/name"))
114
+ n1.children = l10n("#{to_xml(n1.children)}; #{Common::to_xml(n2.children)}")
120
115
  end
121
116
 
122
117
  def merge_preferred_eligible?(first, second)
@@ -132,7 +127,6 @@ module IsoDoc
132
127
  s = desgn.at(ns("./termsource"))
133
128
  name = desgn.at(ns("./expression/name | ./letter-symbol/name | " \
134
129
  "./graphical-symbol")) or return
135
-
136
130
  designation_annotate(desgn, name)
137
131
  s and desgn.next = s
138
132
  end
@@ -156,8 +150,7 @@ module IsoDoc
156
150
  def designation_field(desgn, name)
157
151
  f = desgn.xpath(ns("./field-of-application | ./usage-info"))
158
152
  &.map { |u| to_xml(u.children) }&.join(", ")
159
- return nil if f&.empty?
160
-
153
+ f&.empty? and return nil
161
154
  name << ", &#x3c;#{f}&#x3e;"
162
155
  end
163
156
 
@@ -178,27 +171,21 @@ module IsoDoc
178
171
  loc = [desgn&.at(ns("./expression/@language"))&.text,
179
172
  desgn&.at(ns("./expression/@script"))&.text,
180
173
  desgn&.at(ns("./@geographic-area"))&.text].compact
181
- return if loc.empty?
182
-
174
+ loc.empty? and return
183
175
  name << ", #{loc.join(' ')}"
184
176
  end
185
177
 
186
178
  def designation_pronunciation(desgn, name)
187
179
  f = desgn.at(ns("./expression/pronunciation")) or return
188
-
189
180
  name << ", /#{to_xml(f.children)}/"
190
181
  end
191
182
 
192
183
  def termexample(docxml)
193
- docxml.xpath(ns("//termexample")).each do |f|
194
- example1(f)
195
- end
184
+ docxml.xpath(ns("//termexample")).each { |f| example1(f) }
196
185
  end
197
186
 
198
187
  def termnote(docxml)
199
- docxml.xpath(ns("//termnote")).each do |f|
200
- termnote1(f)
201
- end
188
+ docxml.xpath(ns("//termnote")).each { |f| termnote1(f) }
202
189
  end
203
190
 
204
191
  def termnote1(elem)
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "2.4.1".freeze
2
+ VERSION = "2.4.2".freeze
3
3
  end
@@ -19,14 +19,14 @@ module IsoDoc
19
19
  end
20
20
 
21
21
  def make_body1(body, _docxml)
22
- body.div **{ class: "WordSection1" } do |div1|
22
+ body.div class: "WordSection1" do |div1|
23
23
  div1.p { |p| p << "&#xa0;" } # placeholder
24
24
  end
25
25
  section_break(body)
26
26
  end
27
27
 
28
28
  def make_body2(body, docxml)
29
- body.div **{ class: "WordSection2" } do |div2|
29
+ body.div class: "WordSection2" do |div2|
30
30
  boilerplate docxml, div2
31
31
  preface_block docxml, div2
32
32
  abstract docxml, div2
@@ -40,7 +40,7 @@ module IsoDoc
40
40
  end
41
41
 
42
42
  def make_body3(body, docxml)
43
- body.div **{ class: "WordSection3" } do |div3|
43
+ body.div class: "WordSection3" do |div3|
44
44
  middle docxml, div3
45
45
  footnotes div3
46
46
  comments div3
@@ -93,7 +93,7 @@ module IsoDoc
93
93
 
94
94
  def dl_parse_table(node, out)
95
95
  list_title_parse(node, out)
96
- out.table **{ class: "dl" } do |v|
96
+ out.table class: "dl" do |v|
97
97
  node.elements.select { |n| dt_dd?(n) }
98
98
  .each_slice(2) do |dt, dd|
99
99
  dl_parse_table1(v, dt, dd)
@@ -104,10 +104,10 @@ module IsoDoc
104
104
 
105
105
  def dl_parse_table1(table, dterm, ddefn)
106
106
  table.tr do |tr|
107
- tr.td **{ valign: "top", align: "left" } do |term|
107
+ tr.td valign: "top", align: "left" do |term|
108
108
  dt_parse(dterm, term)
109
109
  end
110
- tr.td **{ valign: "top" } do |listitem|
110
+ tr.td valign: "top" do |listitem|
111
111
  ddefn.children.each { |n| parse(n, listitem) }
112
112
  end
113
113
  end
@@ -118,7 +118,7 @@ module IsoDoc
118
118
  return if remainder.empty?
119
119
 
120
120
  out.tr do |tr|
121
- tr.td **{ colspan: 2 } do |td|
121
+ tr.td colspan: 2 do |td|
122
122
  remainder.each { |n| parse(n, td) }
123
123
  end
124
124
  end
@@ -149,8 +149,8 @@ module IsoDoc
149
149
 
150
150
  def note_p_parse(node, div)
151
151
  name = node&.at(ns("./name"))&.remove
152
- div.p **{ class: "Note" } do |p|
153
- p.span **{ class: "note_label" } do |s|
152
+ div.p class: "Note" do |p|
153
+ p.span class: "note_label" do |s|
154
154
  name&.children&.each { |n| parse(n, s) }
155
155
  end
156
156
  insert_tab(p, 1)
@@ -161,8 +161,8 @@ module IsoDoc
161
161
 
162
162
  def note_parse1(node, div)
163
163
  name = node&.at(ns("./name"))&.remove
164
- div.p **{ class: "Note" } do |p|
165
- p.span **{ class: "note_label" } do |s|
164
+ div.p class: "Note" do |p|
165
+ p.span class: "note_label" do |s|
166
166
  name&.children&.each { |n| parse(n, s) }
167
167
  end
168
168
  insert_tab(p, 1)
@@ -173,7 +173,7 @@ module IsoDoc
173
173
  def termnote_parse(node, out)
174
174
  name = node&.at(ns("./name"))&.remove
175
175
  out.div **note_attrs(node) do |div|
176
- div.p **{ class: "Note" } do |p|
176
+ div.p class: "Note" do |p|
177
177
  if name
178
178
  name.children.each { |n| parse(n, p) }
179
179
  p << termnote_delim
@@ -196,10 +196,10 @@ module IsoDoc
196
196
 
197
197
  def example_table_attr(node)
198
198
  super.merge(
199
- style: "mso-table-lspace:15.0cm;margin-left:423.0pt;"\
200
- "mso-table-rspace:15.0cm;margin-right:423.0pt;"\
201
- "mso-table-anchor-horizontal:column;"\
202
- "mso-table-overlap:never;border-collapse:collapse;"\
199
+ style: "mso-table-lspace:15.0cm;margin-left:423.0pt;" \
200
+ "mso-table-rspace:15.0cm;margin-right:423.0pt;" \
201
+ "mso-table-anchor-horizontal:column;" \
202
+ "mso-table-overlap:never;border-collapse:collapse;" \
203
203
  "#{keep_style(node)}",
204
204
  )
205
205
  end
@@ -1,32 +1,15 @@
1
1
  require "fileutils"
2
2
  require_relative "./postprocess_cover"
3
+ require_relative "./postprocess_toc"
3
4
 
4
5
  module IsoDoc
5
6
  module WordFunction
6
7
  module Postprocess
7
- # add namespaces for Word fragments
8
- WORD_NOKOHEAD = <<~HERE.freeze
9
- <!DOCTYPE html SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
10
- <html xmlns="http://www.w3.org/1999/xhtml"
11
- xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"
12
- xmlns:w="urn:schemas-microsoft-com:office:word"
13
- xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
14
- <head> <title></title> <meta charset="UTF-8" /> </head>
15
- <body> </body> </html>
16
- HERE
17
-
18
- def to_word_xhtml_fragment(xml)
19
- doc = ::Nokogiri::XML.parse(WORD_NOKOHEAD)
20
- ::Nokogiri::XML::DocumentFragment.new(doc, xml, doc.root)
21
- end
22
-
23
8
  def table_note_cleanup(docxml)
24
9
  super
25
10
  # preempt html2doc putting MsoNormal there
26
11
  docxml.xpath("//p[not(self::*[@class])][ancestor::*[@class = 'Note']]")
27
- .each do |p|
28
- p["class"] = "Note"
29
- end
12
+ .each { |p| p["class"] = "Note" }
30
13
  end
31
14
 
32
15
  def postprocess(result, filename, dir)
@@ -56,23 +39,6 @@ module IsoDoc
56
39
  "Sourcecode"
57
40
  end
58
41
 
59
- def wordstylesheet_update
60
- return if @wordstylesheet.nil?
61
-
62
- f = File.open(@wordstylesheet.path, "a")
63
- @landscapestyle.empty? or f.write(@landscapestyle)
64
- s = @meta.get[:code_css] and
65
- f.write(s.gsub(/sourcecode/, "p.#{sourcecode_style}"))
66
- if @wordstylesheet_override && @wordstylesheet
67
- f.write(@wordstylesheet_override.read)
68
- @wordstylesheet_override.close
69
- elsif @wordstylesheet_override && !@wordstylesheet
70
- @wordstylesheet = @wordstylesheet_override
71
- end
72
- f.close
73
- @wordstylesheet
74
- end
75
-
76
42
  def word_admonition_images(docxml)
77
43
  docxml.xpath("//div[@class = 'Admonition']//img").each do |i|
78
44
  i["width"], i["height"] =
@@ -84,6 +50,7 @@ module IsoDoc
84
50
  def word_cleanup(docxml)
85
51
  word_annex_cleanup(docxml)
86
52
  word_preface(docxml)
53
+ word_sourcecode_annotations(docxml)
87
54
  word_sourcecode_table(docxml)
88
55
  word_nested_tables(docxml)
89
56
  word_colgroup(docxml)
@@ -101,18 +68,29 @@ module IsoDoc
101
68
  docxml
102
69
  end
103
70
 
104
- def word_sourcecode_table(docxml)
105
- docxml.xpath("//p[@class='Sourcecode']/div[@class='table_container']")
106
- .each do |d|
107
- pre = d.at(".//p[@class='Sourcecode']")
108
- to_sourcecode_para(pre)
109
- d["id"] = d.parent["id"]
110
- d.parent.replace(d)
71
+ def word_sourcecode_annotations(html)
72
+ ann = ".//div[@class = 'annotation']"
73
+ html.xpath("//p[@class = '#{sourcecode_style}'][#{ann}]")
74
+ .each do |p|
75
+ ins = p.after("<p class='#{sourcecode_style}'/>").next_element
76
+ p.xpath(ann).each do |d|
77
+ ins << d.remove.children
111
78
  end
79
+ end
80
+ end
81
+
82
+ def word_sourcecode_table(docxml)
83
+ s = "p[@class='#{sourcecode_style}']"
84
+ docxml.xpath("//#{s}/div[@class='table_container']").each do |d|
85
+ pre = d.at(".//#{s}")
86
+ to_sourcecode_para(pre)
87
+ d["id"] = d.parent["id"]
88
+ d.parent.replace(d)
89
+ end
112
90
  end
113
91
 
114
92
  def to_sourcecode_para(pre)
115
- @sourcecode = true
93
+ @sourcecode = "pre"
116
94
  pre.traverse do |x|
117
95
  x.text? or next
118
96
  ret = []
@@ -173,8 +151,7 @@ module IsoDoc
173
151
  end
174
152
 
175
153
  def style_update(node, css)
176
- return unless node
177
-
154
+ node or return
178
155
  node["style"] =
179
156
  node["style"] ? node["style"].sub(/;?$/, ";#{css}") : css
180
157
  end
@@ -182,11 +159,11 @@ module IsoDoc
182
159
  def word_image_caption(docxml)
183
160
  docxml.xpath("//p[@class = 'FigureTitle' or @class = 'SourceTitle']")
184
161
  .each do |t|
185
- if t&.previous_element&.name == "img"
162
+ if t.previous_element&.name == "img"
186
163
  img = t.previous_element
187
164
  t.previous_element.swap("<p class='figure'>#{img.to_xml}</p>")
188
165
  end
189
- style_update(t&.previous_element, "page-break-after:avoid;")
166
+ style_update(t.previous_element, "page-break-after:avoid;")
190
167
  end
191
168
  end
192
169
 
@@ -213,16 +190,14 @@ module IsoDoc
213
190
 
214
191
  def word_table_align(docxml)
215
192
  docxml.xpath("//td[@align]/p | //th[@align]/p").each do |p|
216
- next if p["align"]
217
-
193
+ p["align"] and next
218
194
  style_update(p, "text-align: #{p.parent['align']}")
219
195
  end
220
196
  end
221
197
 
222
198
  def word_table_separator(docxml)
223
199
  docxml.xpath("//p[@class = 'TableTitle']").each do |t|
224
- next unless t.children.empty?
225
-
200
+ t.children.empty? or next
226
201
  t["style"] = t["style"].sub(/;?$/, ";font-size:0pt;")
227
202
  t.children = "&#xa0;"
228
203
  end
@@ -23,164 +23,36 @@ module IsoDoc
23
23
  introxml.to_xml(encoding: "US-ASCII")
24
24
  end
25
25
 
26
- def insert_toc(intro, docxml, level)
27
- toc = ""
28
- toc += make_WordToC(docxml, level)
29
- toc += make_table_word_toc(docxml)
30
- toc += make_figure_word_toc(docxml)
31
- toc += make_recommendation_word_toc(docxml)
32
- intro.sub(/WORDTOC/, toc)
33
- end
34
-
35
- def word_toc_entry(toclevel, heading)
36
- bookmark = bookmarkid # Random.rand(1000000000)
37
- <<~TOC
38
- <p class="MsoToc#{toclevel}"><span class="MsoHyperlink"><span lang="EN-GB" style='mso-no-proof:yes'>
39
- <a href="#_Toc#{bookmark}">#{heading}<span lang="EN-GB" class="MsoTocTextSpan">
40
- <span style='mso-tab-count:1 dotted'>. </span>
41
- </span><span lang="EN-GB" class="MsoTocTextSpan">
42
- <span style='mso-element:field-begin'></span></span>
43
- <span lang="EN-GB" class="MsoTocTextSpan"> PAGEREF _Toc#{bookmark} \\h </span>
44
- <span lang="EN-GB" class="MsoTocTextSpan"><span style='mso-element:field-separator'></span></span><span
45
- lang="EN-GB" class="MsoTocTextSpan">1</span>
46
- <span lang="EN-GB" class="MsoTocTextSpan"></span><span
47
- lang="EN-GB" class="MsoTocTextSpan"><span style='mso-element:field-end'></span></span></a></span></span></p>
48
-
49
- TOC
50
- end
51
-
52
- def word_toc_preface(level)
53
- <<~TOC
54
- <span lang="EN-GB"><span style='mso-element:field-begin'></span><span
55
- style='mso-spacerun:yes'>&#xA0;</span>TOC \\o "1-#{level}" \\h \\z \\u <span
56
- style='mso-element:field-separator'></span></span>
57
- TOC
58
- end
59
-
60
- WORD_TOC_SUFFIX1 = <<~TOC.freeze
61
- <p class="MsoToc1"><span lang="EN-GB"><span
62
- style='mso-element:field-end'></span></span><span
63
- lang="EN-GB"><o:p>&#xA0;</o:p></span></p>
64
- TOC
65
-
66
- def make_WordToC(docxml, level)
67
- toc = ""
68
- # docxml.xpath("//h1 | //h2[not(ancestor::*[@class = 'Section3'])]").
69
- xpath = (1..level).each.map { |i| "//h#{i}" }.join (" | ")
70
- docxml.xpath(xpath).each do |h|
71
- toc += word_toc_entry(h.name[1].to_i, header_strip(h))
72
- end
73
- toc.sub(/(<p class="MsoToc1">)/,
74
- %{\\1#{word_toc_preface(level)}}) + WORD_TOC_SUFFIX1
75
- end
76
-
77
- # inheriting gems need to add native Word name of style, if different
78
- # including both CSS style name and human readable style name.
79
- # Any human readable style name needs to come first for the Word template
80
- # to work in regenerating the ToC
81
- def table_toc_class
82
- %w(TableTitle tabletitle)
83
- end
84
-
85
- def figure_toc_class
86
- %w(FigureTitle figuretitle)
87
- end
88
-
89
- def reqt_toc_class
90
- %w(RecommendationTitle RecommendationTestTitle
91
- recommendationtitle recommendationtesttitle)
92
- end
93
-
94
- def toc_word_class_list(classes)
95
- classes.map do |x|
96
- / /.match?(x) ? %(&quot;#{x}&quot;) : x
97
- end.join(",")
98
- end
99
-
100
- def word_toc_reqt_preface1
101
- <<~TOC
102
- <span lang="EN-GB"><span style='mso-element:field-begin'></span><span
103
- style='mso-spacerun:yes'>&#xA0;</span>TOC \\h \\z \\t #{toc_word_class_list reqt_toc_class}
104
- <span style='mso-element:field-separator'></span></span>
105
- TOC
106
- end
107
-
108
- def word_toc_table_preface1
109
- <<~TOC
110
- <span lang="EN-GB"><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&#xA0;</span>TOC
111
- \\h \\z \\t #{toc_word_class_list table_toc_class} <span style='mso-element:field-separator'></span></span>
112
- TOC
113
- end
114
-
115
- def word_toc_figure_preface1
116
- <<~TOC
117
- <span lang="EN-GB"><span style='mso-element:field-begin'></span><span style='mso-spacerun:yes'>&#xA0;</span>TOC
118
- \\h \\z \\t #{toc_word_class_list figure_toc_class} <span style='mso-element:field-separator'></span></span>
119
- TOC
120
- end
121
-
122
- def table_toc_xpath
123
- attr = table_toc_class.map { |x| "@class = '#{x}'" }
124
- "//p[#{attr.join(' or ')}]"
125
- end
126
-
127
- def make_table_word_toc(docxml)
128
- (docxml.at(table_toc_xpath) && @toctablestitle) or return ""
129
- toc = %{<p class="TOCTitle">#{@toctablestitle}</p>}
130
- docxml.xpath(table_toc_xpath).each do |h|
131
- toc += word_toc_entry(1, header_strip(h))
132
- end
133
- toc.sub(/(<p class="MsoToc1">)/,
134
- %{\\1#{word_toc_table_preface1}}) + WORD_TOC_SUFFIX1
135
- end
136
-
137
- def figure_toc_xpath
138
- attr = figure_toc_class.map { |x| "@class = '#{x}'" }
139
- "//p[#{attr.join(' or ')}]"
140
- end
141
-
142
- def make_figure_word_toc(docxml)
143
- (docxml.at(figure_toc_xpath) && @tocfigurestitle) or return ""
144
- toc = %{<p class="TOCTitle">#{@tocfigurestitle}</p>}
145
- docxml.xpath(figure_toc_xpath).each do |h|
146
- toc += word_toc_entry(1, header_strip(h))
147
- end
148
- toc.sub(/(<p class="MsoToc1">)/,
149
- %{\\1#{word_toc_figure_preface1}}) + WORD_TOC_SUFFIX1
150
- end
151
-
152
- def reqt_toc_xpath
153
- attr = reqt_toc_class.map { |x| "@class = '#{x}'" }
154
- "//p[#{attr.join(' or ')}]"
155
- end
156
-
157
- def make_recommendation_word_toc(docxml)
158
- (docxml.at(reqt_toc_xpath) && @tocrecommendationstitle) or return ""
159
- toc = %{<p class="TOCTitle">#{@tocrecommendationstitle}</p>}
160
- docxml.xpath(reqt_toc_xpath).sort_by do |h|
161
- recommmendation_sort_key(h.text)
162
- end.each do |h|
163
- toc += word_toc_entry(1, header_strip(h))
164
- end
165
- toc.sub(/(<p class="MsoToc1">)/,
166
- %{\\1#{word_toc_reqt_preface1}}) + WORD_TOC_SUFFIX1
167
- end
168
-
169
- def recommmendation_sort_key(header)
170
- m = /^([^0-9]+) (\d+)/.match(header) || /^([^:]+)/.match(header)
171
- m ||= [header, nil]
172
- ret = "#{recommmendation_sort_key1(m[1])}::"
173
- m[2] and ret += ("%04d" % m[2].to_i).to_s
174
- ret
175
- end
176
-
177
- def recommmendation_sort_key1(type)
178
- case type&.downcase
179
- when "requirement" then "04"
180
- when "recommendation" then "05"
181
- when "permission" then "06"
182
- else type
26
+ # add namespaces for Word fragments
27
+ WORD_NOKOHEAD = <<~HERE.freeze
28
+ <!DOCTYPE html SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
29
+ <html xmlns="http://www.w3.org/1999/xhtml"
30
+ xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"
31
+ xmlns:w="urn:schemas-microsoft-com:office:word"
32
+ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
33
+ <head> <title></title> <meta charset="UTF-8" /> </head>
34
+ <body> </body> </html>
35
+ HERE
36
+
37
+ def to_word_xhtml_fragment(xml)
38
+ doc = ::Nokogiri::XML.parse(WORD_NOKOHEAD)
39
+ ::Nokogiri::XML::DocumentFragment.new(doc, xml, doc.root)
40
+ end
41
+
42
+ def wordstylesheet_update
43
+ @wordstylesheet.nil? and return
44
+ f = File.open(@wordstylesheet.path, "a")
45
+ @landscapestyle.empty? or f.write(@landscapestyle)
46
+ s = @meta.get[:code_css] and
47
+ f.write(s.gsub(/sourcecode/, "p.#{sourcecode_style}"))
48
+ if @wordstylesheet_override && @wordstylesheet
49
+ f.write(@wordstylesheet_override.read)
50
+ @wordstylesheet_override.close
51
+ elsif @wordstylesheet_override && !@wordstylesheet
52
+ @wordstylesheet = @wordstylesheet_override
183
53
  end
54
+ f.close
55
+ @wordstylesheet
184
56
  end
185
57
 
186
58
  def authority_cleanup1(docxml, klass)