metanorma 2.0.0 → 2.1.2

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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/metanorma/collection/collection.rb +43 -14
  3. data/lib/metanorma/collection/config/bibdata.rb +2 -2
  4. data/lib/metanorma/collection/config/compile_options.rb +4 -5
  5. data/lib/metanorma/collection/config/config.rb +41 -73
  6. data/lib/metanorma/collection/config/converters.rb +27 -1
  7. data/lib/metanorma/collection/config/directive.rb +9 -3
  8. data/lib/metanorma/collection/config/manifest.rb +33 -27
  9. data/lib/metanorma/collection/document/document.rb +12 -10
  10. data/lib/metanorma/collection/filelookup/filelookup.rb +25 -13
  11. data/lib/metanorma/collection/filelookup/filelookup_sectionsplit.rb +57 -20
  12. data/lib/metanorma/collection/manifest/manifest.rb +22 -10
  13. data/lib/metanorma/collection/multilingual/multilingual.rb +660 -0
  14. data/lib/metanorma/collection/renderer/fileparse.rb +119 -104
  15. data/lib/metanorma/collection/renderer/fileprocess.rb +6 -2
  16. data/lib/metanorma/collection/renderer/navigation.rb +1 -1
  17. data/lib/metanorma/collection/renderer/render_word.rb +8 -7
  18. data/lib/metanorma/collection/renderer/renderer.rb +41 -20
  19. data/lib/metanorma/collection/renderer/svg.rb +52 -0
  20. data/lib/metanorma/collection/renderer/utils.rb +55 -18
  21. data/lib/metanorma/collection/sectionsplit/collection.rb +100 -0
  22. data/lib/metanorma/collection/sectionsplit/sectionsplit.rb +104 -101
  23. data/lib/metanorma/collection/util/util.rb +25 -10
  24. data/lib/metanorma/collection/xrefprocess/xrefprocess.rb +42 -28
  25. data/lib/metanorma/compile/compile.rb +12 -2
  26. data/lib/metanorma/compile/compile_options.rb +2 -0
  27. data/lib/metanorma/compile/compile_validate.rb +4 -4
  28. data/lib/metanorma/compile/extract.rb +2 -4
  29. data/lib/metanorma/input/asciidoc.rb +11 -30
  30. data/lib/metanorma/registry/registry.rb +2 -2
  31. data/lib/metanorma/version.rb +1 -1
  32. data/metanorma.gemspec +5 -4
  33. metadata +41 -25
  34. data/lib/metanorma/shale_monkeypatch.rb +0 -15
@@ -16,19 +16,23 @@ 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")
19
21
  @nested || sso or
20
22
  Metanorma::Collection::XrefProcess::xref_process(xml, xml, nil, docid,
21
- @isodoc)
22
- @nested or update_indirect_refs_to_docs(xml, docid, internal_refs)
23
+ @isodoc, sso)
24
+ @ncnames = {}
25
+ @nested or update_indirect_refs_to_docs(xml, docid, internal_refs, sso)
23
26
  @files.add_document_suffix(docid, xml)
24
- @nested or update_sectionsplit_refs_to_docs(xml, internal_refs)
25
- update_direct_refs_to_docs(xml, docid)
27
+ @nested or update_sectionsplit_refs_to_docs(xml, internal_refs, sso)
28
+ update_direct_refs_to_docs(xml, docid, sso)
26
29
  hide_refs(xml)
27
- sso and eref2link(xml)
28
- svgmap_resolve(xml, docid)
30
+ sso and eref2link(xml, sso)
31
+ @nested or svgmap_resolve(xml, docid, sso)
29
32
  xml.to_xml
30
33
  end
31
34
 
35
+ ## sso files are Presentation XML; otherwise, Semantic XML
32
36
  def update_xrefs_prep(file, docid)
33
37
  docxml = file.is_a?(String) ? Nokogiri::XML(file, &:huge) : file
34
38
  supply_repo_ids(docxml)
@@ -36,8 +40,8 @@ module Metanorma
36
40
  [docxml, sso]
37
41
  end
38
42
 
39
- def update_sectionsplit_refs_to_docs(docxml, internal_refs)
40
- Util::gather_citeases(docxml).each do |k, v|
43
+ def update_sectionsplit_refs_to_docs(docxml, internal_refs, presxml)
44
+ Util::gather_citeases(docxml, presxml).each do |k, v|
41
45
  (@files.get(k) && @files.get(k, :sectionsplit)) or next
42
46
  opts = { key: @files.get(k, :indirect_key),
43
47
  source_suffix: docxml.root["document_suffix"],
@@ -49,9 +53,11 @@ module Metanorma
49
53
  end
50
54
  end
51
55
 
56
+ ANCHOR_XPATH = "xmlns:locality[@type = 'anchor']/xmlns:referenceFrom"
57
+ .freeze
58
+
52
59
  def update_sectionsplit_eref_to_doc(eref, internal_refs, doclist, opts)
53
- a = eref.at(ns("./localityStack/locality[@type = 'anchor']/" \
54
- "referenceFrom")) or return
60
+ a = eref.at("./xmlns:localityStack/#{ANCHOR_XPATH}") or return
55
61
  doc = internal_refs[opts[:key]]["#{a.text}_#{opts[:target_suffix]}"]
56
62
  bibitemid = Metanorma::Utils::to_ncname("#{doc}_#{opts[:source_suffix]}")
57
63
  eref["bibitemid"] = bibitemid
@@ -59,19 +65,6 @@ module Metanorma
59
65
  doclist
60
66
  end
61
67
 
62
- def new_hidden_ref(xmldoc)
63
- ins = xmldoc.at(ns("bibliography")) or
64
- xmldoc.root << "<bibliography/>" and ins = xmldoc.at(ns("bibliography"))
65
- ins.at(ns("./referenced[@hidden = 'true']")) or
66
- ins.add_child("<references hidden='true' normative='false'/>").first
67
- end
68
-
69
- def eref2link(docxml)
70
- isodoc = IsoDoc::PresentationXMLConvert.new({})
71
- isodoc.bibitem_lookup(docxml)
72
- isodoc.eref2link(docxml)
73
- end
74
-
75
68
  BIBITEM_NOT_REPO_XPATH = "//bibitem[not(ancestor::bibitem)]" \
76
69
  "[not(./docidentifier[@type = 'repository'])]".freeze
77
70
 
@@ -86,47 +79,38 @@ module Metanorma
86
79
  end
87
80
  end
88
81
 
89
- def svgmap_resolve(docxml, docid)
90
- ids = @files.get(docid, :ids)
91
- dir = File.join(@dirname, File.dirname(@files.get(docid, :rel_path)))
92
- docxml = datauri_encode(docxml, dir)
93
- isodoc = IsoDoc::PresentationXMLConvert.new({})
94
- isodoc.bibitem_lookup(docxml)
95
- docxml.xpath(ns("//svgmap//eref")).each do |e|
96
- svgmap_resolve1(e, isodoc, docxml, ids)
97
- end
98
- Vectory::SvgMapping.new(docxml, "").call
99
- docxml.xpath(ns("//svgmap")).each { |s| isodoc.svgmap_extract(s) }
100
- end
101
-
102
- def svgmap_resolve1(eref, isodoc, _docxml, ids)
103
- href = isodoc.eref_target(eref) or return
104
- href == "##{eref['bibitemid']}" ||
105
- (href =~ /^#/ && !ids[href.sub(/^#/, "")]) and return
106
- eref["target"] = href.strip
107
- eref.name = "link"
108
- eref.elements&.remove
109
- end
110
-
111
82
  # repo(current-metanorma-collection/ISO 17301-1:2016)
112
83
  # replaced by bibdata of "ISO 17301-1:2016" in situ as bibitem.
113
84
  # Any erefs to that bibitem id are replaced with relative URL
114
85
  # Preferably with anchor, and is a job to realise dynamic lookup
115
86
  # of localities.
116
- def update_direct_refs_to_docs(docxml, identifier)
117
- erefs, erefs1 = update_direct_refs_to_docs_prep(docxml)
87
+ def update_direct_refs_to_docs(docxml, identifier, presxml)
88
+ erefs, erefs_no_anchor, anchors, erefs1 =
89
+ update_direct_refs_to_docs_prep(docxml, presxml)
118
90
  docxml.xpath(ns("//bibitem")).each do |b|
119
91
  docid = b.at(ns("./docidentifier[@type = 'repository']")) or next
120
92
  strip_unresolved_repo_erefs(identifier, docid, erefs1, b) or next
121
93
  update_bibitem(b, identifier)
122
94
  docid = docid_to_citeas(b) or next
123
- erefs[docid] and update_anchors(b, docid, erefs[docid])
95
+ erefs[docid] and
96
+ update_anchors(b, docid, erefs[docid], erefs_no_anchor[docid],
97
+ anchors[docid])
124
98
  end
125
99
  end
126
100
 
127
- def update_direct_refs_to_docs_prep(docxml)
128
- @ncnames = {}
129
- [Util::gather_citeases(docxml), Util::gather_bibitemids(docxml)]
101
+ # Hash(docid) of arrays
102
+ def update_direct_refs_to_docs_prep(docxml, presxml)
103
+ erefs = Util::gather_citeases(docxml, presxml)
104
+ no_anchor = erefs.keys.each_with_object({}) { |k, m| m[k] = [] }
105
+ anchors = erefs.keys.each_with_object({}) { |k, m| m[k] = [] }
106
+ erefs.each do |k, v|
107
+ v.each do |e|
108
+ if loc = e.at(".//#{ANCHOR_XPATH}") then anchors[k] << loc
109
+ else no_anchor[k] << e end
110
+ end
111
+ end
112
+ #require "debug"; binding.b
113
+ [erefs, no_anchor, anchors, Util::gather_bibitemids(docxml, presxml)]
130
114
  end
131
115
 
132
116
  # strip erefs if they are repository erefs, but do not point to a document
@@ -144,90 +128,122 @@ module Metanorma
144
128
 
145
129
  # Resolve erefs to a container of ids in another doc,
146
130
  # to an anchor eref (direct link)
147
- def update_indirect_refs_to_docs(docxml, _docidentifier, internal_refs)
148
- bibitems, erefs = update_indirect_refs_to_docs_prep(docxml)
131
+ def update_indirect_refs_to_docs(docxml, _docidentifier, internal_refs, presxml)
132
+ bib, erefs, doc_suffix, doc_type, f = update_indirect_refs_prep(docxml, presxml)
149
133
  internal_refs.each do |schema, ids|
134
+ add_suffix = doc_suffix && doc_type && doc_type != schema
150
135
  ids.each do |id, file|
151
- k = indirect_ref_key(schema, id, docxml)
152
- update_indirect_refs_to_docs1(docxml, k, file, bibitems, erefs)
136
+ f[file] ||= { url: @files.url?(file),
137
+ parentid: @files.get(file) && @files.get(file,
138
+ :parentid) }
139
+ k = indirect_ref_key(schema, id, doc_suffix, add_suffix)
140
+ update_indirect_refs_to_docs1(f[file], k, file, bib, erefs)
153
141
  end
154
142
  end
155
143
  end
156
144
 
157
- def update_indirect_refs_to_docs_prep(docxml)
145
+ def update_indirect_refs_prep(docxml, presxml)
158
146
  @updated_anchors = {}
159
- [Util::gather_bibitems(docxml), Util::gather_bibitemids(docxml)]
147
+ @indirect_keys = {}
148
+ [Util::gather_bibitems(docxml), Util::gather_bibitemids(docxml, presxml),
149
+ docxml.root["document_suffix"], docxml.root["type"], {}]
160
150
  end
161
151
 
162
- def indirect_ref_key(schema, id, docxml)
152
+ # KILL
153
+ def indirect_ref_key(schema, id, doc_suffix, doc_type)
163
154
  /^#{schema}_/.match?(id) and return id
155
+ key = [schema, id, doc_suffix, doc_type].join("::")
156
+ x = @indirect_keys[key] and return x
164
157
  ret = "#{schema}_#{id}"
165
- suffix = docxml.root["document_suffix"]
166
- (k = docxml.root["type"]) && k != schema && suffix and
167
- ret = "#{ret}_#{suffix}"
158
+ doc_suffix && doc_type && doc_type != schema and
159
+ ret = "#{ret}_#{doc_suffix}"
160
+ @indirect_keys[key] = ret
168
161
  ret
169
162
  end
170
163
 
171
- def update_indirect_refs_to_docs1(_docxml, key, file, bibitems, erefs)
164
+ def indirect_ref_key(schema, id, doc_suffix, add_suffix)
165
+ /^#{schema}_/.match?(id) and return id
166
+ #key = "#{schema}_#{id}"
167
+ x = @indirect_keys.dig(schema, id) and return x
168
+ @indirect_keys[schema] ||= {}
169
+ @indirect_keys[schema][id] = if add_suffix
170
+ "#{schema}_#{id}_#{doc_suffix}"
171
+ else
172
+ "#{schema}_#{id}"
173
+ end
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
183
+ end
184
+
185
+ def update_indirect_refs_to_docs1(filec, key, file, bibitems, erefs)
172
186
  erefs[key]&.each do |e|
173
187
  e["citeas"] = file
174
- update_indirect_refs_to_docs_anchor(e, file)
188
+ update_indirect_refs_to_docs_anchor(e, file, filec[:url],
189
+ filec[:parentid])
175
190
  end
176
191
  update_indirect_refs_to_docs_docid(bibitems[key], file)
177
192
  end
178
193
 
179
- def update_indirect_refs_to_docs_anchor(eref, file)
180
- a = eref.at(ns(".//locality[@type = 'anchor']/referenceFrom")) or return
181
- suffix = file
182
- @files.get(file) && p = @files.get(file, :parentid) and
183
- suffix = "#{p}_#{suffix}"
194
+ def update_indirect_refs_to_docs_anchor(eref, file, url, parentid)
195
+ a = eref.at(".//#{ANCHOR_XPATH}") or return
196
+ parentid and file = "#{parentid}_#{file}"
184
197
  existing = a.text
185
- anchor = existing
186
- @files.url?(file) or
187
- anchor = Metanorma::Utils::to_ncname("#{anchor}_#{suffix}")
198
+ anchor = if url then existing
199
+ else
200
+ #suffix_anchor_indirect(existing, suffix)
201
+ #k = "#{existing}_#{file}"
202
+ #@ncnames[k] ||= Metanorma::Utils::to_ncname(k)
203
+ @indirect_keys[existing] ||= {}
204
+ @indirect_keys[existing][file] ||= Metanorma::Utils::to_ncname("#{existing}_#{file}")
205
+ end
188
206
  @updated_anchors[existing] or a.children = anchor
189
207
  @updated_anchors[anchor] = true
190
208
  end
191
209
 
192
- def update_indirect_refs_to_docs_docid(bibitem, file)
193
- docid = bibitem&.at(ns("./docidentifier[@type = 'repository']")) or
194
- return
210
+ def update_indirect_refs_to_docs_docid(bib, file)
211
+ docid = bib&.at(ns("./docidentifier[@type = 'repository']")) or return
195
212
  docid.children = "current-metanorma-collection/#{file}"
196
213
  docid.previous =
197
214
  "<docidentifier type='metanorma-collection'>#{file}</docidentifier>"
198
215
  end
199
216
 
200
- # update crossrefences to other documents, to include
201
- # disambiguating document suffix on id
202
- def update_anchors(bib, docid, erefs)
203
- erefs.each do |e|
204
- if @files.get(docid) then update_anchor_loc(bib, e, docid)
205
- else
206
- msg = "<strong>** Unresolved reference to document #{docid} " \
207
- "from eref</strong>"
208
- e << msg
209
- strip_eref(e)
210
- @log&.add("Cross-References", e, msg)
211
- end
217
+ # bottleneck
218
+ def update_anchors(bib, docid, erefs, erefs_no_anchor, erefs_anchors)
219
+ @files.get(docid) or error_anchor(erefs, docid)
220
+ has_anchors, url, ncn_docid = update_anchors_prep(docid)
221
+ erefs_no_anchor.each do |e|
222
+ update_anchor_create_loc(bib, e, docid)
223
+ end
224
+ !url && has_anchors or return
225
+ erefs_anchors.each do |e|
226
+ update_anchors1(docid, ncn_docid, e)
227
+ end
228
+ end
229
+
230
+ def update_anchors1(docid, ncn_docid, anchor)
231
+ @concat_anchors[anchor.text] ||= "#{ncn_docid}_#{anchor.text}"
232
+ if @files.get(docid).dig(:anchors_lookup, @concat_anchors[anchor.text])
233
+ anchor.content = @concat_anchors[anchor.text]
212
234
  end
213
235
  end
214
236
 
215
- def update_anchor_loc(bib, eref, docid)
216
- loc = eref.at(".//xmlns:locality[@type = 'anchor']") or
217
- return update_anchor_create_loc(bib, eref, docid)
218
- ref = loc.at("./xmlns:referenceFrom") or return
219
- anchor = suffix_anchor(ref, docid)
220
- a = @files.get(docid, :anchors) or return
221
- a.inject([]) { |m, (_, x)| m + x.values }
222
- .include?(anchor) or return
223
- ref.content = anchor
237
+ def update_anchors_prep(docid)
238
+ @concat_anchors = {}
239
+ [@files.get(docid)&.key?(:anchors_lookup), @files.url?(docid),
240
+ Metanorma::Utils::to_ncname(docid)]
224
241
  end
225
242
 
226
- def suffix_anchor(ref, docid)
227
- @ncnames[docid] ||= Metanorma::Utils::to_ncname(docid)
228
- anchor = ref.text
229
- @files.url?(docid) or anchor = "#{@ncnames[docid]}_#{anchor}"
230
- anchor
243
+ # encode both prefix and suffix to NCName
244
+ def suffix_anchor_indirect(prefix, suffix)
245
+ k = "#{prefix}_#{suffix}"
246
+ @ncnames[k] ||= Metanorma::Utils::to_ncname(k)
231
247
  end
232
248
 
233
249
  # if there is a crossref to another document, with no anchor, retrieve the
@@ -237,10 +253,9 @@ module Metanorma
237
253
  type = ins.at(ns("./locality/@type"))&.text
238
254
  type = "clause" if type == "annex"
239
255
  ref = ins.at(ns("./locality/referenceFrom"))&.text
240
- anchor = @files.get(docid, :anchors).dig(type, ref) or return
241
- ins << "<locality type='anchor'><referenceFrom>#{anchor.sub(/^_/,
242
- '')}" \
243
- "</referenceFrom></locality>"
256
+ a = @files.get(docid, :anchors).dig(type, ref) or return
257
+ ins << "<locality type='anchor'><referenceFrom>#{a.sub(/^_/, '')}" \
258
+ "</referenceFrom></locality>"
244
259
  end
245
260
  end
246
261
  end
@@ -15,6 +15,7 @@ module Metanorma
15
15
  format: :asciidoc,
16
16
  extension_keys: @format,
17
17
  output_dir: @outdir,
18
+ type: @flavor,
18
19
  }.merge(compile_options_update(identifier))
19
20
  @compile.compile file, opts
20
21
  @files.set(identifier, :outputs, {})
@@ -35,7 +36,8 @@ module Metanorma
35
36
 
36
37
  def file_compile_formats(filename, identifier)
37
38
  f = @files.get(identifier, :outputs)
38
- @format << :presentation if @format.include?(:pdf)
39
+ concatenate_presentation?({ format: @format }) and
40
+ @format << :presentation
39
41
  @format.each do |e|
40
42
  ext = @compile.processor.output_formats[e]
41
43
  fn = File.basename(filename).sub(/(?<=\.)[^.]+$/, ext.to_s)
@@ -51,7 +53,8 @@ module Metanorma
51
53
  out = out.relative_path_from(File.expand_path(FileUtils.pwd))
52
54
  dest = File.join(@outdir, @disambig.source2dest_filename(out.to_s))
53
55
  FileUtils.mkdir_p(File.dirname(dest))
54
- FileUtils.cp @files.get(identifier, :ref), dest
56
+ source = @files.get(identifier, :ref)
57
+ source != dest and FileUtils.cp_r source, dest, remove_destination: true
55
58
  end
56
59
 
57
60
  # process each file in the collection
@@ -83,6 +86,7 @@ module Metanorma
83
86
  def gather_internal_refs
84
87
  @files.keys.each_with_object({}) do |i, refs|
85
88
  @files.get(i, :attachment) and next
89
+ @files.get(i, :sectionsplit) and next
86
90
  file, = @files.targetfile_id(i, read: true)
87
91
  gather_internal_refs1(file, i, refs)
88
92
  end
@@ -114,7 +114,7 @@ module Metanorma
114
114
  files.each { |f| docrefs(f, u) }
115
115
  end
116
116
  end
117
- r.doc.root&.to_html&.gsub("\n", " ")
117
+ r.doc.root&.to_html&.tr("\n", " ")
118
118
  end
119
119
 
120
120
  def liquid_docrefs(mnfs)
@@ -3,8 +3,8 @@ module Metanorma
3
3
  class Renderer
4
4
  def docconv
5
5
  @tempfile_cache ||= []
6
- doctype = @doctype.to_sym
7
- x = Asciidoctor.load nil, backend: doctype
6
+ flavor = @flavor.to_sym
7
+ x = Asciidoctor.load nil, backend: flavor
8
8
  x.converter.doc_converter(DocOptionsNode.new(@directives, @dirname))
9
9
  end
10
10
 
@@ -34,7 +34,8 @@ module Metanorma
34
34
 
35
35
  def wrapping_doc_body(doc)
36
36
  doc.xpath(ns("//annex | //preface | //bibliography")).each(&:remove)
37
- s = doc.at(ns("//sections"))
37
+ s = doc.at(ns("//sections")) ||
38
+ doc.root.elements[-1].after("<sections/>").next
38
39
  repl = <<~BODY
39
40
  <sections><clause id='_collection_placeholder'><p>PLACEHOLDER</p></clause></sections>
40
41
  BODY
@@ -50,8 +51,8 @@ module Metanorma
50
51
  doc
51
52
  end
52
53
 
53
- SECTION_BREAK = '<p class="MsoNormal"><br clear="all" class="section"/></p>'
54
- .freeze
54
+ SECTION_BREAK =
55
+ '<p class="MsoNormal"><br clear="all" class="section"/></p>'.freeze
55
56
  DIV1 = '<div class="WordSection1">&#xa0;</div>'.freeze
56
57
  DIV2 = '<div class="WordSection2">&#xa0;</div>'.freeze
57
58
 
@@ -69,10 +70,10 @@ module Metanorma
69
70
  end
70
71
 
71
72
  def collection_coverpages(conv, docs)
72
- conv.wordintropage and [DIV2, SECTION_BREAK].reverse.each do |s|
73
+ conv.wordintropage and [DIV2, SECTION_BREAK].reverse_each do |s|
73
74
  docs.unshift(Nokogiri::XML(s).root)
74
75
  end
75
- conv.wordcoverpage and [DIV1, SECTION_BREAK].reverse.each do |s|
76
+ conv.wordcoverpage and [DIV1, SECTION_BREAK].reverse_each do |s|
76
77
  docs.unshift(Nokogiri::XML(s).root)
77
78
  end
78
79
  docs
@@ -4,9 +4,11 @@ require_relative "fileprocess"
4
4
  require_relative "../../util/fontist_helper"
5
5
  require_relative "../../util/util"
6
6
  require_relative "../filelookup/filelookup"
7
+ require_relative "../multilingual/multilingual"
7
8
  require_relative "utils"
8
9
  require_relative "render_word"
9
10
  require_relative "navigation"
11
+ require_relative "svg"
10
12
 
11
13
  module Metanorma
12
14
  class Collection
@@ -36,11 +38,13 @@ module Metanorma
36
38
  @lang = collection.bibdata.language.first || "en"
37
39
  @script = collection.bibdata.script.first || "Latn"
38
40
  @locale = @xml.at("//xmlns:bibdata/xmlns:locale")&.text
39
- @doctype = doctype
41
+ @registry = Metanorma::Registry.instance
42
+ @flavor = options[:flavor] || flavor
40
43
  @compile = Compile.new
41
- @compile.load_flavor(@doctype)
44
+ @compile.load_flavor(@flavor)
42
45
 
43
- @isodoc = isodoc_create # output processor for flavour
46
+ # output processor for flavour
47
+ @isodoc = Util::isodoc_create(@flavor, @lang, @script, @xml)
44
48
  @outdir = dir_name_cleanse(options[:output_folder])
45
49
  @coverpage = options[:coverpage] || collection.coverpage
46
50
  @format = ::Metanorma::Util.sort_extensions_execution(options[:format])
@@ -58,7 +62,8 @@ module Metanorma
58
62
  @final = collection.final
59
63
  @c = HTMLEntities.new
60
64
  @files_to_delete = []
61
- @nested = options[:nested] # if false, this is the root instance of Renderer
65
+ @nested = options[:nested]
66
+ # if false, this is the root instance of Renderer
62
67
  # if true, then this is not the last time Renderer will be run
63
68
  # (e.g. this is sectionsplit)
64
69
 
@@ -71,6 +76,7 @@ module Metanorma
71
76
 
72
77
  def flush_files
73
78
  warn "\n\n\n\n\nDone: #{DateTime.now.strftime('%H:%M:%S')}"
79
+ warn "\nFiles to delete:\n"
74
80
  warn @files.files_to_delete
75
81
  @files.files_to_delete.each { |f| FileUtils.rm_f(f) }
76
82
  @files_to_delete.each { |f| FileUtils.rm_f(f) }
@@ -93,53 +99,68 @@ module Metanorma
93
99
 
94
100
  def concatenate(col, options)
95
101
  warn "\n\n\n\n\nConcatenate: #{DateTime.now.strftime('%H:%M:%S')}"
96
- (options[:format] & %i(pdf doc)).empty? or
102
+ concatenate_presentation?(options) and
97
103
  options[:format] << :presentation
98
104
  concatenate_prep(col, options)
99
105
  concatenate_outputs(options)
100
106
  end
101
107
 
108
+ def concatenate_presentation?(options)
109
+ !(options[:format] & %i(pdf doc)).empty? ||
110
+ (@directives.detect { |d| d.key == "bilingual" } &&
111
+ options[:format].include?(:html))
112
+ end
113
+
102
114
  def concatenate_prep(col, options)
103
115
  %i(xml presentation).each do |e|
104
116
  options[:format].include?(e) or next
105
117
  ext = e == :presentation ? "presentation.xml" : e.to_s
106
118
  File.open(File.join(@outdir, "collection.#{ext}"), "w:UTF-8") do |f|
107
119
  b = concatenate1(col.clone, e).to_xml
108
- e == :presentation and
109
- b.sub!("<metanorma-collection>", "<metanorma-collection xmlns='http://metanorma.org'>")
110
- # TODO BEING FORCED TO DO THAT BECAUSE SHALE IS NOT DEALING WITH DEFAULT NAMESPACES
120
+ e == :presentation and b = concatenate_presentation(b)
111
121
  f.write(b)
112
122
  end
113
123
  end
114
124
  end
115
125
 
126
+ def concatenate_presentation(xml)
127
+ xml.sub!("<metanorma-collection>", "<metanorma-collection xmlns='http://metanorma.org'>")
128
+ # TODO BEING FORCED TO DO THAT BECAUSE SHALE IS NOT DEALING WITH DEFAULT NAMESPACES
129
+ @directives.detect { |d| d.key == "bilingual" } and
130
+ xml = Metanorma::Collection::Multilingual
131
+ .new({ align_cross_elements: %w(p note) }).to_bilingual(xml)
132
+ xml
133
+ end
134
+
116
135
  def concatenate_outputs(options)
117
136
  pres = File.join(@outdir, "collection.presentation.xml")
118
137
  options[:format].include?(:pdf) and pdfconv.convert(pres)
119
138
  options[:format].include?(:doc) and docconv_convert(pres)
139
+ @directives.detect { |d| d.key == "bilingual" } &&
140
+ options[:format].include?(:html) and
141
+ Metanorma::Collection::Multilingual.new(
142
+ { flavor: flavor.to_sym,
143
+ converter_options: PdfOptionsNode.new(flavor, @compile_options),
144
+ outdir: @outdir },
145
+ ).to_html(pres)
120
146
  end
121
147
 
122
148
  def concatenate1(out, ext)
123
- out.directives << ::Metanorma::Collection::Config::Directive.new(key: "documents-inline")
149
+ out.directives << ::Metanorma::Collection::Config::Directive
150
+ .new(key: "documents-inline")
124
151
  out.bibdatas.each_key do |ident|
125
152
  id = @isodoc.docid_prefix(nil, ident.dup)
126
153
  @files.get(id, :attachment) || @files.get(id, :outputs).nil? and next
127
154
  out.documents[Util::key id] =
128
- Metanorma::Collection::Document.raw_file(@files.get(id,
129
- :outputs)[ext])
155
+ Metanorma::Collection::Document
156
+ .raw_file(@files.get(id, :outputs)[ext])
130
157
  end
131
158
  out
132
159
  end
133
160
 
134
- # infer the flavour from the first document identifier; relaton does that
135
- def doctype
136
- if (docid = @xml.at("//bibdata/docidentifier/@type")&.text)
137
- dt = docid.downcase
138
- elsif (docid = @xml.at("//bibdata/docidentifier")&.text)
139
- dt = docid.sub(/\s.*$/, "").lowercase
140
- else return "standoc"
141
- end
142
- @registry = Metanorma::Registry.instance
161
+ # TODO: infer flavor from publisher when available
162
+ def flavor
163
+ dt = @xml.at("//bibdata/ext/flavor")&.text or return "standoc"
143
164
  @registry.alias(dt.to_sym)&.to_s || dt
144
165
  end
145
166
 
@@ -0,0 +1,52 @@
1
+ module Metanorma
2
+ class Collection
3
+ class Renderer
4
+ def svg_datauri(docxml, docid)
5
+ rel = @files.get(docid, :rel_path)
6
+ parent = @files.get(docid, :parentid) and
7
+ rel = @files.get(parent, :rel_path)
8
+ # if sectionsplit, use orig file dir
9
+ dir = File.join(@dirname, File.dirname(rel))
10
+ datauri_encode(docxml, dir)
11
+ end
12
+
13
+ def svgmap_resolve(docxml, docid, presxml)
14
+ #require "debug"; binding.b
15
+ ids = @files.get(docid, :ids)
16
+ docxml = svg_unnest(svg_datauri(docxml, docid))
17
+ isodoc = IsoDoc::PresentationXMLConvert.new({})
18
+ isodoc.bibitem_lookup(docxml)
19
+ tag = presxml ? "fmt-eref" : "eref"
20
+ docxml.xpath(ns("//svgmap//#{tag}")).each do |e|
21
+ #require "debug"; binding.b
22
+ svgmap_resolve_eref(e, isodoc, docxml, ids, presxml)
23
+ end
24
+ docxml.xpath(ns("//svgmap/target")).each do |t| # undo Presentation XML: Vectory takes eref not fmt-eref
25
+ n = t.at(ns(".//fmt-link | .//fmt-xref | .//fmt-eref")) or next
26
+ n.name = n.name.sub(/^fmt-/, "")
27
+ t.children = n
28
+ end
29
+ Vectory::SvgMapping.new(docxml, "").call
30
+ docxml.xpath(ns("//svgmap")).each { |s| isodoc.svgmap_extract(s) }
31
+ end
32
+
33
+ def svg_unnest(docxml)
34
+ docxml.xpath(ns("//svgmap//image[.//*[name() = 'image']]")).each do |i|
35
+ s = i.elements.detect { |e| e.name == "svg" } and
36
+ i.replace(s)
37
+ end
38
+ docxml
39
+ end
40
+
41
+ def svgmap_resolve_eref(eref, isodoc, _docxml, ids, presxml)
42
+ href = isodoc.eref_target(eref) or return
43
+ href = href[:link]
44
+ href == "##{eref['bibitemid']}" ||
45
+ (href =~ /^#/ && !ids[href.sub(/^#/, "")]) and return
46
+ eref["target"] = href.strip
47
+ eref.name = presxml ? "fmt-link" : "link"
48
+ eref.elements&.remove
49
+ end
50
+ end
51
+ end
52
+ end