isodoc 1.6.3 → 1.6.7.1
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/.github/workflows/rake.yml +2 -12
- data/.hound.yml +3 -1
- data/.rubocop.yml +4 -6
- data/isodoc.gemspec +3 -2
- data/lib/isodoc-yaml/i18n-en.yaml +1 -0
- data/lib/isodoc-yaml/i18n-fr.yaml +1 -0
- data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
- data/lib/isodoc.rb +0 -2
- data/lib/isodoc/convert.rb +7 -1
- data/lib/isodoc/function/blocks.rb +5 -4
- data/lib/isodoc/function/cleanup.rb +52 -43
- data/lib/isodoc/function/inline.rb +7 -7
- data/lib/isodoc/function/references.rb +33 -52
- data/lib/isodoc/function/section.rb +28 -16
- data/lib/isodoc/function/table.rb +21 -22
- data/lib/isodoc/function/terms.rb +6 -7
- data/lib/isodoc/function/to_word_html.rb +6 -3
- data/lib/isodoc/function/utils.rb +181 -163
- data/lib/isodoc/gem_tasks.rb +8 -9
- data/lib/isodoc/headlesshtml_convert.rb +8 -7
- data/lib/isodoc/html_convert.rb +5 -1
- data/lib/isodoc/html_function/comments.rb +14 -12
- data/lib/isodoc/html_function/footnotes.rb +14 -7
- data/lib/isodoc/html_function/html.rb +30 -26
- data/lib/isodoc/html_function/postprocess.rb +191 -182
- data/lib/isodoc/html_function/sectionsplit.rb +230 -0
- data/lib/isodoc/metadata.rb +22 -20
- data/lib/isodoc/metadata_contributor.rb +31 -28
- data/lib/isodoc/pdf_convert.rb +11 -13
- data/lib/isodoc/presentation_function/bibdata.rb +50 -22
- data/lib/isodoc/presentation_function/inline.rb +20 -15
- data/lib/isodoc/presentation_function/section.rb +38 -1
- data/lib/isodoc/presentation_xml_convert.rb +2 -0
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/word_function/postprocess.rb +50 -36
- data/lib/isodoc/xref.rb +2 -0
- data/lib/isodoc/xref/xref_gen_seq.rb +60 -35
- data/lib/isodoc/xref/xref_sect_gen.rb +4 -4
- data/spec/assets/scripts_override.html +3 -0
- data/spec/isodoc/blocks_spec.rb +373 -685
- data/spec/isodoc/cleanup_spec.rb +40 -42
- data/spec/isodoc/i18n_spec.rb +694 -821
- data/spec/isodoc/inline_spec.rb +482 -328
- data/spec/isodoc/metadata_spec.rb +384 -379
- data/spec/isodoc/postproc_spec.rb +163 -55
- data/spec/isodoc/presentation_xml_spec.rb +355 -278
- data/spec/isodoc/ref_spec.rb +5 -5
- data/spec/isodoc/section_spec.rb +216 -199
- data/spec/isodoc/sectionsplit_spec.rb +190 -0
- data/spec/isodoc/table_spec.rb +41 -42
- data/spec/isodoc/terms_spec.rb +84 -84
- data/spec/isodoc/xref_spec.rb +974 -932
- metadata +22 -5
data/lib/isodoc/pdf_convert.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
require_relative "html_function/comments
|
2
|
-
require_relative "html_function/footnotes
|
3
|
-
require_relative "html_function/html
|
1
|
+
require_relative "html_function/comments"
|
2
|
+
require_relative "html_function/footnotes"
|
3
|
+
require_relative "html_function/html"
|
4
4
|
require "metanorma"
|
5
5
|
|
6
6
|
module IsoDoc
|
7
7
|
class PdfConvert < ::IsoDoc::Convert
|
8
|
-
|
9
8
|
include HtmlFunction::Comments
|
10
9
|
include HtmlFunction::Footnotes
|
11
10
|
include HtmlFunction::Html
|
@@ -13,6 +12,8 @@ module IsoDoc
|
|
13
12
|
def initialize(options)
|
14
13
|
@standardstylesheet = nil
|
15
14
|
super
|
15
|
+
@format = :pdf
|
16
|
+
@suffix = "pdf"
|
16
17
|
@scripts = @scripts_pdf if @scripts_pdf
|
17
18
|
@maxwidth = 500
|
18
19
|
@maxheight = 800
|
@@ -22,22 +23,19 @@ module IsoDoc
|
|
22
23
|
"_pdfimages"
|
23
24
|
end
|
24
25
|
|
25
|
-
def initialize(options)
|
26
|
-
@format = :pdf
|
27
|
-
@suffix = "pdf"
|
28
|
-
super
|
29
|
-
end
|
30
|
-
|
31
26
|
def convert(input_filename, file = nil, debug = false, output_filename = nil)
|
32
27
|
file = File.read(input_filename, encoding: "utf-8") if file.nil?
|
33
28
|
@openmathdelim, @closemathdelim = extract_delims(file)
|
34
29
|
docxml, filename, dir = convert_init(file, input_filename, debug)
|
35
30
|
result = convert1(docxml, filename, dir)
|
36
31
|
return result if debug
|
37
|
-
|
32
|
+
|
33
|
+
postprocess(result, "#{filename}.tmp.html", dir)
|
38
34
|
FileUtils.rm_rf dir
|
39
|
-
::Metanorma::Output::Pdf.new.convert(
|
40
|
-
|
35
|
+
::Metanorma::Output::Pdf.new.convert(
|
36
|
+
"#{filename}.tmp.html",
|
37
|
+
output_filename || "#{filename}.#{@suffix}",
|
38
|
+
)
|
41
39
|
FileUtils.rm_rf ["#{filename}.tmp.html", tmpimagedir]
|
42
40
|
end
|
43
41
|
|
@@ -1,13 +1,40 @@
|
|
1
1
|
module IsoDoc
|
2
2
|
class PresentationXMLConvert < ::IsoDoc::Convert
|
3
3
|
def bibdata(docxml)
|
4
|
+
docid_prefixes(docxml)
|
4
5
|
a = bibdata_current(docxml) or return
|
6
|
+
address_precompose(a)
|
5
7
|
bibdata_i18n(a)
|
6
8
|
a.next =
|
7
9
|
"<localized-strings>#{i8n_name(trim_hash(@i18n.get), '').join('')}"\
|
8
10
|
"</localized-strings>"
|
9
11
|
end
|
10
12
|
|
13
|
+
def docid_prefixes(docxml)
|
14
|
+
docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
|
15
|
+
i.children = @xrefs.klass.docid_prefix(i["type"], i.text)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def address_precompose(bib)
|
20
|
+
bib.xpath(ns("//bibdata//address")).each do |b|
|
21
|
+
next if b.at(ns("./formattedAddress"))
|
22
|
+
|
23
|
+
x = address_precompose1(b)
|
24
|
+
b.children = "<formattedAddress>#{x}</formattedAddress>"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def address_precompose1(addr)
|
29
|
+
ret = []
|
30
|
+
addr.xpath(ns("./street")).each { |s| ret << s.children.to_xml }
|
31
|
+
a = addr.at(ns("./city")) and ret << a.children.to_xml
|
32
|
+
addr.xpath(ns("./state")).each { |s| ret << s.children.to_xml }
|
33
|
+
a = addr.at(ns("./country")) and ret << a.children.to_xml
|
34
|
+
a = addr.at(ns("./postcode")) and ret[-1] += " #{a.children.to_xml}"
|
35
|
+
ret.join("<br/>")
|
36
|
+
end
|
37
|
+
|
11
38
|
def bibdata_current(docxml)
|
12
39
|
a = docxml.at(ns("//bibdata")) or return
|
13
40
|
a.xpath(ns("./language")).each do |l|
|
@@ -35,27 +62,28 @@ module IsoDoc
|
|
35
62
|
x.next.children = hash[x.text]
|
36
63
|
end
|
37
64
|
|
38
|
-
def i18n_tag(
|
39
|
-
"<localized-string key='#{
|
65
|
+
def i18n_tag(key, value)
|
66
|
+
"<localized-string key='#{key}' language='#{@lang}'>#{value}"\
|
67
|
+
"</localized-string>"
|
40
68
|
end
|
41
69
|
|
42
|
-
def i18n_safe(
|
43
|
-
|
70
|
+
def i18n_safe(key)
|
71
|
+
key.to_s.gsub(/\s|\./, "_")
|
44
72
|
end
|
45
73
|
|
46
|
-
def i8n_name(
|
47
|
-
if
|
48
|
-
elsif
|
49
|
-
|
74
|
+
def i8n_name(hash, pref)
|
75
|
+
if hash.is_a? Hash then i8n_name1(hash, pref)
|
76
|
+
elsif hash.is_a? Array
|
77
|
+
hash.reject { |a| blank?(a) }.each_with_object([])
|
50
78
|
.with_index do |(v1, g), i|
|
51
79
|
i8n_name(v1, "#{i18n_safe(k)}.#{i}").each { |x| g << x }
|
52
80
|
end
|
53
|
-
else [i18n_tag(pref,
|
81
|
+
else [i18n_tag(pref, hash)]
|
54
82
|
end
|
55
83
|
end
|
56
84
|
|
57
|
-
def i8n_name1(
|
58
|
-
|
85
|
+
def i8n_name1(hash, pref)
|
86
|
+
hash.reject { |_k, v| blank?(v) }.each_with_object([]) do |(k, v), g|
|
59
87
|
if v.is_a? Hash then i8n_name(v, i18n_safe(k)).each { |x| g << x }
|
60
88
|
elsif v.is_a? Array
|
61
89
|
v.reject { |a| blank?(a) }.each_with_index do |v1, i|
|
@@ -68,28 +96,28 @@ module IsoDoc
|
|
68
96
|
end
|
69
97
|
|
70
98
|
# https://stackoverflow.com/a/31822406
|
71
|
-
def blank?(
|
72
|
-
|
99
|
+
def blank?(elem)
|
100
|
+
elem.nil? || elem.respond_to?(:empty?) && elem.empty?
|
73
101
|
end
|
74
102
|
|
75
|
-
def trim_hash(
|
103
|
+
def trim_hash(hash)
|
76
104
|
loop do
|
77
|
-
h_new = trim_hash1(
|
78
|
-
break
|
105
|
+
h_new = trim_hash1(hash)
|
106
|
+
break hash if hash == h_new
|
79
107
|
|
80
|
-
|
108
|
+
hash = h_new
|
81
109
|
end
|
82
110
|
end
|
83
111
|
|
84
|
-
def trim_hash1(
|
85
|
-
return
|
112
|
+
def trim_hash1(hash)
|
113
|
+
return hash unless hash.is_a? Hash
|
86
114
|
|
87
|
-
|
115
|
+
hash.each_with_object({}) do |(k, v), g|
|
88
116
|
next if blank?(v)
|
89
117
|
|
90
|
-
g[k] = if v.is_a? Hash then trim_hash1(
|
118
|
+
g[k] = if v.is_a? Hash then trim_hash1(hash[k])
|
91
119
|
elsif v.is_a? Array
|
92
|
-
|
120
|
+
hash[k].map { |a| trim_hash1(a) }.reject { |a| blank?(a) }
|
93
121
|
else
|
94
122
|
v
|
95
123
|
end
|
@@ -9,8 +9,8 @@ module IsoDoc
|
|
9
9
|
return @xrefs.anchor(node["bibitemid"], :xref) || "???"
|
10
10
|
elsif node["target"] && node["droploc"]
|
11
11
|
return @xrefs.anchor(node["target"], :value) ||
|
12
|
-
|
13
|
-
|
12
|
+
@xrefs.anchor(node["target"], :label) ||
|
13
|
+
@xrefs.anchor(node["target"], :xref) || "???"
|
14
14
|
elsif node["target"] && !/.#./.match(node["target"])
|
15
15
|
linkend = anchor_linkend1(node)
|
16
16
|
end
|
@@ -33,6 +33,10 @@ module IsoDoc
|
|
33
33
|
return linkend&.downcase if node["case"] == "lowercase"
|
34
34
|
return linkend if linkend[0, 1].match?(/\p{Upper}/)
|
35
35
|
|
36
|
+
capitalise_xref1(node, linkend)
|
37
|
+
end
|
38
|
+
|
39
|
+
def capitalise_xref1(node, linkend)
|
36
40
|
prec = nearest_block_parent(node).xpath("./descendant-or-self::text()") &
|
37
41
|
node.xpath("./preceding::text()")
|
38
42
|
if prec.empty? || /(?!<[^.].)\.\s+$/.match(prec.map(&:text).join)
|
@@ -43,8 +47,8 @@ module IsoDoc
|
|
43
47
|
|
44
48
|
def nearest_block_parent(node)
|
45
49
|
until %w(p title td th name formula li dt dd sourcecode pre)
|
46
|
-
|
47
|
-
|
50
|
+
.include?(node.name)
|
51
|
+
node = node.parent
|
48
52
|
end
|
49
53
|
node
|
50
54
|
end
|
@@ -90,7 +94,7 @@ module IsoDoc
|
|
90
94
|
ret
|
91
95
|
end
|
92
96
|
|
93
|
-
def eref_localities0(ref,
|
97
|
+
def eref_localities0(ref, _idx, target, delim, node)
|
94
98
|
if ref["type"] == "whole" then l10n("#{delim} #{@i18n.wholeoftext}")
|
95
99
|
else
|
96
100
|
eref_localities1(target, ref["type"], ref.at(ns("./referenceFrom")),
|
@@ -99,24 +103,24 @@ module IsoDoc
|
|
99
103
|
end
|
100
104
|
|
101
105
|
# TODO: move to localization file
|
102
|
-
def eref_localities1_zh(_target, type, from,
|
106
|
+
def eref_localities1_zh(_target, type, from, upto, node, delim)
|
103
107
|
ret = "#{delim} 第#{from.text}" if from
|
104
|
-
ret += "–#{
|
108
|
+
ret += "–#{upto.text}" if upto
|
105
109
|
loc = (@i18n.locality[type] || type.sub(/^locality:/, "").capitalize)
|
106
110
|
ret += " #{loc}" unless node["droploc"] == "true"
|
107
111
|
ret
|
108
112
|
end
|
109
113
|
|
110
114
|
# TODO: move to localization file
|
111
|
-
def eref_localities1(target, type, from,
|
115
|
+
def eref_localities1(target, type, from, upto, delim, node, lang = "en")
|
112
116
|
return "" if type == "anchor"
|
113
117
|
|
114
118
|
lang == "zh" and
|
115
|
-
return l10n(eref_localities1_zh(target, type, from,
|
119
|
+
return l10n(eref_localities1_zh(target, type, from, upto, node, delim))
|
116
120
|
ret = delim
|
117
121
|
ret += eref_locality_populate(type, node)
|
118
122
|
ret += " #{from.text}" if from
|
119
|
-
ret += "–#{
|
123
|
+
ret += "–#{upto.text}" if upto
|
120
124
|
l10n(ret)
|
121
125
|
end
|
122
126
|
|
@@ -161,11 +165,12 @@ module IsoDoc
|
|
161
165
|
content = node.first_element_child.children.reject do |c|
|
162
166
|
%w{locality localityStack}.include? c.name
|
163
167
|
end.select { |c| !c.text? || /\S/.match(c) }
|
164
|
-
if
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
168
|
+
n = if content.empty?
|
169
|
+
@i18n.term_defined_in.sub(/%/, node.first_element_child.to_xml)
|
170
|
+
else
|
171
|
+
"<em>#{node.children.to_xml}</em>"
|
172
|
+
end
|
173
|
+
node.replace(n)
|
169
174
|
end
|
170
175
|
|
171
176
|
def variant(docxml)
|
@@ -44,10 +44,47 @@ module IsoDoc
|
|
44
44
|
prefix_name(elem, "", "#{lbl}#{clausedelim}", "name")
|
45
45
|
end
|
46
46
|
|
47
|
-
def references(docxml)
|
47
|
+
def references(docxml)
|
48
|
+
end
|
49
|
+
|
50
|
+
def docid_prefixes(docxml)
|
51
|
+
docxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
|
52
|
+
i.children = @xrefs.klass.docid_prefix(i["type"], i.text)
|
53
|
+
end
|
54
|
+
end
|
48
55
|
|
49
56
|
def index(docxml)
|
50
57
|
docxml.xpath(ns("//index | //index-xref | //indexsect")).each(&:remove)
|
51
58
|
end
|
59
|
+
|
60
|
+
def display_order_at(docxml, xpath, idx)
|
61
|
+
return idx unless c = docxml.at(ns(xpath))
|
62
|
+
|
63
|
+
idx += 1
|
64
|
+
c["displayorder"] = idx
|
65
|
+
idx
|
66
|
+
end
|
67
|
+
|
68
|
+
def display_order_xpath(docxml, xpath, idx)
|
69
|
+
docxml.xpath(ns(xpath)).each do |c|
|
70
|
+
idx += 1
|
71
|
+
c["displayorder"] = idx
|
72
|
+
end
|
73
|
+
idx
|
74
|
+
end
|
75
|
+
|
76
|
+
def display_order(docxml)
|
77
|
+
i = 0
|
78
|
+
i = display_order_xpath(docxml, "//preface/*", i)
|
79
|
+
i = display_order_at(docxml, "//clause[@type = 'scope']", i)
|
80
|
+
i = display_order_at(docxml, @xrefs.klass.norm_ref_xpath, i)
|
81
|
+
i = display_order_at(docxml, "//sections/terms | "\
|
82
|
+
"//sections/clause[descendant::terms]", i)
|
83
|
+
i = display_order_at(docxml, "//sections/definitions", i)
|
84
|
+
i = display_order_xpath(docxml, @xrefs.klass.middle_clause(docxml), i)
|
85
|
+
i = display_order_xpath(docxml, "//annex", i)
|
86
|
+
i = display_order_xpath(docxml, @xrefs.klass.bibliography_xpath, i)
|
87
|
+
display_order_xpath(docxml, "//indexsect", i)
|
88
|
+
end
|
52
89
|
end
|
53
90
|
end
|
@@ -22,12 +22,14 @@ module IsoDoc
|
|
22
22
|
|
23
23
|
def conversions(docxml)
|
24
24
|
bibdata docxml
|
25
|
+
@xrefs.parse docxml
|
25
26
|
section docxml
|
26
27
|
block docxml
|
27
28
|
inline docxml
|
28
29
|
end
|
29
30
|
|
30
31
|
def section(docxml)
|
32
|
+
display_order docxml
|
31
33
|
clause docxml
|
32
34
|
annex docxml
|
33
35
|
term docxml
|
data/lib/isodoc/version.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
require "fileutils"
|
2
|
-
require_relative "./postprocess_cover
|
2
|
+
require_relative "./postprocess_cover"
|
3
3
|
|
4
4
|
module IsoDoc::WordFunction
|
5
5
|
module Postprocess
|
6
6
|
# add namespaces for Word fragments
|
7
7
|
WORD_NOKOHEAD = <<~HERE.freeze
|
8
|
-
|
9
|
-
|
10
|
-
xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"
|
11
|
-
xmlns:w="urn:schemas-microsoft-com:office:word"
|
12
|
-
xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
|
13
|
-
|
14
|
-
|
8
|
+
<!DOCTYPE html SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
9
|
+
<html xmlns="http://www.w3.org/1999/xhtml"
|
10
|
+
xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"
|
11
|
+
xmlns:w="urn:schemas-microsoft-com:office:word"
|
12
|
+
xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
|
13
|
+
<head> <title></title> <meta charset="UTF-8" /> </head>
|
14
|
+
<body> </body> </html>
|
15
15
|
HERE
|
16
16
|
|
17
17
|
def to_word_xhtml_fragment(xml)
|
@@ -22,7 +22,8 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
|
|
22
22
|
def table_note_cleanup(docxml)
|
23
23
|
super
|
24
24
|
# preempt html2doc putting MsoNormal there
|
25
|
-
docxml.xpath("//p[not(self::*[@class])][ancestor::*[@class = 'Note']]")
|
25
|
+
docxml.xpath("//p[not(self::*[@class])][ancestor::*[@class = 'Note']]")
|
26
|
+
.each do |p|
|
26
27
|
p["class"] = "Note"
|
27
28
|
end
|
28
29
|
end
|
@@ -38,16 +39,21 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
|
|
38
39
|
def toWord(result, filename, dir, header)
|
39
40
|
result = from_xhtml(word_cleanup(to_xhtml(result)))
|
40
41
|
@wordstylesheet = wordstylesheet_update
|
41
|
-
Html2Doc.process(
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
Html2Doc.process(
|
43
|
+
result,
|
44
|
+
filename: filename,
|
45
|
+
stylesheet: @wordstylesheet&.path,
|
46
|
+
header_file: header&.path, dir: dir,
|
47
|
+
asciimathdelims: [@openmathdelim, @closemathdelim],
|
48
|
+
liststyles: { ul: @ulstyle, ol: @olstyle }
|
49
|
+
)
|
45
50
|
header&.unlink
|
46
|
-
@wordstylesheet
|
51
|
+
@wordstylesheet.unlink if @wordstylesheet.is_a?(Tempfile)
|
47
52
|
end
|
48
53
|
|
49
|
-
def wordstylesheet_update
|
54
|
+
def wordstylesheet_update
|
50
55
|
return if @wordstylesheet.nil?
|
56
|
+
|
51
57
|
f = File.open(@wordstylesheet.path, "a")
|
52
58
|
@landscapestyle.empty? or f.write(@landscapestyle)
|
53
59
|
if @wordstylesheet_override && @wordstylesheet
|
@@ -62,7 +68,8 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
|
|
62
68
|
|
63
69
|
def word_admonition_images(docxml)
|
64
70
|
docxml.xpath("//div[@class = 'Admonition']//img").each do |i|
|
65
|
-
i["width"], i["height"] =
|
71
|
+
i["width"], i["height"] =
|
72
|
+
Html2Doc.image_resize(i, image_localfile(i), @maxheight, 300)
|
66
73
|
end
|
67
74
|
end
|
68
75
|
|
@@ -88,21 +95,23 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
|
|
88
95
|
cells2d = {}
|
89
96
|
docxml.xpath("//table[colgroup]").each do |t|
|
90
97
|
w = colgroup_widths(t)
|
91
|
-
t.xpath(".//tr").each_with_index { |
|
98
|
+
t.xpath(".//tr").each_with_index { |_tr, r| cells2d[r] = {} }
|
92
99
|
t.xpath(".//tr").each_with_index do |tr, r|
|
93
|
-
tr.xpath("./td | ./th").each_with_index do |td,
|
100
|
+
tr.xpath("./td | ./th").each_with_index do |td, _i|
|
94
101
|
x = 0
|
95
102
|
rs = td&.attr("rowspan")&.to_i || 1
|
96
103
|
cs = td&.attr("colspan")&.to_i || 1
|
97
|
-
while cells2d[r][x]
|
98
|
-
x += 1
|
104
|
+
while cells2d[r][x]
|
105
|
+
x += 1
|
99
106
|
end
|
100
|
-
|
101
|
-
|
107
|
+
(r..(r + rs - 1)).each do |y2|
|
108
|
+
(x..(x + cs - 1)).each do |x2|
|
102
109
|
cells2d[y2][x2] = 1
|
103
110
|
end
|
104
111
|
end
|
105
|
-
width = (x..(x+cs-1)).each_with_object({width: 0})
|
112
|
+
width = (x..(x + cs - 1)).each_with_object({ width: 0 }) do |z, m|
|
113
|
+
m[:width] += w[z]
|
114
|
+
end
|
106
115
|
td["width"] = "#{width[:width]}%"
|
107
116
|
x += cs
|
108
117
|
end
|
@@ -111,8 +120,8 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
|
|
111
120
|
end
|
112
121
|
|
113
122
|
# assume percentages
|
114
|
-
def colgroup_widths(
|
115
|
-
|
123
|
+
def colgroup_widths(table)
|
124
|
+
table.xpath("./colgroup/col").each_with_object([]) do |c, m|
|
116
125
|
m << c["width"].sub(/%$/, "").to_f
|
117
126
|
end
|
118
127
|
end
|
@@ -127,12 +136,13 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
|
|
127
136
|
|
128
137
|
def style_update(node, css)
|
129
138
|
return unless node
|
130
|
-
|
139
|
+
|
140
|
+
node["style"] = node["style"] ? node["style"].sub(/;?$/, ";#{css}") : css
|
131
141
|
end
|
132
142
|
|
133
143
|
def word_image_caption(docxml)
|
134
|
-
docxml.xpath("//p[@class = 'FigureTitle' or @class = 'SourceTitle']")
|
135
|
-
each do |t|
|
144
|
+
docxml.xpath("//p[@class = 'FigureTitle' or @class = 'SourceTitle']")
|
145
|
+
.each do |t|
|
136
146
|
if t&.previous_element&.name == "img"
|
137
147
|
img = t.previous_element
|
138
148
|
t.previous_element.swap("<p class=\'figure\'>#{img.to_xml}</p>")
|
@@ -150,7 +160,8 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
|
|
150
160
|
xpath.each do |list|
|
151
161
|
(list.xpath(".//li") - list.xpath(".//ol//li | .//ul//li")).each do |l|
|
152
162
|
l.xpath("./p | ./div | ./table").each_with_index do |p, i|
|
153
|
-
next if i
|
163
|
+
next if i.zero?
|
164
|
+
|
154
165
|
p.wrap(%{<div class="ListContLevel#{lvl}"/>})
|
155
166
|
end
|
156
167
|
list_add(l.xpath(".//ul") - l.xpath(".//ul//ul | .//ol//ul"), lvl + 1)
|
@@ -162,20 +173,21 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
|
|
162
173
|
def word_table_align(docxml)
|
163
174
|
docxml.xpath("//td[@align]/p | //th[@align]/p").each do |p|
|
164
175
|
next if p["align"]
|
165
|
-
|
176
|
+
|
177
|
+
style_update(p, "text-align: #{p.parent['align']}")
|
166
178
|
end
|
167
179
|
end
|
168
180
|
|
169
181
|
def word_table_separator(docxml)
|
170
182
|
docxml.xpath("//p[@class = 'TableTitle']").each do |t|
|
171
183
|
next unless t.children.empty?
|
184
|
+
|
172
185
|
t["style"] = t["style"].sub(/;?$/, ";font-size:0pt;")
|
173
186
|
t.children = " "
|
174
187
|
end
|
175
188
|
end
|
176
189
|
|
177
|
-
def word_annex_cleanup(docxml)
|
178
|
-
end
|
190
|
+
def word_annex_cleanup(docxml); end
|
179
191
|
|
180
192
|
def word_example_cleanup(docxml)
|
181
193
|
docxml.xpath("//div[@class = 'example']//p[not(@class)]").each do |p|
|
@@ -194,19 +206,21 @@ xmlns:m="http://schemas.microsoft.com/office/2004/12/omml">
|
|
194
206
|
docxml.xpath("//div[p/br]").each do |d|
|
195
207
|
/^WordSection\d+_\d+$/.match(d["class"]) or next
|
196
208
|
d.elements[0].name == "p" && !d.elements[0].elements.empty? or next
|
197
|
-
d.elements[0].elements[0].name == "br" &&
|
198
|
-
"
|
209
|
+
d.elements[0].elements[0].name == "br" &&
|
210
|
+
d.elements[0].elements[0]["style"] ==
|
211
|
+
"mso-special-character:line-break;page-break-before:always" or next
|
199
212
|
d.elements[0].remove
|
200
213
|
end
|
201
214
|
end
|
202
215
|
|
203
216
|
def word_footnote_format(docxml)
|
204
|
-
# the content is in a[@epub:type = 'footnote']//sup, but in Word,
|
217
|
+
# the content is in a[@epub:type = 'footnote']//sup, but in Word,
|
205
218
|
# we need to inject content around the autonumbered footnote reference
|
206
219
|
docxml.xpath("//a[@epub:type = 'footnote']").each do |x|
|
207
220
|
footnote_reference_format(x)
|
208
221
|
end
|
209
|
-
docxml.xpath("//a[@class = 'TableFootnoteRef'] |
|
222
|
+
docxml.xpath("//a[@class = 'TableFootnoteRef'] | "\
|
223
|
+
"//span[@class = 'TableFootnoteRef']").each do |x|
|
210
224
|
table_footnote_reference_format(x)
|
211
225
|
end
|
212
226
|
docxml
|