isodoc 2.3.2 → 2.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.hound.yml +5 -0
- data/.oss-guides.rubocop.yml +1077 -0
- data/.rubocop.yml +10 -0
- data/isodoc.gemspec +6 -6
- data/lib/isodoc/base_style/blocks.scss +1 -1
- data/lib/isodoc/convert.rb +3 -1
- data/lib/isodoc/function/references.rb +4 -4
- data/lib/isodoc/function/section.rb +1 -1
- data/lib/isodoc/function/to_word_html.rb +5 -4
- data/lib/isodoc/function/utils.rb +30 -41
- data/lib/isodoc/html_function/postprocess.rb +7 -157
- data/lib/isodoc/html_function/postprocess_cover.rb +167 -0
- data/lib/isodoc/presentation_function/image.rb +6 -1
- data/lib/isodoc/presentation_function/inline.rb +22 -7
- data/lib/isodoc/presentation_function/refs.rb +2 -6
- data/lib/isodoc/presentation_function/section.rb +20 -8
- data/lib/isodoc/presentation_function/xrefs.rb +29 -13
- data/lib/isodoc/presentation_xml_convert.rb +1 -1
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/word_function/inline.rb +2 -0
- data/lib/isodoc/xref/xref_sect_gen.rb +51 -36
- data/lib/isodoc-yaml/i18n-en.yaml +1 -1
- data/lib/isodoc-yaml/i18n-fr.yaml +5 -5
- metadata +14 -10
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{
|
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.
|
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.
|
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.
|
42
|
+
spec.add_dependency "metanorma-utils", "~> 1.4.5"
|
43
43
|
spec.add_dependency "mn2pdf"
|
44
|
-
spec.add_dependency "mn-requirements", "~> 0.
|
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"
|
data/lib/isodoc/convert.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
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"]
|