metanorma 1.6.2 → 1.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e498e9799f9d0decd9e01cc9c29a1092c6e1f99c25336e8e59e7990342f389eb
4
- data.tar.gz: 7535c76f7fbf92ab903ef5b1aebacb20e8673ba7007d1b5e2999ba1491bc4cef
3
+ metadata.gz: abbc191b2e898bbeeea46f7867bb9d25d44cfd7f9a0dd2c690fcbdb8383136fd
4
+ data.tar.gz: a9e184662fcf25a575c278d604440b8215fd7b54b76f980a4cf4bfd5f8a1f543
5
5
  SHA512:
6
- metadata.gz: 48cc96f2dc81cfcc2bcdbb622db0a1d323bf4e2c0c3be8202056b4baa5f0f1951718fc5cf2512e519e3be620a3fd0c5c994b13d70fb77408a8ca5272b199bd63
7
- data.tar.gz: f7627d831dc78159c8a9282d233b1c7d98e61854c0eace215b9d1d4a34a96bf9f7dd2535e013464d264fd4eddd4c135401de68a4c74c7cf12dc521fa42415bb1
6
+ metadata.gz: bfc28efd7f7f48f0bfd7dfa630bf88f1186006022dc6d5f82f188a3749304bc73837c9e96dd9246655de67f2b1ee29d9525f49c2ba568e2116d4329bf3689bda
7
+ data.tar.gz: 40bc185f4dbe9b4570349e22a15334a2e3fb089dfe3002ab43cb4a8ffa4afe4f2a3ae8357f80e61d585a57ab3b64e24dd5fb2700241dd6f1b958693214afdbc6
@@ -9,16 +9,11 @@ require_relative "util"
9
9
  module Metanorma
10
10
  # Metanorma collection of documents
11
11
  class Collection
12
- # @return [String]
13
12
  attr_reader :file
14
13
 
15
14
  # @return [Array<String>] documents-inline to inject the XML into
16
15
  # the collection manifest; documents-external to keeps them outside
17
- attr_accessor :directives
18
-
19
- # @return [Hash<String, Metanorma::Document>]
20
- attr_accessor :documents, :bibdatas, :coverpage
21
-
16
+ attr_accessor :directives, :documents, :bibdatas, :coverpage
22
17
  attr_accessor :disambig, :manifest
23
18
 
24
19
  # @param file [String] path to source file
@@ -92,8 +87,7 @@ module Metanorma
92
87
  elem.each_with_object([]) do |(k, v), m|
93
88
  m << "<#{k}>#{obj_to_xml(v)}</#{k}>"
94
89
  end.join
95
- else elem
96
- end
90
+ else elem end
97
91
  end
98
92
 
99
93
  def render(opts)
@@ -115,7 +109,7 @@ module Metanorma
115
109
  private
116
110
 
117
111
  def parse_xml(file)
118
- xml = Nokogiri::XML File.read(file, encoding: "UTF-8") { |c| c.huge }
112
+ xml = Nokogiri::XML(File.read(file, encoding: "UTF-8"), &:huge)
119
113
  (b = xml.at("/xmlns:metanorma-collection/xmlns:bibdata")) and
120
114
  bd = Relaton::Cli.parse_xml(b)
121
115
  mnf_xml = xml.at("/xmlns:metanorma-collection/xmlns:manifest")
@@ -133,15 +127,14 @@ module Metanorma
133
127
  # TODO refine
134
128
  def directives_from_xml(dir)
135
129
  dir.each_with_object([]) do |d, m|
136
- if d.at("./xmlns:value")
137
- m << x.xpath("./xmlns:value").map(&:text)
138
- elsif d.at("./*")
139
- out = d.elements.each_with_object({}) do |e, ret|
140
- ret[e.name] = e.children.to_xml
141
- end
142
- m << out
143
- else m << d.children.to_xml
144
- end
130
+ m << if d.at("./xmlns:value")
131
+ x.xpath("./xmlns:value").map(&:text)
132
+ elsif d.at("./*")
133
+ d.elements.each_with_object({}) do |e, ret|
134
+ ret[e.name] = e.children.to_xml
135
+ end
136
+ else d.children.to_xml
137
+ end
145
138
  end
146
139
  end
147
140
 
@@ -174,8 +167,7 @@ module Metanorma
174
167
  # @param xml [Nokogiri::XML::Element, nil]
175
168
  # @return [String, nil]
176
169
  def pref_final_content(xml)
177
- return unless xml
178
-
170
+ xml or return
179
171
  <<~CONT
180
172
 
181
173
  == #{xml.at('title')&.text}
@@ -212,13 +204,12 @@ module Metanorma
212
204
  # @return [String] XML
213
205
  def sections(cnt)
214
206
  c = Asciidoctor.convert(cnt, backend: doctype.to_sym, header_footer: true)
215
- Nokogiri::XML(c).at("//xmlns:sections").children.to_xml
207
+ Nokogiri::XML(c, &:huge).at("//xmlns:sections").children.to_xml
216
208
  end
217
209
 
218
210
  # @param builder [Nokogiri::XML::Builder]
219
211
  def doccontainer(builder)
220
- return unless Array(@directives).include? "documents-inline"
221
-
212
+ Array(@directives).include? "documents-inline" or return
222
213
  documents.each_with_index do |(_, d), i|
223
214
  doccontainer1(builder, d, i)
224
215
  end
@@ -235,16 +226,13 @@ module Metanorma
235
226
  end
236
227
  end
237
228
 
238
- # @return [String]
239
229
  def doctype
240
230
  @doctype ||= fetch_doctype || "standoc"
241
231
  end
242
232
 
243
- # @return [String]
244
233
  def fetch_doctype
245
234
  docid = @bibdata.docidentifier.first
246
- return unless docid
247
-
235
+ docid or return
248
236
  docid.type&.downcase || docid.id&.sub(/\s.*$/, "")&.downcase
249
237
  end
250
238
  end
@@ -1,82 +1,40 @@
1
1
  module Metanorma
2
2
  # XML collection renderer
3
3
  class CollectionRenderer
4
- =begin
5
- # map locality type and label (e.g. "clause" "1") to id = anchor for
6
- # a document
7
- # Note: will only key clauses, which have unambiguous reference label in
8
- # locality. Notes, examples etc with containers are just plunked against
9
- # UUIDs, so that their IDs can at least be registered to be tracked
10
- # as existing.
11
- def read_anchors(xml)
12
- xrefs = @isodoc.xref_init(@lang, @script, @isodoc, @isodoc.i18n,
13
- { locale: @locale })
14
- xrefs.parse xml
15
- xrefs.get.each_with_object({}) do |(k, v), ret|
16
- read_anchors1(k, v, ret)
17
- end
18
- end
19
-
20
- def read_anchors1(key, val, ret)
21
- val[:type] ||= "clause"
22
- ret[val[:type]] ||= {}
23
- index = if val[:container] || val[:label].nil? || val[:label].empty?
24
- UUIDTools::UUID.random_create.to_s
25
- else val[:label]
26
- end
27
- ret[val[:type]][index] = key
28
- ret[val[:type]][val[:value]] = key if val[:value]
29
- end
30
-
31
- # @param id [String]
32
- # @param read [Boolean]
33
- # @return [Array<String, nil>]
34
- def xml_file(id, read)
35
- file = @xml.at(ns("//doc-container[@id = '#{id}']")).to_xml if read
36
- filename = "#{id}.html"
37
- [file, filename]
38
- end
39
- =end
40
-
41
4
  # @param bib [Nokogiri::XML::Element]
42
5
  # @param identifier [String]
43
6
  def update_bibitem(bib, identifier)
44
7
  docid = get_bibitem_docid(bib, identifier) or return
45
8
  newbib = dup_bibitem(docid, bib)
9
+ _file, url = @files
10
+ .targetfile_id(docid, relative: true, read: false,
11
+ doc: !@files.get(docid, :attachment))
12
+ dest = newbib.at("./docidentifier") || newbib.at(ns("./docidentifier"))
13
+ dest.previous = "<uri type='citation'>#{url}</uri>"
46
14
  bib.replace(newbib)
47
- #_file, url = targetfile(@files[docid], relative: true, read: false, doc: !@files[docid][:attachment])
48
- _file, url = @files.targetfile_id(docid, relative: true, read: false, doc: !@files.get(docid,:attachment))
49
- uri_node = Nokogiri::XML::Node.new "uri", newbib.document
50
- uri_node[:type] = "citation"
51
- uri_node.content = url
52
- newbib.at(ns("./docidentifier")).previous = uri_node
53
15
  end
54
16
 
55
17
  def get_bibitem_docid(bib, identifier)
56
18
  # IDs for repo references are untyped by default
57
19
  docid = bib.at(ns("./docidentifier[not(@type)]")) ||
58
20
  bib.at(ns("./docidentifier"))
59
- docid &&= @c.decode(@isodoc
60
- .docid_prefix(docid["type"], docid.children.to_xml)).gsub(/\s/, " ")
61
- #if @files[docid] then docid
62
- if @files.get(docid) || @files.get("X #{docid}") then docid
21
+ docid &&= docid_prefix(docid)
22
+ if @files.get(docid) then docid
63
23
  else
64
- #require "debug"; binding.b
65
24
  fail_update_bibitem(docid, identifier)
66
25
  nil
67
26
  end
68
27
  end
69
28
 
70
- def fail_update_bibitem(docid, identifier)
71
- error = "[metanorma] Cannot find crossreference to document #{docid} " \
72
- "in document #{identifier}."
73
- @log&.add("Cross-References", nil, error)
74
- Util.log(error, :warning)
29
+ def docid_prefix(docid)
30
+ type = docid["type"]
31
+ type == "metanorma-collection" and type = nil
32
+ @c.decode(@isodoc
33
+ .docid_prefix(type, docid.children.to_xml)).gsub(/\s/, " ")
75
34
  end
76
35
 
77
36
  def dup_bibitem(docid, bib)
78
- #newbib = @files[docid][:bibdata].dup
79
- newbib = @files.get(docid,:bibdata).dup
37
+ newbib = @files.get(docid, :bibdata).dup
80
38
  newbib.name = "bibitem"
81
39
  newbib["hidden"] = "true"
82
40
  newbib&.at("./*[local-name() = 'ext']")&.remove
@@ -95,16 +53,24 @@ module Metanorma
95
53
  # anchor to filename
96
54
  # @return [String] XML content
97
55
  def update_xrefs(file, identifier, internal_refs)
98
- docxml = Nokogiri::XML(file) { |config| config.huge }
56
+ docxml = file.is_a?(String) ? Nokogiri::XML(file, &:huge) : file
99
57
  supply_repo_ids(docxml)
100
58
  update_indirect_refs_to_docs(docxml, internal_refs)
59
+ ids = @files.get(identifier, :ids)
101
60
  @files.add_document_suffix(identifier, docxml)
102
61
  update_direct_refs_to_docs(docxml, identifier)
103
- svgmap_resolve(datauri_encode(docxml))
104
62
  hide_refs(docxml)
63
+ @files.get(identifier, :sectionsplit_output) and eref2link(docxml)
64
+ svgmap_resolve(datauri_encode(docxml), ids)
105
65
  docxml.to_xml
106
66
  end
107
67
 
68
+ def eref2link(docxml)
69
+ isodoc = IsoDoc::PresentationXMLConvert.new({})
70
+ isodoc.bibitem_lookup(docxml)
71
+ isodoc.eref2link(docxml)
72
+ end
73
+
108
74
  def hide_refs(docxml)
109
75
  docxml.xpath(ns("//references[bibitem][not(./bibitem[not(@hidden) or " \
110
76
  "@hidden = 'false'])]")).each do |f|
@@ -114,41 +80,31 @@ module Metanorma
114
80
 
115
81
  def supply_repo_ids(docxml)
116
82
  docxml.xpath(ns("//bibitem[not(ancestor::bibitem)]")).each do |b|
117
- next if b&.at(ns("./docidentifier[@type = 'repository']"))
118
-
83
+ b.at(ns("./docidentifier[@type = 'repository']")) and next
119
84
  b.xpath(ns("./docidentifier")).each do |docid|
120
- #id = @c.decode(@isodoc
121
- #.docid_prefix(docid["type"], docid.children.to_xml))
122
85
  id = @isodoc
123
- .docid_prefix(docid["type"], docid.children.to_xml)
124
- #@files[id] or next
86
+ .docid_prefix(docid["type"], docid.children.to_xml)
125
87
  @files.get(id) or next
126
88
  docid.next = "<docidentifier type='repository'>" \
127
- "current-metanorma-collection/#{id}"
89
+ "current-metanorma-collection/#{id}</docidentifier>"
128
90
  end
129
91
  end
130
92
  end
131
93
 
132
- def datauri_encode(docxml)
133
- docxml.xpath(ns("//image")).each do |i|
134
- i["src"] = Metanorma::Utils::datauri(i["src"])
135
- end
136
- docxml
137
- end
138
-
139
- def svgmap_resolve(docxml)
94
+ def svgmap_resolve(docxml, ids)
140
95
  isodoc = IsoDoc::PresentationXMLConvert.new({})
141
96
  isodoc.bibitem_lookup(docxml)
142
97
  docxml.xpath(ns("//svgmap//eref")).each do |e|
143
- svgmap_resolve1(e, isodoc)
98
+ svgmap_resolve1(e, isodoc, docxml, ids)
144
99
  end
145
100
  Metanorma::Utils::svgmap_rewrite(docxml, "")
101
+ docxml.xpath(ns("//svgmap")).each { |s| isodoc.svgmap_extract(s) }
146
102
  end
147
103
 
148
- def svgmap_resolve1(eref, isodoc)
104
+ def svgmap_resolve1(eref, isodoc, _docxml, ids)
149
105
  href = isodoc.eref_target(eref)
150
106
  return if href == "##{eref['bibitemid']}" ||
151
- (href =~ /^#/ && !docxml.at("//*[@id = '#{href.sub(/^#/, '')}']"))
107
+ (href =~ /^#/ && !ids[href.sub(/^#/, "")])
152
108
 
153
109
  eref["target"] = href.strip
154
110
  eref.name = "link"
@@ -161,21 +117,21 @@ module Metanorma
161
117
  # Preferably with anchor, and is a job to realise dynamic lookup
162
118
  # of localities.
163
119
  def update_direct_refs_to_docs(docxml, identifier)
164
- erefs = collect_erefs(docxml)
165
- docxml.xpath(ns("//bibitem[not(ancestor::bibitem)]")).each do |b|
120
+ @ncnames = {}
121
+ erefs = Util::gather_citeases(docxml)
122
+ docxml.xpath(ns("//bibitem")).each do |b|
166
123
  docid = b.at(ns("./docidentifier[@type = 'repository']"))
167
124
  (docid && %r{^current-metanorma-collection/}.match(docid.text)) or next
168
125
  update_bibitem(b, identifier)
169
126
  docid = docid_to_citeas(b) or next
170
- erefs[:citeas][docid] and update_anchors(b, docxml, docid)
127
+ erefs[docid] and update_anchors(b, docid, erefs[docid])
171
128
  end
172
129
  end
173
130
 
174
131
  def docid_to_citeas(bib)
175
132
  docid = bib.at(ns("./docidentifier[@primary = 'true']")) ||
176
133
  bib.at(ns("./docidentifier")) or return
177
- @c.decode(@isodoc
178
- .docid_prefix(docid["type"], docid.children.to_xml))
134
+ docid_prefix(docid)
179
135
  end
180
136
 
181
137
  def collect_erefs(docxml)
@@ -189,31 +145,33 @@ module Metanorma
189
145
  # Resolve erefs to a container of ids in another doc,
190
146
  # to an anchor eref (direct link)
191
147
  def update_indirect_refs_to_docs(docxml, internal_refs)
148
+ bibitems = Util::gather_bibitems(docxml)
149
+ erefs = Util::gather_bibitemids(docxml)
192
150
  internal_refs.each do |schema, ids|
193
151
  ids.each do |id, file|
194
- update_indirect_refs_to_docs1(docxml, schema, id, file)
152
+ update_indirect_refs_to_docs1(docxml, "#{schema}_#{id}",
153
+ file, bibitems, erefs)
195
154
  end
196
155
  end
197
156
  end
198
157
 
199
- def update_indirect_refs_to_docs1(docxml, schema, id, file)
200
- docxml.xpath(ns("//eref[@bibitemid = '#{schema}_#{id}']")).each do |e|
158
+ def update_indirect_refs_to_docs1(_docxml, key, file, bibitems, erefs)
159
+ erefs[key]&.each do |e|
201
160
  e["citeas"] = file
202
- if a = e.at(ns(".//locality[@type = 'anchor']/referenceFrom"))
161
+ a = e.at(ns(".//locality[@type = 'anchor']/referenceFrom")) and
203
162
  a.children = "#{a.text}_#{Metanorma::Utils::to_ncname(file)}"
204
- end
205
163
  end
206
- docid = docxml.at(ns("//bibitem[@id = '#{schema}_#{id}']/" \
207
- "docidentifier[@type = 'repository']")) or return
164
+ docid = bibitems[key]&.at(ns("./docidentifier[@type = 'repository']")) or
165
+ return
208
166
  docid.children = "current-metanorma-collection/#{file}"
209
- docid.previous = "<docidentifier type='X'>#{file}</docidentifier>"
167
+ docid.previous =
168
+ "<docidentifier type='metanorma-collection'>#{file}</docidentifier>"
210
169
  end
211
170
 
212
171
  # update crossrefences to other documents, to include
213
172
  # disambiguating document suffix on id
214
- def update_anchors(bib, docxml, docid) # rubocop:disable Metrics/AbcSize
215
- docxml.xpath("//xmlns:eref[@citeas = '#{docid}']").each do |e|
216
- #if @files[docid] then update_anchor_loc(bib, e, docid)
173
+ def update_anchors(bib, docid, erefs)
174
+ erefs.each do |e|
217
175
  if @files.get(docid) then update_anchor_loc(bib, e, docid)
218
176
  else
219
177
  e << "<strong>** Unresolved reference to document #{docid} " \
@@ -223,13 +181,12 @@ module Metanorma
223
181
  end
224
182
 
225
183
  def update_anchor_loc(bib, eref, docid)
226
- loc = eref.at(ns(".//locality[@type = 'anchor']")) or
184
+ loc = eref.at(".//xmlns:locality[@type = 'anchor']") or
227
185
  return update_anchor_create_loc(bib, eref, docid)
228
- document_suffix = Metanorma::Utils::to_ncname(docid)
229
- ref = loc.at(ns("./referenceFrom")) or return
230
- anchor = "#{ref.text}_#{document_suffix}"
231
- #return unless @files[docid][:anchors].inject([]) do |m, (_, x)|
232
- return unless @files.get(docid,:anchors).inject([]) do |m, (_, x)|
186
+ @ncnames[docid] ||= Metanorma::Utils::to_ncname(docid)
187
+ ref = loc.at("./xmlns:referenceFrom") or return
188
+ anchor = "#{ref.text}_#{@ncnames[docid]}"
189
+ return unless @files.get(docid, :anchors).inject([]) do |m, (_, x)|
233
190
  m += x.values
234
191
  end.include?(anchor)
235
192
 
@@ -243,41 +200,36 @@ module Metanorma
243
200
  type = ins.at(ns("./locality/@type"))&.text
244
201
  type = "clause" if type == "annex"
245
202
  ref = ins.at(ns("./locality/referenceFrom"))&.text
246
- #anchor = @files[docid][:anchors].dig(type, ref) or return
247
- anchor = @files.get(docid,:anchors).dig(type, ref) or return
203
+ anchor = @files.get(docid, :anchors).dig(type, ref) or return
248
204
  ins << "<locality type='anchor'><referenceFrom>#{anchor.sub(/^_/, '')}" \
249
205
  "</referenceFrom></locality>"
250
206
  end
251
207
 
252
208
  # gather internal bibitem references
253
209
  def gather_internal_refs
254
- #@files.each.with_object({}) do |(_, x), refs|
255
210
  @files.keys.each_with_object({}) do |i, refs|
256
- #x[:attachment] and next
257
- @files.get(i,:attachment) and next
258
- #file, = targetfile(x, read: true)
211
+ @files.get(i, :attachment) and next
259
212
  file, = @files.targetfile_id(i, read: true)
260
- Nokogiri::XML(file)
261
- .xpath(ns("//bibitem[@type = 'internal']/" \
262
- "docidentifier[@type = 'repository']")).each do |d|
263
- a = d.text.split(%r{/}, 2)
264
- a.size > 1 or next
265
- refs[a[0]] ||= {}
266
- refs[a[0]][a[1]] = true
267
- end
213
+ gather_internal_refs1(file, refs)
214
+ end
215
+ end
216
+
217
+ def gather_internal_refs1(file, refs)
218
+ Nokogiri::XML(file, &:huge)
219
+ .xpath(ns("//bibitem[@type = 'internal']/" \
220
+ "docidentifier[@type = 'repository']")).each do |d|
221
+ a = d.text.split(%r{/}, 2)
222
+ a.size > 1 or next
223
+ refs[a[0]] ||= {}
224
+ refs[a[0]][a[1]] = true
268
225
  end
269
226
  end
270
227
 
271
228
  # resolve file location for the target of each internal reference
272
229
  def locate_internal_refs
273
- #require 'debug'; binding.b
274
230
  refs = gather_internal_refs
275
- #@files.keys.reject { |k| @files[k][:attachment] }.each do |identifier|
276
- @files.keys.reject { |k| @files.get(k,:attachment) }.each do |identifier|
277
- #id = @c.decode(@isodoc.docid_prefix("", identifier.dup))
278
- #locate_internal_refs1(refs, identifier, @files[id])
279
- id = @isodoc.docid_prefix("", identifier.dup)
280
- locate_internal_refs1(refs, identifier, id)
231
+ @files.keys.reject { |k| @files.get(k, :attachment) }.each do |ident|
232
+ locate_internal_refs1(refs, ident, @isodoc.docid_prefix("", ident.dup))
281
233
  end
282
234
  refs.each do |schema, ids|
283
235
  ids.each do |id, key|
@@ -287,19 +239,20 @@ module Metanorma
287
239
  refs
288
240
  end
289
241
 
290
- #def locate_internal_refs1(refs, identifier, filedesc)
291
242
  def locate_internal_refs1(refs, identifier, ident)
292
- #file, _filename = targetfile(filedesc, read: true)
293
- file, _filename = @files.targetfile_id(ident, read: true)
294
- xml = Nokogiri::XML(file) { |config| config.huge }
295
- t = xml.xpath("//*/@id").each_with_object({}) { |i, x| x[i.text] = true }
243
+ t = locate_internal_refs1_prep(ident)
296
244
  refs.each do |schema, ids|
297
245
  ids.keys.select { |id| t[id] }.each do |id|
298
- n = xml.at("//*[@id = '#{id}']") and
299
- n.at("./ancestor-or-self::*[@type = '#{schema}']") and
246
+ t[id].at("./ancestor-or-self::*[@type = '#{schema}']") and
300
247
  refs[schema][id] = identifier
301
248
  end
302
249
  end
303
250
  end
251
+
252
+ def locate_internal_refs1_prep(ident)
253
+ file, _filename = @files.targetfile_id(ident, read: true)
254
+ xml = Nokogiri::XML(file, &:huge)
255
+ xml.xpath("//*[@id]").each_with_object({}) { |i, x| x[i["id"]] = i }
256
+ end
304
257
  end
305
258
  end