isodoc 1.2.7 → 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +14 -9
- data/README.adoc +1 -3
- data/isodoc.gemspec +1 -1
- data/lib/isodoc-yaml/i18n-en.yaml +56 -0
- data/lib/isodoc-yaml/i18n-fr.yaml +64 -7
- data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
- data/lib/isodoc/base_style/blocks.scss +2 -2
- data/lib/isodoc/base_style/typography.scss +1 -1
- data/lib/isodoc/convert.rb +13 -85
- data/lib/isodoc/css.rb +95 -0
- data/lib/isodoc/function/inline.rb +0 -33
- data/lib/isodoc/function/inline_simple.rb +10 -1
- data/lib/isodoc/function/lists.rb +2 -1
- data/lib/isodoc/function/references.rb +8 -13
- data/lib/isodoc/function/section.rb +1 -1
- data/lib/isodoc/function/table.rb +10 -0
- data/lib/isodoc/function/to_word_html.rb +2 -2
- data/lib/isodoc/gem_tasks.rb +4 -0
- data/lib/isodoc/html_function/html.rb +7 -0
- data/lib/isodoc/html_function/mathvariant_to_plain.rb +82 -0
- data/lib/isodoc/html_function/postprocess.rb +41 -20
- data/lib/isodoc/i18n.rb +15 -2
- data/lib/isodoc/metadata_contributor.rb +4 -3
- data/lib/isodoc/presentation_function/bibdata.rb +3 -3
- data/lib/isodoc/presentation_function/block.rb +14 -9
- data/lib/isodoc/presentation_function/inline.rb +126 -22
- data/lib/isodoc/presentation_function/section.rb +9 -0
- data/lib/isodoc/presentation_xml_convert.rb +5 -0
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/word_convert.rb +0 -20
- data/lib/isodoc/word_function/body.rb +12 -0
- data/lib/isodoc/word_function/postprocess.rb +38 -80
- data/lib/isodoc/word_function/postprocess_cover.rb +55 -0
- data/lib/isodoc/word_function/table.rb +10 -0
- data/lib/isodoc/xref.rb +1 -0
- data/lib/isodoc/xref/xref_counter.rb +20 -9
- data/lib/isodoc/xref/xref_gen.rb +20 -2
- data/lib/isodoc/xref/xref_sect_gen.rb +1 -1
- data/spec/assets/html.scss +14 -0
- data/spec/assets/i18n.yaml +7 -6
- data/spec/isodoc/blocks_spec.rb +2 -1
- data/spec/isodoc/cleanup_spec.rb +0 -1
- data/spec/isodoc/footnotes_spec.rb +4 -5
- data/spec/isodoc/i18n_spec.rb +23 -2
- data/spec/isodoc/inline_spec.rb +182 -202
- data/spec/isodoc/lists_spec.rb +1 -1
- data/spec/isodoc/metadata_spec.rb +3 -1
- data/spec/isodoc/postproc_spec.rb +472 -11
- data/spec/isodoc/presentation_xml_spec.rb +584 -1
- data/spec/isodoc/ref_spec.rb +325 -7
- data/spec/isodoc/table_spec.rb +28 -0
- data/spec/isodoc/xref_spec.rb +162 -17
- metadata +18 -16
data/lib/isodoc/i18n.rb
CHANGED
@@ -4,8 +4,21 @@ module IsoDoc
|
|
4
4
|
class I18n
|
5
5
|
def load_yaml(lang, script, i18nyaml = nil)
|
6
6
|
ret = load_yaml1(lang, script)
|
7
|
-
return ret.merge(YAML.load_file(i18nyaml)) if i18nyaml
|
8
|
-
ret
|
7
|
+
return normalise_hash(ret.merge(YAML.load_file(i18nyaml))) if i18nyaml
|
8
|
+
normalise_hash(ret)
|
9
|
+
end
|
10
|
+
|
11
|
+
def normalise_hash(ret)
|
12
|
+
if ret.is_a? Hash
|
13
|
+
ret.each do |k, v|
|
14
|
+
ret[k] = normalise_hash(v)
|
15
|
+
end
|
16
|
+
ret
|
17
|
+
elsif ret.is_a? Array then ret.map { |n| normalise_hash(n) }
|
18
|
+
elsif ret.is_a? String then ret.unicode_normalize(:nfc)
|
19
|
+
else
|
20
|
+
ret
|
21
|
+
end
|
9
22
|
end
|
10
23
|
|
11
24
|
def load_yaml1(lang, script)
|
@@ -17,9 +17,10 @@ module IsoDoc
|
|
17
17
|
def extract_person_affiliations(authors)
|
18
18
|
authors.reduce([]) do |m, a|
|
19
19
|
name = a&.at(ns('./affiliation/organization/name'))&.text
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
subdivs = a&.xpath(ns('./affiliation/organization/subdivision'))&.map(&:text)&.join(", ")
|
21
|
+
name and subdivs and !subdivs.empty? and name = l10n("#{name}, #{subdivs}", @lang, @script)
|
22
|
+
location = a&.at(ns('./affiliation/organization/address/formattedAddress'))&.text
|
23
|
+
m << (!name.nil? && !location.nil? ? l10n("#{name}, #{location}", @lang, @script) :
|
23
24
|
(name || location || ''))
|
24
25
|
m
|
25
26
|
end
|
@@ -25,13 +25,13 @@ module IsoDoc
|
|
25
25
|
hash_translate(b, @i18n.get["substage_dict"], "./status/substage")
|
26
26
|
end
|
27
27
|
|
28
|
-
def hash_translate(bibdata, hash, xpath)
|
28
|
+
def hash_translate(bibdata, hash, xpath, lang = @lang)
|
29
29
|
x = bibdata.at(ns(xpath)) or return
|
30
30
|
x["language"] = ""
|
31
31
|
hash.is_a? Hash or return
|
32
32
|
hash[x.text] or return
|
33
33
|
x.next = x.dup
|
34
|
-
x.next["language"] =
|
34
|
+
x.next["language"] = lang
|
35
35
|
x.next.children = hash[x.text]
|
36
36
|
end
|
37
37
|
|
@@ -40,7 +40,7 @@ module IsoDoc
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def i18n_safe(k)
|
43
|
-
k.gsub(/\s|\./, "_")
|
43
|
+
k.to_s.gsub(/\s|\./, "_")
|
44
44
|
end
|
45
45
|
|
46
46
|
def i8n_name(h, pref)
|
@@ -1,5 +1,10 @@
|
|
1
1
|
module IsoDoc
|
2
2
|
class PresentationXMLConvert < ::IsoDoc::Convert
|
3
|
+
def lower2cap(s)
|
4
|
+
return s if /^[[:upper:]][[:upper:]]/.match(s)
|
5
|
+
s.capitalize
|
6
|
+
end
|
7
|
+
|
3
8
|
def figure(docxml)
|
4
9
|
docxml.xpath(ns("//figure")).each do |f|
|
5
10
|
figure1(f)
|
@@ -12,7 +17,7 @@ module IsoDoc
|
|
12
17
|
return if labelled_ancestor(f) && f.ancestors("figure").empty?
|
13
18
|
return if f.at(ns("./figure")) and !f.at(ns("./name"))
|
14
19
|
lbl = @xrefs.anchor(f['id'], :label, false) or return
|
15
|
-
prefix_name(f, " — ", l10n("#{@i18n.figure} #{lbl}"), "name")
|
20
|
+
prefix_name(f, " — ", l10n("#{lower2cap @i18n.figure} #{lbl}"), "name")
|
16
21
|
end
|
17
22
|
|
18
23
|
def prefix_name(f, delim, number, elem)
|
@@ -36,7 +41,7 @@ module IsoDoc
|
|
36
41
|
return if labelled_ancestor(f)
|
37
42
|
return unless f.ancestors("example").empty?
|
38
43
|
lbl = @xrefs.anchor(f['id'], :label, false) or return
|
39
|
-
prefix_name(f, " — ", l10n("#{@i18n.figure} #{lbl}"), "name")
|
44
|
+
prefix_name(f, " — ", l10n("#{lower2cap @i18n.figure} #{lbl}"), "name")
|
40
45
|
end
|
41
46
|
|
42
47
|
def formula(docxml)
|
@@ -65,7 +70,7 @@ module IsoDoc
|
|
65
70
|
|
66
71
|
def example1(f)
|
67
72
|
n = @xrefs.get[f["id"]]
|
68
|
-
lbl = (n.nil? || n[:label].nil? || n[:label].empty?) ? @i18n.example
|
73
|
+
lbl = (n.nil? || n[:label].nil? || n[:label].empty?) ? @i18n.example:
|
69
74
|
l10n("#{@i18n.example} #{n[:label]}")
|
70
75
|
prefix_name(f, " — ", lbl, "name")
|
71
76
|
end
|
@@ -81,7 +86,7 @@ module IsoDoc
|
|
81
86
|
return if f.parent.name == "bibitem"
|
82
87
|
n = @xrefs.get[f["id"]]
|
83
88
|
lbl = (@i18n.note if n.nil? || n[:label].nil? || n[:label].empty?) ?
|
84
|
-
@i18n.note
|
89
|
+
@i18n.note: l10n("#{@i18n.note} #{n[:label]}")
|
85
90
|
prefix_name(f, "", lbl, "name")
|
86
91
|
end
|
87
92
|
|
@@ -94,24 +99,24 @@ module IsoDoc
|
|
94
99
|
# introduce name element
|
95
100
|
def termnote1(f)
|
96
101
|
lbl = l10n(@xrefs.anchor(f['id'], :label) || '???')
|
97
|
-
prefix_name(f, "", lbl, "name")
|
102
|
+
prefix_name(f, "", lower2cap(lbl), "name")
|
98
103
|
end
|
99
104
|
|
100
105
|
def recommendation(docxml)
|
101
106
|
docxml.xpath(ns("//recommendation")).each do |f|
|
102
|
-
recommendation1(f, @i18n.recommendation)
|
107
|
+
recommendation1(f, lower2cap(@i18n.recommendation))
|
103
108
|
end
|
104
109
|
end
|
105
110
|
|
106
111
|
def requirement(docxml)
|
107
112
|
docxml.xpath(ns("//requirement")).each do |f|
|
108
|
-
recommendation1(f, @i18n.requirement)
|
113
|
+
recommendation1(f, lower2cap(@i18n.requirement))
|
109
114
|
end
|
110
115
|
end
|
111
116
|
|
112
117
|
def permission(docxml)
|
113
118
|
docxml.xpath(ns("//permission")).each do |f|
|
114
|
-
recommendation1(f, @i18n.permission)
|
119
|
+
recommendation1(f, lower2cap(@i18n.permission))
|
115
120
|
end
|
116
121
|
end
|
117
122
|
|
@@ -132,7 +137,7 @@ module IsoDoc
|
|
132
137
|
return if labelled_ancestor(f)
|
133
138
|
return if f["unnumbered"] && !f.at(ns("./name"))
|
134
139
|
n = @xrefs.anchor(f['id'], :label, false)
|
135
|
-
prefix_name(f, " — ", l10n("#{@i18n.table} #{n}"), "name")
|
140
|
+
prefix_name(f, " — ", l10n("#{lower2cap @i18n.table} #{n}"), "name")
|
136
141
|
end
|
137
142
|
|
138
143
|
# we use this to eliminate the semantic amend blocks from rendering
|
@@ -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(
|
55
|
-
contents = non_locality_elems(
|
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(
|
58
|
-
link += eref_localities(
|
59
|
-
non_locality_elems(
|
60
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
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)
|
data/lib/isodoc/version.rb
CHANGED
data/lib/isodoc/word_convert.rb
CHANGED
@@ -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
|
-
|
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
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
101
|
-
|
102
|
-
|
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'> </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.merge(@labels || {}).merge(@meta.labels || {})
|
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
|