metanorma 1.6.2 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e498e9799f9d0decd9e01cc9c29a1092c6e1f99c25336e8e59e7990342f389eb
4
- data.tar.gz: 7535c76f7fbf92ab903ef5b1aebacb20e8673ba7007d1b5e2999ba1491bc4cef
3
+ metadata.gz: ca433d59b111534c114a96b7ce386ccf0267a70cedcbfbe61ef11cf2f42737d3
4
+ data.tar.gz: c1a73eb056acb7910d255c8348273dd9abf79dd06ef4826ac3ab3d5474543242
5
5
  SHA512:
6
- metadata.gz: 48cc96f2dc81cfcc2bcdbb622db0a1d323bf4e2c0c3be8202056b4baa5f0f1951718fc5cf2512e519e3be620a3fd0c5c994b13d70fb77408a8ca5272b199bd63
7
- data.tar.gz: f7627d831dc78159c8a9282d233b1c7d98e61854c0eace215b9d1d4a34a96bf9f7dd2535e013464d264fd4eddd4c135401de68a4c74c7cf12dc521fa42415bb1
6
+ metadata.gz: 2e57292cdc5217cb985be7beb617035ee8edcfb0c9ee3c38cd2c6dc49e71c63468c05d3e6c3000985e93e94a4313f7cf77b24a24c4affe80778f3727c3c7a5b8
7
+ data.tar.gz: b1a33f6b99669f384af4426cf75e3052f480c0878ec9f1d5716661bc5340e228273f6993930aacba3b1bfe6da7f166791718b0c02c0c71440f83d8642e019355
@@ -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)
61
+ svgmap_resolve(datauri_encode(docxml), ids)
102
62
  update_direct_refs_to_docs(docxml, identifier)
103
- svgmap_resolve(datauri_encode(docxml))
104
63
  hide_refs(docxml)
64
+ @files.get(identifier, :sectionsplit_output) and eref2link(docxml)
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, "")
146
101
  end
147
102
 
148
- def svgmap_resolve1(eref, isodoc)
103
+ def svgmap_resolve1(eref, isodoc, _docxml, ids)
149
104
  href = isodoc.eref_target(eref)
150
105
  return if href == "##{eref['bibitemid']}" ||
151
- (href =~ /^#/ && !docxml.at("//*[@id = '#{href.sub(/^#/, '')}']"))
106
+ # (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,35 @@ 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|
160
+ # docxml.xpath(ns("//eref[@bibitemid = '#{key}']")).each do |e|
201
161
  e["citeas"] = file
202
- if a = e.at(ns(".//locality[@type = 'anchor']/referenceFrom"))
162
+ a = e.at(ns(".//locality[@type = 'anchor']/referenceFrom")) and
203
163
  a.children = "#{a.text}_#{Metanorma::Utils::to_ncname(file)}"
204
- end
205
164
  end
206
- docid = docxml.at(ns("//bibitem[@id = '#{schema}_#{id}']/" \
207
- "docidentifier[@type = 'repository']")) or return
165
+ docid = bibitems[key]&.at(ns("./docidentifier[@type = 'repository']")) or
166
+ return
208
167
  docid.children = "current-metanorma-collection/#{file}"
209
- docid.previous = "<docidentifier type='X'>#{file}</docidentifier>"
168
+ docid.previous =
169
+ "<docidentifier type='metanorma-collection'>#{file}</docidentifier>"
210
170
  end
211
171
 
212
172
  # update crossrefences to other documents, to include
213
173
  # 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)
174
+ def update_anchors(bib, docid, erefs)
175
+ #docxml.xpath("//xmlns:eref[@citeas = '#{docid}']").each do |e|
176
+ erefs.each do |e|
217
177
  if @files.get(docid) then update_anchor_loc(bib, e, docid)
218
178
  else
219
179
  e << "<strong>** Unresolved reference to document #{docid} " \
@@ -223,13 +183,12 @@ module Metanorma
223
183
  end
224
184
 
225
185
  def update_anchor_loc(bib, eref, docid)
226
- loc = eref.at(ns(".//locality[@type = 'anchor']")) or
186
+ loc = eref.at(".//xmlns:locality[@type = 'anchor']") or
227
187
  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)|
188
+ @ncnames[docid] ||= Metanorma::Utils::to_ncname(docid)
189
+ ref = loc.at("./xmlns:referenceFrom") or return
190
+ anchor = "#{ref.text}_#{@ncnames[docid]}"
191
+ return unless @files.get(docid, :anchors).inject([]) do |m, (_, x)|
233
192
  m += x.values
234
193
  end.include?(anchor)
235
194
 
@@ -243,41 +202,36 @@ module Metanorma
243
202
  type = ins.at(ns("./locality/@type"))&.text
244
203
  type = "clause" if type == "annex"
245
204
  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
205
+ anchor = @files.get(docid, :anchors).dig(type, ref) or return
248
206
  ins << "<locality type='anchor'><referenceFrom>#{anchor.sub(/^_/, '')}" \
249
207
  "</referenceFrom></locality>"
250
208
  end
251
209
 
252
210
  # gather internal bibitem references
253
211
  def gather_internal_refs
254
- #@files.each.with_object({}) do |(_, x), refs|
255
212
  @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)
213
+ @files.get(i, :attachment) and next
259
214
  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
215
+ gather_internal_refs1(file, refs)
216
+ end
217
+ end
218
+
219
+ def gather_internal_refs1(file, refs)
220
+ Nokogiri::XML(file, &:huge)
221
+ .xpath(ns("//bibitem[@type = 'internal']/" \
222
+ "docidentifier[@type = 'repository']")).each do |d|
223
+ a = d.text.split(%r{/}, 2)
224
+ a.size > 1 or next
225
+ refs[a[0]] ||= {}
226
+ refs[a[0]][a[1]] = true
268
227
  end
269
228
  end
270
229
 
271
230
  # resolve file location for the target of each internal reference
272
231
  def locate_internal_refs
273
- #require 'debug'; binding.b
274
232
  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)
233
+ @files.keys.reject { |k| @files.get(k, :attachment) }.each do |ident|
234
+ locate_internal_refs1(refs, ident, @isodoc.docid_prefix("", ident.dup))
281
235
  end
282
236
  refs.each do |schema, ids|
283
237
  ids.each do |id, key|
@@ -287,19 +241,20 @@ module Metanorma
287
241
  refs
288
242
  end
289
243
 
290
- #def locate_internal_refs1(refs, identifier, filedesc)
291
244
  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 }
245
+ t = locate_internal_refs1_prep(ident)
296
246
  refs.each do |schema, ids|
297
247
  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
248
+ t[id].at("./ancestor-or-self::*[@type = '#{schema}']") and
300
249
  refs[schema][id] = identifier
301
250
  end
302
251
  end
303
252
  end
253
+
254
+ def locate_internal_refs1_prep(ident)
255
+ file, _filename = @files.targetfile_id(ident, read: true)
256
+ xml = Nokogiri::XML(file, &:huge)
257
+ xml.xpath("//*[@id]").each_with_object({}) { |i, x| x[i["id"]] = i }
258
+ end
304
259
  end
305
260
  end