isodoc 1.6.4 → 1.6.5
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 +1 -1
- data/.rubocop.yml +1 -1
- data/isodoc.gemspec +2 -1
- 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/convert.rb +3 -1
- data/lib/isodoc/function/blocks.rb +5 -4
- data/lib/isodoc/function/references.rb +32 -51
- data/lib/isodoc/function/section.rb +0 -1
- data/lib/isodoc/function/table.rb +21 -22
- data/lib/isodoc/function/terms.rb +6 -7
- data/lib/isodoc/gem_tasks.rb +8 -9
- data/lib/isodoc/html_convert.rb +5 -1
- data/lib/isodoc/html_function/comments.rb +12 -12
- data/lib/isodoc/html_function/html.rb +2 -2
- data/lib/isodoc/html_function/postprocess.rb +191 -185
- 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/presentation_function/section.rb +39 -1
- data/lib/isodoc/presentation_xml_convert.rb +1 -0
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/xref.rb +2 -0
- data/spec/isodoc/blocks_spec.rb +184 -447
- data/spec/isodoc/cleanup_spec.rb +40 -42
- data/spec/isodoc/i18n_spec.rb +694 -821
- data/spec/isodoc/inline_spec.rb +43 -42
- data/spec/isodoc/metadata_spec.rb +384 -379
- data/spec/isodoc/postproc_spec.rb +53 -6
- data/spec/isodoc/presentation_xml_spec.rb +4 -4
- 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 +1 -1
- data/spec/isodoc/xref_spec.rb +974 -932
- metadata +19 -3
data/lib/isodoc/html_convert.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
require_relative "html_function/comments"
|
2
2
|
require_relative "html_function/footnotes"
|
3
3
|
require_relative "html_function/html"
|
4
|
-
require_relative "html_function/form"
|
5
4
|
require_relative "html_function/postprocess"
|
5
|
+
require_relative "html_function/sectionsplit"
|
6
|
+
require_relative "html_function/form"
|
6
7
|
|
7
8
|
module IsoDoc
|
8
9
|
class HtmlConvert < ::IsoDoc::Convert
|
@@ -23,6 +24,9 @@ module IsoDoc
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def convert(filename, file = nil, debug = false, output_filename = nil)
|
27
|
+
@sectionsplit and
|
28
|
+
return sectionsplit_convert(filename, file, debug, output_filename)
|
29
|
+
|
26
30
|
ret = super
|
27
31
|
Dir.exists?(tmpimagedir) and Dir["#{tmpimagedir}/*"].empty? and
|
28
32
|
FileUtils.rm_r tmpimagedir
|
@@ -24,16 +24,16 @@ module IsoDoc::HtmlFunction
|
|
24
24
|
=end
|
25
25
|
end
|
26
26
|
|
27
|
-
def comment_link_attrs(
|
28
|
-
{ style: "MsoCommentReference", target:
|
27
|
+
def comment_link_attrs(fnote, node)
|
28
|
+
{ style: "MsoCommentReference", target: fnote,
|
29
29
|
class: "commentLink", from: node["from"],
|
30
30
|
to: node["to"] }
|
31
31
|
end
|
32
32
|
|
33
33
|
# add in from and to links to move the comment into place
|
34
|
-
def make_comment_link(out,
|
35
|
-
out.span(**comment_link_attrs(
|
36
|
-
s1.a **{ style: "mso-comment-reference:SMC_#{
|
34
|
+
def make_comment_link(out, fnote, node)
|
35
|
+
out.span(**comment_link_attrs(fnote, node)) do |s1|
|
36
|
+
s1.a **{ style: "mso-comment-reference:SMC_#{fnote};"\
|
37
37
|
"mso-comment-date:#{node['date'].gsub(/[-:Z]/, '')}" }
|
38
38
|
end
|
39
39
|
end
|
@@ -44,9 +44,9 @@ module IsoDoc::HtmlFunction
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
def make_comment_text(node,
|
47
|
+
def make_comment_text(node, fnote)
|
48
48
|
noko do |xml|
|
49
|
-
xml.div **{ style: "mso-element:comment", id:
|
49
|
+
xml.div **{ style: "mso-element:comment", id: fnote } do |div|
|
50
50
|
div.span **{ style: %{mso-comment-author:"#{node['reviewer']}"} }
|
51
51
|
make_comment_target(div)
|
52
52
|
node.children.each { |n| parse(n, div) }
|
@@ -99,13 +99,13 @@ module IsoDoc::HtmlFunction
|
|
99
99
|
from["style"] != "mso-special-character:comment"
|
100
100
|
end
|
101
101
|
|
102
|
-
def insert_comment_cont(from,
|
103
|
-
# includes_to = from.at(".//*[@id='#{
|
104
|
-
while !from.nil? && from["id"] !=
|
102
|
+
def insert_comment_cont(from, upto, target)
|
103
|
+
# includes_to = from.at(".//*[@id='#{upto}']")
|
104
|
+
while !from.nil? && from["id"] != upto
|
105
105
|
following = from.xpath("./following::*")
|
106
|
-
(from = following.shift) && incl_to = from.at(".//*[@id='#{
|
106
|
+
(from = following.shift) && incl_to = from.at(".//*[@id='#{upto}']")
|
107
107
|
while !incl_to.nil? && !from.nil? && skip_comment_wrap(from)
|
108
|
-
(from = following.shift) && incl_to = from.at(".//*[@id='#{
|
108
|
+
(from = following.shift) && incl_to = from.at(".//*[@id='#{upto}']")
|
109
109
|
end
|
110
110
|
wrap_comment_cont(from, target) if !from.nil?
|
111
111
|
end
|
@@ -64,8 +64,8 @@ module IsoDoc::HtmlFunction
|
|
64
64
|
<script type="text/javascript">#{toclevel}</script>
|
65
65
|
|
66
66
|
<!--Google fonts-->
|
67
|
-
|
68
|
-
|
67
|
+
<link rel="preconnect" href="https://fonts.gstatic.com">#{' '}
|
68
|
+
#{googlefonts}
|
69
69
|
<!--Font awesome import for the link icon-->
|
70
70
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/solid.css" integrity="sha384-v2Tw72dyUXeU3y4aM2Y0tBJQkGfplr39mxZqlTBDUZAb9BGoC40+rdFCG0m10lXk" crossorigin="anonymous">
|
71
71
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.8/css/fontawesome.css" integrity="sha384-q3jl8XQu1OpdLgGFvNRnPdj5VIlCvgsDQTQB6owSOHWlAurxul7f+JpUOVdAiJ5P" crossorigin="anonymous">
|
@@ -1,227 +1,233 @@
|
|
1
1
|
require "isodoc/html_function/mathvariant_to_plain"
|
2
2
|
require_relative "postprocess_footnotes"
|
3
3
|
|
4
|
-
module IsoDoc
|
5
|
-
module
|
6
|
-
|
7
|
-
result
|
8
|
-
|
9
|
-
|
10
|
-
|
4
|
+
module IsoDoc
|
5
|
+
module HtmlFunction
|
6
|
+
module Html
|
7
|
+
def postprocess(result, filename, _dir)
|
8
|
+
result = from_xhtml(cleanup(to_xhtml(textcleanup(result))))
|
9
|
+
toHTML(result, filename)
|
10
|
+
@files_to_delete.each { |f| FileUtils.rm_rf f }
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
def script_cdata(result)
|
14
|
+
result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>")
|
15
|
+
.gsub(%r{\]\]>\s*</script>}, "</script>")
|
16
|
+
.gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>")
|
17
|
+
.gsub(%r{</script>\s*\]\]>}, "</script>")
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
def toHTML(result, filename)
|
21
|
+
result = from_xhtml(html_cleanup(to_xhtml(result)))
|
22
|
+
# result = populate_template(result, :html)
|
23
|
+
result = from_xhtml(move_images(to_xhtml(result)))
|
24
|
+
result = html5(script_cdata(inject_script(result)))
|
25
|
+
File.open(filename, "w:UTF-8") { |f| f.write(result) }
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def html5(doc)
|
29
|
+
doc.sub(%r{<!DOCTYPE html [^>]+>}, "<!DOCTYPE html>")
|
30
|
+
.sub(%r{<\?xml[^>]+>}, "")
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
footnote_format(
|
35
|
-
|
36
|
-
|
37
|
-
term_header(html_footnote_filter(html_preface(htmlstyle(html)))),
|
38
|
-
),
|
39
|
-
),
|
40
|
-
),
|
41
|
-
)
|
42
|
-
end
|
33
|
+
def html_cleanup(html)
|
34
|
+
html = term_header(html_footnote_filter(html_preface(htmlstyle(html))))
|
35
|
+
html = footnote_format(footnote_backlinks(html_toc(html)))
|
36
|
+
mathml(html_list_clean(html))
|
37
|
+
end
|
43
38
|
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
def html_list_clean(html)
|
40
|
+
html.xpath("//ol/div | //ul/div").each do |div|
|
41
|
+
li = div&.xpath("./preceding-sibling::li")&.last ||
|
42
|
+
div.at("./following-sibling::li")
|
43
|
+
div.parent = li
|
44
|
+
end
|
45
|
+
html
|
46
|
+
end
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
def mathml(docxml)
|
49
|
+
IsoDoc::HtmlFunction::MathvariantToPlain.new(docxml).convert
|
50
|
+
end
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
52
|
+
def htmlstylesheet(file)
|
53
|
+
return if file.nil?
|
54
|
+
|
55
|
+
file.open if file.is_a?(Tempfile)
|
56
|
+
stylesheet = file.read
|
57
|
+
xml = Nokogiri::XML("<style/>")
|
58
|
+
xml.children.first << Nokogiri::XML::Comment
|
59
|
+
.new(xml, "\n#{stylesheet}\n")
|
60
|
+
file.close
|
61
|
+
file.unlink if file.is_a?(Tempfile)
|
62
|
+
xml.root.to_s
|
63
|
+
end
|
59
64
|
|
60
|
-
|
61
|
-
|
65
|
+
def htmlstyle(docxml)
|
66
|
+
return docxml unless @htmlstylesheet
|
62
67
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
+
head = docxml.at("//*[local-name() = 'head']")
|
69
|
+
head << htmlstylesheet(@htmlstylesheet)
|
70
|
+
s = htmlstylesheet(@htmlstylesheet_override) and head << s
|
71
|
+
docxml
|
72
|
+
end
|
68
73
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
74
|
+
def html_preface(docxml)
|
75
|
+
html_cover(docxml) if @htmlcoverpage && !@bare
|
76
|
+
html_intro(docxml) if @htmlintropage && !@bare
|
77
|
+
docxml.at("//body") << mathjax(@openmathdelim, @closemathdelim)
|
78
|
+
docxml.at("//body") << sourcecode_highlighter
|
79
|
+
html_main(docxml)
|
80
|
+
authority_cleanup(docxml)
|
81
|
+
docxml
|
82
|
+
end
|
78
83
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
84
|
+
def authority_cleanup1(docxml, klass)
|
85
|
+
dest = docxml.at("//div[@id = 'boilerplate-#{klass}-destination']")
|
86
|
+
auth = docxml.at("//div[@id = 'boilerplate-#{klass}' or "\
|
87
|
+
"@class = 'boilerplate-#{klass}']")
|
88
|
+
auth&.xpath(".//h1[not(text())] | .//h2[not(text())]")&.each(&:remove)
|
89
|
+
auth&.xpath(".//h1 | .//h2")&.each { |h| h["class"] = "IntroTitle" }
|
90
|
+
dest and auth and dest.replace(auth.remove)
|
91
|
+
end
|
87
92
|
|
88
|
-
|
89
|
-
|
90
|
-
|
93
|
+
def authority_cleanup(docxml)
|
94
|
+
%w(copyright license legal feedback).each do |t|
|
95
|
+
authority_cleanup1(docxml, t)
|
96
|
+
end
|
91
97
|
end
|
92
|
-
end
|
93
98
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
99
|
+
def html_cover(docxml)
|
100
|
+
doc = to_xhtml_fragment(File.read(@htmlcoverpage, encoding: "UTF-8"))
|
101
|
+
d = docxml.at('//div[@class="title-section"]')
|
102
|
+
# d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
|
103
|
+
d.children.first.add_previous_sibling(
|
104
|
+
populate_template(doc.to_xml(encoding: "US-ASCII"), :html),
|
105
|
+
)
|
106
|
+
end
|
102
107
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
108
|
+
def html_intro(docxml)
|
109
|
+
doc = to_xhtml_fragment(File.read(@htmlintropage, encoding: "UTF-8"))
|
110
|
+
d = docxml.at('//div[@class="prefatory-section"]')
|
111
|
+
# d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
|
112
|
+
d.children.first.add_previous_sibling(
|
113
|
+
populate_template(doc.to_xml(encoding: "US-ASCII"), :html),
|
114
|
+
)
|
115
|
+
end
|
111
116
|
|
112
|
-
|
113
|
-
|
117
|
+
def html_toc_entry(level, header)
|
118
|
+
%(<li class="#{level}"><a href="##{header['id']}">\
|
114
119
|
#{header_strip(header)}</a></li>)
|
115
|
-
|
116
|
-
|
117
|
-
def toclevel_classes
|
118
|
-
(1..@htmlToClevels).reduce([]) { |m, i| m << "h#{i}" }
|
119
|
-
end
|
120
|
+
end
|
120
121
|
|
121
|
-
|
122
|
-
|
123
|
-
"#{l}:not(:empty):not(.TermNum):not(.noTOC)"
|
122
|
+
def toclevel_classes
|
123
|
+
(1..@htmlToClevels).reduce([]) { |m, i| m << "h#{i}" }
|
124
124
|
end
|
125
|
-
<<~HEAD.freeze
|
126
|
-
function toclevel() { return "#{ret.join(',')}";}
|
127
|
-
HEAD
|
128
|
-
end
|
129
125
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
126
|
+
def toclevel
|
127
|
+
ret = toclevel_classes.map do |l|
|
128
|
+
"#{l}:not(:empty):not(.TermNum):not(.noTOC)"
|
129
|
+
end
|
130
|
+
<<~HEAD.freeze
|
131
|
+
function toclevel() { return "#{ret.join(',')}";}
|
132
|
+
HEAD
|
136
133
|
end
|
137
|
-
|
138
|
-
|
139
|
-
|
134
|
+
|
135
|
+
# needs to be same output as toclevel
|
136
|
+
def html_toc(docxml)
|
137
|
+
idx = docxml.at("//div[@id = 'toc']") or return docxml
|
138
|
+
toc = "<ul>"
|
139
|
+
path = toclevel_classes.map do |l|
|
140
|
+
"//main//#{l}[not(@class = 'TermNum')][not(@class = 'noTOC')][text()]"
|
141
|
+
end
|
142
|
+
docxml.xpath(path.join(" | ")).each_with_index do |h, tocidx|
|
143
|
+
h["id"] ||= "toc#{tocidx}"
|
144
|
+
toc += html_toc_entry(h.name, h)
|
145
|
+
end
|
146
|
+
idx.children = "#{toc}</ul>"
|
147
|
+
docxml
|
140
148
|
end
|
141
|
-
idx.children = "#{toc}</ul>"
|
142
|
-
docxml
|
143
|
-
end
|
144
149
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
150
|
+
# presupposes that the image source is local
|
151
|
+
def move_images(docxml)
|
152
|
+
FileUtils.rm_rf tmpimagedir
|
153
|
+
FileUtils.mkdir tmpimagedir
|
154
|
+
docxml.xpath("//*[local-name() = 'img']").each do |i|
|
155
|
+
i["width"], i["height"] = Html2Doc.image_resize(i, image_localfile(i),
|
156
|
+
@maxheight, @maxwidth)
|
157
|
+
next if /^data:/.match? i["src"]
|
153
158
|
|
154
|
-
|
159
|
+
@datauriimage ? datauri(i) : move_image1(i)
|
160
|
+
end
|
161
|
+
docxml
|
155
162
|
end
|
156
|
-
docxml
|
157
|
-
end
|
158
163
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
164
|
+
def datauri(img)
|
165
|
+
type = img["src"].split(".")[-1]
|
166
|
+
supertype = type == "xml" ? "application" : "image"
|
167
|
+
bin = IO.binread(image_localfile(img))
|
168
|
+
data = Base64.strict_encode64(bin)
|
169
|
+
img["src"] = "data:#{supertype}/#{type};base64,#{data}"
|
170
|
+
end
|
166
171
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
172
|
+
def image_suffix(img)
|
173
|
+
type = img["mimetype"]&.sub(%r{^[^/*]+/}, "")
|
174
|
+
matched = /\.(?<suffix>[^. \r\n\t]+)$/.match img["src"]
|
175
|
+
type and !type.empty? and return type
|
171
176
|
|
172
|
-
|
173
|
-
|
174
|
-
|
177
|
+
!matched.nil? and matched[:suffix] and return matched[:suffix]
|
178
|
+
"png"
|
179
|
+
end
|
175
180
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
181
|
+
def move_image1(img)
|
182
|
+
suffix = image_suffix(img)
|
183
|
+
uuid = UUIDTools::UUID.random_create.to_s
|
184
|
+
fname = "#{uuid}.#{suffix}"
|
185
|
+
new_full_filename = File.join(tmpimagedir, fname)
|
186
|
+
local_filename = image_localfile(img)
|
187
|
+
FileUtils.cp local_filename, new_full_filename
|
188
|
+
img["src"] = File.join(rel_tmpimagedir, fname)
|
189
|
+
end
|
185
190
|
|
186
|
-
|
187
|
-
|
191
|
+
def inject_script(doc)
|
192
|
+
return doc unless @scripts
|
188
193
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
194
|
+
scripts = File.read(@scripts, encoding: "UTF-8")
|
195
|
+
scripts_override = ""
|
196
|
+
@scripts_override and
|
197
|
+
scripts_override = File.read(@scripts_override, encoding: "UTF-8")
|
198
|
+
a = doc.split(%r{</body>})
|
199
|
+
"#{a[0]}#{scripts}#{scripts_override}</body>#{a[1]}"
|
200
|
+
end
|
196
201
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
202
|
+
def sourcecode_highlighter
|
203
|
+
'<script src="https://cdn.rawgit.com/google/code-prettify/master/'\
|
204
|
+
'loader/run_prettify.js"></script>'
|
205
|
+
end
|
201
206
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
207
|
+
MATHJAX_ADDR =
|
208
|
+
"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js".freeze
|
209
|
+
MATHJAX = <<~"MATHJAX".freeze
|
210
|
+
<script type="text/x-mathjax-config">
|
211
|
+
MathJax.Hub.Config({
|
212
|
+
"HTML-CSS": { preferredFont: "STIX" },
|
213
|
+
asciimath2jax: { delimiters: [['OPEN', 'CLOSE']] }
|
214
|
+
});
|
215
|
+
</script>
|
216
|
+
<script src="#{MATHJAX_ADDR}?config=MML_HTMLorMML-full" async="async"></script>
|
217
|
+
MATHJAX
|
218
|
+
|
219
|
+
def mathjax(open, close)
|
220
|
+
MATHJAX.gsub("OPEN", open).gsub("CLOSE", close)
|
221
|
+
end
|
217
222
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
223
|
+
def term_header(docxml)
|
224
|
+
%w(h1 h2 h3 h4 h5 h6 h7 h8).each do |h|
|
225
|
+
docxml.xpath("//p[@class = 'TermNum'][../#{h}]").each do |p|
|
226
|
+
p.name = "h#{h[1].to_i + 1}"
|
227
|
+
end
|
222
228
|
end
|
229
|
+
docxml
|
223
230
|
end
|
224
|
-
docxml
|
225
231
|
end
|
226
232
|
end
|
227
233
|
end
|