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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ff51f3c21ebf20a813ca5e0a64f0284ce479dcea8752cc6f40a6d49af4e5a325
4
- data.tar.gz: e1385e83fe57b5e7c3b9bd7dec912437a18c12f4b27ba1403da3839dbd535a2b
3
+ metadata.gz: 1c17faca6084ff975799b3c8ffd31b6fffeaf6d11145547042e59c6be7abf8e6
4
+ data.tar.gz: dbb039f5b14cdcd30579eeaea0b7cbbe5e0496e20d566280a9350f9a14ce2177
5
5
  SHA512:
6
- metadata.gz: 881d006ae01107292d309b437a261ca1ad07dacdda64ee9349ce1b5e790e0c14c75e91d63217207c43d1fc19695995ecf9e957b2e8240a815d48d5bf262c7d56
7
- data.tar.gz: '0159616d6bf2d7b03f30409e08703c9b2261e8fa0373a51f8c5714e81670b9b8672e14a0ee5707dde49845c2de0991ad9ec8a7957320fa26beb36844c546db20'
6
+ metadata.gz: e50e9e38683d8a21577d96e81c8c38771c89b4fce3b6482cda3c12e6812385151601c5a3e1085dc47e0fedbf6d561dd4c308c0b9a55e3936ed5cc0c4068188ac
7
+ data.tar.gz: ddc25eddf928b63c959fca69570c76fd6264b811601432e2869efc91bf6553c7e633f4ae3bb29c17e5a157ac2ade5949827aba9d930333dea0d715fb79bef25b
@@ -2,7 +2,11 @@
2
2
  # use ci-master https://github.com/metanorma/metanorma-build-scripts
3
3
  name: macos
4
4
 
5
- on: [push, pull_request]
5
+ on:
6
+ push:
7
+ branches: [ master ]
8
+ pull_request:
9
+ branches: [ '**' ]
6
10
 
7
11
  jobs:
8
12
  test-macos:
@@ -2,7 +2,11 @@
2
2
  # use ci-master https://github.com/metanorma/metanorma-build-scripts
3
3
  name: ubuntu
4
4
 
5
- on: [push, pull_request]
5
+ on:
6
+ push:
7
+ branches: [ master ]
8
+ pull_request:
9
+ branches: [ '**' ]
6
10
 
7
11
  jobs:
8
12
  test-linux:
@@ -2,7 +2,11 @@
2
2
  # use ci-master https://github.com/metanorma/metanorma-build-scripts
3
3
  name: windows
4
4
 
5
- on: [push, pull_request]
5
+ on:
6
+ push:
7
+ branches: [ master ]
8
+ pull_request:
9
+ branches: [ '**' ]
6
10
 
7
11
  jobs:
8
12
  test-windows:
@@ -58,7 +58,8 @@
58
58
  line-height: 1.6em;
59
59
  padding: 1.5em;
60
60
  margin: 2em 0 1em 0;
61
- overflow: auto;
61
+ overflow-y: auto;
62
+ overflow-x: scroll;;
62
63
  }
63
64
 
64
65
  @mixin pseudocodeBlock($colorBg, $colorFg: null) {
@@ -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
- linkend = prefix_container(container, linkend, node["target"])
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
- out.a(**{ "href": target }) { |l| l << get_linkend(node) }
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
- def image_title_parse(out, caption)
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 }
@@ -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
@@ -1,6 +1,7 @@
1
1
  require_relative "html_function/comments.rb"
2
2
  require_relative "html_function/footnotes.rb"
3
3
  require_relative "html_function/html.rb"
4
+ require_relative "html_function/postprocess.rb"
4
5
 
5
6
  module IsoDoc
6
7
  class HtmlConvert < ::IsoDoc::Convert
@@ -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']}'>&#x21A9;</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']}'>&#x21A9;</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
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "1.0.13".freeze
2
+ VERSION = "1.0.14".freeze
3
3
  end
@@ -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/>Control-class: Technical<br/>Priority: P0<br/>Family: System and Communications Protection<br/>Family: System and Communications Protocols</i></p>
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>
@@ -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.&#160; 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.&#160; 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.13
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-07 00:00:00.000000000 Z
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