metanorma 2.1.7 → 2.1.9
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/lib/metanorma/collection/collection.rb +1 -1
- data/lib/metanorma/collection/document/document.rb +2 -0
- data/lib/metanorma/collection/filelookup/filelookup.rb +2 -2
- data/lib/metanorma/collection/filelookup/filelookup_sectionsplit.rb +3 -2
- data/lib/metanorma/collection/renderer/fileparse.rb +12 -39
- data/lib/metanorma/collection/renderer/renderer.rb +3 -1
- data/lib/metanorma/collection/renderer/utils.rb +3 -9
- data/lib/metanorma/collection/sectionsplit/collection.rb +1 -0
- data/lib/metanorma/collection/sectionsplit/sectionsplit.rb +84 -49
- data/lib/metanorma/collection/util/util.rb +24 -11
- data/lib/metanorma/collection/xrefprocess/xrefprocess.rb +2 -3
- data/lib/metanorma/compile/assets/icc-boilerplate.adoc +41 -0
- data/lib/metanorma/compile/compile.rb +29 -204
- data/lib/metanorma/compile/compile_options.rb +27 -12
- data/lib/metanorma/compile/flavor.rb +3 -6
- data/lib/metanorma/compile/render.rb +178 -0
- data/lib/metanorma/compile/validator.rb +2 -4
- data/lib/metanorma/input/asciidoc.rb +12 -6
- data/lib/metanorma/registry/registry.rb +6 -8
- data/lib/metanorma/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6f662b6213511d30fb8f16f0bc51bb4209959a4f17ac385d81bdd02f1135088
|
4
|
+
data.tar.gz: 4021db66267ad5cbc213058d7b2252d6a2f9572e6efd686df2f84ba1f1965cbb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ba138f8fd28e6e4ee1d0fcc786f49b17b816483c39a6d2dda89643b9611bed93068ac8f3e700ba199a01f0f0446ce2c46be97d4a7e705a67df04e6b1d898432
|
7
|
+
data.tar.gz: 45a50ed06452ff4e598bc95ce07412eeca39b33afe7158a48f17080381417cda79ba4ed4286901652a6e4f6311d0ad70e083388aba4e3150c22f543f56825dde
|
@@ -172,7 +172,7 @@ module Metanorma
|
|
172
172
|
def fetch_flavor
|
173
173
|
docid = @bibdata.docidentifier.first or return
|
174
174
|
f = docid.type.downcase || docid.id.sub(/\s.*$/, "").downcase or return
|
175
|
-
require ::Metanorma::Compile.new.
|
175
|
+
require ::Metanorma::Compile.new.stdtype2flavor_gem(f)
|
176
176
|
f
|
177
177
|
rescue LoadError
|
178
178
|
nil
|
@@ -18,6 +18,7 @@ module Metanorma
|
|
18
18
|
@parent = parent
|
19
19
|
@xml = parent.xml
|
20
20
|
@isodoc = parent.isodoc
|
21
|
+
@isodoc_presxml = parent.isodoc_presxml
|
21
22
|
@path = path
|
22
23
|
@compile = parent.compile
|
23
24
|
@documents = parent.documents
|
@@ -131,7 +132,7 @@ module Metanorma
|
|
131
132
|
|
132
133
|
def add_document_suffix(identifier, doc)
|
133
134
|
document_suffix = Metanorma::Utils::to_ncname(identifier)
|
134
|
-
|
135
|
+
Util::anchor_id_attributes.each do |(tag_name, attr_name)|
|
135
136
|
Util::add_suffix_to_attrs(doc, document_suffix, tag_name, attr_name,
|
136
137
|
@isodoc)
|
137
138
|
end
|
@@ -230,7 +231,6 @@ module Metanorma
|
|
230
231
|
ret = {}
|
231
232
|
xml.traverse do |x|
|
232
233
|
x.text? and next
|
233
|
-
/^semantic__/.match?(x.name) and next
|
234
234
|
x["id"] and ret[x["id"]] = true
|
235
235
|
end
|
236
236
|
ret
|
@@ -110,8 +110,9 @@ module Metanorma
|
|
110
110
|
@sectionsplit = ::Metanorma::Collection::Sectionsplit
|
111
111
|
.new(input: file, base: @files[ident][:out_path],
|
112
112
|
dir: File.dirname(file), output: @files[ident][:out_path],
|
113
|
-
compile_opts: @parent.compile_options,
|
114
|
-
fileslookup: self,
|
113
|
+
compile_opts: @parent.compile_options, ident: ident,
|
114
|
+
fileslookup: self, isodoc: @isodoc,
|
115
|
+
isodoc_presxml: @isodoc_presxml,
|
115
116
|
document_suffix: @files[ident][:document_suffix])
|
116
117
|
coll = @sectionsplit.sectionsplit.sort_by { |f| f[:order] }
|
117
118
|
xml = Nokogiri::XML(File.read(file, encoding: "UTF-8"), &:huge)
|
@@ -16,8 +16,6 @@ module Metanorma
|
|
16
16
|
# @return [String] XML content
|
17
17
|
def update_xrefs(file, docid, internal_refs)
|
18
18
|
xml, sso = update_xrefs_prep(file, docid)
|
19
|
-
#require "debug"; binding.b if /This document is also unrelated/.match?(xml.to_xml)
|
20
|
-
#warn (/fmt-title/.match?(xml.to_xml) ? "*** PRESENTATION" : "*** SEMANTIC")
|
21
19
|
@nested || sso or
|
22
20
|
Metanorma::Collection::XrefProcess::xref_process(xml, xml, nil, docid,
|
23
21
|
@isodoc, sso)
|
@@ -26,7 +24,7 @@ module Metanorma
|
|
26
24
|
@files.add_document_suffix(docid, xml)
|
27
25
|
@nested or update_sectionsplit_refs_to_docs(xml, internal_refs, sso)
|
28
26
|
update_direct_refs_to_docs(xml, docid, sso)
|
29
|
-
hide_refs(xml)
|
27
|
+
::Metanorma::Collection::Util::hide_refs(xml)
|
30
28
|
sso and eref2link(xml, sso)
|
31
29
|
@nested or svgmap_resolve(xml, docid, sso)
|
32
30
|
xml.to_xml
|
@@ -109,7 +107,6 @@ module Metanorma
|
|
109
107
|
else no_anchor[k] << e end
|
110
108
|
end
|
111
109
|
end
|
112
|
-
#require "debug"; binding.b
|
113
110
|
[erefs, no_anchor, anchors, Util::gather_bibitemids(docxml, presxml)]
|
114
111
|
end
|
115
112
|
|
@@ -128,8 +125,9 @@ module Metanorma
|
|
128
125
|
|
129
126
|
# Resolve erefs to a container of ids in another doc,
|
130
127
|
# to an anchor eref (direct link)
|
131
|
-
def update_indirect_refs_to_docs(docxml,
|
132
|
-
bib, erefs, doc_suffix, doc_type, f = update_indirect_refs_prep(docxml,
|
128
|
+
def update_indirect_refs_to_docs(docxml, _docid, internal_refs, presxml)
|
129
|
+
bib, erefs, doc_suffix, doc_type, f = update_indirect_refs_prep(docxml,
|
130
|
+
presxml)
|
133
131
|
internal_refs.each do |schema, ids|
|
134
132
|
add_suffix = doc_suffix && doc_type && doc_type != schema
|
135
133
|
ids.each do |id, file|
|
@@ -149,37 +147,15 @@ module Metanorma
|
|
149
147
|
docxml.root["document_suffix"], docxml.root["type"], {}]
|
150
148
|
end
|
151
149
|
|
152
|
-
# KILL
|
153
|
-
def indirect_ref_key(schema, id, doc_suffix, doc_type)
|
154
|
-
/^#{schema}_/.match?(id) and return id
|
155
|
-
key = [schema, id, doc_suffix, doc_type].join("::")
|
156
|
-
x = @indirect_keys[key] and return x
|
157
|
-
ret = "#{schema}_#{id}"
|
158
|
-
doc_suffix && doc_type && doc_type != schema and
|
159
|
-
ret = "#{ret}_#{doc_suffix}"
|
160
|
-
@indirect_keys[key] = ret
|
161
|
-
ret
|
162
|
-
end
|
163
|
-
|
164
150
|
def indirect_ref_key(schema, id, doc_suffix, add_suffix)
|
165
151
|
/^#{schema}_/.match?(id) and return id
|
166
|
-
#key = "#{schema}_#{id}"
|
167
152
|
x = @indirect_keys.dig(schema, id) and return x
|
168
153
|
@indirect_keys[schema] ||= {}
|
169
154
|
@indirect_keys[schema][id] = if add_suffix
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
end
|
175
|
-
|
176
|
-
# KILL
|
177
|
-
def indirect_ref_keyx(schema, id, doc_suffix, doc_type)
|
178
|
-
/^#{schema}_/.match?(id) and return id
|
179
|
-
ret = "#{schema}_#{id}"
|
180
|
-
doc_suffix && doc_type && doc_type != schema and
|
181
|
-
ret = "#{ret}_#{doc_suffix}"
|
182
|
-
ret
|
155
|
+
"#{schema}_#{id}_#{doc_suffix}"
|
156
|
+
else
|
157
|
+
"#{schema}_#{id}"
|
158
|
+
end
|
183
159
|
end
|
184
160
|
|
185
161
|
def update_indirect_refs_to_docs1(filec, key, file, bibitems, erefs)
|
@@ -196,13 +172,10 @@ module Metanorma
|
|
196
172
|
parentid and file = "#{parentid}_#{file}"
|
197
173
|
existing = a.text
|
198
174
|
anchor = if url then existing
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
@indirect_keys[existing] ||= {}
|
204
|
-
@indirect_keys[existing][file] ||= Metanorma::Utils::to_ncname("#{existing}_#{file}")
|
205
|
-
end
|
175
|
+
else
|
176
|
+
@indirect_keys[existing] ||= {}
|
177
|
+
@indirect_keys[existing][file] ||= Metanorma::Utils::to_ncname("#{existing}_#{file}")
|
178
|
+
end
|
206
179
|
@updated_anchors[existing] or a.children = anchor
|
207
180
|
@updated_anchors[anchor] = true
|
208
181
|
end
|
@@ -15,7 +15,7 @@ module Metanorma
|
|
15
15
|
class Renderer
|
16
16
|
FORMATS = %i[html xml doc pdf].freeze
|
17
17
|
|
18
|
-
attr_accessor :isodoc, :nested
|
18
|
+
attr_accessor :isodoc, :isodoc_presxml, :nested
|
19
19
|
attr_reader :xml, :compile, :compile_options, :documents, :outdir,
|
20
20
|
:manifest
|
21
21
|
|
@@ -45,6 +45,8 @@ module Metanorma
|
|
45
45
|
|
46
46
|
# output processor for flavour
|
47
47
|
@isodoc = Util::isodoc_create(@flavor, @lang, @script, @xml)
|
48
|
+
@isodoc_presxml = Util::isodoc_create(@flavor, @lang, @script, @xml,
|
49
|
+
presxml: true)
|
48
50
|
@outdir = dir_name_cleanse(options[:output_folder])
|
49
51
|
@coverpage = options[:coverpage] || collection.coverpage
|
50
52
|
@format = ::Metanorma::Util.sort_extensions_execution(options[:format])
|
@@ -17,6 +17,7 @@ module Metanorma
|
|
17
17
|
newbib["hidden"] = "true"
|
18
18
|
newbib&.at("./*[local-name() = 'ext']")&.remove
|
19
19
|
newbib["id"] = bib["id"]
|
20
|
+
bib["anchor"] and newbib["anchor"] = bib["anchor"]
|
20
21
|
newbib
|
21
22
|
end
|
22
23
|
|
@@ -37,17 +38,10 @@ module Metanorma
|
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
|
-
def hide_refs(docxml)
|
41
|
-
docxml.xpath(ns("//references[bibitem][not(./bibitem[not(@hidden) or " \
|
42
|
-
"@hidden = 'false'])]")).each do |f|
|
43
|
-
f["hidden"] = "true"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
41
|
def new_hidden_ref(xmldoc)
|
48
42
|
ins = xmldoc.at(ns("bibliography")) or
|
49
43
|
xmldoc.root << "<bibliography/>" and ins = xmldoc.at(ns("bibliography"))
|
50
|
-
ins.at(ns("./
|
44
|
+
ins.at(ns("./references[@hidden = 'true']")) or
|
51
45
|
ins.add_child("<references hidden='true' normative='false'/>").first
|
52
46
|
end
|
53
47
|
|
@@ -81,7 +75,7 @@ module Metanorma
|
|
81
75
|
refs.each do |k, v|
|
82
76
|
url = @files.url(v, {})
|
83
77
|
ins << <<~XML
|
84
|
-
<bibitem id="#{k}">#{docid_xml(v)}<uri type='citation'>#{url}</uri></bibitem>
|
78
|
+
<bibitem id="#{k}" anchor="#{k}">#{docid_xml(v)}<uri type='citation'>#{url}</uri></bibitem>
|
85
79
|
XML
|
86
80
|
end
|
87
81
|
end
|
@@ -19,6 +19,7 @@ module Metanorma
|
|
19
19
|
@fileslookup = opts[:fileslookup]
|
20
20
|
@ident = opts[:ident]
|
21
21
|
@isodoc = opts[:isodoc]
|
22
|
+
@isodoc_presxml = opts[:isodoc_presxml]
|
22
23
|
@document_suffix = opts[:document_suffix]
|
23
24
|
end
|
24
25
|
|
@@ -32,18 +33,19 @@ module Metanorma
|
|
32
33
|
["//bibliography/*[not(@hidden = 'true')]", "bibliography"],
|
33
34
|
["//indexsect", nil], ["//colophon", nil]].freeze
|
34
35
|
|
35
|
-
# Input XML is Semantic
|
36
|
+
# Input XML is Semantic XML
|
36
37
|
def sectionsplit
|
37
38
|
xml = sectionsplit_prep(File.read(@input_filename), @base, @dir)
|
38
39
|
@key = Metanorma::Collection::XrefProcess::xref_preprocess(xml, @isodoc)
|
39
40
|
empty = empty_doc(xml)
|
40
41
|
empty1 = empty_attachments(empty)
|
41
42
|
@mutex = Mutex.new
|
42
|
-
|
43
|
+
# @pool = Concurrent::FixedThreadPool.new(4)
|
43
44
|
@pool = Concurrent::FixedThreadPool.new(1)
|
44
45
|
sectionsplit1(xml, empty, empty1, 0)
|
45
46
|
end
|
46
47
|
|
48
|
+
# xml is Presentation XML
|
47
49
|
def sectionsplit1(xml, empty, empty1, idx)
|
48
50
|
ret = SPLITSECTIONS.each_with_object([]) do |n, m|
|
49
51
|
conflate_floatingtitles(xml.xpath(ns(n[0]))).each do |s|
|
@@ -59,12 +61,14 @@ module Metanorma
|
|
59
61
|
|
60
62
|
def sectionsplit2(xml, empty, chunks, parentnode, opt)
|
61
63
|
@pool.post do
|
64
|
+
warn "#{@base}.#{opt[:idx]}"
|
62
65
|
a = sectionfile(xml, empty, "#{@base}.#{opt[:idx]}", chunks,
|
63
66
|
parentnode)
|
64
67
|
@mutex.synchronize { opt[:acc] << a }
|
65
68
|
end
|
66
69
|
end
|
67
70
|
|
71
|
+
# TODO move to metanorma-utils
|
68
72
|
def block?(node)
|
69
73
|
%w(p table formula admonition ol ul dl figure quote sourcecode example
|
70
74
|
pre note pagebreak hr bookmark requirement recommendation permission
|
@@ -86,7 +90,6 @@ module Metanorma
|
|
86
90
|
xml, type = sectionsplit_preprocess_semxml(file, filename)
|
87
91
|
flags = { format: :asciidoc, extension_keys: [:presentation],
|
88
92
|
type: type }.merge(@compile_opts)
|
89
|
-
#require "debug"; binding.b
|
90
93
|
Compile.new.compile(xml, flags)
|
91
94
|
f = File.open(xml.sub(/\.xml$/, ".presentation.xml"), encoding: "utf-8")
|
92
95
|
r = Nokogiri::XML(f, &:huge)
|
@@ -109,7 +112,6 @@ module Metanorma
|
|
109
112
|
if c = @fileslookup&.parent
|
110
113
|
n = c.nested
|
111
114
|
c.nested = true # so unresolved erefs are not deleted
|
112
|
-
#require "debug"; binding.b
|
113
115
|
c.update_xrefs(xml, @ident, {})
|
114
116
|
c.nested = n
|
115
117
|
xml.xpath("//xmlns:svgmap").each { |x| x.name = "svgmap1" }
|
@@ -125,35 +127,19 @@ module Metanorma
|
|
125
127
|
outname
|
126
128
|
end
|
127
129
|
|
128
|
-
def emptydoc(xml, ordinal)
|
129
|
-
out = xml.dup
|
130
|
-
out.xpath(
|
131
|
-
ns("//preface | //sections | //annex | //bibliography/clause | " \
|
132
|
-
"//bibliography/references[not(@hidden = 'true')] | " \
|
133
|
-
"//indexsect | //colophon"),
|
134
|
-
).each(&:remove)
|
135
|
-
ordinal.zero? or out.xpath(ns("//metanorma-ext//attachment | " \
|
136
|
-
"//semantic__metanorma-ext//semantic__attachment"))
|
137
|
-
.each(&:remove) # keep only one copy of attachments
|
138
|
-
out
|
139
|
-
end
|
140
|
-
|
141
130
|
def empty_doc(xml)
|
142
131
|
out = xml.dup
|
143
132
|
out.xpath(
|
144
|
-
ns("//preface | //sections | //annex |
|
145
|
-
|
146
|
-
|
133
|
+
ns("//preface | //sections | //annex | " \
|
134
|
+
"//references/bibitem[not(@hidden = 'true')] | " \
|
135
|
+
"//indexsect | //colophon"),
|
147
136
|
).each(&:remove)
|
137
|
+
::Metanorma::Collection::Util::hide_refs(out)
|
148
138
|
out
|
149
139
|
end
|
150
140
|
|
151
141
|
def empty_attachments(xml)
|
152
|
-
|
153
|
-
out.xpath(ns("//metanorma-ext//attachment | " \
|
154
|
-
"//semantic__metanorma-ext//semantic__attachment"))
|
155
|
-
.each(&:remove) # keep only one copy of attachments
|
156
|
-
out
|
142
|
+
xml.dup
|
157
143
|
end
|
158
144
|
|
159
145
|
def sectionfile(fulldoc, xml, file, chunks, parentnode)
|
@@ -164,11 +150,10 @@ module Metanorma
|
|
164
150
|
|
165
151
|
def create_sectionfile(xml, out, file, chunks, parentnode)
|
166
152
|
ins = out.at(ns("//metanorma-extension")) || out.at(ns("//bibdata"))
|
167
|
-
#require "debug"; binding.b
|
168
153
|
sectionfile_insert(ins, chunks, parentnode)
|
154
|
+
sectionfile_fn_filter(sectionfile_review_filter(out))
|
169
155
|
Metanorma::Collection::XrefProcess::xref_process(out, xml, @key,
|
170
156
|
@ident, @isodoc, true)
|
171
|
-
#truncate_semxml(out, chunks)
|
172
157
|
outname = "#{file}.xml"
|
173
158
|
File.open(File.join(@splitdir, outname), "w:UTF-8") do |f|
|
174
159
|
f.write(out)
|
@@ -176,36 +161,86 @@ module Metanorma
|
|
176
161
|
outname
|
177
162
|
end
|
178
163
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
164
|
+
def sectionfile_insert(ins, chunks, parentnode)
|
165
|
+
if parentnode
|
166
|
+
ins.next = "<#{parentnode}/>"
|
167
|
+
chunks.each { |c| ins.next.add_child(c.dup) }
|
168
|
+
else chunks.each { |c| ins.next = c.dup }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def sectionfile_fn_filter(xml)
|
173
|
+
ids = sectionfile_fn_filter_prep(xml)
|
174
|
+
xml.root.xpath(ns("./fmt-footnote-container/fmt-fn-body")).each do |f|
|
175
|
+
ids.has_key?(f["id"]) or f.remove
|
176
|
+
end
|
177
|
+
seen = {}
|
178
|
+
xml.root.xpath(ns("/fmt-footnote-container/fmt-fn-body"))
|
179
|
+
.each_with_index do |fnbody, i|
|
180
|
+
sectionfile_fn_filter_renumber(fnbody, i, ids, seen)
|
186
181
|
end
|
182
|
+
xml
|
183
|
+
end
|
184
|
+
|
185
|
+
# map fmt-fn-body/@id = fn/@target to fn
|
186
|
+
def sectionfile_fn_filter_prep(xml)
|
187
|
+
xml.xpath(ns("//fn")).each_with_object({}) do |f, m|
|
188
|
+
m[f["target"]] ||= []
|
189
|
+
m[f["target"]] << f
|
187
190
|
end
|
188
191
|
end
|
189
192
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
193
|
+
FN_CAPTIONS = ".//fmt-fn-label/span[@class = 'fmt-caption-label']".freeze
|
194
|
+
|
195
|
+
def sectionfile_fn_filter_renumber(fnbody, idx, ids, seen)
|
196
|
+
sectionfile_fn_filter_fn_renumber(fnbody, idx, ids, seen)
|
197
|
+
sectionfile_fn_filter_fnbody_renumber(fnbody, idx, ids)
|
198
|
+
end
|
199
|
+
|
200
|
+
def sectionfile_fn_filter_fn_renumber(fnbody, idx, ids, seen)
|
201
|
+
ids[fnbody["id"]].each do |f|
|
202
|
+
@isodoc_presxml.renumber_document_footnote(f, idx, seen)
|
203
|
+
fnlabel = f.at(ns(FN_CAPTIONS)) and
|
204
|
+
fnlabel.children = @isodoc_presxml.fn_ref_label(f)
|
194
205
|
end
|
195
206
|
end
|
196
207
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
nodes.each_value(&:remove)
|
208
|
+
def sectionfile_fn_filter_fnbody_renumber(fnbody, _idx, ids)
|
209
|
+
fnlabel = fnbody.at(ns(FN_CAPTIONS)) or return
|
210
|
+
fnbody["reference"] = ids[fnbody["id"]].first["reference"]
|
211
|
+
fnlabel.children = @isodoc_presxml.fn_body_label(fnbody)
|
202
212
|
end
|
203
213
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
214
|
+
# map fmt-review-body/@id = fmt-review-{start/end}/@target
|
215
|
+
# to fmt-review-{stary/end}
|
216
|
+
def sectionfile_review_filter_prep(xml)
|
217
|
+
xml.xpath(ns("//fmt-review-start | //fmt-review-end"))
|
218
|
+
.each_with_object({}) do |f, m|
|
219
|
+
m[f["target"]] ||= []
|
220
|
+
m[f["target"]] << f
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def sectionfile_review_filter(xml)
|
225
|
+
ids = sectionfile_review_filter_prep(xml)
|
226
|
+
xml.root.xpath(ns("./review-container/fmt-review-body")).each do |f|
|
227
|
+
ids.has_key?(f["id"]) or f.remove
|
228
|
+
end
|
229
|
+
xml.root.xpath(ns("./review-container/fmt-review-body"))
|
230
|
+
.each_with_index do |fnbody, i|
|
231
|
+
sectionfile_review_filter_renumber(fnbody, i, ids)
|
232
|
+
end
|
233
|
+
xml
|
234
|
+
end
|
235
|
+
|
236
|
+
def sectionfile_review_filter_renumber(fnbody, _idx, ids)
|
237
|
+
ids[fnbody["id"]].each do |f|
|
238
|
+
case f.name
|
239
|
+
when "fmt-review-start"
|
240
|
+
f.children = @isodoc_presxml.comment_bookmark_start_label(f)
|
241
|
+
when "fmt-review-end"
|
242
|
+
f.children = @isodoc_presxml.comment_bookmark_end_label(f)
|
243
|
+
end
|
209
244
|
end
|
210
245
|
end
|
211
246
|
|
@@ -214,7 +249,7 @@ module Metanorma
|
|
214
249
|
t = title.dup
|
215
250
|
t.xpath(ns(".//tab | .//br")).each { |x| x.replace(" ") }
|
216
251
|
t.xpath(ns(".//bookmark")).each(&:remove)
|
217
|
-
t.xpath(
|
252
|
+
t.xpath(".//text()").map(&:text).join
|
218
253
|
end
|
219
254
|
end
|
220
255
|
end
|
@@ -2,6 +2,11 @@ module Metanorma
|
|
2
2
|
class Collection
|
3
3
|
module Util
|
4
4
|
class << self
|
5
|
+
def anchor_id_attributes
|
6
|
+
Metanorma::Utils::anchor_attributes(presxml: true) +
|
7
|
+
[%w(* id), %w(* anchor), %w(link bibitemid), %w(fmt-link bibitemid)]
|
8
|
+
end
|
9
|
+
|
5
10
|
def gather_bibitems(xml)
|
6
11
|
xml.xpath("//xmlns:bibitem[@id]").each_with_object({}) do |b, m|
|
7
12
|
if m[b["id"]]
|
@@ -16,7 +21,6 @@ module Metanorma
|
|
16
21
|
|
17
22
|
def gather_bibitemids(xml, presxml)
|
18
23
|
xml.xpath("//*[@bibitemid]").each_with_object({}) do |e, m|
|
19
|
-
#/^semantic__/.match?(e.name) and next
|
20
24
|
presxml && %w(xref eref link).include?(e.name) and next
|
21
25
|
m[e["bibitemid"]] ||= []
|
22
26
|
m[e["bibitemid"]] << e
|
@@ -25,7 +29,6 @@ module Metanorma
|
|
25
29
|
|
26
30
|
def gather_citeases(xml, presxml)
|
27
31
|
xml.xpath("//*[@citeas]").each_with_object({}) do |e, m|
|
28
|
-
#/^semantic__/.match?(e.name) and next
|
29
32
|
presxml && %w(xref eref link).include?(e.name) and next
|
30
33
|
k = key(e["citeas"])
|
31
34
|
m[k] ||= []
|
@@ -36,6 +39,8 @@ module Metanorma
|
|
36
39
|
def add_suffix_to_attrs(doc, suffix, tag_name, attr_name, isodoc)
|
37
40
|
(suffix.nil? || suffix.empty?) and return
|
38
41
|
doc.xpath(isodoc.ns("//#{tag_name}[@#{attr_name}]")).each do |elem|
|
42
|
+
#warn "#{tag_name} : #{elem.name}" if attr_name == "bibitemid"
|
43
|
+
#require 'debug'; binding.b if attr_name == "bibitemid" && #!%w(eref fmt-eref link fmt-link).include?(elem.name)
|
39
44
|
a = elem.attributes[attr_name].value
|
40
45
|
/_#{suffix}$/.match?(a) or
|
41
46
|
elem.attributes[attr_name].value = "#{a}_#{suffix}"
|
@@ -55,6 +60,14 @@ module Metanorma
|
|
55
60
|
p.absolute? ? path : File.join(dir, path)
|
56
61
|
end
|
57
62
|
|
63
|
+
def hide_refs(docxml)
|
64
|
+
p = "//xmlns:references[xmlns:bibitem]"\
|
65
|
+
"[not(./xmlns:bibitem[not(@hidden) or @hidden = 'false'])]"
|
66
|
+
docxml.xpath(p).each do |f|
|
67
|
+
f["hidden"] = "true"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
58
71
|
def key(ident)
|
59
72
|
@c ||= HTMLEntities.new
|
60
73
|
@c.decode(ident).gsub(/(\p{Zs})+/, " ")
|
@@ -67,20 +80,20 @@ module Metanorma
|
|
67
80
|
def load_isodoc(flavor, presxml: false)
|
68
81
|
x = Asciidoctor.load nil, backend: flavor.to_sym
|
69
82
|
if presxml
|
70
|
-
|
83
|
+
x.converter.presentation_xml_converter(Dummy.new)
|
71
84
|
else
|
72
|
-
|
85
|
+
x.converter.html_converter(Dummy.new) # to obtain Isodoc class
|
73
86
|
end
|
74
87
|
end
|
75
88
|
|
76
89
|
def isodoc_create(flavor, lang, script, xml, presxml: false)
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
90
|
+
isodoc = Util::load_isodoc(flavor, presxml: presxml)
|
91
|
+
isodoc.i18n_init(lang, script, nil) # read in internationalisation
|
92
|
+
# TODO locale?
|
93
|
+
isodoc.metadata_init(lang, script, nil, isodoc.i18n)
|
94
|
+
isodoc.info(xml, nil)
|
95
|
+
isodoc
|
96
|
+
end
|
84
97
|
end
|
85
98
|
end
|
86
99
|
end
|
@@ -10,8 +10,7 @@ module Metanorma
|
|
10
10
|
@isodoc = isodoc
|
11
11
|
key = (0...8).map { rand(65..90).chr }.join # random string
|
12
12
|
xml.root["type"] = key
|
13
|
-
|
14
|
-
.each do |(tag_name, attr_name)|
|
13
|
+
Util::anchor_id_attributes.each do |(tag_name, attr_name)|
|
15
14
|
#tag_name == "xref" and tag_name = "fmt-xref"
|
16
15
|
::Metanorma::Collection::Util::add_suffix_to_attrs(
|
17
16
|
xml, xml.root["document_suffix"], tag_name, attr_name, isodoc
|
@@ -225,7 +224,7 @@ module Metanorma
|
|
225
224
|
|
226
225
|
def new_indirect_bibitem(ident, prefix)
|
227
226
|
<<~BIBENTRY
|
228
|
-
<bibitem id="#{ident}" type="internal">
|
227
|
+
<bibitem id="#{ident}" anchor="#{ident}" type="internal">
|
229
228
|
<docidentifier type="repository">#{ident.sub(/^#{prefix}_/, "#{prefix}/")}</docidentifier>
|
230
229
|
</bibitem>
|
231
230
|
BIBENTRY
|
@@ -0,0 +1,41 @@
|
|
1
|
+
== copyright-statement
|
2
|
+
=== Copyright notice
|
3
|
+
|
4
|
+
Copyright © 1994-{{docyear}} International Color Consortium®
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
7
|
+
the Specification and associated documentation files (the “Specification”) to
|
8
|
+
deal in the Specification without restriction, including without limitation the
|
9
|
+
rights to use, copy, modify, merge, publish, distribute, and/or sublicense
|
10
|
+
copies of the Specification, and to permit persons to whom the Specification is
|
11
|
+
furnished to do so, subject to the following conditions.
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
14
|
+
copies or substantial portions of the Specification.
|
15
|
+
|
16
|
+
The Specification is provided "as is", without warranty of any kind, express,
|
17
|
+
implied, or otherwise, including but not limited to the warranties of
|
18
|
+
merchantability, fitness for a particular purpose and noninfringement. In no
|
19
|
+
event shall the International Color Consortium be liable for any claim, damages
|
20
|
+
or other liability, whether in an action of contract, tort or otherwise, arising
|
21
|
+
from, out of, or in connection with the Specification or the use or other
|
22
|
+
dealings in the Specification.
|
23
|
+
|
24
|
+
Except as contained in this notice, the name of the International Color
|
25
|
+
Consortium shall not be used in advertising or otherwise to promote the use or
|
26
|
+
other dealings in this Specification without prior written authorization from
|
27
|
+
the International Color Consortium.
|
28
|
+
|
29
|
+
== license-statement
|
30
|
+
=== Licenses and trademarks
|
31
|
+
|
32
|
+
International Color Consortium and the ICC logo are registered trademarks of the
|
33
|
+
International Color Consortium. Rather than put a trademark symbol in every
|
34
|
+
occurrence of other trademarked names, we state that we are using the names only
|
35
|
+
in an editorial fashion, and to the benefit of the trademark owner, with no
|
36
|
+
intention of infringement of the trademark.
|
37
|
+
|
38
|
+
== feedback-statement
|
39
|
+
=== For additional information on the ICC
|
40
|
+
|
41
|
+
Visit the ICC Web site: http://www.color.org
|
@@ -18,6 +18,7 @@ require_relative "output_filename"
|
|
18
18
|
require_relative "output_filename_config"
|
19
19
|
require_relative "flavor"
|
20
20
|
require_relative "relaton_drop"
|
21
|
+
require_relative "render"
|
21
22
|
|
22
23
|
module Metanorma
|
23
24
|
class Compile
|
@@ -114,20 +115,18 @@ module Metanorma
|
|
114
115
|
# @param options [Hash] compilation options
|
115
116
|
# @return [Hash] paths for different output formats
|
116
117
|
def prepare_output_paths(filename, bibdata, options)
|
117
|
-
basename = if
|
118
|
+
basename = if options[:filename_template].nil?
|
119
|
+
filename.sub(/\.[^.]+$/, "")
|
120
|
+
else
|
118
121
|
drop = RelatonDrop.new(bibdata)
|
119
122
|
config = OutputFilenameConfig.new(options[:filename_template])
|
120
123
|
config.generate_filename(drop)
|
121
|
-
else
|
122
|
-
filename.sub(/\.[^.]+$/, "")
|
123
124
|
end
|
124
|
-
|
125
125
|
@output_filename = OutputFilename.new(
|
126
126
|
basename,
|
127
127
|
options[:output_dir],
|
128
128
|
@processor,
|
129
129
|
)
|
130
|
-
|
131
130
|
{
|
132
131
|
xml: @output_filename.semantic_xml,
|
133
132
|
orig_filename: filename,
|
@@ -175,53 +174,40 @@ module Metanorma
|
|
175
174
|
end
|
176
175
|
end
|
177
176
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
)
|
185
|
-
end
|
186
|
-
|
187
|
-
# Generate multiple output formats with parallel processing
|
188
|
-
def generate_outputs_parallel(
|
189
|
-
source_file, semantic_xml, bibdata, extensions, output_paths, options
|
190
|
-
)
|
191
|
-
@queue = ::Metanorma::Util::WorkersPool.new(
|
192
|
-
ENV["METANORMA_PARALLEL"]&.to_i || DEFAULT_NUM_WORKERS,
|
193
|
-
)
|
194
|
-
|
195
|
-
# Install required fonts for all extensions
|
196
|
-
gather_and_install_fonts(source_file, options.dup, extensions)
|
197
|
-
|
198
|
-
# Process each extension in order
|
199
|
-
process_extensions_in_order(
|
200
|
-
source_file, semantic_xml, bibdata, extensions, output_paths, options
|
201
|
-
)
|
202
|
-
|
203
|
-
@queue.shutdown
|
177
|
+
def process_input_adoc_hdr(file, options)
|
178
|
+
hdr, rest = Metanorma::Input::Asciidoc.new.header(file)
|
179
|
+
attrs = hdr.split("\n")
|
180
|
+
options[:asciimath] and attrs << ":mn-keep-asciimath:"
|
181
|
+
process_input_adoc_overrides(attrs, options)
|
182
|
+
"#{attrs.join("\n")}\n\n#{rest}"
|
204
183
|
end
|
205
184
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
185
|
+
# TODO: to config
|
186
|
+
def process_input_adoc_overrides(attrs, options)
|
187
|
+
case options[:supplied_type]
|
188
|
+
when :icc
|
189
|
+
f = File.join(File.dirname(__FILE__), "assets", "icc-boilerplate.adoc")
|
190
|
+
[":boilerplate-authority: #{f}",
|
191
|
+
":publisher: International Color Consortium",
|
192
|
+
":publisher_abbr: ICC"].each { |a| attrs << a }
|
193
|
+
options[":boilerplate-authority:"] = f
|
213
194
|
end
|
195
|
+
attrs
|
214
196
|
end
|
215
197
|
|
216
|
-
def
|
217
|
-
Util.log("[metanorma] Processing: AsciiDoc input.", :info)
|
218
|
-
file = read_file(filename)
|
219
|
-
options[:asciimath] and
|
220
|
-
file.sub!(/^(=[^\n]+\n)/, "\\1:mn-keep-asciimath:\n")
|
198
|
+
def process_input_adoc_includes(file, filename)
|
221
199
|
dir = File.dirname(filename)
|
222
200
|
dir != "." and
|
223
201
|
file = file.gsub(/^include::/, "include::#{dir}/")
|
224
202
|
.gsub(/^embed::/, "embed::#{dir}/")
|
203
|
+
file
|
204
|
+
end
|
205
|
+
|
206
|
+
def process_input_adoc(filename, options)
|
207
|
+
Util.log("[metanorma] Processing: AsciiDoc input.", :info)
|
208
|
+
file = read_file(filename)
|
209
|
+
file = process_input_adoc_hdr(file, options)
|
210
|
+
file = process_input_adoc_includes(file, filename)
|
225
211
|
[file, @processor.input_to_isodoc(file, filename, options)]
|
226
212
|
end
|
227
213
|
|
@@ -235,166 +221,5 @@ module Metanorma
|
|
235
221
|
def read_file(filename)
|
236
222
|
File.read(filename, encoding: "utf-8").gsub("\r\n", "\n")
|
237
223
|
end
|
238
|
-
|
239
|
-
# Export given bibliographic data to Relaton XML on disk
|
240
|
-
# @param bibdata [Nokogiri::XML::Element] the bibliographic data element
|
241
|
-
# @param options [Hash] compilation options
|
242
|
-
def export_relaton_from_bibdata(bibdata, options)
|
243
|
-
return unless options[:relaton]
|
244
|
-
|
245
|
-
# docid = bibdata&.at("./xmlns:docidentifier")&.text || options[:filename]
|
246
|
-
# outname = docid.sub(/^\s+/, "").sub(/\s+$/, "").gsub(/\s+/, "-") + ".xml"
|
247
|
-
export_output(options[:relaton], bibdata.to_xml)
|
248
|
-
end
|
249
|
-
|
250
|
-
# @param xml [Nokogiri::XML::Document] the XML document
|
251
|
-
# @return [Nokogiri::XML::Element] the bibliographic data element
|
252
|
-
def extract_relaton_metadata(xml)
|
253
|
-
xml.at("//bibdata") || xml.at("//xmlns:bibdata")
|
254
|
-
end
|
255
|
-
|
256
|
-
def wrap_html(options, file_extension, outfilename)
|
257
|
-
if options[:wrapper] && /html$/.match(file_extension)
|
258
|
-
outfilename = outfilename.sub(/\.html$/, "")
|
259
|
-
FileUtils.mkdir_p outfilename
|
260
|
-
FileUtils.mv "#{outfilename}.html", outfilename
|
261
|
-
FileUtils.mv "#{outfilename}_images", outfilename, force: true
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
# isodoc is Raw Metanorma XML
|
266
|
-
|
267
|
-
def gather_and_install_fonts(source_file, options, extensions)
|
268
|
-
Util.sort_extensions_execution(extensions).each do |ext|
|
269
|
-
isodoc_options = get_isodoc_options(source_file, options, ext)
|
270
|
-
font_install(isodoc_options.merge(options))
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
# Process a single extension (output format)
|
275
|
-
def process_ext(ext, source_file, semantic_xml, bibdata, output_paths,
|
276
|
-
options)
|
277
|
-
output_paths[:ext] = @processor.output_formats[ext]
|
278
|
-
output_paths[:out] = @output_filename.for_format(ext) ||
|
279
|
-
output_paths[:xml].sub(/\.[^.]+$/, ".#{output_paths[:ext]}")
|
280
|
-
isodoc_options = get_isodoc_options(source_file, options, ext)
|
281
|
-
|
282
|
-
# Handle special cases first
|
283
|
-
return true if process_ext_special(
|
284
|
-
ext, semantic_xml, bibdata, output_paths, options, isodoc_options
|
285
|
-
)
|
286
|
-
|
287
|
-
# Otherwise, determine if it uses presentation XML
|
288
|
-
if @processor.use_presentation_xml(ext)
|
289
|
-
# Format requires presentation XML first, then convert to final format
|
290
|
-
process_via_presentation_xml(ext, output_paths, options, isodoc_options)
|
291
|
-
else
|
292
|
-
# Format can be generated directly from semantic XML
|
293
|
-
process_from_semantic_xml(
|
294
|
-
ext, output_paths, semantic_xml, isodoc_options
|
295
|
-
)
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
# Process special extensions with custom handling
|
300
|
-
def process_ext_special(
|
301
|
-
ext, semantic_xml, bibdata, output_paths, options, isodoc_options
|
302
|
-
)
|
303
|
-
if ext == :rxl
|
304
|
-
|
305
|
-
# Special case: Relaton export
|
306
|
-
export_relaton_from_bibdata(
|
307
|
-
bibdata,
|
308
|
-
options.merge(relaton: output_paths[:out]),
|
309
|
-
)
|
310
|
-
true
|
311
|
-
|
312
|
-
elsif ext == :presentation && options[:passthrough_presentation_xml]
|
313
|
-
|
314
|
-
# Special case: Pass through presentation XML
|
315
|
-
f = if File.exist?(output_paths[:orig_filename])
|
316
|
-
output_paths[:orig_filename]
|
317
|
-
else
|
318
|
-
output_paths[:xml]
|
319
|
-
end
|
320
|
-
|
321
|
-
FileUtils.cp f, output_paths[:presentationxml]
|
322
|
-
true
|
323
|
-
|
324
|
-
elsif ext == :html && options[:sectionsplit]
|
325
|
-
|
326
|
-
# Special case: Split HTML into sections
|
327
|
-
sectionsplit_convert(
|
328
|
-
output_paths[:xml], semantic_xml, output_paths[:out], isodoc_options
|
329
|
-
)
|
330
|
-
true
|
331
|
-
else
|
332
|
-
false
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
|
-
# Process format that requires presentation XML
|
337
|
-
def process_via_presentation_xml(ext, output_paths, options, isodoc_options)
|
338
|
-
@queue.schedule(ext, output_paths.dup, options.dup,
|
339
|
-
isodoc_options.dup) do |a, b, c, d|
|
340
|
-
process_output_from_presentation_xml(a, b, c, d)
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
# Generate output format from presentation XML
|
345
|
-
def process_output_from_presentation_xml(ext, output_paths, options,
|
346
|
-
isodoc_options)
|
347
|
-
@processor.output(nil, output_paths[:presentationxml],
|
348
|
-
output_paths[:out], ext, isodoc_options)
|
349
|
-
wrap_html(options, output_paths[:ext], output_paths[:out])
|
350
|
-
rescue StandardError => e
|
351
|
-
strict = ext == :presentation || isodoc_options[:strict] == true
|
352
|
-
isodoc_error_process(e, strict, false)
|
353
|
-
end
|
354
|
-
|
355
|
-
# Process format directly from semantic XML
|
356
|
-
def process_from_semantic_xml(ext, output_paths, semantic_xml,
|
357
|
-
isodoc_options)
|
358
|
-
@processor.output(semantic_xml, output_paths[:xml], output_paths[:out],
|
359
|
-
ext, isodoc_options)
|
360
|
-
true # Return as Thread equivalent
|
361
|
-
rescue StandardError => e
|
362
|
-
strict = ext == :presentation || isodoc_options[:strict] == "true"
|
363
|
-
isodoc_error_process(e, strict, true)
|
364
|
-
ext != :presentation
|
365
|
-
end
|
366
|
-
|
367
|
-
# assume we pass in Presentation XML, but we want to recover Semantic XML
|
368
|
-
def sectionsplit_convert(input_filename, file, output_filename = nil,
|
369
|
-
opts = {})
|
370
|
-
@isodoc ||= IsoDoc::PresentationXMLConvert.new({})
|
371
|
-
input_filename += ".xml" unless input_filename.match?(/\.xml$/)
|
372
|
-
File.exist?(input_filename) or
|
373
|
-
export_output(input_filename, file)
|
374
|
-
presxml = File.read(input_filename, encoding: "utf-8")
|
375
|
-
_xml, filename, dir = @isodoc.convert_init(presxml, input_filename, false)
|
376
|
-
|
377
|
-
::Metanorma::Collection::Sectionsplit.new(
|
378
|
-
input: input_filename,
|
379
|
-
isodoc: @isodoc,
|
380
|
-
xml: presxml,
|
381
|
-
base: File.basename(output_filename || filename),
|
382
|
-
output: output_filename || filename,
|
383
|
-
dir: dir,
|
384
|
-
compile_opts: opts,
|
385
|
-
).build_collection
|
386
|
-
end
|
387
|
-
|
388
|
-
private
|
389
|
-
|
390
|
-
def isodoc_error_process(err, strict, must_abort)
|
391
|
-
if strict || err.message.include?("Fatal:")
|
392
|
-
@errors << err.message
|
393
|
-
else
|
394
|
-
puts err.message
|
395
|
-
end
|
396
|
-
puts err.backtrace.join("\n")
|
397
|
-
must_abort and 1
|
398
|
-
end
|
399
224
|
end
|
400
225
|
end
|
@@ -18,17 +18,9 @@ module Metanorma
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def extract_options(filename, options)
|
21
|
-
|
22
|
-
o
|
23
|
-
|
24
|
-
options[:type] ||= o[:type]&.to_sym
|
25
|
-
t = @registry.alias(options[:type]) and options[:type] = t
|
26
|
-
dir = filename.sub(%r(/[^/]+$), "/")
|
27
|
-
options[:relaton] ||= File.join(dir, o[:relaton]) if o[:relaton]
|
28
|
-
if o[:sourcecode]
|
29
|
-
options[:sourcecode] ||= File.join(dir,
|
30
|
-
o[:sourcecode])
|
31
|
-
end
|
21
|
+
o = options_in_file(filename)
|
22
|
+
extract_flavor_options(options, o)
|
23
|
+
extract_dir_options(options, o, filename)
|
32
24
|
options[:extension_keys] ||= o[:extensions]&.split(/, */)&.map(&:to_sym)
|
33
25
|
options[:extension_keys] = nil if options[:extension_keys] == [:all]
|
34
26
|
options[:format] ||= :asciidoc
|
@@ -38,6 +30,29 @@ module Metanorma
|
|
38
30
|
options
|
39
31
|
end
|
40
32
|
|
33
|
+
def options_in_file(filename)
|
34
|
+
content = read_file(filename)
|
35
|
+
Metanorma::Input::Asciidoc.new.extract_metanorma_options(content)
|
36
|
+
.merge(extract_xml_options(content))
|
37
|
+
end
|
38
|
+
|
39
|
+
def extract_flavor_options(options, options_in_file)
|
40
|
+
options[:type] ||= options_in_file[:type]
|
41
|
+
options[:type] = options[:type]&.to_sym
|
42
|
+
options[:supplied_type] = options[:type]
|
43
|
+
t = @registry.alias(options[:type]) and options[:type] = t
|
44
|
+
end
|
45
|
+
|
46
|
+
def extract_dir_options(options, options_in_file, filename)
|
47
|
+
dir = filename.sub(%r(/[^/]+$), "/")
|
48
|
+
options_in_file[:relaton] and
|
49
|
+
options[:relaton] ||= File.join(dir,
|
50
|
+
options_in_file[:relaton])
|
51
|
+
options_in_file[:sourcecode] and
|
52
|
+
options[:sourcecode] ||= File.join(dir,
|
53
|
+
options_in_file[:sourcecode])
|
54
|
+
end
|
55
|
+
|
41
56
|
def get_extensions(options)
|
42
57
|
ext = extract_extensions(options)
|
43
58
|
!ext.include?(:presentation) && ext.any? do |e|
|
@@ -70,7 +85,7 @@ module Metanorma
|
|
70
85
|
|
71
86
|
def unsupported_format_error(ext)
|
72
87
|
message = "[metanorma] Error: #{ext} format is not supported " \
|
73
|
-
|
88
|
+
"for this standard."
|
74
89
|
@errors << message
|
75
90
|
Util.log(message, :error)
|
76
91
|
end
|
@@ -8,7 +8,7 @@ module Metanorma
|
|
8
8
|
# @return [void]
|
9
9
|
def load_flavor(stdtype)
|
10
10
|
stdtype = stdtype.to_sym
|
11
|
-
flavor =
|
11
|
+
flavor = stdtype2flavor_gem(stdtype)
|
12
12
|
@registry.supported_backends.include? stdtype or
|
13
13
|
Util.log("[metanorma] Info: Loading `#{flavor}` gem "\
|
14
14
|
"for standard type `#{stdtype}`.", :info)
|
@@ -21,15 +21,12 @@ module Metanorma
|
|
21
21
|
# Convert the standard type to the flavor gem name
|
22
22
|
# @param stdtype [Symbol] the standard type
|
23
23
|
# @return [String] the flavor gem name
|
24
|
-
def
|
25
|
-
|
26
|
-
"metanorma-#{flavor}"
|
24
|
+
def stdtype2flavor_gem(stdtype)
|
25
|
+
"metanorma-#{stdtype}"
|
27
26
|
end
|
28
27
|
|
29
28
|
private
|
30
29
|
|
31
|
-
STDTYPE2FLAVOR = {}.freeze
|
32
|
-
|
33
30
|
def require_flavor(flavor)
|
34
31
|
require flavor
|
35
32
|
Util.log("[metanorma] Info: gem `#{flavor}` loaded.", :info)
|
@@ -0,0 +1,178 @@
|
|
1
|
+
module Metanorma
|
2
|
+
class Compile
|
3
|
+
# Generate presentation XML from semantic XML
|
4
|
+
def generate_presentation_xml(source_file, xml, bibdata, output_paths, opt)
|
5
|
+
process_ext(:presentation, source_file, xml, bibdata, output_paths, opt)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Generate multiple output formats with parallel processing
|
9
|
+
def generate_outputs_parallel(
|
10
|
+
source_file, semantic_xml, bibdata, extensions, output_paths, options
|
11
|
+
)
|
12
|
+
@queue = ::Metanorma::Util::WorkersPool.new(
|
13
|
+
ENV["METANORMA_PARALLEL"]&.to_i || DEFAULT_NUM_WORKERS,
|
14
|
+
)
|
15
|
+
# Install required fonts for all extensions
|
16
|
+
gather_and_install_fonts(source_file, options.dup, extensions)
|
17
|
+
# Process each extension in order
|
18
|
+
process_extensions_in_order(
|
19
|
+
source_file, semantic_xml, bibdata, extensions, output_paths, options
|
20
|
+
)
|
21
|
+
@queue.shutdown
|
22
|
+
end
|
23
|
+
|
24
|
+
def process_extensions_in_order(
|
25
|
+
source_file, semantic_xml, bibdata, extensions, output_paths, options
|
26
|
+
)
|
27
|
+
Util.sort_extensions_execution(extensions).each do |ext|
|
28
|
+
process_ext(
|
29
|
+
ext, source_file, semantic_xml, bibdata, output_paths, options
|
30
|
+
) or break
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Export given bibliographic data to Relaton XML on disk
|
35
|
+
# @param bibdata [Nokogiri::XML::Element] the bibliographic data element
|
36
|
+
# @param options [Hash] compilation options
|
37
|
+
def export_relaton_from_bibdata(bibdata, options)
|
38
|
+
options[:relaton] or return
|
39
|
+
export_output(options[:relaton], bibdata.to_xml)
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param xml [Nokogiri::XML::Document] the XML document
|
43
|
+
# @return [Nokogiri::XML::Element] the bibliographic data element
|
44
|
+
def extract_relaton_metadata(xml)
|
45
|
+
xml.at("//bibdata") || xml.at("//xmlns:bibdata")
|
46
|
+
end
|
47
|
+
|
48
|
+
def wrap_html(options, file_extension, outfilename)
|
49
|
+
if options[:wrapper] && /html$/.match(file_extension)
|
50
|
+
outfilename = outfilename.sub(/\.html$/, "")
|
51
|
+
FileUtils.mkdir_p outfilename
|
52
|
+
FileUtils.mv "#{outfilename}.html", outfilename
|
53
|
+
FileUtils.mv "#{outfilename}_images", outfilename, force: true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# isodoc is Raw Metanorma XML
|
58
|
+
def gather_and_install_fonts(source_file, options, extensions)
|
59
|
+
Util.sort_extensions_execution(extensions).each do |ext|
|
60
|
+
isodoc_options = get_isodoc_options(source_file, options, ext)
|
61
|
+
font_install(isodoc_options.merge(options))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Process a single extension (output format)
|
66
|
+
def process_ext(ext, source_file, semantic_xml, bibdata, output_paths,
|
67
|
+
options)
|
68
|
+
output_paths[:ext] = @processor.output_formats[ext]
|
69
|
+
output_paths[:out] = @output_filename.for_format(ext) ||
|
70
|
+
output_paths[:xml].sub(/\.[^.]+$/, ".#{output_paths[:ext]}")
|
71
|
+
isodoc_options = get_isodoc_options(source_file, options, ext)
|
72
|
+
|
73
|
+
# Handle special cases first
|
74
|
+
return true if process_ext_special(
|
75
|
+
ext, semantic_xml, bibdata, output_paths, options, isodoc_options
|
76
|
+
)
|
77
|
+
|
78
|
+
# Otherwise, determine if it uses presentation XML
|
79
|
+
if @processor.use_presentation_xml(ext)
|
80
|
+
# Format requires presentation XML first, then convert to final format
|
81
|
+
process_via_presentation_xml(ext, output_paths, options, isodoc_options)
|
82
|
+
else
|
83
|
+
# Format can be generated directly from semantic XML
|
84
|
+
process_from_semantic_xml(
|
85
|
+
ext, output_paths, semantic_xml, isodoc_options
|
86
|
+
)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Process special extensions with custom handling
|
91
|
+
def process_ext_special(
|
92
|
+
ext, sem_xml, bibdata, output_paths, options, isodoc_options
|
93
|
+
)
|
94
|
+
if ext == :rxl
|
95
|
+
# Special case: Relaton export
|
96
|
+
export_relaton_from_bibdata(
|
97
|
+
bibdata,
|
98
|
+
options.merge(relaton: output_paths[:out]),
|
99
|
+
)
|
100
|
+
true
|
101
|
+
elsif ext == :presentation && options[:passthrough_presentation_xml]
|
102
|
+
# Special case: Pass through presentation XML
|
103
|
+
f = if File.exist?(output_paths[:orig_filename])
|
104
|
+
output_paths[:orig_filename]
|
105
|
+
else
|
106
|
+
output_paths[:xml]
|
107
|
+
end
|
108
|
+
FileUtils.cp f, output_paths[:presentationxml]
|
109
|
+
true
|
110
|
+
elsif ext == :html && options[:sectionsplit]
|
111
|
+
# Special case: Split HTML into sections
|
112
|
+
sectionsplit_convert(
|
113
|
+
output_paths[:xml], sem_xml, output_paths[:out], isodoc_options
|
114
|
+
)
|
115
|
+
true
|
116
|
+
else
|
117
|
+
false
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Process format that requires presentation XML
|
122
|
+
def process_via_presentation_xml(ext, output_paths, options, isodoc_options)
|
123
|
+
@queue.schedule(ext, output_paths.dup, options.dup,
|
124
|
+
isodoc_options.dup) do |a, b, c, d|
|
125
|
+
process_output_from_presentation_xml(a, b, c, d)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Generate output format from presentation XML
|
130
|
+
def process_output_from_presentation_xml(ext, output_paths, options,
|
131
|
+
isodoc_options)
|
132
|
+
@processor.output(nil, output_paths[:presentationxml],
|
133
|
+
output_paths[:out], ext, isodoc_options)
|
134
|
+
wrap_html(options, output_paths[:ext], output_paths[:out])
|
135
|
+
rescue StandardError => e
|
136
|
+
strict = ext == :presentation || isodoc_options[:strict] == true
|
137
|
+
isodoc_error_process(e, strict, false)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Process format directly from semantic XML
|
141
|
+
def process_from_semantic_xml(ext, output_paths, sem_xml, isodoc_options)
|
142
|
+
@processor.output(sem_xml, output_paths[:xml], output_paths[:out],
|
143
|
+
ext, isodoc_options)
|
144
|
+
true # Return as Thread equivalent
|
145
|
+
rescue StandardError => e
|
146
|
+
strict = ext == :presentation || isodoc_options[:strict] == "true"
|
147
|
+
isodoc_error_process(e, strict, true)
|
148
|
+
ext != :presentation
|
149
|
+
end
|
150
|
+
|
151
|
+
# assume we pass in Presentation XML, but we want to recover Semantic XML
|
152
|
+
def sectionsplit_convert(input_filename, file, output_filename = nil,
|
153
|
+
opts = {})
|
154
|
+
@isodoc ||= IsoDoc::PresentationXMLConvert.new({})
|
155
|
+
input_filename += ".xml" unless input_filename.match?(/\.xml$/)
|
156
|
+
File.exist?(input_filename) or export_output(input_filename, file)
|
157
|
+
presxml = File.read(input_filename, encoding: "utf-8")
|
158
|
+
_xml, filename, dir = @isodoc.convert_init(presxml, input_filename, false)
|
159
|
+
::Metanorma::Collection::Sectionsplit.new(
|
160
|
+
input: input_filename, isodoc: @isodoc, xml: presxml,
|
161
|
+
base: File.basename(output_filename || filename),
|
162
|
+
output: output_filename || filename, dir: dir, compile_opts: opts
|
163
|
+
).build_collection
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
|
168
|
+
def isodoc_error_process(err, strict, must_abort)
|
169
|
+
if strict || err.message.include?("Fatal:")
|
170
|
+
@errors << err.message
|
171
|
+
else
|
172
|
+
puts err.message
|
173
|
+
end
|
174
|
+
puts err.backtrace.join("\n")
|
175
|
+
must_abort and 1
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -9,19 +9,17 @@ module Metanorma
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def validate_type!(options)
|
12
|
-
|
12
|
+
options[:type] or
|
13
13
|
Util.log("[metanorma] Error: Please specify a standard type: "\
|
14
14
|
"#{@registry.supported_backends}.", :fatal)
|
15
|
-
end
|
16
15
|
stdtype = options[:type].to_sym
|
17
16
|
load_flavor(stdtype)
|
18
17
|
end
|
19
18
|
|
20
19
|
def validate_format!(options)
|
21
|
-
|
20
|
+
options[:format] == :asciidoc or
|
22
21
|
Util.log("[metanorma] Error: Only source file format currently "\
|
23
22
|
"supported is 'asciidoc'.", :fatal)
|
24
|
-
end
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
@@ -13,8 +13,14 @@ module Metanorma
|
|
13
13
|
::Asciidoctor.convert(file, out_opts)
|
14
14
|
end
|
15
15
|
|
16
|
+
def header(file)
|
17
|
+
ret = file.split("\n\n", 2) or return [nil, nil]
|
18
|
+
ret[0] and ret[0] += "\n"
|
19
|
+
[ret[0], ret[1]]
|
20
|
+
end
|
21
|
+
|
16
22
|
def extract_metanorma_options(file)
|
17
|
-
hdr = file
|
23
|
+
hdr, = header(file)
|
18
24
|
/\n:(?:mn-)?(?:document-class|flavor):\s+(?<type>\S[^\n]*)\n/ =~ hdr
|
19
25
|
/\n:(?:mn-)?output-extensions:\s+(?<extensions>\S[^\n]*)\n/ =~ hdr
|
20
26
|
/\n:(?:mn-)?relaton-output-file:\s+(?<relaton>\S[^\n]*)\n/ =~ hdr
|
@@ -22,7 +28,7 @@ module Metanorma
|
|
22
28
|
/\n(?<novalid>:novalid:[^\n]*)\n/ =~ hdr
|
23
29
|
if defined?(asciimath)
|
24
30
|
asciimath =
|
25
|
-
!asciimath.nil? && !/keep-asciimath
|
31
|
+
!asciimath.nil? && !/keep-asciimath:\s*false/.match?(asciimath)
|
26
32
|
end
|
27
33
|
asciimath = nil if asciimath == false
|
28
34
|
{
|
@@ -68,17 +74,17 @@ module Metanorma
|
|
68
74
|
end
|
69
75
|
|
70
76
|
def extract_options(file)
|
71
|
-
|
77
|
+
hdr, = header(file)
|
72
78
|
ret = ADOC_OPTIONS.each_with_object({}) do |w, acc|
|
73
|
-
m = /\n:#{w}:\s+([^\n]+)\n/.match(
|
79
|
+
m = /\n:#{w}:\s+([^\n]+)\n/.match(hdr) or next
|
74
80
|
acc[attr_name_normalise(w)] = m[1]&.strip
|
75
81
|
end
|
76
82
|
ret2 = EMPTY_ADOC_OPTIONS_DEFAULT_TRUE.each_with_object({}) do |w, acc|
|
77
|
-
m = /\n:#{w}:([^\n]*)\n/.match(
|
83
|
+
m = /\n:#{w}:([^\n]*)\n/.match(hdr) || [nil, "true"]
|
78
84
|
acc[attr_name_normalise(w)] = (m[1].strip != "false")
|
79
85
|
end
|
80
86
|
ret3 = EMPTY_ADOC_OPTIONS_DEFAULT_FALSE.each_with_object({}) do |w, acc|
|
81
|
-
m = /\n:#{w}:([^\n]*)\n/.match(
|
87
|
+
m = /\n:#{w}:([^\n]*)\n/.match(hdr) || [nil, "false"]
|
82
88
|
acc[attr_name_normalise(w)] = !["false"].include?(m[1].strip)
|
83
89
|
end
|
84
90
|
ret.merge(ret2).merge(ret3).compact
|
@@ -11,9 +11,11 @@ module Metanorma
|
|
11
11
|
|
12
12
|
attr_reader :processors
|
13
13
|
|
14
|
+
# TODO: make aliases configurable
|
14
15
|
def initialize
|
15
16
|
@processors = {}
|
16
|
-
@aliases = { csd: :cc, m3d: :m3aawg, mpfd: :mpfa, csand: :csa
|
17
|
+
@aliases = { csd: :cc, m3d: :m3aawg, mpfd: :mpfa, csand: :csa,
|
18
|
+
icc: :iso }
|
17
19
|
end
|
18
20
|
|
19
21
|
def alias(flavour)
|
@@ -21,18 +23,14 @@ module Metanorma
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def register(processor)
|
24
|
-
|
25
|
-
|
26
|
+
processor < ::Metanorma::Processor or raise Error
|
26
27
|
p = processor.new
|
27
28
|
# p.short[-1] is the canonical name
|
28
29
|
short = Array(p.short)
|
29
30
|
@processors[short[-1]] = p
|
30
|
-
short.each
|
31
|
-
@aliases[s] = short[-1]
|
32
|
-
end
|
31
|
+
short.each { |s| @aliases[s] = short[-1] }
|
33
32
|
Array(p.short)
|
34
|
-
Util.log("[metanorma] processor \"#{Array(p.short)[0]}\" registered",
|
35
|
-
:info)
|
33
|
+
Util.log("[metanorma] processor \"#{Array(p.short)[0]}\" registered", :info)
|
36
34
|
end
|
37
35
|
|
38
36
|
def find_processor(short)
|
data/lib/metanorma/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metanorma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-05-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciidoctor
|
@@ -338,6 +338,7 @@ files:
|
|
338
338
|
- lib/metanorma/collection/util/disambig_files.rb
|
339
339
|
- lib/metanorma/collection/util/util.rb
|
340
340
|
- lib/metanorma/collection/xrefprocess/xrefprocess.rb
|
341
|
+
- lib/metanorma/compile/assets/icc-boilerplate.adoc
|
341
342
|
- lib/metanorma/compile/compile.rb
|
342
343
|
- lib/metanorma/compile/compile_options.rb
|
343
344
|
- lib/metanorma/compile/extract.rb
|
@@ -345,6 +346,7 @@ files:
|
|
345
346
|
- lib/metanorma/compile/output_filename.rb
|
346
347
|
- lib/metanorma/compile/output_filename_config.rb
|
347
348
|
- lib/metanorma/compile/relaton_drop.rb
|
349
|
+
- lib/metanorma/compile/render.rb
|
348
350
|
- lib/metanorma/compile/validator.rb
|
349
351
|
- lib/metanorma/compile/writeable.rb
|
350
352
|
- lib/metanorma/config/config.rb
|