isodoc 1.0.13 → 1.0.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/macos.yml +5 -1
- data/.github/workflows/ubuntu.yml +5 -1
- data/.github/workflows/windows.yml +5 -1
- data/lib/isodoc/base_style/blocks.scss +2 -1
- data/lib/isodoc/base_style/reset.scss +28 -0
- data/lib/isodoc/base_style/typography.scss +1 -27
- data/lib/isodoc/function/inline.rb +21 -4
- data/lib/isodoc/function/reqt.rb +4 -4
- data/lib/isodoc/function/to_word_html.rb +2 -0
- data/lib/isodoc/html_convert.rb +1 -0
- data/lib/isodoc/html_function/html.rb +0 -218
- data/lib/isodoc/html_function/postprocess.rb +226 -0
- data/lib/isodoc/version.rb +1 -1
- data/spec/isodoc/blocks_spec.rb +8 -6
- data/spec/isodoc/inline_spec.rb +117 -0
- 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: 1c17faca6084ff975799b3c8ffd31b6fffeaf6d11145547042e59c6be7abf8e6
|
4
|
+
data.tar.gz: dbb039f5b14cdcd30579eeaea0b7cbbe5e0496e20d566280a9350f9a14ce2177
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e50e9e38683d8a21577d96e81c8c38771c89b4fce3b6482cda3c12e6812385151601c5a3e1085dc47e0fedbf6d561dd4c308c0b9a55e3936ed5cc0c4068188ac
|
7
|
+
data.tar.gz: ddc25eddf928b63c959fca69570c76fd6264b811601432e2869efc91bf6553c7e633f4ae3bb29c17e5a157ac2ade5949827aba9d930333dea0d715fb79bef25b
|
data/.github/workflows/macos.yml
CHANGED
@@ -96,3 +96,31 @@ blockquote, q {
|
|
96
96
|
content: none;
|
97
97
|
}
|
98
98
|
}
|
99
|
+
|
100
|
+
.h2Annex {
|
101
|
+
font-family: $headerfont;
|
102
|
+
}
|
103
|
+
|
104
|
+
dl {
|
105
|
+
display: grid;
|
106
|
+
grid-template-columns: max-content auto;
|
107
|
+
|
108
|
+
dt, dd {
|
109
|
+
p {
|
110
|
+
margin-top: 0;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
dt {
|
115
|
+
grid-column-start: 1;
|
116
|
+
}
|
117
|
+
|
118
|
+
dd {
|
119
|
+
grid-column-start: 2;
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
b, strong {
|
124
|
+
font-weight: bold;
|
125
|
+
}
|
126
|
+
|
@@ -1,30 +1,3 @@
|
|
1
|
-
.h2Annex {
|
2
|
-
font-family: $headerfont;
|
3
|
-
}
|
4
|
-
|
5
|
-
dl {
|
6
|
-
display: grid;
|
7
|
-
grid-template-columns: max-content auto;
|
8
|
-
|
9
|
-
dt, dd {
|
10
|
-
p {
|
11
|
-
margin-top: 0;
|
12
|
-
}
|
13
|
-
}
|
14
|
-
|
15
|
-
dt {
|
16
|
-
grid-column-start: 1;
|
17
|
-
}
|
18
|
-
|
19
|
-
dd {
|
20
|
-
grid-column-start: 2;
|
21
|
-
}
|
22
|
-
}
|
23
|
-
|
24
|
-
b, strong {
|
25
|
-
font-weight: bold;
|
26
|
-
}
|
27
|
-
|
28
1
|
@mixin bodyStyle1($fontSize, $lineHeight, $colorText, $colorBackground, $fontWeight: 400) {
|
29
2
|
margin-left: auto;
|
30
3
|
margin-right: auto;
|
@@ -38,6 +11,7 @@ b, strong {
|
|
38
11
|
main {
|
39
12
|
margin: 0 3em 0 6em;
|
40
13
|
}
|
14
|
+
|
41
15
|
}
|
42
16
|
|
43
17
|
@mixin elementStyles($color, $colorHighlightBg, $colorHighlightFg) {
|
@@ -45,7 +45,7 @@ module IsoDoc::Function
|
|
45
45
|
container = anchor(node["target"], :container, false)
|
46
46
|
(container && get_note_container_id(node) != container &&
|
47
47
|
@anchors[node["target"]]) &&
|
48
|
-
|
48
|
+
linkend = prefix_container(container, linkend, node["target"])
|
49
49
|
end
|
50
50
|
linkend || "???"
|
51
51
|
end
|
@@ -53,7 +53,8 @@ module IsoDoc::Function
|
|
53
53
|
def get_linkend(node)
|
54
54
|
link = anchor_linkend(node, docid_l10n(node["target"] || node["citeas"]))
|
55
55
|
link += eref_localities(node.xpath(ns("./locality")), link)
|
56
|
-
contents = node.children.select { |c| c.name != "locality" }
|
56
|
+
contents = node.children.select { |c| c.name != "locality" }.
|
57
|
+
select { |c| !c.text? || /\S/.match(c) }
|
57
58
|
return link if contents.nil? || contents.empty?
|
58
59
|
Nokogiri::XML::NodeSet.new(node.document, contents).to_xml
|
59
60
|
# so not <origin bibitemid="ISO7301" citeas="ISO 7301">
|
@@ -63,7 +64,7 @@ module IsoDoc::Function
|
|
63
64
|
def xref_parse(node, out)
|
64
65
|
target = /#/.match(node["target"]) ? node["target"].sub(/#/, ".html#") :
|
65
66
|
"##{node["target"]}"
|
66
|
-
|
67
|
+
out.a(**{ "href": target }) { |l| l << get_linkend(node) }
|
67
68
|
end
|
68
69
|
|
69
70
|
def eref_localities(refs, target)
|
@@ -89,6 +90,22 @@ module IsoDoc::Function
|
|
89
90
|
end
|
90
91
|
end
|
91
92
|
|
93
|
+
def termrefelem_parse(node, out)
|
94
|
+
out << "Termbase #{node['base']}, term ID #{node['target']}"
|
95
|
+
end
|
96
|
+
|
97
|
+
def concept_parse(node, out)
|
98
|
+
content = node.first_element_child.children.select { |c| c.name != "locality" }.
|
99
|
+
select { |c| !c.text? || /\S/.match(c) }
|
100
|
+
if content.empty?
|
101
|
+
out << "[Term defined in "
|
102
|
+
parse(node.first_element_child, out)
|
103
|
+
out << "]"
|
104
|
+
else
|
105
|
+
content.each { |n| parse(n, out) }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
92
109
|
def stem_parse(node, out)
|
93
110
|
ooml = if node["type"] == "AsciiMath"
|
94
111
|
"#{@openmathdelim}#{HTMLEntities.new.encode(node.text)}#{@closemathdelim}"
|
@@ -101,7 +118,7 @@ module IsoDoc::Function
|
|
101
118
|
end
|
102
119
|
end
|
103
120
|
|
104
|
-
|
121
|
+
def image_title_parse(out, caption)
|
105
122
|
unless caption.nil?
|
106
123
|
out.p **{ class: "FigureTitle", style: "text-align:center;" } do |p|
|
107
124
|
p.b { |b| b << caption.to_s }
|
data/lib/isodoc/function/reqt.rb
CHANGED
@@ -22,10 +22,10 @@ module IsoDoc::Function
|
|
22
22
|
out = []
|
23
23
|
oblig = node["obligation"] and out << "Obligation: #{oblig}"
|
24
24
|
subj = node&.at(ns("./subject"))&.text and out << "Subject: #{subj}"
|
25
|
+
node.xpath(ns("./inherit")).each { |i| out << "Inherit: #{i.text}" }
|
25
26
|
node.xpath(ns("./classification")).each do |c|
|
26
|
-
tag = c.at(ns("./tag"))
|
27
|
-
value = c.at(ns("./value"))
|
28
|
-
tag && value or next
|
27
|
+
tag = c.at(ns("./tag")) or next
|
28
|
+
value = c.at(ns("./value")) or next
|
29
29
|
out << "#{tag.text.capitalize}: #{value.text}"
|
30
30
|
end
|
31
31
|
out
|
@@ -42,7 +42,7 @@ module IsoDoc::Function
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def reqt_metadata_node(n)
|
45
|
-
%w(label title subject classification tag value).include? n.name
|
45
|
+
%w(label title subject classification tag value inherit).include? n.name
|
46
46
|
end
|
47
47
|
|
48
48
|
def recommendation_parse(node, out)
|
@@ -249,6 +249,8 @@ module IsoDoc::Function
|
|
249
249
|
when "verification" then requirement_component_parse(node, out)
|
250
250
|
when "import" then requirement_component_parse(node, out)
|
251
251
|
when "index" then index_parse(node, out)
|
252
|
+
when "concept" then concept_parse(node, out)
|
253
|
+
when "termref" then termrefelem_parse(node, out)
|
252
254
|
else
|
253
255
|
error_parse(node, out)
|
254
256
|
end
|
data/lib/isodoc/html_convert.rb
CHANGED
@@ -28,62 +28,6 @@ module IsoDoc::HtmlFunction
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
def postprocess(result, filename, dir)
|
32
|
-
result = from_xhtml(cleanup(to_xhtml(result)))
|
33
|
-
toHTML(result, filename)
|
34
|
-
@files_to_delete.each { |f| FileUtils.rm_rf f }
|
35
|
-
end
|
36
|
-
|
37
|
-
def script_cdata(result)
|
38
|
-
result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>").
|
39
|
-
gsub(%r{\]\]>\s*</script>}, "</script>").
|
40
|
-
gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>").
|
41
|
-
gsub(%r{</script>\s*\]\]>}, "</script>")
|
42
|
-
end
|
43
|
-
|
44
|
-
def toHTML(result, filename)
|
45
|
-
result = (from_xhtml(html_cleanup(to_xhtml(result))))
|
46
|
-
result = populate_template(result, :html)
|
47
|
-
result = from_xhtml(move_images(to_xhtml(result)))
|
48
|
-
result = html5(script_cdata(inject_script(result)))
|
49
|
-
File.open("#{filename}.html", "w:UTF-8") { |f| f.write(result) }
|
50
|
-
end
|
51
|
-
|
52
|
-
def html5(doc)
|
53
|
-
doc.sub(%r{<!DOCTYPE html [^>]+>}, "<!DOCTYPE html>").
|
54
|
-
sub(%r{<\?xml[^>]+>}, "")
|
55
|
-
end
|
56
|
-
|
57
|
-
def html_cleanup(x)
|
58
|
-
footnote_backlinks(html_toc(
|
59
|
-
term_header((html_footnote_filter(html_preface(htmlstyle(x))))))
|
60
|
-
)
|
61
|
-
end
|
62
|
-
|
63
|
-
MATHJAX_ADDR =
|
64
|
-
"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js".freeze
|
65
|
-
MATHJAX = <<~"MATHJAX".freeze
|
66
|
-
<script type="text/x-mathjax-config">
|
67
|
-
MathJax.Hub.Config({
|
68
|
-
asciimath2jax: { delimiters: [['OPEN', 'CLOSE']] }
|
69
|
-
});
|
70
|
-
</script>
|
71
|
-
<script src="#{MATHJAX_ADDR}?config=MML_HTMLorMML-full" async="async"></script>
|
72
|
-
MATHJAX
|
73
|
-
|
74
|
-
def mathjax(open, close)
|
75
|
-
MATHJAX.gsub("OPEN", open).gsub("CLOSE", close)
|
76
|
-
end
|
77
|
-
|
78
|
-
def term_header(docxml)
|
79
|
-
%w(h1 h2 h3 h4 h5 h6 h7 h8).each do |h|
|
80
|
-
docxml.xpath("//p[@class = 'TermNum'][../#{h}]").each do |p|
|
81
|
-
p.name = "h#{h[1].to_i + 1}"
|
82
|
-
end
|
83
|
-
end
|
84
|
-
docxml
|
85
|
-
end
|
86
|
-
|
87
31
|
def googlefonts()
|
88
32
|
<<~HEAD.freeze
|
89
33
|
<link href="https://fonts.googleapis.com/css?family=Overpass:300,300i,600,900" rel="stylesheet">
|
@@ -121,10 +65,6 @@ module IsoDoc::HtmlFunction
|
|
121
65
|
d.children.empty? or d.children.first.previous = html_button()
|
122
66
|
end
|
123
67
|
|
124
|
-
def sourcecode_highlighter
|
125
|
-
'<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>'
|
126
|
-
end
|
127
|
-
|
128
68
|
def sourcecodelang(lang)
|
129
69
|
return unless lang
|
130
70
|
case lang.downcase
|
@@ -154,163 +94,5 @@ module IsoDoc::HtmlFunction
|
|
154
94
|
sourcecode_name_parse(node, div, name) if name
|
155
95
|
end
|
156
96
|
end
|
157
|
-
|
158
|
-
def html_preface(docxml)
|
159
|
-
html_cover(docxml) if @htmlcoverpage
|
160
|
-
html_intro(docxml) if @htmlintropage
|
161
|
-
docxml.at("//body") << mathjax(@openmathdelim, @closemathdelim)
|
162
|
-
docxml.at("//body") << sourcecode_highlighter
|
163
|
-
html_main(docxml)
|
164
|
-
docxml
|
165
|
-
end
|
166
|
-
|
167
|
-
def inject_script(doc)
|
168
|
-
return doc unless @scripts
|
169
|
-
scripts = File.read(@scripts, encoding: "UTF-8")
|
170
|
-
doc.sub("</body>", scripts + "\n</body>")
|
171
|
-
end
|
172
|
-
|
173
|
-
def html_cover(docxml)
|
174
|
-
doc = to_xhtml_fragment(File.read(@htmlcoverpage, encoding: "UTF-8"))
|
175
|
-
d = docxml.at('//div[@class="title-section"]')
|
176
|
-
d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
|
177
|
-
end
|
178
|
-
|
179
|
-
def html_intro(docxml)
|
180
|
-
doc = to_xhtml_fragment(File.read(@htmlintropage, encoding: "UTF-8"))
|
181
|
-
d = docxml.at('//div[@class="prefatory-section"]')
|
182
|
-
d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
|
183
|
-
end
|
184
|
-
|
185
|
-
def htmlstylesheet
|
186
|
-
#stylesheet = File.read(@htmlstylesheet, encoding: "UTF-8")
|
187
|
-
@htmlstylesheet.open
|
188
|
-
stylesheet = @htmlstylesheet.read
|
189
|
-
xml = Nokogiri::XML("<style/>")
|
190
|
-
xml.children.first << Nokogiri::XML::Comment.new(xml, "\n#{stylesheet}\n")
|
191
|
-
@htmlstylesheet.close!
|
192
|
-
xml.root.to_s
|
193
|
-
end
|
194
|
-
|
195
|
-
def htmlstyle(docxml)
|
196
|
-
return docxml unless @htmlstylesheet
|
197
|
-
title = docxml.at("//*[local-name() = 'head']/*[local-name() = 'title']")
|
198
|
-
head = docxml.at("//*[local-name() = 'head']")
|
199
|
-
=begin
|
200
|
-
css = htmlstylesheet
|
201
|
-
if title.nil? then head.children.first.add_previous_sibling css
|
202
|
-
else
|
203
|
-
title.add_next_sibling css
|
204
|
-
end
|
205
|
-
=end
|
206
|
-
head << htmlstylesheet
|
207
|
-
docxml
|
208
|
-
end
|
209
|
-
|
210
|
-
def update_footnote_filter(fn, x, i, seen)
|
211
|
-
if seen[fn.text]
|
212
|
-
x.at("./sup").content = seen[fn.text][:num].to_s
|
213
|
-
fn.remove unless x["href"] == seen[fn.text][:href]
|
214
|
-
x["href"] = seen[fn.text][:href]
|
215
|
-
else
|
216
|
-
seen[fn.text] = { num: i, href: x["href"] }
|
217
|
-
x.at("./sup").content = i.to_s
|
218
|
-
i += 1
|
219
|
-
end
|
220
|
-
[i, seen]
|
221
|
-
end
|
222
|
-
|
223
|
-
def html_footnote_filter(docxml)
|
224
|
-
seen = {}
|
225
|
-
i = 1
|
226
|
-
docxml.xpath('//a[@epub:type = "footnote"]').each do |x|
|
227
|
-
fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
|
228
|
-
i, seen = update_footnote_filter(fn, x, i, seen)
|
229
|
-
end
|
230
|
-
docxml
|
231
|
-
end
|
232
|
-
|
233
|
-
def footnote_backlinks(docxml)
|
234
|
-
seen = {}
|
235
|
-
docxml.xpath('//a[@epub:type = "footnote"]').each_with_index do |x, i|
|
236
|
-
seen[x["href"]] and next or seen[x["href"]] = true
|
237
|
-
fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
|
238
|
-
xdup = x.dup
|
239
|
-
xdup.remove["id"]
|
240
|
-
fn.elements.first.children.first.previous = xdup
|
241
|
-
x["id"] ||= "fnref:#{i + 1}"
|
242
|
-
fn.add_child "<a href='##{x['id']}'>↩</a>"
|
243
|
-
end
|
244
|
-
docxml
|
245
|
-
end
|
246
|
-
|
247
|
-
# presupposes that the image source is local
|
248
|
-
def move_images(docxml)
|
249
|
-
FileUtils.rm_rf tmpimagedir
|
250
|
-
FileUtils.mkdir tmpimagedir
|
251
|
-
docxml.xpath("//*[local-name() = 'img']").each do |i|
|
252
|
-
i["width"], i["height"] = Html2Doc.image_resize(i, image_localfile(i),
|
253
|
-
@maxheight, @maxwidth)
|
254
|
-
next if /^data:image/.match i["src"]
|
255
|
-
@datauriimage ? datauri(i) : move_image1(i)
|
256
|
-
end
|
257
|
-
docxml
|
258
|
-
end
|
259
|
-
|
260
|
-
def datauri(i)
|
261
|
-
type = i["src"].split(".")[-1]
|
262
|
-
bin = IO.binread(image_localfile(i))
|
263
|
-
data = Base64.strict_encode64(bin)
|
264
|
-
i["src"] = "data:image/#{type};base64,#{data}"
|
265
|
-
end
|
266
|
-
|
267
|
-
def image_suffix(i)
|
268
|
-
type = i["mimetype"]&.sub(%r{^[^/*]+/}, "")
|
269
|
-
matched = /\.(?<suffix>[^. \r\n\t]+)$/.match i["src"]
|
270
|
-
type and !type.empty? and return type
|
271
|
-
!matched.nil? and matched[:suffix] and return matched[:suffix]
|
272
|
-
"png"
|
273
|
-
end
|
274
|
-
|
275
|
-
def move_image1(i)
|
276
|
-
suffix = image_suffix(i)
|
277
|
-
uuid = UUIDTools::UUID.random_create.to_s
|
278
|
-
fname = "#{uuid}.#{suffix}"
|
279
|
-
new_full_filename = File.join(tmpimagedir, fname)
|
280
|
-
local_filename = image_localfile(i)
|
281
|
-
FileUtils.cp local_filename, new_full_filename
|
282
|
-
i["src"] = File.join(rel_tmpimagedir, fname)
|
283
|
-
end
|
284
|
-
|
285
|
-
def html_toc_entry(level, header)
|
286
|
-
%(<li class="#{level}"><a href="##{header['id']}">\
|
287
|
-
#{header_strip(header)}</a></li>)
|
288
|
-
end
|
289
|
-
|
290
|
-
def toclevel_classes
|
291
|
-
(1..@htmlToClevels).inject([]) { |m, i| m << "h#{i}" }
|
292
|
-
end
|
293
|
-
|
294
|
-
def toclevel
|
295
|
-
ret = toclevel_classes.map { |l| "#{l}:not(:empty):not(.TermNum):not(.noTOC)" }
|
296
|
-
<<~HEAD.freeze
|
297
|
-
function toclevel() { return "#{ret.join(',')}";}
|
298
|
-
HEAD
|
299
|
-
end
|
300
|
-
|
301
|
-
# needs to be same output as toclevel
|
302
|
-
def html_toc(docxml)
|
303
|
-
idx = docxml.at("//div[@id = 'toc']") or return docxml
|
304
|
-
toc = "<ul>"
|
305
|
-
path = toclevel_classes.map do |l|
|
306
|
-
"//main//#{l}[not(@class = 'TermNum')][not(@class = 'noTOC')][not(text())]"
|
307
|
-
end
|
308
|
-
docxml.xpath(path.join(" | ")).each_with_index do |h, tocidx|
|
309
|
-
h["id"] ||= "toc#{tocidx}"
|
310
|
-
toc += html_toc_entry(h.name, h)
|
311
|
-
end
|
312
|
-
idx.children = "#{toc}</ul>"
|
313
|
-
docxml
|
314
|
-
end
|
315
97
|
end
|
316
98
|
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
module IsoDoc::HtmlFunction
|
2
|
+
module Html
|
3
|
+
def postprocess(result, filename, dir)
|
4
|
+
result = from_xhtml(cleanup(to_xhtml(result)))
|
5
|
+
toHTML(result, filename)
|
6
|
+
@files_to_delete.each { |f| FileUtils.rm_rf f }
|
7
|
+
end
|
8
|
+
|
9
|
+
def script_cdata(result)
|
10
|
+
result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>").
|
11
|
+
gsub(%r{\]\]>\s*</script>}, "</script>").
|
12
|
+
gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>").
|
13
|
+
gsub(%r{</script>\s*\]\]>}, "</script>")
|
14
|
+
end
|
15
|
+
|
16
|
+
def toHTML(result, filename)
|
17
|
+
result = (from_xhtml(html_cleanup(to_xhtml(result))))
|
18
|
+
result = populate_template(result, :html)
|
19
|
+
result = from_xhtml(move_images(to_xhtml(result)))
|
20
|
+
result = html5(script_cdata(inject_script(result)))
|
21
|
+
File.open("#{filename}.html", "w:UTF-8") { |f| f.write(result) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def html5(doc)
|
25
|
+
doc.sub(%r{<!DOCTYPE html [^>]+>}, "<!DOCTYPE html>").
|
26
|
+
sub(%r{<\?xml[^>]+>}, "")
|
27
|
+
end
|
28
|
+
|
29
|
+
def html_cleanup(x)
|
30
|
+
footnote_backlinks(html_toc(
|
31
|
+
term_header((html_footnote_filter(html_preface(htmlstyle(x))))))
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def htmlstylesheet
|
36
|
+
@htmlstylesheet.open
|
37
|
+
stylesheet = @htmlstylesheet.read
|
38
|
+
xml = Nokogiri::XML("<style/>")
|
39
|
+
xml.children.first << Nokogiri::XML::Comment.new(xml, "\n#{stylesheet}\n")
|
40
|
+
@htmlstylesheet.close!
|
41
|
+
xml.root.to_s
|
42
|
+
end
|
43
|
+
|
44
|
+
def htmlstyle(docxml)
|
45
|
+
return docxml unless @htmlstylesheet
|
46
|
+
title = docxml.at("//*[local-name() = 'head']/*[local-name() = 'title']")
|
47
|
+
head = docxml.at("//*[local-name() = 'head']")
|
48
|
+
head << htmlstylesheet
|
49
|
+
docxml
|
50
|
+
end
|
51
|
+
|
52
|
+
def html_preface(docxml)
|
53
|
+
html_cover(docxml) if @htmlcoverpage
|
54
|
+
html_intro(docxml) if @htmlintropage
|
55
|
+
docxml.at("//body") << mathjax(@openmathdelim, @closemathdelim)
|
56
|
+
docxml.at("//body") << sourcecode_highlighter
|
57
|
+
html_main(docxml)
|
58
|
+
docxml
|
59
|
+
end
|
60
|
+
|
61
|
+
def html_cover(docxml)
|
62
|
+
doc = to_xhtml_fragment(File.read(@htmlcoverpage, encoding: "UTF-8"))
|
63
|
+
d = docxml.at('//div[@class="title-section"]')
|
64
|
+
d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
|
65
|
+
end
|
66
|
+
|
67
|
+
def html_intro(docxml)
|
68
|
+
doc = to_xhtml_fragment(File.read(@htmlintropage, encoding: "UTF-8"))
|
69
|
+
d = docxml.at('//div[@class="prefatory-section"]')
|
70
|
+
d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def html_cover(docxml)
|
75
|
+
doc = to_xhtml_fragment(File.read(@htmlcoverpage, encoding: "UTF-8"))
|
76
|
+
d = docxml.at('//div[@class="title-section"]')
|
77
|
+
d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
|
78
|
+
end
|
79
|
+
|
80
|
+
def html_intro(docxml)
|
81
|
+
doc = to_xhtml_fragment(File.read(@htmlintropage, encoding: "UTF-8"))
|
82
|
+
d = docxml.at('//div[@class="prefatory-section"]')
|
83
|
+
d.children.first.add_previous_sibling doc.to_xml(encoding: "US-ASCII")
|
84
|
+
end
|
85
|
+
|
86
|
+
def html_toc_entry(level, header)
|
87
|
+
%(<li class="#{level}"><a href="##{header['id']}">\
|
88
|
+
#{header_strip(header)}</a></li>)
|
89
|
+
end
|
90
|
+
|
91
|
+
def toclevel_classes
|
92
|
+
(1..@htmlToClevels).inject([]) { |m, i| m << "h#{i}" }
|
93
|
+
end
|
94
|
+
|
95
|
+
def toclevel
|
96
|
+
ret = toclevel_classes.map { |l| "#{l}:not(:empty):not(.TermNum):not(.noTOC)" }
|
97
|
+
<<~HEAD.freeze
|
98
|
+
function toclevel() { return "#{ret.join(',')}";}
|
99
|
+
HEAD
|
100
|
+
end
|
101
|
+
|
102
|
+
# needs to be same output as toclevel
|
103
|
+
def html_toc(docxml)
|
104
|
+
idx = docxml.at("//div[@id = 'toc']") or return docxml
|
105
|
+
toc = "<ul>"
|
106
|
+
path = toclevel_classes.map do |l|
|
107
|
+
"//main//#{l}[not(@class = 'TermNum')][not(@class = 'noTOC')][not(text())]"
|
108
|
+
end
|
109
|
+
docxml.xpath(path.join(" | ")).each_with_index do |h, tocidx|
|
110
|
+
h["id"] ||= "toc#{tocidx}"
|
111
|
+
toc += html_toc_entry(h.name, h)
|
112
|
+
end
|
113
|
+
idx.children = "#{toc}</ul>"
|
114
|
+
docxml
|
115
|
+
end
|
116
|
+
|
117
|
+
# presupposes that the image source is local
|
118
|
+
def move_images(docxml)
|
119
|
+
FileUtils.rm_rf tmpimagedir
|
120
|
+
FileUtils.mkdir tmpimagedir
|
121
|
+
docxml.xpath("//*[local-name() = 'img']").each do |i|
|
122
|
+
i["width"], i["height"] = Html2Doc.image_resize(i, image_localfile(i),
|
123
|
+
@maxheight, @maxwidth)
|
124
|
+
next if /^data:image/.match i["src"]
|
125
|
+
@datauriimage ? datauri(i) : move_image1(i)
|
126
|
+
end
|
127
|
+
docxml
|
128
|
+
end
|
129
|
+
|
130
|
+
def datauri(i)
|
131
|
+
type = i["src"].split(".")[-1]
|
132
|
+
bin = IO.binread(image_localfile(i))
|
133
|
+
data = Base64.strict_encode64(bin)
|
134
|
+
i["src"] = "data:image/#{type};base64,#{data}"
|
135
|
+
end
|
136
|
+
|
137
|
+
def image_suffix(i)
|
138
|
+
type = i["mimetype"]&.sub(%r{^[^/*]+/}, "")
|
139
|
+
matched = /\.(?<suffix>[^. \r\n\t]+)$/.match i["src"]
|
140
|
+
type and !type.empty? and return type
|
141
|
+
!matched.nil? and matched[:suffix] and return matched[:suffix]
|
142
|
+
"png"
|
143
|
+
end
|
144
|
+
|
145
|
+
def move_image1(i)
|
146
|
+
suffix = image_suffix(i)
|
147
|
+
uuid = UUIDTools::UUID.random_create.to_s
|
148
|
+
fname = "#{uuid}.#{suffix}"
|
149
|
+
new_full_filename = File.join(tmpimagedir, fname)
|
150
|
+
local_filename = image_localfile(i)
|
151
|
+
FileUtils.cp local_filename, new_full_filename
|
152
|
+
i["src"] = File.join(rel_tmpimagedir, fname)
|
153
|
+
end
|
154
|
+
|
155
|
+
def inject_script(doc)
|
156
|
+
return doc unless @scripts
|
157
|
+
scripts = File.read(@scripts, encoding: "UTF-8")
|
158
|
+
doc.sub("</body>", scripts + "\n</body>")
|
159
|
+
end
|
160
|
+
|
161
|
+
def update_footnote_filter(fn, x, i, seen)
|
162
|
+
if seen[fn.text]
|
163
|
+
x.at("./sup").content = seen[fn.text][:num].to_s
|
164
|
+
fn.remove unless x["href"] == seen[fn.text][:href]
|
165
|
+
x["href"] = seen[fn.text][:href]
|
166
|
+
else
|
167
|
+
seen[fn.text] = { num: i, href: x["href"] }
|
168
|
+
x.at("./sup").content = i.to_s
|
169
|
+
i += 1
|
170
|
+
end
|
171
|
+
[i, seen]
|
172
|
+
end
|
173
|
+
|
174
|
+
def html_footnote_filter(docxml)
|
175
|
+
seen = {}
|
176
|
+
i = 1
|
177
|
+
docxml.xpath('//a[@epub:type = "footnote"]').each do |x|
|
178
|
+
fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
|
179
|
+
i, seen = update_footnote_filter(fn, x, i, seen)
|
180
|
+
end
|
181
|
+
docxml
|
182
|
+
end
|
183
|
+
|
184
|
+
def footnote_backlinks(docxml)
|
185
|
+
seen = {}
|
186
|
+
docxml.xpath('//a[@epub:type = "footnote"]').each_with_index do |x, i|
|
187
|
+
seen[x["href"]] and next or seen[x["href"]] = true
|
188
|
+
fn = docxml.at(%<//*[@id = '#{x['href'].sub(/^#/, '')}']>) || next
|
189
|
+
xdup = x.dup
|
190
|
+
xdup.remove["id"]
|
191
|
+
fn.elements.first.children.first.previous = xdup
|
192
|
+
x["id"] ||= "fnref:#{i + 1}"
|
193
|
+
fn.add_child "<a href='##{x['id']}'>↩</a>"
|
194
|
+
end
|
195
|
+
docxml
|
196
|
+
end
|
197
|
+
|
198
|
+
def sourcecode_highlighter
|
199
|
+
'<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>'
|
200
|
+
end
|
201
|
+
|
202
|
+
MATHJAX_ADDR =
|
203
|
+
"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js".freeze
|
204
|
+
MATHJAX = <<~"MATHJAX".freeze
|
205
|
+
<script type="text/x-mathjax-config">
|
206
|
+
MathJax.Hub.Config({
|
207
|
+
asciimath2jax: { delimiters: [['OPEN', 'CLOSE']] }
|
208
|
+
});
|
209
|
+
</script>
|
210
|
+
<script src="#{MATHJAX_ADDR}?config=MML_HTMLorMML-full" async="async"></script>
|
211
|
+
MATHJAX
|
212
|
+
|
213
|
+
def mathjax(open, close)
|
214
|
+
MATHJAX.gsub("OPEN", open).gsub("CLOSE", close)
|
215
|
+
end
|
216
|
+
|
217
|
+
def term_header(docxml)
|
218
|
+
%w(h1 h2 h3 h4 h5 h6 h7 h8).each do |h|
|
219
|
+
docxml.xpath("//p[@class = 'TermNum'][../#{h}]").each do |p|
|
220
|
+
p.name = "h#{h[1].to_i + 1}"
|
221
|
+
end
|
222
|
+
end
|
223
|
+
docxml
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
data/lib/isodoc/version.rb
CHANGED
data/spec/isodoc/blocks_spec.rb
CHANGED
@@ -785,6 +785,7 @@ World</p>
|
|
785
785
|
<permission id="_">
|
786
786
|
<label>/ogc/recommendation/wfs/2</label>
|
787
787
|
<inherit>/ss/584/2015/level/1</inherit>
|
788
|
+
<inherit>/ss/584/2015/level/2</inherit>
|
788
789
|
<subject>user</subject>
|
789
790
|
<classification> <tag>control-class</tag> <value>Technical</value> </classification><classification> <tag>priority</tag> <value>P0</value> </classification><classification> <tag>family</tag> <value>System and Communications Protection</value> </classification><classification> <tag>family</tag> <value>System and Communications Protocols</value> </classification>
|
790
791
|
<description>
|
@@ -834,9 +835,12 @@ World</p>
|
|
834
835
|
<div>
|
835
836
|
<h1 class="ForewordTitle">Foreword</h1>
|
836
837
|
<div class="permission"><p class="RecommendationTitle">Permission 1:<br/>/ogc/recommendation/wfs/2</p>
|
837
|
-
<p><i>Subject: user<br/>
|
838
|
+
<p><i>Subject: user<br/>
|
839
|
+
Inherit: /ss/584/2015/level/1
|
840
|
+
<br/>
|
841
|
+
Inherit: /ss/584/2015/level/2
|
842
|
+
<br/>Control-class: Technical<br/>Priority: P0<br/>Family: System and Communications Protection<br/>Family: System and Communications Protocols</i></p>
|
838
843
|
|
839
|
-
<div class="requirement-inherit">/ss/584/2015/level/1</div>
|
840
844
|
<div class="requirement-description">
|
841
845
|
<p id="_">I recommend <i>this</i>.</p>
|
842
846
|
</div>
|
@@ -919,9 +923,8 @@ World</p>
|
|
919
923
|
<br/>
|
920
924
|
<div>
|
921
925
|
<h1 class="ForewordTitle">Foreword</h1>
|
922
|
-
<div class="require"><p class="RecommendationTitle">Requirement:<br/>/ogc/recommendation/wfs/2. A New Requirement</p><p><i>Subject: user</i></p>
|
926
|
+
<div class="require"><p class="RecommendationTitle">Requirement:<br/>/ogc/recommendation/wfs/2. A New Requirement</p><p><i>Subject: user<br/>Inherit: /ss/584/2015/level/1</i></p>
|
923
927
|
|
924
|
-
<div class="requirement-inherit">/ss/584/2015/level/1</div>
|
925
928
|
<div class="requirement-description">
|
926
929
|
<p id="_">I recommend <i>this</i>.</p>
|
927
930
|
</div>
|
@@ -1005,8 +1008,7 @@ World</p>
|
|
1005
1008
|
<br/>
|
1006
1009
|
<div>
|
1007
1010
|
<h1 class="ForewordTitle">Foreword</h1>
|
1008
|
-
<div class="recommend"><p class="RecommendationTitle">Recommendation 1:<br/>/ogc/recommendation/wfs/2</p><p><i>Obligation: shall,could<br/>Subject: user<br/>Type: text<br/>Language: BASIC</i></p>
|
1009
|
-
<div class="requirement-inherit">/ss/584/2015/level/1</div>
|
1011
|
+
<div class="recommend"><p class="RecommendationTitle">Recommendation 1:<br/>/ogc/recommendation/wfs/2</p><p><i>Obligation: shall,could<br/>Subject: user<br/>Inherit: /ss/584/2015/level/1<br/>Type: text<br/>Language: BASIC</i></p>
|
1010
1012
|
<div class="requirement-description">
|
1011
1013
|
<p id="_">I recommend <i>this</i>.</p>
|
1012
1014
|
</div>
|
data/spec/isodoc/inline_spec.rb
CHANGED
@@ -53,6 +53,123 @@ RSpec.describe IsoDoc do
|
|
53
53
|
OUTPUT
|
54
54
|
end
|
55
55
|
|
56
|
+
it "processes concept markup" do
|
57
|
+
expect(xmlpp(IsoDoc::HtmlConvert.new({}).convert("test", <<~"INPUT", true))).to be_equivalent_to xmlpp(<<~"OUTPUT")
|
58
|
+
<iso-standard xmlns="http://riboseinc.com/isoxml">
|
59
|
+
<preface><foreword>
|
60
|
+
<p>
|
61
|
+
<ul>
|
62
|
+
<li><concept term='term'>
|
63
|
+
<xref target='clause1'/>
|
64
|
+
</concept></li>
|
65
|
+
<li><concept term='term'>
|
66
|
+
<xref target='clause1'>w[o]rd</xref>
|
67
|
+
</concept></li>
|
68
|
+
<li><concept term='term'>
|
69
|
+
<eref bibitemid="ISO712" type="inline" citeas="ISO 712"/>
|
70
|
+
</concept></li>
|
71
|
+
<li><concept term='term'>
|
72
|
+
<eref bibitemid="ISO712" type="inline" citeas="ISO 712">word</eref>
|
73
|
+
</concept></li>
|
74
|
+
<li><concept>
|
75
|
+
<eref bibitemid="ISO712" type="inline" citeas="ISO 712">
|
76
|
+
<locality type='clause'>
|
77
|
+
<referenceFrom>3.1</referenceFrom>
|
78
|
+
</locality>
|
79
|
+
<locality type='figure'>
|
80
|
+
<referenceFrom>a</referenceFrom>
|
81
|
+
</locality>
|
82
|
+
</eref>
|
83
|
+
</concept></li>
|
84
|
+
<li><concept>
|
85
|
+
<eref bibitemid="ISO712" type="inline" citeas="ISO 712">
|
86
|
+
<locality type='clause'>
|
87
|
+
<referenceFrom>3.1</referenceFrom>
|
88
|
+
</locality>
|
89
|
+
<locality type='figure'>
|
90
|
+
<referenceFrom>a</referenceFrom>
|
91
|
+
</locality>
|
92
|
+
<em>word</em>
|
93
|
+
</eref>
|
94
|
+
</concept></li>
|
95
|
+
<li><concept term='term'>
|
96
|
+
<termref base='IEV' target='135-13-13'/>
|
97
|
+
</concept></li>
|
98
|
+
<li><concept term='term'>
|
99
|
+
<termref base='IEV' target='135-13-13'><em>word</em> word</termref>
|
100
|
+
</concept></li>
|
101
|
+
</ul>
|
102
|
+
</p>
|
103
|
+
</foreword></preface>
|
104
|
+
<sections>
|
105
|
+
<clause id="clause1"><title>Clause 1</title></clause>
|
106
|
+
</sections>
|
107
|
+
<bibliography><references id="_normative_references" obligation="informative"><title>Normative References</title>
|
108
|
+
<p>The following documents are referred to in the text in such a way that some or all of their content constitutes requirements of this document. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.</p>
|
109
|
+
<bibitem id="ISO712" type="standard">
|
110
|
+
<title format="text/plain">Cereals or cereal products</title>
|
111
|
+
<title type="main" format="text/plain">Cereals and cereal products</title>
|
112
|
+
<docidentifier type="ISO">ISO 712</docidentifier>
|
113
|
+
<contributor>
|
114
|
+
<role type="publisher"/>
|
115
|
+
<organization>
|
116
|
+
<name>International Organization for Standardization</name>
|
117
|
+
</organization>
|
118
|
+
</contributor>
|
119
|
+
</bibitem>
|
120
|
+
</references></bibliography>
|
121
|
+
</iso-standard>
|
122
|
+
INPUT
|
123
|
+
#{HTML_HDR}
|
124
|
+
<br/>
|
125
|
+
<div>
|
126
|
+
<h1 class='ForewordTitle'>Foreword</h1>
|
127
|
+
<p>
|
128
|
+
<ul>
|
129
|
+
<li>
|
130
|
+
[Term defined in <a href='#clause1'>Clause 2</a>]
|
131
|
+
</li>
|
132
|
+
<li>w[o]rd</li>
|
133
|
+
<li>
|
134
|
+
[Term defined in <a href='#ISO712'>ISO 712</a>]
|
135
|
+
</li>
|
136
|
+
<li>word</li>
|
137
|
+
<li>
|
138
|
+
[Term defined in <a href='#ISO712'>ISO 712, Clause 3.1, Figure a</a>]
|
139
|
+
</li>
|
140
|
+
<li>
|
141
|
+
<i>word</i>
|
142
|
+
</li>
|
143
|
+
<li>[Term defined in Termbase IEV, term ID 135-13-13]</li>
|
144
|
+
<li>
|
145
|
+
<i>word</i> word
|
146
|
+
</li>
|
147
|
+
</ul>
|
148
|
+
</p>
|
149
|
+
</div>
|
150
|
+
<p class='zzSTDTitle1'/>
|
151
|
+
<div>
|
152
|
+
<h1>1.  Normative references</h1>
|
153
|
+
<p>
|
154
|
+
The following documents are referred to in the text in such a way that
|
155
|
+
some or all of their content constitutes requirements of this
|
156
|
+
document. For dated references, only the edition cited applies. For
|
157
|
+
undated references, the latest edition of the referenced document
|
158
|
+
(including any amendments) applies.
|
159
|
+
</p>
|
160
|
+
<p id='ISO712' class='NormRef'>
|
161
|
+
ISO 712, <i>Cereals and cereal products</i>
|
162
|
+
</p>
|
163
|
+
</div>
|
164
|
+
<div id='clause1'>
|
165
|
+
<h1>2.  Clause 1</h1>
|
166
|
+
</div>
|
167
|
+
</div>
|
168
|
+
</body>
|
169
|
+
</html>
|
170
|
+
OUTPUT
|
171
|
+
end
|
172
|
+
|
56
173
|
it "processes embedded inline formatting" do
|
57
174
|
expect(xmlpp(IsoDoc::HtmlConvert.new({}).convert("test", <<~"INPUT", true))).to be_equivalent_to xmlpp(<<~"OUTPUT")
|
58
175
|
<iso-standard xmlns="http://riboseinc.com/isoxml">
|
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: 1.0.
|
4
|
+
version: 1.0.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-01-
|
11
|
+
date: 2020-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciimath
|
@@ -341,6 +341,7 @@ files:
|
|
341
341
|
- lib/isodoc/html_function/comments.rb
|
342
342
|
- lib/isodoc/html_function/footnotes.rb
|
343
343
|
- lib/isodoc/html_function/html.rb
|
344
|
+
- lib/isodoc/html_function/postprocess.rb
|
344
345
|
- lib/isodoc/metadata.rb
|
345
346
|
- lib/isodoc/pdf_convert.rb
|
346
347
|
- lib/isodoc/version.rb
|