isodoc 2.3.2 → 2.3.4

Sign up to get free protection for your applications and to get access to all the features.
data/.rubocop.yml ADDED
@@ -0,0 +1,10 @@
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
3
+ inherit_from:
4
+ - https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
5
+
6
+ # local repo-specific modifications
7
+ # ...
8
+
9
+ AllCops:
10
+ TargetRubyVersion: 2.5
data/isodoc.gemspec CHANGED
@@ -25,23 +25,23 @@ Gem::Specification.new do |spec|
25
25
  spec.bindir = "bin"
26
26
  spec.require_paths = ["lib"]
27
27
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
28
- f.match(%r{^(test|spec|features|.github)/}) \
29
- || f.match(%r{\.[a-zA-Z0-9_-]+\.yml|Rakefile|bin/rspec})
28
+ f.match(%r{^(test|spec|features|bin|.github)/}) \
29
+ || f.match(%r{Rakefile|bin/rspec})
30
30
  end
31
31
  spec.test_files = `git ls-files -- {spec}/*`.split("\n")
32
- spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
32
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
33
33
 
34
34
  spec.add_dependency "asciimath"
35
- spec.add_dependency "html2doc", "~> 1.4.1"
35
+ spec.add_dependency "html2doc", "~> 1.4.3"
36
36
  spec.add_dependency "htmlentities", "~> 4.3.4"
37
37
  # spec.add_dependency "isodoc-i18n", "~> 1.1.0" # already in relaton-render and mn-requirements
38
38
  spec.add_dependency "liquid", "~> 4"
39
39
  # spec.add_dependency "metanorma", ">= 1.2.0"
40
40
  spec.add_dependency "emf2svg"
41
41
  spec.add_dependency "mathml2asciimath"
42
- spec.add_dependency "metanorma-utils", "~> 1.4.3"
42
+ spec.add_dependency "metanorma-utils", "~> 1.4.5"
43
43
  spec.add_dependency "mn2pdf"
44
- spec.add_dependency "mn-requirements", "~> 0.1.7"
44
+ spec.add_dependency "mn-requirements", "~> 0.2.0"
45
45
  spec.add_dependency "relaton-cli"
46
46
  spec.add_dependency "relaton-render", "~> 0.5.2"
47
47
  spec.add_dependency "roman-numerals"
@@ -35,7 +35,7 @@
35
35
  @include blockTitle();
36
36
  }
37
37
 
38
- > img {
38
+ > img, > svg {
39
39
  margin-left: auto;
40
40
  margin-right: auto;
41
41
  display: block;
@@ -47,6 +47,7 @@ module IsoDoc
47
47
  # tocrecommendations: add ToC for rcommendations
48
48
  # fonts: fontist fonts to install
49
49
  # fontlicenseagreement: fontist font license agreement
50
+ # modspecidentifierbase: base prefix for any Modspec identifiers
50
51
  def initialize(options) # rubocop:disable Lint/MissingSuper
51
52
  @options = options_preprocess(options)
52
53
  init_stylesheets(@options)
@@ -78,6 +79,7 @@ module IsoDoc
78
79
  @suppressasciimathdup = options[:suppressasciimathdup] == "true"
79
80
  @bare = options[:bare]
80
81
  @aligncrosselements = options[:aligncrosselements]
82
+ @modspecidentifierbase = options[:modspecidentifierbase]
81
83
  end
82
84
 
83
85
  def init_i18n(options)
@@ -216,7 +218,7 @@ module IsoDoc
216
218
  i18n_init(@lang, @script, @locale)
217
219
  @reqt_models = requirements_processor
218
220
  .new({ default: "default", lang: @lang, script: @script, locale: @locale,
219
- labels: @i18n.get })
221
+ labels: @i18n.get, modspecidentifierbase: @modspecidentifierbase })
220
222
  end
221
223
 
222
224
  def convert(input_filename, file = nil, debug = false,
@@ -71,7 +71,7 @@ module IsoDoc
71
71
  def bibitem_ref_code(bib)
72
72
  id = bib.at(ns("./docidentifier[@type = 'metanorma']"))
73
73
  id1 = pref_ref_code(bib)
74
- id2 = bib.at(ns("./docidentifier[@type = 'DOI' or @type = 'ISSN' or "\
74
+ id2 = bib.at(ns("./docidentifier[@type = 'DOI' or @type = 'ISSN' or " \
75
75
  "@type = 'ISBN']"))
76
76
  id3 = bib.at(ns("./docidentifier[@type = 'metanorma-ordinal']"))
77
77
  return [id, id1, id2, id3] if id || id1 || id2 || id3
@@ -179,7 +179,7 @@ module IsoDoc
179
179
  end
180
180
 
181
181
  def norm_ref_xpath
182
- "//bibliography/references[@normative = 'true'] | "\
182
+ "//bibliography/references[@normative = 'true'] | " \
183
183
  "//bibliography/clause[.//references[@normative = 'true']]"
184
184
  end
185
185
 
@@ -198,8 +198,8 @@ module IsoDoc
198
198
  end
199
199
 
200
200
  def bibliography_xpath
201
- "//bibliography/clause[.//references]"\
202
- "[not(.//references[@normative = 'true'])] | "\
201
+ "//bibliography/clause[.//references]" \
202
+ "[not(.//references[@normative = 'true'])] | " \
203
203
  "//bibliography/references[@normative = 'false']"
204
204
  end
205
205
 
@@ -82,7 +82,7 @@ module IsoDoc
82
82
  f = isoxml.at(ns("//sections/definitions")) or return num
83
83
  out.div **attr_code(id: f["id"], class: "Symbols") do |div|
84
84
  num = num + 1
85
- clause_name(num, f&.at(ns("./title")) || @i18n.symbols, div, nil)
85
+ clause_name(num, f.at(ns("./title")), div, nil)
86
86
  f.elements.each do |e|
87
87
  parse(e, div) unless e.name == "title"
88
88
  end
@@ -32,7 +32,8 @@ module IsoDoc
32
32
  def init_dir(filename, debug)
33
33
  dir = "#{filename}#{@tmpfilesdir_suffix}"
34
34
  unless debug
35
- Dir.mkdir(dir, 0o777) unless File.exist?(dir)
35
+ FileUtils.mkdir_p(dir)
36
+ FileUtils.chmod 0o777, dir
36
37
  FileUtils.rm_rf "#{dir}/*"
37
38
  end
38
39
  dir
@@ -205,10 +206,10 @@ module IsoDoc
205
206
  when "recommendation" then recommendation_parse(node, out)
206
207
  when "permission" then permission_parse(node, out)
207
208
  when "div" then div_parse(node, out)
208
- #when "subject", "classification"
209
+ # when "subject", "classification"
209
210
  # requirement_skip_parse(node, out)
210
- #when "inherit", "description", "specification", "measurement-target",
211
- #"verification", "import", "component"
211
+ # when "inherit", "description", "specification", "measurement-target",
212
+ # "verification", "import", "component"
212
213
  # requirement_component_parse(node, out)
213
214
  when "index" then index_parse(node, out)
214
215
  when "index-xref" then index_xref_parse(node, out)
@@ -1,3 +1,5 @@
1
+ require "metanorma-utils"
2
+
1
3
  module IsoDoc
2
4
  module Function
3
5
  module Utils
@@ -18,24 +20,8 @@ module IsoDoc
18
20
  [1..count].each { out << tab }
19
21
  end
20
22
 
21
- # add namespaces for Word fragments
22
- NOKOHEAD = <<~HERE.freeze
23
- <!DOCTYPE html SYSTEM
24
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
25
- <html xmlns="http://www.w3.org/1999/xhtml">
26
- <head> <title></title> <meta charset="UTF-8" /> </head>
27
- <body> </body> </html>
28
- HERE
29
-
30
- # block for processing XML document fragments as XHTML,
31
- # to allow for HTMLentities
32
23
  def noko(&block)
33
- doc = ::Nokogiri::XML.parse(NOKOHEAD)
34
- fragment = doc.fragment("")
35
- ::Nokogiri::XML::Builder.with fragment, &block
36
- fragment.to_xml(encoding: "US-ASCII").lines.map do |l|
37
- l.gsub(/\s*\n/, "")
38
- end
24
+ Metanorma::Utils::noko_html(&block)
39
25
  end
40
26
 
41
27
  def attr_code(attributes)
@@ -44,7 +30,7 @@ module IsoDoc
44
30
  end
45
31
  end
46
32
 
47
- DOCTYPE_HDR = "<!DOCTYPE html SYSTEM "\
33
+ DOCTYPE_HDR = "<!DOCTYPE html SYSTEM " \
48
34
  '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'.freeze
49
35
 
50
36
  def to_xhtml(xml)
@@ -55,19 +41,13 @@ module IsoDoc
55
41
  File.open("#{@filename}.#{@format}.err", "w:UTF-8") do |f|
56
42
  f.write xml
57
43
  end
58
- abort "Malformed Output XML for #{@format}: #{e} "\
44
+ abort "Malformed Output XML for #{@format}: #{e} " \
59
45
  "(see #{@filename}.#{@format}.err)"
60
46
  end
61
47
  end
62
48
 
63
49
  def numeric_escapes(xml)
64
- c = HTMLEntities.new
65
- xml.split(/(&[^ \r\n\t#;]+;)/).map do |t|
66
- if /^(&[^ \t\r\n#;]+;)/.match?(t)
67
- c.encode(c.decode(t), :hexadecimal)
68
- else t
69
- end
70
- end.join
50
+ Metanorma::Utils::numeric_escapes(xml)
71
51
  end
72
52
 
73
53
  def to_xhtml_prep(xml)
@@ -77,8 +57,7 @@ module IsoDoc
77
57
  end
78
58
 
79
59
  def to_xhtml_fragment(xml)
80
- doc = ::Nokogiri::XML.parse(NOKOHEAD)
81
- doc.fragment(xml)
60
+ Metanorma::Utils::to_xhtml_fragment(xml)
82
61
  end
83
62
 
84
63
  def from_xhtml(xml)
@@ -87,11 +66,11 @@ module IsoDoc
87
66
  end
88
67
 
89
68
  CLAUSE_ANCESTOR =
90
- ".//ancestor::*[local-name() = 'annex' or "\
91
- "local-name() = 'definitions' or "\
92
- "local-name() = 'acknowledgements' or local-name() = 'term' or "\
93
- "local-name() = 'appendix' or local-name() = 'foreword' or "\
94
- "local-name() = 'introduction' or local-name() = 'terms' or "\
69
+ ".//ancestor::*[local-name() = 'annex' or " \
70
+ "local-name() = 'definitions' or " \
71
+ "local-name() = 'acknowledgements' or local-name() = 'term' or " \
72
+ "local-name() = 'appendix' or local-name() = 'foreword' or " \
73
+ "local-name() = 'introduction' or local-name() = 'terms' or " \
95
74
  "local-name() = 'clause' or local-name() = 'references']/@id".freeze
96
75
 
97
76
  def get_clause_id(node)
@@ -99,12 +78,12 @@ module IsoDoc
99
78
  end
100
79
 
101
80
  NOTE_CONTAINER_ANCESTOR =
102
- ".//ancestor::*[local-name() = 'annex' or "\
103
- "local-name() = 'foreword' or local-name() = 'appendix' or "\
104
- "local-name() = 'introduction' or local-name() = 'terms' or "\
105
- "local-name() = 'acknowledgements' or local-name() = 'term' or "\
106
- "local-name() = 'clause' or local-name() = 'references' or "\
107
- "local-name() = 'figure' or local-name() = 'formula' or "\
81
+ ".//ancestor::*[local-name() = 'annex' or " \
82
+ "local-name() = 'foreword' or local-name() = 'appendix' or " \
83
+ "local-name() = 'introduction' or local-name() = 'terms' or " \
84
+ "local-name() = 'acknowledgements' or local-name() = 'term' or " \
85
+ "local-name() = 'clause' or local-name() = 'references' or " \
86
+ "local-name() = 'figure' or local-name() = 'formula' or " \
108
87
  "local-name() = 'table' or local-name() = 'example']/@id".freeze
109
88
 
110
89
  # no recursion on references
@@ -121,7 +100,7 @@ module IsoDoc
121
100
 
122
101
  if array.length == 1 then array[0]
123
102
  else
124
- @i18n.l10n("#{array[0..-2].join(', ')} "\
103
+ @i18n.l10n("#{array[0..-2].join(', ')} " \
125
104
  "#{@i18n.and} #{array.last}",
126
105
  @lang, @script)
127
106
  end
@@ -197,7 +176,17 @@ module IsoDoc
197
176
  end
198
177
  end
199
178
 
179
+ def save_svg(img)
180
+ Tempfile.open(["image", ".svg"]) do |f|
181
+ f.write(img.to_xml)
182
+ @tempfile_cache << f # persist to the end
183
+ f.path
184
+ end
185
+ end
186
+
200
187
  def image_localfile(img)
188
+ img.name == "svg" && !img["src"] and
189
+ return save_svg(img)
201
190
  case img["src"]
202
191
  when /^data:/ then save_dataimage(img["src"], false)
203
192
  when %r{^([A-Z]:)?/} then img["src"]
@@ -206,7 +195,7 @@ module IsoDoc
206
195
  end
207
196
 
208
197
  def labelled_ancestor(node)
209
- !node.ancestors("example, requirement, recommendation, permission, "\
198
+ !node.ancestors("example, requirement, recommendation, permission, " \
210
199
  "note, table, figure, sourcecode").empty?
211
200
  end
212
201
 
@@ -1,5 +1,6 @@
1
1
  require "isodoc/html_function/mathvariant_to_plain"
2
2
  require_relative "postprocess_footnotes"
3
+ require_relative "postprocess_cover"
3
4
  require "metanorma-utils"
4
5
 
5
6
  module IsoDoc
@@ -11,16 +12,9 @@ module IsoDoc
11
12
  @files_to_delete.each { |f| FileUtils.rm_rf f }
12
13
  end
13
14
 
14
- def script_cdata(result)
15
- result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>")
16
- .gsub(%r{\]\]>\s*</script>}, "</script>")
17
- .gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>")
18
- .gsub(%r{</script>\s*\]\]>}, "</script>")
19
- end
20
-
21
15
  def toHTML(result, filename)
22
16
  result = from_xhtml(html_cleanup(to_xhtml(result)))
23
- result = from_xhtml(move_images(to_xhtml(result)))
17
+ result = from_xhtml(move_images(resize_images(to_xhtml(result))))
24
18
  result = html5(script_cdata(inject_script(result)))
25
19
  File.open(filename, "w:UTF-8") { |f| f.write(result) }
26
20
  end
@@ -56,132 +50,20 @@ module IsoDoc
56
50
  IsoDoc::HtmlFunction::MathvariantToPlain.new(docxml).convert
57
51
  end
58
52
 
59
- def htmlstylesheet(file)
60
- return if file.nil?
61
-
62
- file.open if file.is_a?(Tempfile)
63
- stylesheet = file.read
64
- xml = Nokogiri::XML("<style/>")
65
- xml.children.first << Nokogiri::XML::Comment
66
- .new(xml, "\n#{stylesheet}\n")
67
- file.close
68
- file.unlink if file.is_a?(Tempfile)
69
- xml.root.to_s
70
- end
71
-
72
- def htmlstyle(docxml)
73
- return docxml unless @htmlstylesheet
74
-
75
- head = docxml.at("//*[local-name() = 'head']")
76
- head << htmlstylesheet(@htmlstylesheet)
77
- s = htmlstylesheet(@htmlstylesheet_override) and head << s
78
- @bare and
79
- head << "<style>body {margin-left: 2em; margin-right: 2em;}</style>"
80
- docxml
81
- end
82
-
83
- def html_preface(docxml)
84
- html_cover(docxml) if @htmlcoverpage && !@bare
85
- html_intro(docxml) if @htmlintropage && !@bare
86
- docxml.at("//body") << mathjax(@openmathdelim, @closemathdelim)
87
- docxml.at("//body") << sourcecode_highlighter
88
- html_main(docxml)
89
- authority_cleanup(docxml)
90
- docxml
91
- end
92
-
93
- def authority_cleanup1(docxml, klass)
94
- dest = docxml.at("//div[@id = 'boilerplate-#{klass}-destination']")
95
- auth = docxml.at("//div[@id = 'boilerplate-#{klass}' or "\
96
- "@class = 'boilerplate-#{klass}']")
97
- auth&.xpath(".//h1[not(text())] | .//h2[not(text())]")&.each(&:remove)
98
- auth&.xpath(".//h1 | .//h2")&.each { |h| h["class"] = "IntroTitle" }
99
- dest and auth and dest.replace(auth.remove)
100
- end
101
-
102
- def authority_cleanup(docxml)
103
- %w(copyright license legal feedback).each do |t|
104
- authority_cleanup1(docxml, t)
105
- end
106
- coverpage_note_cleanup(docxml)
107
- end
108
-
109
- def coverpage_note_cleanup(docxml)
110
- if dest = docxml.at("//div[@id = 'coverpage-note-destination']")
111
- auth = docxml.xpath("//*[@coverpage]")
112
- if auth.empty? then dest.remove
113
- else
114
- auth.each do |x|
115
- dest << x.remove
116
- end
117
- end
118
- end
119
- docxml.xpath("//*[@coverpage]").each { |x| x.delete("coverpage") }
120
- end
121
-
122
- def html_cover(docxml)
123
- doc = to_xhtml_fragment(File.read(@htmlcoverpage, encoding: "UTF-8"))
124
- d = docxml.at('//div[@class="title-section"]')
125
- d.children.first.add_previous_sibling(
126
- populate_template(doc.to_xml(encoding: "US-ASCII"), :html),
127
- )
128
- end
129
-
130
- def html_intro(docxml)
131
- doc = to_xhtml_fragment(File.read(@htmlintropage, encoding: "UTF-8"))
132
- d = docxml.at('//div[@class="prefatory-section"]')
133
- d.children.first.add_previous_sibling(
134
- populate_template(doc.to_xml(encoding: "US-ASCII"), :html),
135
- )
136
- end
137
-
138
- def html_toc_entry(level, header)
139
- content = header.at("./following-sibling::p"\
140
- "[@class = 'variant-title-toc']") || header
141
- %(<li class="#{level}"><a href="##{header['id']}">\
142
- #{header_strip(content)}</a></li>)
143
- end
144
-
145
- def toclevel_classes
146
- (1..@htmlToClevels).reduce([]) { |m, i| m << "h#{i}" }
147
- end
148
-
149
- def toclevel
150
- ret = toclevel_classes.map do |l|
151
- "#{l}:not(:empty):not(.TermNum):not(.noTOC)"
152
- end
153
- <<~HEAD.freeze
154
- function toclevel() { return "#{ret.join(',')}";}
155
- HEAD
156
- end
157
-
158
- # needs to be same output as toclevel
159
- def html_toc(docxml)
160
- idx = docxml.at("//div[@id = 'toc']") or return docxml
161
- toc = "<ul>"
162
- path = toclevel_classes.map do |l|
163
- "//main//#{l}#{toc_exclude_class}"
164
- end
165
- docxml.xpath(path.join(" | ")).each_with_index do |h, tocidx|
166
- h["id"] ||= "toc#{tocidx}"
167
- toc += html_toc_entry(h.name, h)
53
+ def resize_images(docxml)
54
+ docxml.xpath("//*[local-name() = 'img' or local-name() = 'svg']")
55
+ .each do |i|
56
+ i["width"], i["height"] = Html2Doc.new({})
57
+ .image_resize(i, image_localfile(i), @maxheight, @maxwidth)
168
58
  end
169
- idx.children = "#{toc}</ul>"
170
59
  docxml
171
60
  end
172
61
 
173
- def toc_exclude_class
174
- "[not(@class = 'TermNum')][not(@class = 'noTOC')]"\
175
- "[string-length(normalize-space(.))>0]"
176
- end
177
-
178
62
  # presupposes that the image source is local
179
63
  def move_images(docxml)
180
64
  FileUtils.rm_rf tmpimagedir
181
65
  FileUtils.mkdir tmpimagedir
182
66
  docxml.xpath("//*[local-name() = 'img']").each do |i|
183
- i["width"], i["height"] = Html2Doc.new({})
184
- .image_resize(i, image_localfile(i), @maxheight, @maxwidth)
185
67
  next if /^data:/.match? i["src"]
186
68
 
187
69
  @datauriimage ? datauri(i) : move_image1(i)
@@ -212,38 +94,6 @@ module IsoDoc
212
94
  img["src"] = File.join(rel_tmpimagedir, fname)
213
95
  end
214
96
 
215
- def inject_script(doc)
216
- return doc unless @scripts
217
-
218
- scripts = File.read(@scripts, encoding: "UTF-8")
219
- scripts_override = ""
220
- @scripts_override and
221
- scripts_override = File.read(@scripts_override, encoding: "UTF-8")
222
- a = doc.split(%r{</body>})
223
- "#{a[0]}#{scripts}#{scripts_override}</body>#{a[1]}"
224
- end
225
-
226
- def sourcecode_highlighter
227
- '<script src="https://cdn.rawgit.com/google/code-prettify/master/'\
228
- 'loader/run_prettify.js"></script>'
229
- end
230
-
231
- MATHJAX_ADDR =
232
- "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js".freeze
233
- MATHJAX = <<~"MATHJAX".freeze
234
- <script type="text/x-mathjax-config">
235
- MathJax.Hub.Config({
236
- "HTML-CSS": { preferredFont: "STIX" },
237
- asciimath2jax: { delimiters: [['OPEN', 'CLOSE']] }
238
- });
239
- </script>
240
- <script src="#{MATHJAX_ADDR}?config=MML_HTMLorMML-full" async="async"></script>
241
- MATHJAX
242
-
243
- def mathjax(open, close)
244
- MATHJAX.gsub("OPEN", open).gsub("CLOSE", close)
245
- end
246
-
247
97
  def term_header(docxml)
248
98
  %w(h1 h2 h3 h4 h5 h6 h7 h8).each do |h|
249
99
  docxml.xpath("//p[@class = 'TermNum'][../#{h}]").each do |p|
@@ -0,0 +1,167 @@
1
+ require "isodoc/html_function/mathvariant_to_plain"
2
+ require_relative "postprocess_footnotes"
3
+ require "metanorma-utils"
4
+
5
+ module IsoDoc
6
+ module HtmlFunction
7
+ module Html
8
+ def script_cdata(result)
9
+ result.gsub(%r{<script([^>]*)>\s*<!\[CDATA\[}m, "<script\\1>")
10
+ .gsub(%r{\]\]>\s*</script>}, "</script>")
11
+ .gsub(%r{<!\[CDATA\[\s*<script([^>]*)>}m, "<script\\1>")
12
+ .gsub(%r{</script>\s*\]\]>}, "</script>")
13
+ end
14
+
15
+ def htmlstylesheet(file)
16
+ return if file.nil?
17
+
18
+ file.open if file.is_a?(Tempfile)
19
+ stylesheet = file.read
20
+ xml = Nokogiri::XML("<style/>")
21
+ xml.children.first << Nokogiri::XML::Comment
22
+ .new(xml, "\n#{stylesheet}\n")
23
+ file.close
24
+ file.unlink if file.is_a?(Tempfile)
25
+ xml.root.to_s
26
+ end
27
+
28
+ def htmlstyle(docxml)
29
+ return docxml unless @htmlstylesheet
30
+
31
+ head = docxml.at("//*[local-name() = 'head']")
32
+ head << htmlstylesheet(@htmlstylesheet)
33
+ s = htmlstylesheet(@htmlstylesheet_override) and head << s
34
+ @bare and
35
+ head << "<style>body {margin-left: 2em; margin-right: 2em;}</style>"
36
+ docxml
37
+ end
38
+
39
+ def html_preface(docxml)
40
+ html_cover(docxml) if @htmlcoverpage && !@bare
41
+ html_intro(docxml) if @htmlintropage && !@bare
42
+ docxml.at("//body") << mathjax(@openmathdelim, @closemathdelim)
43
+ docxml.at("//body") << sourcecode_highlighter
44
+ html_main(docxml)
45
+ authority_cleanup(docxml)
46
+ docxml
47
+ end
48
+
49
+ def authority_cleanup1(docxml, klass)
50
+ dest = docxml.at("//div[@id = 'boilerplate-#{klass}-destination']")
51
+ auth = docxml.at("//div[@id = 'boilerplate-#{klass}' or "\
52
+ "@class = 'boilerplate-#{klass}']")
53
+ auth&.xpath(".//h1[not(text())] | .//h2[not(text())]")&.each(&:remove)
54
+ auth&.xpath(".//h1 | .//h2")&.each { |h| h["class"] = "IntroTitle" }
55
+ dest and auth and dest.replace(auth.remove)
56
+ end
57
+
58
+ def authority_cleanup(docxml)
59
+ %w(copyright license legal feedback).each do |t|
60
+ authority_cleanup1(docxml, t)
61
+ end
62
+ coverpage_note_cleanup(docxml)
63
+ end
64
+
65
+ def coverpage_note_cleanup(docxml)
66
+ if dest = docxml.at("//div[@id = 'coverpage-note-destination']")
67
+ auth = docxml.xpath("//*[@coverpage]")
68
+ if auth.empty? then dest.remove
69
+ else
70
+ auth.each do |x|
71
+ dest << x.remove
72
+ end
73
+ end
74
+ end
75
+ docxml.xpath("//*[@coverpage]").each { |x| x.delete("coverpage") }
76
+ end
77
+
78
+ def html_cover(docxml)
79
+ doc = to_xhtml_fragment(File.read(@htmlcoverpage, encoding: "UTF-8"))
80
+ d = docxml.at('//div[@class="title-section"]')
81
+ d.children.first.add_previous_sibling(
82
+ populate_template(doc.to_xml(encoding: "US-ASCII"), :html),
83
+ )
84
+ end
85
+
86
+ def html_intro(docxml)
87
+ doc = to_xhtml_fragment(File.read(@htmlintropage, encoding: "UTF-8"))
88
+ d = docxml.at('//div[@class="prefatory-section"]')
89
+ d.children.first.add_previous_sibling(
90
+ populate_template(doc.to_xml(encoding: "US-ASCII"), :html),
91
+ )
92
+ end
93
+
94
+ def html_toc_entry(level, header)
95
+ content = header.at("./following-sibling::p"\
96
+ "[@class = 'variant-title-toc']") || header
97
+ %(<li class="#{level}"><a href="##{header['id']}">\
98
+ #{header_strip(content)}</a></li>)
99
+ end
100
+
101
+ def toclevel_classes
102
+ (1..@htmlToClevels).reduce([]) { |m, i| m << "h#{i}" }
103
+ end
104
+
105
+ def toclevel
106
+ ret = toclevel_classes.map do |l|
107
+ "#{l}:not(:empty):not(.TermNum):not(.noTOC)"
108
+ end
109
+ <<~HEAD.freeze
110
+ function toclevel() { return "#{ret.join(',')}";}
111
+ HEAD
112
+ end
113
+
114
+ # needs to be same output as toclevel
115
+ def html_toc(docxml)
116
+ idx = docxml.at("//div[@id = 'toc']") or return docxml
117
+ toc = "<ul>"
118
+ path = toclevel_classes.map do |l|
119
+ "//main//#{l}#{toc_exclude_class}"
120
+ end
121
+ docxml.xpath(path.join(" | ")).each_with_index do |h, tocidx|
122
+ h["id"] ||= "toc#{tocidx}"
123
+ toc += html_toc_entry(h.name, h)
124
+ end
125
+ idx.children = "#{toc}</ul>"
126
+ docxml
127
+ end
128
+
129
+ def toc_exclude_class
130
+ "[not(@class = 'TermNum')][not(@class = 'noTOC')]"\
131
+ "[string-length(normalize-space(.))>0]"
132
+ end
133
+
134
+ def inject_script(doc)
135
+ return doc unless @scripts
136
+
137
+ scripts = File.read(@scripts, encoding: "UTF-8")
138
+ scripts_override = ""
139
+ @scripts_override and
140
+ scripts_override = File.read(@scripts_override, encoding: "UTF-8")
141
+ a = doc.split(%r{</body>})
142
+ "#{a[0]}#{scripts}#{scripts_override}</body>#{a[1]}"
143
+ end
144
+
145
+ def sourcecode_highlighter
146
+ '<script src="https://cdn.rawgit.com/google/code-prettify/master/'\
147
+ 'loader/run_prettify.js"></script>'
148
+ end
149
+
150
+ MATHJAX_ADDR =
151
+ "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js".freeze
152
+ MATHJAX = <<~"MATHJAX".freeze
153
+ <script type="text/x-mathjax-config">
154
+ MathJax.Hub.Config({
155
+ "HTML-CSS": { preferredFont: "STIX" },
156
+ asciimath2jax: { delimiters: [['OPEN', 'CLOSE']] }
157
+ });
158
+ </script>
159
+ <script src="#{MATHJAX_ADDR}?config=MML_HTMLorMML-full" async="async"></script>
160
+ MATHJAX
161
+
162
+ def mathjax(open, close)
163
+ MATHJAX.gsub("OPEN", open).gsub("CLOSE", close)
164
+ end
165
+ end
166
+ end
167
+ end
@@ -108,6 +108,11 @@ module IsoDoc
108
108
 
109
109
  def svg_to_emf(node)
110
110
  uri = svg_to_emf_uri(node)
111
+ if node.elements&.first&.name == "svg" &&
112
+ (!node["height"] || node["height"] == "auto")
113
+ node["height"] = node.elements.first["height"]
114
+ node["width"] = node.elements.first["width"]
115
+ end
111
116
  ret = imgfile_suffix(uri, "emf")
112
117
  File.exist?(ret) and return ret
113
118
  inkscape_convert(uri, ret, '--export-type="emf"')
@@ -143,7 +148,7 @@ module IsoDoc
143
148
  end
144
149
 
145
150
  def svg_to_emf_uri_convert(node)
146
- if node&.elements&.first&.name == "svg"
151
+ if node.elements&.first&.name == "svg"
147
152
  a = Base64.strict_encode64(node.children.to_xml)
148
153
  "data:image/svg+xml;base64,#{a}"
149
154
  else node["src"]