isodoc 2.4.1 → 2.4.3
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.
- checksums.yaml +4 -4
- data/lib/isodoc/base_style/all.css +29 -0
- data/lib/isodoc/base_style/metanorma_word.css +9 -0
- data/lib/isodoc/base_style/metanorma_word.scss +11 -0
- data/lib/isodoc/base_style/reset.css +29 -0
- data/lib/isodoc/base_style/reset.scss +34 -0
- data/lib/isodoc/base_style/rouge.css +39 -0
- data/lib/isodoc/base_style/typography.scss +1 -1
- data/lib/isodoc/convert.rb +10 -3
- data/lib/isodoc/function/blocks.rb +29 -16
- data/lib/isodoc/function/inline.rb +13 -13
- data/lib/isodoc/function/inline_simple.rb +1 -1
- data/lib/isodoc/function/references.rb +17 -38
- data/lib/isodoc/function/table.rb +1 -1
- data/lib/isodoc/function/to_word_html.rb +0 -4
- data/lib/isodoc/function/utils.rb +6 -2
- data/lib/isodoc/html_function/html.rb +13 -13
- data/lib/isodoc/html_function/postprocess.rb +14 -1
- data/lib/isodoc/metadata.rb +1 -1
- data/lib/isodoc/presentation_function/bibdata.rb +3 -3
- data/lib/isodoc/presentation_function/block.rb +1 -98
- data/lib/isodoc/presentation_function/math.rb +15 -4
- data/lib/isodoc/presentation_function/sourcecode.rb +122 -0
- data/lib/isodoc/presentation_function/terms.rb +14 -27
- data/lib/isodoc/presentation_xml_convert.rb +38 -0
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/word_function/body.rb +19 -19
- data/lib/isodoc/word_function/comments.rb +23 -18
- data/lib/isodoc/word_function/footnotes.rb +8 -8
- data/lib/isodoc/word_function/postprocess.rb +25 -118
- data/lib/isodoc/word_function/postprocess_cover.rb +29 -157
- data/lib/isodoc/word_function/postprocess_table.rb +85 -0
- data/lib/isodoc/word_function/postprocess_toc.rb +165 -0
- data/lib/isodoc/word_function/table.rb +34 -15
- data/lib/isodoc/xref/xref_gen.rb +2 -4
- metadata +6 -2
@@ -4,7 +4,7 @@ module IsoDoc
|
|
4
4
|
def comments(div)
|
5
5
|
return if @comments.empty?
|
6
6
|
|
7
|
-
div.div
|
7
|
+
div.div style: "mso-element:comment-list" do |div1|
|
8
8
|
@comments.each { |fn| div1.parent << fn }
|
9
9
|
end
|
10
10
|
end
|
@@ -26,28 +26,27 @@ module IsoDoc
|
|
26
26
|
# add in from and to links to move the comment into place
|
27
27
|
def make_comment_link(out, fnote, node)
|
28
28
|
out.span(**comment_link_attrs(fnote, node)) do |s1|
|
29
|
-
s1.span
|
30
|
-
s2.a
|
29
|
+
s1.span lang: "EN-GB", style: "font-size:9.0pt" do |s2|
|
30
|
+
s2.a style: "mso-comment-reference:SMC_#{fnote};" \
|
31
31
|
"mso-comment-date:#{node['date'].gsub(/[:-]+/,
|
32
|
-
'')}"
|
33
|
-
s2.span
|
34
|
-
target: fnote } # do |s|
|
32
|
+
'')}"
|
33
|
+
s2.span style: "mso-special-character:comment", target: fnote # do |s|
|
35
34
|
end
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
39
38
|
def make_comment_target(out)
|
40
|
-
out.span
|
41
|
-
s1.span
|
42
|
-
s2.span
|
39
|
+
out.span style: "MsoCommentReference" do |s1|
|
40
|
+
s1.span lang: "EN-GB", style: "font-size:9.0pt" do |s2|
|
41
|
+
s2.span style: "mso-special-character:comment"
|
43
42
|
end
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
47
46
|
def make_comment_text(node, fnote)
|
48
47
|
noko do |xml|
|
49
|
-
xml.div
|
50
|
-
div.span
|
48
|
+
xml.div style: "mso-element:comment", id: fnote do |div|
|
49
|
+
div.span style: %{mso-comment-author:"#{node['reviewer']}"}
|
51
50
|
make_comment_target(div)
|
52
51
|
node.children.each { |n| parse(n, div) }
|
53
52
|
end
|
@@ -61,7 +60,7 @@ module IsoDoc
|
|
61
60
|
end
|
62
61
|
|
63
62
|
COMMENT_IN_COMMENT_LIST1 =
|
64
|
-
'//div[@style="mso-element:comment-list"]//'\
|
63
|
+
'//div[@style="mso-element:comment-list"]//' \
|
65
64
|
'span[@style="MsoCommentReference"]'.freeze
|
66
65
|
|
67
66
|
def embed_comment_in_comment_list(docxml)
|
@@ -80,18 +79,24 @@ module IsoDoc
|
|
80
79
|
link.children = fromlink
|
81
80
|
end
|
82
81
|
|
83
|
-
def comment_attributes(docxml,
|
84
|
-
fromlink = docxml.at("//*[@id='#{
|
82
|
+
def comment_attributes(docxml, span)
|
83
|
+
fromlink = docxml.at("//*[@id='#{span['from']}']")
|
85
84
|
return(nil) if fromlink.nil?
|
86
85
|
|
87
|
-
tolink = docxml.at("//*[@id='#{
|
88
|
-
target = docxml.at("//*[@id='#{
|
86
|
+
tolink = docxml.at("//*[@id='#{span['to']}']") || fromlink
|
87
|
+
target = docxml.at("//*[@id='#{span['target']}']")
|
89
88
|
{ from: fromlink, to: tolink, target: target }
|
90
89
|
end
|
91
90
|
|
92
91
|
def wrap_comment_cont(from, target)
|
93
|
-
|
94
|
-
|
92
|
+
if %w(ol ul li div p).include?(from.name)
|
93
|
+
from.children.each do |c|
|
94
|
+
wrap_comment_cont(c, target)
|
95
|
+
end
|
96
|
+
else
|
97
|
+
s = from.replace("<span style='mso-comment-continuation:#{target}'>")
|
98
|
+
s.first.children = from
|
99
|
+
end
|
95
100
|
end
|
96
101
|
|
97
102
|
def skip_comment_wrap(from)
|
@@ -45,7 +45,7 @@ module IsoDoc
|
|
45
45
|
|
46
46
|
def make_generic_footnote_text(node, fnid)
|
47
47
|
noko do |xml|
|
48
|
-
xml.aside
|
48
|
+
xml.aside id: "ftn#{fnid}" do |div|
|
49
49
|
node.children.each { |n| parse(n, div) }
|
50
50
|
end
|
51
51
|
end.join("\n")
|
@@ -72,13 +72,13 @@ module IsoDoc
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def seen_footnote_parse(_node, out, footnote)
|
75
|
-
out.span
|
75
|
+
out.span style: "mso-element:field-begin"
|
76
76
|
out << " NOTEREF _Ref#{@fn_bookmarks[footnote]} \\f \\h"
|
77
|
-
out.span
|
78
|
-
out.span
|
77
|
+
out.span style: "mso-element:field-separator"
|
78
|
+
out.span class: "MsoFootnoteReference" do |s|
|
79
79
|
s << footnote
|
80
80
|
end
|
81
|
-
out.span
|
81
|
+
out.span style: "mso-element:field-end"
|
82
82
|
end
|
83
83
|
|
84
84
|
def footnote_parse(node, out)
|
@@ -89,9 +89,9 @@ module IsoDoc
|
|
89
89
|
return seen_footnote_parse(node, out, fn) if @seen_footnote.include?(fn)
|
90
90
|
|
91
91
|
@fn_bookmarks[fn] = bookmarkid
|
92
|
-
out.span
|
93
|
-
s.a
|
94
|
-
|
92
|
+
out.span style: "mso-bookmark:_Ref#{@fn_bookmarks[fn]}" do |s|
|
93
|
+
s.a class: "FootnoteRef", "epub:type": "footnote",
|
94
|
+
href: "#ftn#{fn}" do |a|
|
95
95
|
a.sup { |sup| sup << fn }
|
96
96
|
end
|
97
97
|
end
|
@@ -1,34 +1,11 @@
|
|
1
1
|
require "fileutils"
|
2
2
|
require_relative "./postprocess_cover"
|
3
|
+
require_relative "./postprocess_toc"
|
4
|
+
require_relative "./postprocess_table"
|
3
5
|
|
4
6
|
module IsoDoc
|
5
7
|
module WordFunction
|
6
8
|
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
|
-
def table_note_cleanup(docxml)
|
24
|
-
super
|
25
|
-
# preempt html2doc putting MsoNormal there
|
26
|
-
docxml.xpath("//p[not(self::*[@class])][ancestor::*[@class = 'Note']]")
|
27
|
-
.each do |p|
|
28
|
-
p["class"] = "Note"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
9
|
def postprocess(result, filename, dir)
|
33
10
|
filename = filename.sub(/\.doc$/, "")
|
34
11
|
header = generate_header(filename, dir)
|
@@ -56,23 +33,6 @@ module IsoDoc
|
|
56
33
|
"Sourcecode"
|
57
34
|
end
|
58
35
|
|
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
36
|
def word_admonition_images(docxml)
|
77
37
|
docxml.xpath("//div[@class = 'Admonition']//img").each do |i|
|
78
38
|
i["width"], i["height"] =
|
@@ -84,10 +44,12 @@ module IsoDoc
|
|
84
44
|
def word_cleanup(docxml)
|
85
45
|
word_annex_cleanup(docxml)
|
86
46
|
word_preface(docxml)
|
47
|
+
word_sourcecode_annotations(docxml)
|
87
48
|
word_sourcecode_table(docxml)
|
88
49
|
word_nested_tables(docxml)
|
89
50
|
word_colgroup(docxml)
|
90
51
|
word_table_align(docxml)
|
52
|
+
word_table_pagebreak(docxml)
|
91
53
|
word_table_separator(docxml)
|
92
54
|
word_admonition_images(docxml)
|
93
55
|
word_list_continuations(docxml)
|
@@ -101,18 +63,29 @@ module IsoDoc
|
|
101
63
|
docxml
|
102
64
|
end
|
103
65
|
|
104
|
-
def
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
d.
|
66
|
+
def word_sourcecode_annotations(html)
|
67
|
+
ann = ".//div[@class = 'annotation']"
|
68
|
+
html.xpath("//p[@class = '#{sourcecode_style}'][#{ann}]")
|
69
|
+
.each do |p|
|
70
|
+
ins = p.after("<p class='#{sourcecode_style}'/>").next_element
|
71
|
+
p.xpath(ann).each do |d|
|
72
|
+
ins << d.remove.children
|
111
73
|
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def word_sourcecode_table(docxml)
|
78
|
+
s = "p[@class='#{sourcecode_style}']"
|
79
|
+
docxml.xpath("//#{s}/div[@class='table_container']").each do |d|
|
80
|
+
pre = d.at(".//#{s}")
|
81
|
+
to_sourcecode_para(pre)
|
82
|
+
d["id"] = d.parent["id"]
|
83
|
+
d.parent.replace(d)
|
84
|
+
end
|
112
85
|
end
|
113
86
|
|
114
87
|
def to_sourcecode_para(pre)
|
115
|
-
@sourcecode =
|
88
|
+
@sourcecode = "pre"
|
116
89
|
pre.traverse do |x|
|
117
90
|
x.text? or next
|
118
91
|
ret = []
|
@@ -130,63 +103,14 @@ module IsoDoc
|
|
130
103
|
end
|
131
104
|
end
|
132
105
|
|
133
|
-
def word_colgroup(docxml)
|
134
|
-
cells2d = {}
|
135
|
-
docxml.xpath("//table[colgroup]").each do |t|
|
136
|
-
w = colgroup_widths(t)
|
137
|
-
t.xpath(".//tr").each_with_index { |_tr, r| cells2d[r] = {} }
|
138
|
-
t.xpath(".//tr").each_with_index do |tr, r|
|
139
|
-
tr.xpath("./td | ./th").each_with_index do |td, _i|
|
140
|
-
x = 0
|
141
|
-
rs = td.attr("rowspan")&.to_i || 1
|
142
|
-
cs = td.attr("colspan")&.to_i || 1
|
143
|
-
while cells2d[r][x]
|
144
|
-
x += 1
|
145
|
-
end
|
146
|
-
(r..(r + rs - 1)).each do |y2|
|
147
|
-
cells2d[y2].nil? and next
|
148
|
-
(x..(x + cs - 1)).each { |x2| cells2d[y2][x2] = 1 }
|
149
|
-
end
|
150
|
-
width = (x..(x + cs - 1)).each_with_object({ width: 0 }) do |z, m|
|
151
|
-
m[:width] += w[z]
|
152
|
-
end
|
153
|
-
td["width"] = "#{width[:width]}%"
|
154
|
-
x += cs
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
# assume percentages
|
161
|
-
def colgroup_widths(table)
|
162
|
-
table.xpath("./colgroup/col").each_with_object([]) do |c, m|
|
163
|
-
m << c["width"].sub(/%$/, "").to_f
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
def word_nested_tables(docxml)
|
168
|
-
docxml.xpath("//table").each do |t|
|
169
|
-
t.xpath(".//table").reverse.each do |tt|
|
170
|
-
t.next = tt.remove
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
def style_update(node, css)
|
176
|
-
return unless node
|
177
|
-
|
178
|
-
node["style"] =
|
179
|
-
node["style"] ? node["style"].sub(/;?$/, ";#{css}") : css
|
180
|
-
end
|
181
|
-
|
182
106
|
def word_image_caption(docxml)
|
183
107
|
docxml.xpath("//p[@class = 'FigureTitle' or @class = 'SourceTitle']")
|
184
108
|
.each do |t|
|
185
|
-
if t
|
109
|
+
if t.previous_element&.name == "img"
|
186
110
|
img = t.previous_element
|
187
111
|
t.previous_element.swap("<p class='figure'>#{img.to_xml}</p>")
|
188
112
|
end
|
189
|
-
style_update(t
|
113
|
+
style_update(t.previous_element, "page-break-after:avoid;")
|
190
114
|
end
|
191
115
|
end
|
192
116
|
|
@@ -211,23 +135,6 @@ module IsoDoc
|
|
211
135
|
end
|
212
136
|
end
|
213
137
|
|
214
|
-
def word_table_align(docxml)
|
215
|
-
docxml.xpath("//td[@align]/p | //th[@align]/p").each do |p|
|
216
|
-
next if p["align"]
|
217
|
-
|
218
|
-
style_update(p, "text-align: #{p.parent['align']}")
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
def word_table_separator(docxml)
|
223
|
-
docxml.xpath("//p[@class = 'TableTitle']").each do |t|
|
224
|
-
next unless t.children.empty?
|
225
|
-
|
226
|
-
t["style"] = t["style"].sub(/;?$/, ";font-size:0pt;")
|
227
|
-
t.children = " "
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
138
|
def word_annex_cleanup(docxml); end
|
232
139
|
|
233
140
|
def word_example_cleanup(docxml)
|
@@ -23,164 +23,36 @@ module IsoDoc
|
|
23
23
|
introxml.to_xml(encoding: "US-ASCII")
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
<<~TOC
|
54
|
-
<span lang="EN-GB"><span style='mso-element:field-begin'></span><span
|
55
|
-
style='mso-spacerun:yes'> </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> </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) ? %("#{x}") : 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'> </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'> </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'> </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)
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module IsoDoc
|
2
|
+
module WordFunction
|
3
|
+
module Postprocess
|
4
|
+
def table_note_cleanup(docxml)
|
5
|
+
super
|
6
|
+
# preempt html2doc putting MsoNormal there
|
7
|
+
docxml.xpath("//p[not(self::*[@class])][ancestor::*[@class = 'Note']]")
|
8
|
+
.each { |p| p["class"] = "Note" }
|
9
|
+
end
|
10
|
+
|
11
|
+
def word_colgroup(docxml)
|
12
|
+
cells2d = {}
|
13
|
+
docxml.xpath("//table[colgroup]").each do |t|
|
14
|
+
w = colgroup_widths(t)
|
15
|
+
t.xpath(".//tr").each_with_index { |_tr, r| cells2d[r] = {} }
|
16
|
+
t.xpath(".//tr").each_with_index do |tr, r|
|
17
|
+
tr.xpath("./td | ./th").each_with_index do |td, _i|
|
18
|
+
x = 0
|
19
|
+
rs = td.attr("rowspan")&.to_i || 1
|
20
|
+
cs = td.attr("colspan")&.to_i || 1
|
21
|
+
while cells2d[r][x]
|
22
|
+
x += 1
|
23
|
+
end
|
24
|
+
(r..(r + rs - 1)).each do |y2|
|
25
|
+
cells2d[y2].nil? and next
|
26
|
+
(x..(x + cs - 1)).each { |x2| cells2d[y2][x2] = 1 }
|
27
|
+
end
|
28
|
+
width = (x..(x + cs - 1)).each_with_object({ width: 0 }) do |z, m|
|
29
|
+
m[:width] += w[z]
|
30
|
+
end
|
31
|
+
td["width"] = "#{width[:width]}%"
|
32
|
+
x += cs
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# assume percentages
|
39
|
+
def colgroup_widths(table)
|
40
|
+
table.xpath("./colgroup/col").each_with_object([]) do |c, m|
|
41
|
+
m << c["width"].sub(/%$/, "").to_f
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def word_nested_tables(docxml)
|
46
|
+
docxml.xpath("//table").each do |t|
|
47
|
+
t.xpath(".//table").reverse.each do |tt|
|
48
|
+
t.next = tt.remove
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def style_update(node, css)
|
54
|
+
node or return
|
55
|
+
node["style"] =
|
56
|
+
node["style"] ? node["style"].sub(/;?$/, ";#{css}") : css
|
57
|
+
end
|
58
|
+
|
59
|
+
def word_table_align(docxml)
|
60
|
+
docxml.xpath("//td[@align]/p | //th[@align]/p").each do |p|
|
61
|
+
p["align"] and next
|
62
|
+
style_update(p, "text-align: #{p.parent['align']}")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def word_table_separator(docxml)
|
67
|
+
docxml.xpath("//p[@class = 'TableTitle']").each do |t|
|
68
|
+
t.children.empty? or next
|
69
|
+
t["style"] = t["style"].sub(/;?$/, ";font-size:0pt;")
|
70
|
+
t.children = " "
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def word_table_pagebreak(docxml)
|
75
|
+
docxml.xpath("//td[@style] | //th[@style]").each do |t|
|
76
|
+
s = /(page-break-after:[^;]+)/.match(t["style"])
|
77
|
+
(s && s[1]) or next
|
78
|
+
t.xpath(".//div | .//p | .//pre").each do |p|
|
79
|
+
style_update(p, s[1])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|