isodoc 2.4.2 → 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/convert.rb +10 -3
- data/lib/isodoc/function/blocks.rb +5 -2
- data/lib/isodoc/function/inline_simple.rb +1 -1
- data/lib/isodoc/function/references.rb +17 -38
- data/lib/isodoc/function/utils.rb +1 -1
- data/lib/isodoc/metadata.rb +1 -1
- data/lib/isodoc/presentation_function/bibdata.rb +3 -3
- data/lib/isodoc/presentation_function/math.rb +15 -4
- data/lib/isodoc/presentation_function/sourcecode.rb +14 -6
- data/lib/isodoc/presentation_xml_convert.rb +38 -0
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/word_function/body.rb +3 -3
- 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 +2 -70
- data/lib/isodoc/word_function/postprocess_table.rb +85 -0
- data/lib/isodoc/word_function/table.rb +32 -14
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0720c3026536785125b4c6c495e4f2573dfa7b2186094c0f36efa9c20a1fbd3
|
4
|
+
data.tar.gz: 9ea3325d067e417956b865edd0baf70dff9a5cb80008e6dfe5fbfbdaaaf16ff4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e97827c7adacaa26ef823222897672413056219fba5a3e0a6dee92079ac680cd50a9f1dde9cb7c40fddf23ef000fcb0478709a95916a4e6b222bf3d4e94ca54
|
7
|
+
data.tar.gz: 888734821add95629f8709aac1e5ac8b95b372b6a33d43e366e78e0c4ec6a3957dc9264a86015501458ca2752b881f44053e1f7a3997c5d0fb1b43ec816abc74
|
data/lib/isodoc/convert.rb
CHANGED
@@ -50,6 +50,8 @@ module IsoDoc
|
|
50
50
|
# fontlicenseagreement: fontist font license agreement
|
51
51
|
# modspecidentifierbase: base prefix for any Modspec identifiers
|
52
52
|
# sourcehighlighter: whether to apply sourcecode highlighting
|
53
|
+
# semantic_xml_insert: whether to insert into presentation XML
|
54
|
+
# a copy of semantic XML
|
53
55
|
def initialize(options) # rubocop:disable Lint/MissingSuper
|
54
56
|
@options = options_preprocess(options)
|
55
57
|
init_stylesheets(@options)
|
@@ -60,6 +62,7 @@ module IsoDoc
|
|
60
62
|
init_locations(@options)
|
61
63
|
init_i18n(@options)
|
62
64
|
init_rendering(@options)
|
65
|
+
init_arrangement(@options)
|
63
66
|
end
|
64
67
|
|
65
68
|
def options_preprocess(options)
|
@@ -77,14 +80,18 @@ module IsoDoc
|
|
77
80
|
@datauriimage = options[:datauriimage]
|
78
81
|
@suppressheadingnumbers = options[:suppressheadingnumbers]
|
79
82
|
@break_up_urls_in_tables = options[:breakupurlsintables]
|
80
|
-
@sectionsplit = options[:sectionsplit] == "true"
|
81
83
|
@suppressasciimathdup = options[:suppressasciimathdup]
|
82
|
-
@bare = options[:bare]
|
83
84
|
@aligncrosselements = options[:aligncrosselements]
|
84
85
|
@modspecidentifierbase = options[:modspecidentifierbase]
|
85
86
|
@sourcehighlighter = options[:sourcehighlighter]
|
86
87
|
end
|
87
88
|
|
89
|
+
def init_arrangement(options)
|
90
|
+
@sectionsplit = options[:sectionsplit] == "true"
|
91
|
+
@bare = options[:bare]
|
92
|
+
@semantic_xml_insert = options[:semanticxmlinsert] != "false"
|
93
|
+
end
|
94
|
+
|
88
95
|
def init_i18n(options)
|
89
96
|
@i18nyaml = options[:i18nyaml]
|
90
97
|
@lang = options[:language] || "en"
|
@@ -187,7 +194,7 @@ module IsoDoc
|
|
187
194
|
@xrefs.parse docxml
|
188
195
|
bibitem_lookup(docxml)
|
189
196
|
noko do |xml|
|
190
|
-
xml.html
|
197
|
+
xml.html lang: @lang.to_s do |html|
|
191
198
|
html.parent.add_namespace("epub", "http://www.idpf.org/2007/ops")
|
192
199
|
info docxml, nil
|
193
200
|
populate_css
|
@@ -82,8 +82,11 @@ module IsoDoc
|
|
82
82
|
|
83
83
|
def sourcecode_parse1(node, div)
|
84
84
|
@sourcecode = "pre"
|
85
|
-
node.at(ns(".//table
|
85
|
+
node.at(ns(".//table[@class = 'rouge-line-table']")) ||
|
86
|
+
node.at("./ancestor::xmlns:table[@class = 'rouge-line-table']") and
|
86
87
|
@sourcecode = "table"
|
88
|
+
# !node.ancestors("table").empty? and
|
89
|
+
# @sourcecode = "table"
|
87
90
|
node.children.each { |n| parse(n, div) unless n.name == "name" }
|
88
91
|
@sourcecode = false
|
89
92
|
end
|
@@ -96,7 +99,7 @@ module IsoDoc
|
|
96
99
|
@sourcecode = false
|
97
100
|
@annotation = true
|
98
101
|
out.div class: "annotation" do |div|
|
99
|
-
#node.at("./preceding-sibling::*[local-name() = 'annotation']") or
|
102
|
+
# node.at("./preceding-sibling::*[local-name() = 'annotation']") or
|
100
103
|
# div << "<br/>"
|
101
104
|
callout = node.at(ns("//callout[@target='#{node['id']}']"))
|
102
105
|
div << "<span class='c'><#{callout.text}></span> "
|
@@ -4,55 +4,35 @@ module IsoDoc
|
|
4
4
|
# This is highly specific to ISO, but it's not a bad precedent for
|
5
5
|
# references anyway; keeping here instead of in IsoDoc::Iso for now
|
6
6
|
def docid_l10n(text)
|
7
|
-
|
8
|
-
|
9
|
-
text.gsub(/
|
7
|
+
text.nil? and return text
|
8
|
+
@i18n.all_parts and text.gsub!(/All Parts/i, @i18n.all_parts.downcase)
|
9
|
+
text.size < 20 and text.gsub!(/ /, " ")
|
10
10
|
text
|
11
11
|
end
|
12
12
|
|
13
|
-
def nonstd_bibitem(list, bib, _ordinal, biblio)
|
13
|
+
def nonstd_bibitem(list, bib, _ordinal, biblio)
|
14
14
|
list.p **attr_code(iso_bibitem_entry_attrs(bib, biblio)) do |ref|
|
15
|
-
# ids = bibitem_ref_code(bib)
|
16
|
-
# idents = render_identifier(ids)
|
17
|
-
# if biblio then ref_entry_code(ref, ordinal, idents, ids)
|
18
|
-
# else
|
19
|
-
# ref << (idents[:ordinal] || idents[:metanorma] || idents[:sdo]).to_s
|
20
|
-
# ref << ", #{idents[sdo]}" if idents[:ordinal] && idents[:sdo]
|
21
|
-
# end
|
22
|
-
# ref << "," if idents[:sdo]
|
23
15
|
tag = bib.at(ns("./biblio-tag"))
|
24
16
|
tag&.children&.each { |n| parse(n, ref) }
|
25
17
|
reference_format(bib, ref)
|
26
18
|
end
|
27
19
|
end
|
28
20
|
|
29
|
-
def std_bibitem_entry(list, bib, _ordinal, biblio)
|
21
|
+
def std_bibitem_entry(list, bib, _ordinal, biblio)
|
30
22
|
list.p **attr_code(iso_bibitem_entry_attrs(bib, biblio)) do |ref|
|
31
|
-
# idents = render_identifier(bibitem_ref_code(bib))
|
32
|
-
# if biblio then ref_entry_code(ref, ordinal, idents, nil)
|
33
|
-
# else
|
34
|
-
# ref << (idents[:ordinal] || idents[:metanorma] || idents[:sdo]).to_s
|
35
|
-
# ref << ", #{idents[:sdo]}" if (idents[:ordinal] ||
|
36
|
-
# idents[:metanorma]) && idents[:sdo]
|
37
|
-
# end
|
38
|
-
# date_note_process(bib, ref)
|
39
|
-
# ref << "," if idents[:sdo]
|
40
23
|
tag = bib.at(ns("./biblio-tag"))
|
41
24
|
tag&.children&.each { |n| parse(n, ref) }
|
42
25
|
reference_format(bib, ref)
|
43
26
|
end
|
44
27
|
end
|
45
28
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# prefix_bracketed_ref(ref, ids[:ordinal] || ids[:metanorma] ||
|
50
|
-
# "[#{ordinal}]")
|
51
|
-
# ids[:sdo] and ref << (ids[:sdo]).to_s
|
52
|
-
# end
|
29
|
+
SKIP_DOCID = <<~XPATH.strip.freeze
|
30
|
+
@type = 'DOI' or @type = 'doi' or @type = 'ISSN' or @type = 'issn' or @type = 'ISBN' or @type = 'isbn' or starts-with(@type, 'ISSN.') or starts-with(@type, 'ISBN.') or starts-with(@type, 'issn.') or starts-with(@type, 'isbn.')
|
31
|
+
XPATH
|
53
32
|
|
54
|
-
|
55
|
-
|
33
|
+
SKIP_DOC1 = <<~XPATH.strip.freeze
|
34
|
+
#{SKIP_DOCID} or @type = 'metanorma-ordinal' or @type = 'metanorma'
|
35
|
+
XPATH
|
56
36
|
|
57
37
|
def pref_ref_code(bib)
|
58
38
|
bib["suppress_identifier"] == "true" and return nil
|
@@ -61,8 +41,8 @@ module IsoDoc
|
|
61
41
|
ret.empty? and
|
62
42
|
ret = bib.xpath(ns("./docidentifier[@primary = 'true']"))
|
63
43
|
ret.empty? and
|
64
|
-
ret = bib.at(ns("./docidentifier[not(#{
|
65
|
-
bib.at(ns("./docidentifier[not(#{
|
44
|
+
ret = bib.at(ns("./docidentifier[not(#{SKIP_DOC1})]#{lang}")) ||
|
45
|
+
bib.at(ns("./docidentifier[not(#{SKIP_DOC1})]"))
|
66
46
|
ret
|
67
47
|
end
|
68
48
|
|
@@ -70,8 +50,7 @@ module IsoDoc
|
|
70
50
|
def bibitem_ref_code(bib)
|
71
51
|
id = bib.at(ns("./docidentifier[@type = 'metanorma']"))
|
72
52
|
id1 = pref_ref_code(bib)
|
73
|
-
id2 = bib.at(ns("./docidentifier[
|
74
|
-
"@type = 'ISBN']"))
|
53
|
+
id2 = bib.at(ns("./docidentifier[#{SKIP_DOCID}]"))
|
75
54
|
id3 = bib.at(ns("./docidentifier[@type = 'metanorma-ordinal']"))
|
76
55
|
return [id, id1, id2, id3] if id || id1 || id2 || id3
|
77
56
|
return [nil, nil, nil, nil] if bib["suppress_identifier"] == "true"
|
@@ -139,9 +118,9 @@ module IsoDoc
|
|
139
118
|
|
140
119
|
def standard?(bib)
|
141
120
|
ret = false
|
142
|
-
drop = %w(metanorma DOI ISSN ISBN)
|
143
121
|
bib.xpath(ns("./docidentifier")).each do |id|
|
144
|
-
next if id["type"].nil? ||
|
122
|
+
next if id["type"].nil? ||
|
123
|
+
id.at(".//self::*[#{SKIP_DOCID} or @type = 'metanorma']")
|
145
124
|
|
146
125
|
ret = true
|
147
126
|
end
|
@@ -194,7 +173,7 @@ module IsoDoc
|
|
194
173
|
return
|
195
174
|
page_break(out)
|
196
175
|
out.div do |div|
|
197
|
-
div.h1
|
176
|
+
div.h1 class: "Section3" do |h1|
|
198
177
|
f.at(ns("./title"))&.children&.each { |c2| parse(c2, h1) }
|
199
178
|
end
|
200
179
|
biblio_list(f, div, true)
|
data/lib/isodoc/metadata.rb
CHANGED
@@ -170,7 +170,7 @@ module IsoDoc
|
|
170
170
|
end
|
171
171
|
|
172
172
|
def code_css(isoxml, _out)
|
173
|
-
c = isoxml.at(ns("//
|
173
|
+
c = isoxml.at(ns("//metanorma-extension/source-highlighter-css")) or return
|
174
174
|
set(:code_css, c.text)
|
175
175
|
end
|
176
176
|
end
|
@@ -17,8 +17,8 @@ module IsoDoc
|
|
17
17
|
def toc_metadata(docxml)
|
18
18
|
return unless @tocfigures || @toctables || @tocrecommendations
|
19
19
|
|
20
|
-
ins = docxml.at(ns("//
|
21
|
-
docxml.at(ns("//bibdata")).after("<
|
20
|
+
ins = docxml.at(ns("//metanorma-extension")) ||
|
21
|
+
docxml.at(ns("//bibdata")).after("<metanorma-extension/>").next_element
|
22
22
|
@tocfigures and
|
23
23
|
ins << "<toc type='figure'><title>#{@i18n.toc_figures}</title></toc>"
|
24
24
|
@toctables and
|
@@ -41,7 +41,7 @@ module IsoDoc
|
|
41
41
|
return unless @fontist_fonts
|
42
42
|
|
43
43
|
ins = xmldoc.at(ns("//presentation-metadata")) ||
|
44
|
-
xmldoc.at(ns("//
|
44
|
+
xmldoc.at(ns("//metanorma-extension")) || xmldoc.at(ns("//bibdata"))
|
45
45
|
CSV.parse_line(@fontist_fonts, col_sep: ";").map(&:strip).each do |f|
|
46
46
|
ins.next = presmeta("fonts", f)
|
47
47
|
end
|
@@ -32,7 +32,7 @@ module IsoDoc
|
|
32
32
|
return localized unless twitter_cldr_reader_symbols[:decimal]
|
33
33
|
|
34
34
|
integer, fraction = localized.split(twitter_cldr_reader_symbols[:decimal])
|
35
|
-
return localized if fraction.nil? || fraction.
|
35
|
+
return localized if fraction.nil? || fraction.empty?
|
36
36
|
|
37
37
|
[integer, decorate_fraction_part(fraction, locale)]
|
38
38
|
.join(twitter_cldr_reader_symbols[:decimal])
|
@@ -97,14 +97,25 @@ module IsoDoc
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def mathml1(node, locale)
|
100
|
+
mathml_style_inherit(node)
|
100
101
|
asciimath_dup(node)
|
101
102
|
localize_maths(node, locale)
|
102
|
-
|
103
|
+
mathml_number_to_number(node)
|
104
|
+
end
|
105
|
+
|
106
|
+
def mathml_style_inherit(node)
|
107
|
+
node.at("./ancestor::xmlns:strong") or return
|
108
|
+
node.children =
|
109
|
+
"<mstyle fontweight='bold'>#{node.children.to_xml}</mstyle>"
|
110
|
+
end
|
103
111
|
|
112
|
+
def mathml_number_to_number(node)
|
113
|
+
(node.elements.size == 1 && node.elements.first.name == "mn") or return
|
114
|
+
repl = node.at("./m:mn", MATHML).children
|
104
115
|
if node.parent.name == "stem"
|
105
|
-
node.parent.replace(
|
116
|
+
node.parent.replace(repl)
|
106
117
|
else
|
107
|
-
node.replace(
|
118
|
+
node.replace(repl)
|
108
119
|
end
|
109
120
|
end
|
110
121
|
end
|
@@ -2,8 +2,8 @@ module IsoDoc
|
|
2
2
|
class PresentationXMLConvert < ::IsoDoc::Convert
|
3
3
|
def sourcehighlighter_css(docxml)
|
4
4
|
@sourcehighlighter or return
|
5
|
-
ins = docxml.at(ns("//
|
6
|
-
docxml.at(ns("//bibdata")).after("<
|
5
|
+
ins = docxml.at(ns("//metanorma-extension")) ||
|
6
|
+
docxml.at(ns("//bibdata")).after("<metanorma-extension/>").next_element
|
7
7
|
ins << "<source-highlighter-css>#{sourcehighlighter_css_file}" \
|
8
8
|
"</source-highlighter-css>"
|
9
9
|
end
|
@@ -15,10 +15,11 @@ module IsoDoc
|
|
15
15
|
|
16
16
|
def sourcehighlighter
|
17
17
|
@sourcehighlighter or return
|
18
|
+
Rouge::Formatter.enable_escape!
|
18
19
|
f = Rouge::Formatters::HTML.new
|
19
20
|
opts = { gutter_class: "rouge-gutter", code_class: "rouge-code" }
|
20
|
-
|
21
|
-
|
21
|
+
f1 = Rouge::Formatters::HTMLLineTable.new(f, opts)
|
22
|
+
{ formatter: f, formatter_line: f1 }
|
22
23
|
end
|
23
24
|
|
24
25
|
def sourcecode(docxml)
|
@@ -50,6 +51,11 @@ module IsoDoc
|
|
50
51
|
def source_remove_markup(elem)
|
51
52
|
ret = {}
|
52
53
|
name = elem.at(ns("./name")) and ret[:name] = name.remove.to_xml
|
54
|
+
source_remove_annotations(ret, elem)
|
55
|
+
ret
|
56
|
+
end
|
57
|
+
|
58
|
+
def source_remove_annotations(ret, elem)
|
53
59
|
ret[:ann] = elem.xpath(ns("./annotation")).each(&:remove)
|
54
60
|
ret[:call] = elem.xpath(ns("./callout")).each_with_object([]) do |c, m|
|
55
61
|
m << { xml: c.remove.to_xml, line: c.line - elem.line }
|
@@ -99,9 +105,11 @@ module IsoDoc
|
|
99
105
|
end
|
100
106
|
|
101
107
|
def source_lex(elem)
|
102
|
-
|
108
|
+
lexer = (Rouge::Lexer.find(elem["lang"] || "plaintext") ||
|
103
109
|
Rouge::Lexer.find("plaintext"))
|
104
|
-
l.
|
110
|
+
l = Rouge::Lexers::Escape.new(start: "{^^{", end: "}^^}", lang: lexer)
|
111
|
+
source = to_xml(elem.children).gsub(/</, "{^^{<").gsub(/>/, ">}^^}")
|
112
|
+
l.lex(@c.decode(source))
|
105
113
|
end
|
106
114
|
|
107
115
|
def source_label(elem)
|
@@ -24,6 +24,7 @@ module IsoDoc
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def conversions(docxml)
|
27
|
+
semantic_xml_insert(docxml)
|
27
28
|
bibdata docxml
|
28
29
|
@xrefs.parse docxml
|
29
30
|
section docxml
|
@@ -84,6 +85,43 @@ module IsoDoc
|
|
84
85
|
related docxml
|
85
86
|
end
|
86
87
|
|
88
|
+
def semantic_xml_insert(xml)
|
89
|
+
@semantic_xml_insert or return
|
90
|
+
embed = to_xml(embedable_semantic_xml(xml))
|
91
|
+
ins = metanorma_extension_insert_pt(xml)
|
92
|
+
ins = ins.at(ns("./metanorma")) || ins.add_child("<metanorma/>").first
|
93
|
+
ins << "<source>#{embed}</source>"
|
94
|
+
end
|
95
|
+
|
96
|
+
def metanorma_extension_insert_pt(xml)
|
97
|
+
xml.at(ns("//metanorma-extension")) ||
|
98
|
+
xml.at(ns("//bibdata"))&.after("<metanorma-extension/>")
|
99
|
+
&.next_element ||
|
100
|
+
xml.root.elements.first.before("<metanorma-extension/>")
|
101
|
+
.previous_element
|
102
|
+
end
|
103
|
+
|
104
|
+
def embedable_semantic_xml(xml)
|
105
|
+
xml = embedable_semantic_xml_tags(xml)
|
106
|
+
embedable_semantic_xml_attributes(xml)
|
107
|
+
end
|
108
|
+
|
109
|
+
def embedable_semantic_xml_tags(xml)
|
110
|
+
Nokogiri::XML(to_xml(xml).gsub(%r{(</?)([[:alpha:]])},
|
111
|
+
"\\1semantic__\\2")).root
|
112
|
+
end
|
113
|
+
|
114
|
+
def embedable_semantic_xml_attributes(xml)
|
115
|
+
Metanorma::Utils::anchor_attributes.each do |(tag_name, attr_name)|
|
116
|
+
tag_name == "*" or tag_name = "semantic__#{tag_name}"
|
117
|
+
xml.xpath(ns("//#{tag_name}[@#{attr_name}]")).each do |elem|
|
118
|
+
elem.attributes[attr_name].value =
|
119
|
+
"semantic__#{elem.attributes[attr_name].value}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
xml
|
123
|
+
end
|
124
|
+
|
87
125
|
def postprocess(result, filename, _dir)
|
88
126
|
to_xml_file(result, filename)
|
89
127
|
@files_to_delete.each { |f| FileUtils.rm_rf f }
|
data/lib/isodoc/version.rb
CHANGED
@@ -244,11 +244,11 @@ module IsoDoc
|
|
244
244
|
|
245
245
|
def info(isoxml, out)
|
246
246
|
@tocfigurestitle =
|
247
|
-
isoxml&.at(ns("//
|
247
|
+
isoxml&.at(ns("//metanorma-extension/toc[@type = 'figure']/title"))&.text
|
248
248
|
@toctablestitle =
|
249
|
-
isoxml&.at(ns("//
|
249
|
+
isoxml&.at(ns("//metanorma-extension/toc[@type = 'table']/title"))&.text
|
250
250
|
@tocrecommendationstitle = isoxml
|
251
|
-
&.at(ns("//
|
251
|
+
&.at(ns("//metanorma-extension/toc[@type = 'recommendation']/title"))&.text
|
252
252
|
super
|
253
253
|
end
|
254
254
|
end
|
@@ -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,17 +1,11 @@
|
|
1
1
|
require "fileutils"
|
2
2
|
require_relative "./postprocess_cover"
|
3
3
|
require_relative "./postprocess_toc"
|
4
|
+
require_relative "./postprocess_table"
|
4
5
|
|
5
6
|
module IsoDoc
|
6
7
|
module WordFunction
|
7
8
|
module Postprocess
|
8
|
-
def table_note_cleanup(docxml)
|
9
|
-
super
|
10
|
-
# preempt html2doc putting MsoNormal there
|
11
|
-
docxml.xpath("//p[not(self::*[@class])][ancestor::*[@class = 'Note']]")
|
12
|
-
.each { |p| p["class"] = "Note" }
|
13
|
-
end
|
14
|
-
|
15
9
|
def postprocess(result, filename, dir)
|
16
10
|
filename = filename.sub(/\.doc$/, "")
|
17
11
|
header = generate_header(filename, dir)
|
@@ -55,6 +49,7 @@ module IsoDoc
|
|
55
49
|
word_nested_tables(docxml)
|
56
50
|
word_colgroup(docxml)
|
57
51
|
word_table_align(docxml)
|
52
|
+
word_table_pagebreak(docxml)
|
58
53
|
word_table_separator(docxml)
|
59
54
|
word_admonition_images(docxml)
|
60
55
|
word_list_continuations(docxml)
|
@@ -108,54 +103,6 @@ module IsoDoc
|
|
108
103
|
end
|
109
104
|
end
|
110
105
|
|
111
|
-
def word_colgroup(docxml)
|
112
|
-
cells2d = {}
|
113
|
-
docxml.xpath("//table[colgroup]").each do |t|
|
114
|
-
w = colgroup_widths(t)
|
115
|
-
t.xpath(".//tr").each_with_index { |_tr, r| cells2d[r] = {} }
|
116
|
-
t.xpath(".//tr").each_with_index do |tr, r|
|
117
|
-
tr.xpath("./td | ./th").each_with_index do |td, _i|
|
118
|
-
x = 0
|
119
|
-
rs = td.attr("rowspan")&.to_i || 1
|
120
|
-
cs = td.attr("colspan")&.to_i || 1
|
121
|
-
while cells2d[r][x]
|
122
|
-
x += 1
|
123
|
-
end
|
124
|
-
(r..(r + rs - 1)).each do |y2|
|
125
|
-
cells2d[y2].nil? and next
|
126
|
-
(x..(x + cs - 1)).each { |x2| cells2d[y2][x2] = 1 }
|
127
|
-
end
|
128
|
-
width = (x..(x + cs - 1)).each_with_object({ width: 0 }) do |z, m|
|
129
|
-
m[:width] += w[z]
|
130
|
-
end
|
131
|
-
td["width"] = "#{width[:width]}%"
|
132
|
-
x += cs
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
# assume percentages
|
139
|
-
def colgroup_widths(table)
|
140
|
-
table.xpath("./colgroup/col").each_with_object([]) do |c, m|
|
141
|
-
m << c["width"].sub(/%$/, "").to_f
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def word_nested_tables(docxml)
|
146
|
-
docxml.xpath("//table").each do |t|
|
147
|
-
t.xpath(".//table").reverse.each do |tt|
|
148
|
-
t.next = tt.remove
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
def style_update(node, css)
|
154
|
-
node or return
|
155
|
-
node["style"] =
|
156
|
-
node["style"] ? node["style"].sub(/;?$/, ";#{css}") : css
|
157
|
-
end
|
158
|
-
|
159
106
|
def word_image_caption(docxml)
|
160
107
|
docxml.xpath("//p[@class = 'FigureTitle' or @class = 'SourceTitle']")
|
161
108
|
.each do |t|
|
@@ -188,21 +135,6 @@ module IsoDoc
|
|
188
135
|
end
|
189
136
|
end
|
190
137
|
|
191
|
-
def word_table_align(docxml)
|
192
|
-
docxml.xpath("//td[@align]/p | //th[@align]/p").each do |p|
|
193
|
-
p["align"] and next
|
194
|
-
style_update(p, "text-align: #{p.parent['align']}")
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
def word_table_separator(docxml)
|
199
|
-
docxml.xpath("//p[@class = 'TableTitle']").each do |t|
|
200
|
-
t.children.empty? or next
|
201
|
-
t["style"] = t["style"].sub(/;?$/, ";font-size:0pt;")
|
202
|
-
t.children = " "
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
138
|
def word_annex_cleanup(docxml); end
|
207
139
|
|
208
140
|
def word_example_cleanup(docxml)
|
@@ -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
|
@@ -24,35 +24,53 @@ module IsoDoc
|
|
24
24
|
def make_tr_attr(cell, row, totalrows, header, bordered)
|
25
25
|
style = cell.name == "th" ? "font-weight:bold;" : ""
|
26
26
|
rowmax = cell["rowspan"] ? row + cell["rowspan"].to_i - 1 : row
|
27
|
-
style += make_tr_attr_style(row, rowmax, totalrows,
|
27
|
+
style += make_tr_attr_style(cell, row, rowmax, totalrows,
|
28
|
+
{ header: header, bordered: bordered })
|
28
29
|
{ rowspan: cell["rowspan"], colspan: cell["colspan"],
|
29
30
|
valign: cell["valign"], align: cell["align"], style: style,
|
30
31
|
class: cell["class"] }
|
31
32
|
end
|
32
33
|
|
33
|
-
def make_tr_attr_style(row, rowmax, totalrows,
|
34
|
+
def make_tr_attr_style(cell, row, rowmax, totalrows, opt)
|
35
|
+
top = row.zero? ? "#{SW1} 1.5pt;" : "none;"
|
36
|
+
bottom = "#{SW1} #{rowmax >= totalrows ? '1.5' : '1.0'}pt;"
|
34
37
|
ret = <<~STYLE.gsub(/\n/, "")
|
35
|
-
border-top:#{
|
36
|
-
mso-border-
|
37
|
-
border-bottom:#{SW1} #{rowmax >= totalrows ? '1.5' : '1.0'}pt;
|
38
|
-
mso-border-bottom-alt:#{SW1} #{rowmax >= totalrows ? '1.5' : '1.0'}pt;
|
38
|
+
border-top:#{top}mso-border-top-alt:#{top}
|
39
|
+
border-bottom:#{bottom}mso-border-bottom-alt:#{bottom}
|
39
40
|
STYLE
|
40
|
-
bordered or ret = ""
|
41
|
-
pb =
|
41
|
+
opt[:bordered] or ret = ""
|
42
|
+
pb = keep_rows_together(cell, rowmax, totalrows, opt) ? "avoid" : "auto"
|
42
43
|
"#{ret}page-break-after:#{pb};"
|
43
44
|
end
|
44
45
|
|
46
|
+
def keep_rows_together(cell, rowmax, totalrows, opt)
|
47
|
+
opt[:header] and return true
|
48
|
+
table_line_count(cell.parent.parent) > 15 and return false
|
49
|
+
(totalrows <= 10 && rowmax < totalrows)
|
50
|
+
end
|
51
|
+
|
52
|
+
def table_line_count(tbody)
|
53
|
+
sum = 0
|
54
|
+
tbody.xpath(ns(".//tr")).each do |r|
|
55
|
+
i = 1
|
56
|
+
r.xpath(ns(".//td | .//th")).each do |c|
|
57
|
+
n = c.xpath(ns(".//li | .//p | .//br")).size
|
58
|
+
n > i and i = n
|
59
|
+
end
|
60
|
+
sum += i
|
61
|
+
end
|
62
|
+
sum
|
63
|
+
end
|
64
|
+
|
45
65
|
def table_attrs(node)
|
46
66
|
c = node["class"]
|
47
67
|
bordered = "border-spacing:0;border-width:1px;"
|
48
68
|
(%w(modspec).include?(c) || !c) or bordered = nil
|
49
69
|
ret = {
|
50
|
-
summary: node["summary"],
|
51
|
-
width: node["width"],
|
70
|
+
summary: node["summary"], width: node["width"],
|
52
71
|
style: "mso-table-anchor-horizontal:column;mso-table-overlap:never;" \
|
53
72
|
"#{bordered}#{keep_style(node)}",
|
54
|
-
class: (node.text.length > 4000 ? "MsoISOTableBig" : "MsoISOTable")
|
55
|
-
}
|
73
|
+
class: (node.text.length > 4000 ? "MsoISOTableBig" : "MsoISOTable") }
|
56
74
|
bordered or ret.delete(:class)
|
57
75
|
super.merge(attr_code(ret))
|
58
76
|
end
|
@@ -61,7 +79,7 @@ module IsoDoc
|
|
61
79
|
colgroup = node.at(ns("./colgroup")) or return
|
62
80
|
table.colgroup do |cg|
|
63
81
|
colgroup.xpath(ns("./col")).each do |c|
|
64
|
-
cg.col
|
82
|
+
cg.col width: c["width"]
|
65
83
|
end
|
66
84
|
end
|
67
85
|
end
|
@@ -69,7 +87,7 @@ module IsoDoc
|
|
69
87
|
def table_parse(node, out)
|
70
88
|
@in_table = true
|
71
89
|
table_title_parse(node, out)
|
72
|
-
out.div
|
90
|
+
out.div align: "center", class: "table_container" do |div|
|
73
91
|
div.table **table_attrs(node) do |t|
|
74
92
|
colgroup(node, t)
|
75
93
|
thead_parse(node, t)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: isodoc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.4.
|
4
|
+
version: 2.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciimath
|
@@ -480,6 +480,7 @@ files:
|
|
480
480
|
- lib/isodoc/word_function/inline.rb
|
481
481
|
- lib/isodoc/word_function/postprocess.rb
|
482
482
|
- lib/isodoc/word_function/postprocess_cover.rb
|
483
|
+
- lib/isodoc/word_function/postprocess_table.rb
|
483
484
|
- lib/isodoc/word_function/postprocess_toc.rb
|
484
485
|
- lib/isodoc/word_function/table.rb
|
485
486
|
- lib/isodoc/xref.rb
|