isodoc 2.3.2 → 2.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.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"]
|