isodoc 2.4.0 → 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.
- checksums.yaml +4 -4
- data/isodoc.gemspec +1 -0
- 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 +6 -3
- data/lib/isodoc/convert.rb +7 -4
- data/lib/isodoc/function/blocks.rb +26 -16
- data/lib/isodoc/function/inline.rb +17 -17
- data/lib/isodoc/function/references.rb +38 -52
- data/lib/isodoc/function/table.rb +22 -13
- data/lib/isodoc/function/to_word_html.rb +1 -4
- data/lib/isodoc/function/utils.rb +5 -1
- data/lib/isodoc/html_function/html.rb +13 -34
- data/lib/isodoc/html_function/postprocess.rb +14 -1
- data/lib/isodoc/html_function/postprocess_cover.rb +6 -9
- data/lib/isodoc/metadata.rb +5 -0
- data/lib/isodoc/presentation_function/block.rb +15 -46
- data/lib/isodoc/presentation_function/refs.rb +75 -3
- data/lib/isodoc/presentation_function/sourcecode.rb +114 -0
- data/lib/isodoc/presentation_function/terms.rb +29 -37
- data/lib/isodoc/presentation_function/xrefs.rb +9 -6
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/word_function/body.rb +16 -16
- data/lib/isodoc/word_function/postprocess.rb +47 -43
- data/lib/isodoc/word_function/postprocess_cover.rb +29 -157
- data/lib/isodoc/word_function/postprocess_toc.rb +165 -0
- data/lib/isodoc/word_function/table.rb +25 -13
- data/lib/isodoc/xref/xref_gen.rb +2 -4
- metadata +19 -2
@@ -1,17 +1,19 @@
|
|
1
1
|
module IsoDoc
|
2
2
|
class PresentationXMLConvert < ::IsoDoc::Convert
|
3
3
|
def concept(docxml)
|
4
|
+
@definition_ids = docxml.xpath(ns("//definitions//dt"))
|
5
|
+
.each_with_object({}) { |x, m| m[x["id"]] = true }
|
4
6
|
docxml.xpath(ns("//concept")).each { |f| concept1(f) }
|
5
7
|
end
|
6
8
|
|
7
9
|
def concept1(node)
|
8
10
|
xref = node&.at(ns("./xref/@target"))&.text or
|
9
|
-
return concept_render(node, ital: "true", ref: "true",
|
11
|
+
return concept_render(node, ital: "true", ref: "true", bold: "false",
|
10
12
|
linkref: "true", linkmention: "false")
|
11
|
-
if
|
12
|
-
concept_render(node, ital: "false", ref: "false",
|
13
|
+
if @definition_ids[xref]
|
14
|
+
concept_render(node, ital: "false", ref: "false", bold: "false",
|
13
15
|
linkref: "true", linkmention: "false")
|
14
|
-
else concept_render(node, ital: "true", ref: "true",
|
16
|
+
else concept_render(node, ital: "true", ref: "true", bold: "false",
|
15
17
|
linkref: "true", linkmention: "false")
|
16
18
|
end
|
17
19
|
end
|
@@ -20,21 +22,23 @@ module IsoDoc
|
|
20
22
|
opts, render, ref = concept_render_init(node, defaults)
|
21
23
|
node&.at(ns("./refterm"))&.remove
|
22
24
|
ref && opts[:ref] != "false" and render&.next = " "
|
23
|
-
opts[:ital] == "true" and render&.name = "em"
|
24
25
|
concept1_linkmention(ref, render, opts)
|
25
26
|
concept1_ref(node, ref, opts)
|
26
|
-
|
27
|
+
concept1_style(node, opts)
|
27
28
|
node.replace(node.children)
|
28
29
|
end
|
29
30
|
|
30
|
-
def
|
31
|
-
|
32
|
-
r =
|
33
|
-
|
31
|
+
def concept1_style(node, opts)
|
32
|
+
r = node.at(ns(".//renderterm")) or return
|
33
|
+
opts[:ital] == "true" and r.children = "<em>#{to_xml(r.children)}</em>"
|
34
|
+
opts[:bold] == "true" and
|
35
|
+
r.children = "<strong>#{to_xml(r.children)}</strong>"
|
36
|
+
r.replace(r.children)
|
34
37
|
end
|
35
38
|
|
36
39
|
def concept_render_init(node, defaults)
|
37
|
-
opts = %i(ital ref linkref linkmention)
|
40
|
+
opts = %i(bold ital ref linkref linkmention)
|
41
|
+
.each_with_object({}) do |x, m|
|
38
42
|
m[x] = node[x.to_s] || defaults[x]
|
39
43
|
end
|
40
44
|
[opts, node.at(ns("./renderterm")),
|
@@ -42,8 +46,8 @@ module IsoDoc
|
|
42
46
|
end
|
43
47
|
|
44
48
|
def concept1_linkmention(ref, renderterm, opts)
|
45
|
-
|
46
|
-
|
49
|
+
(opts[:linkmention] == "true" &&
|
50
|
+
!renderterm.nil? && !ref.nil?) or return
|
47
51
|
ref2 = ref.clone
|
48
52
|
r2 = renderterm.clone
|
49
53
|
renderterm.replace(ref2).children = r2
|
@@ -51,16 +55,14 @@ module IsoDoc
|
|
51
55
|
|
52
56
|
def concept1_ref(_node, ref, opts)
|
53
57
|
ref.nil? and return
|
54
|
-
|
55
|
-
|
58
|
+
opts[:ref] == "false" and return ref.remove
|
56
59
|
r = concept1_ref_content(ref)
|
57
60
|
ref = r.at("./descendant-or-self::xmlns:xref | " \
|
58
61
|
"./descendant-or-self::xmlns:eref | " \
|
59
62
|
"./descendant-or-self::xmlns:termref")
|
60
63
|
%w(xref eref).include? ref&.name and get_linkend(ref)
|
61
|
-
|
64
|
+
opts[:linkref] == "false" && %w(xref eref).include?(ref&.name) and
|
62
65
|
ref.replace(ref.children)
|
63
|
-
end
|
64
66
|
end
|
65
67
|
|
66
68
|
def concept1_ref_content(ref)
|
@@ -92,9 +94,8 @@ module IsoDoc
|
|
92
94
|
|
93
95
|
def designation(docxml)
|
94
96
|
docxml.xpath(ns("//term")).each { |t| merge_second_preferred(t) }
|
95
|
-
docxml.xpath(ns("//preferred | //admitted | //deprecates"))
|
96
|
-
designation1(p)
|
97
|
-
end
|
97
|
+
docxml.xpath(ns("//preferred | //admitted | //deprecates"))
|
98
|
+
.each { |p| designation1(p) }
|
98
99
|
end
|
99
100
|
|
100
101
|
def merge_second_preferred(term)
|
@@ -107,11 +108,10 @@ module IsoDoc
|
|
107
108
|
end
|
108
109
|
|
109
110
|
def merge_second_preferred1(pref, second)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
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)}")
|
115
115
|
end
|
116
116
|
|
117
117
|
def merge_preferred_eligible?(first, second)
|
@@ -127,7 +127,6 @@ module IsoDoc
|
|
127
127
|
s = desgn.at(ns("./termsource"))
|
128
128
|
name = desgn.at(ns("./expression/name | ./letter-symbol/name | " \
|
129
129
|
"./graphical-symbol")) or return
|
130
|
-
|
131
130
|
designation_annotate(desgn, name)
|
132
131
|
s and desgn.next = s
|
133
132
|
end
|
@@ -151,8 +150,7 @@ module IsoDoc
|
|
151
150
|
def designation_field(desgn, name)
|
152
151
|
f = desgn.xpath(ns("./field-of-application | ./usage-info"))
|
153
152
|
&.map { |u| to_xml(u.children) }&.join(", ")
|
154
|
-
|
155
|
-
|
153
|
+
f&.empty? and return nil
|
156
154
|
name << ", <#{f}>"
|
157
155
|
end
|
158
156
|
|
@@ -173,27 +171,21 @@ module IsoDoc
|
|
173
171
|
loc = [desgn&.at(ns("./expression/@language"))&.text,
|
174
172
|
desgn&.at(ns("./expression/@script"))&.text,
|
175
173
|
desgn&.at(ns("./@geographic-area"))&.text].compact
|
176
|
-
|
177
|
-
|
174
|
+
loc.empty? and return
|
178
175
|
name << ", #{loc.join(' ')}"
|
179
176
|
end
|
180
177
|
|
181
178
|
def designation_pronunciation(desgn, name)
|
182
179
|
f = desgn.at(ns("./expression/pronunciation")) or return
|
183
|
-
|
184
180
|
name << ", /#{to_xml(f.children)}/"
|
185
181
|
end
|
186
182
|
|
187
183
|
def termexample(docxml)
|
188
|
-
docxml.xpath(ns("//termexample")).each
|
189
|
-
example1(f)
|
190
|
-
end
|
184
|
+
docxml.xpath(ns("//termexample")).each { |f| example1(f) }
|
191
185
|
end
|
192
186
|
|
193
187
|
def termnote(docxml)
|
194
|
-
docxml.xpath(ns("//termnote")).each
|
195
|
-
termnote1(f)
|
196
|
-
end
|
188
|
+
docxml.xpath(ns("//termnote")).each { |f| termnote1(f) }
|
197
189
|
end
|
198
190
|
|
199
191
|
def termnote1(elem)
|
@@ -38,15 +38,18 @@ module IsoDoc
|
|
38
38
|
def anchor_xref(node, target)
|
39
39
|
x = @xrefs.anchor(target, :xref)
|
40
40
|
t = @xrefs.anchor(target, :title)
|
41
|
-
case node["style"]
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
41
|
+
ret = case node["style"]
|
42
|
+
when "basic" then t
|
43
|
+
when "full" then anchor_xref_full(x, t)
|
44
|
+
when "short", nil then x
|
45
|
+
else @xrefs.anchor(target, node[:style].to_sym)
|
46
|
+
end
|
47
|
+
ret || x
|
47
48
|
end
|
48
49
|
|
49
50
|
def anchor_xref_full(num, title)
|
51
|
+
(!title.nil? && !title.empty?) or return nil
|
52
|
+
|
50
53
|
l10n("#{num}, #{title}")
|
51
54
|
end
|
52
55
|
|
data/lib/isodoc/version.rb
CHANGED
@@ -19,14 +19,14 @@ module IsoDoc
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def make_body1(body, _docxml)
|
22
|
-
body.div
|
22
|
+
body.div class: "WordSection1" do |div1|
|
23
23
|
div1.p { |p| p << " " } # placeholder
|
24
24
|
end
|
25
25
|
section_break(body)
|
26
26
|
end
|
27
27
|
|
28
28
|
def make_body2(body, docxml)
|
29
|
-
body.div
|
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
|
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
|
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
|
107
|
+
tr.td valign: "top", align: "left" do |term|
|
108
108
|
dt_parse(dterm, term)
|
109
109
|
end
|
110
|
-
tr.td
|
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
|
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
|
153
|
-
p.span
|
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
|
165
|
-
p.span
|
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
|
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
|
28
|
-
p["class"] = "Note"
|
29
|
-
end
|
12
|
+
.each { |p| p["class"] = "Note" }
|
30
13
|
end
|
31
14
|
|
32
15
|
def postprocess(result, filename, dir)
|
@@ -52,31 +35,23 @@ module IsoDoc
|
|
52
35
|
@wordstylesheet.unlink if @wordstylesheet.is_a?(Tempfile)
|
53
36
|
end
|
54
37
|
|
55
|
-
def
|
56
|
-
|
57
|
-
|
58
|
-
f = File.open(@wordstylesheet.path, "a")
|
59
|
-
@landscapestyle.empty? or f.write(@landscapestyle)
|
60
|
-
if @wordstylesheet_override && @wordstylesheet
|
61
|
-
f.write(@wordstylesheet_override.read)
|
62
|
-
@wordstylesheet_override.close
|
63
|
-
elsif @wordstylesheet_override && !@wordstylesheet
|
64
|
-
@wordstylesheet = @wordstylesheet_override
|
65
|
-
end
|
66
|
-
f.close
|
67
|
-
@wordstylesheet
|
38
|
+
def sourcecode_style
|
39
|
+
"Sourcecode"
|
68
40
|
end
|
69
41
|
|
70
42
|
def word_admonition_images(docxml)
|
71
43
|
docxml.xpath("//div[@class = 'Admonition']//img").each do |i|
|
72
44
|
i["width"], i["height"] =
|
73
|
-
Html2Doc.new({}).image_resize(i, image_localfile(i), @maxheight,
|
45
|
+
Html2Doc.new({}).image_resize(i, image_localfile(i), @maxheight,
|
46
|
+
300)
|
74
47
|
end
|
75
48
|
end
|
76
49
|
|
77
50
|
def word_cleanup(docxml)
|
78
51
|
word_annex_cleanup(docxml)
|
79
52
|
word_preface(docxml)
|
53
|
+
word_sourcecode_annotations(docxml)
|
54
|
+
word_sourcecode_table(docxml)
|
80
55
|
word_nested_tables(docxml)
|
81
56
|
word_colgroup(docxml)
|
82
57
|
word_table_align(docxml)
|
@@ -93,6 +68,38 @@ module IsoDoc
|
|
93
68
|
docxml
|
94
69
|
end
|
95
70
|
|
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
|
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
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_sourcecode_para(pre)
|
93
|
+
@sourcecode = "pre"
|
94
|
+
pre.traverse do |x|
|
95
|
+
x.text? or next
|
96
|
+
ret = []
|
97
|
+
text_parse(x, ret)
|
98
|
+
x.replace(ret.join)
|
99
|
+
end
|
100
|
+
@sourcecode = false
|
101
|
+
end
|
102
|
+
|
96
103
|
def word_tab_clean(docxml)
|
97
104
|
docxml.xpath("//p[@class='Biblio']//span[@style='mso-tab-count:1']")
|
98
105
|
.each do |s|
|
@@ -144,8 +151,7 @@ module IsoDoc
|
|
144
151
|
end
|
145
152
|
|
146
153
|
def style_update(node, css)
|
147
|
-
|
148
|
-
|
154
|
+
node or return
|
149
155
|
node["style"] =
|
150
156
|
node["style"] ? node["style"].sub(/;?$/, ";#{css}") : css
|
151
157
|
end
|
@@ -153,11 +159,11 @@ module IsoDoc
|
|
153
159
|
def word_image_caption(docxml)
|
154
160
|
docxml.xpath("//p[@class = 'FigureTitle' or @class = 'SourceTitle']")
|
155
161
|
.each do |t|
|
156
|
-
if t
|
162
|
+
if t.previous_element&.name == "img"
|
157
163
|
img = t.previous_element
|
158
|
-
t.previous_element.swap("<p class
|
164
|
+
t.previous_element.swap("<p class='figure'>#{img.to_xml}</p>")
|
159
165
|
end
|
160
|
-
style_update(t
|
166
|
+
style_update(t.previous_element, "page-break-after:avoid;")
|
161
167
|
end
|
162
168
|
end
|
163
169
|
|
@@ -184,16 +190,14 @@ module IsoDoc
|
|
184
190
|
|
185
191
|
def word_table_align(docxml)
|
186
192
|
docxml.xpath("//td[@align]/p | //th[@align]/p").each do |p|
|
187
|
-
|
188
|
-
|
193
|
+
p["align"] and next
|
189
194
|
style_update(p, "text-align: #{p.parent['align']}")
|
190
195
|
end
|
191
196
|
end
|
192
197
|
|
193
198
|
def word_table_separator(docxml)
|
194
199
|
docxml.xpath("//p[@class = 'TableTitle']").each do |t|
|
195
|
-
|
196
|
-
|
200
|
+
t.children.empty? or next
|
197
201
|
t["style"] = t["style"].sub(/;?$/, ";font-size:0pt;")
|
198
202
|
t.children = " "
|
199
203
|
end
|
@@ -231,7 +235,7 @@ module IsoDoc
|
|
231
235
|
docxml.xpath("//a[@epub:type = 'footnote']").each do |x|
|
232
236
|
footnote_reference_format(x)
|
233
237
|
end
|
234
|
-
docxml.xpath("//a[@class = 'TableFootnoteRef'] | "\
|
238
|
+
docxml.xpath("//a[@class = 'TableFootnoteRef'] | " \
|
235
239
|
"//span[@class = 'TableFootnoteRef']").each do |x|
|
236
240
|
table_footnote_reference_format(x)
|
237
241
|
end
|
@@ -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)
|