metanorma 1.7.7 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -1
  3. data/lib/metanorma/array_monkeypatch.rb +9 -0
  4. data/lib/metanorma/asciidoctor_extensions/glob_include_processor.rb +13 -11
  5. data/lib/metanorma/collection/collection.rb +225 -0
  6. data/lib/metanorma/collection/config/bibdata.rb +12 -0
  7. data/lib/metanorma/collection/config/compile_options.rb +13 -0
  8. data/lib/metanorma/collection/config/config.rb +163 -0
  9. data/lib/metanorma/collection/config/converters.rb +30 -0
  10. data/lib/metanorma/collection/config/directive.rb +10 -0
  11. data/lib/metanorma/collection/config/manifest.rb +88 -0
  12. data/lib/metanorma/collection/document/document.rb +133 -0
  13. data/lib/metanorma/collection/filelookup/filelookup.rb +250 -0
  14. data/lib/metanorma/collection/filelookup/filelookup_sectionsplit.rb +87 -0
  15. data/lib/metanorma/collection/manifest/manifest.rb +237 -0
  16. data/lib/metanorma/collection/renderer/fileparse.rb +247 -0
  17. data/lib/metanorma/collection/renderer/fileprocess.rb +173 -0
  18. data/lib/metanorma/collection/renderer/navigation.rb +133 -0
  19. data/lib/metanorma/collection/renderer/render_word.rb +133 -0
  20. data/lib/metanorma/collection/renderer/renderer.rb +157 -0
  21. data/lib/metanorma/collection/renderer/utils.rb +183 -0
  22. data/lib/metanorma/collection/sectionsplit/sectionsplit.rb +218 -0
  23. data/lib/metanorma/collection/util/disambig_files.rb +37 -0
  24. data/lib/metanorma/collection/util/util.rb +72 -0
  25. data/lib/metanorma/collection/xrefprocess/xrefprocess.rb +222 -0
  26. data/lib/metanorma/{compile.rb → compile/compile.rb} +17 -11
  27. data/lib/metanorma/{compile_options.rb → compile/compile_options.rb} +9 -5
  28. data/lib/metanorma/{compile_validate.rb → compile/compile_validate.rb} +1 -1
  29. data/lib/metanorma/{extract.rb → compile/extract.rb} +2 -2
  30. data/lib/metanorma/{config.rb → config/config.rb} +1 -1
  31. data/lib/metanorma/input/asciidoc.rb +3 -3
  32. data/lib/metanorma/input/base.rb +1 -5
  33. data/lib/metanorma/processor/processor.rb +54 -0
  34. data/lib/metanorma/processor.rb +1 -49
  35. data/lib/metanorma/{registry.rb → registry/registry.rb} +0 -1
  36. data/lib/metanorma/shale_monkeypatch.rb +15 -0
  37. data/lib/metanorma/util/fontist_helper.rb +130 -0
  38. data/lib/metanorma/util/util.rb +45 -0
  39. data/lib/metanorma/util/worker_pool.rb +39 -0
  40. data/lib/metanorma/version.rb +1 -1
  41. data/lib/metanorma.rb +13 -8
  42. data/metanorma.gemspec +2 -1
  43. metadata +50 -24
  44. data/lib/metanorma/collection.rb +0 -244
  45. data/lib/metanorma/collection_fileparse.rb +0 -257
  46. data/lib/metanorma/collection_fileprocess.rb +0 -168
  47. data/lib/metanorma/collection_manifest.rb +0 -168
  48. data/lib/metanorma/collection_render_utils.rb +0 -169
  49. data/lib/metanorma/collection_render_word.rb +0 -131
  50. data/lib/metanorma/collection_renderer.rb +0 -237
  51. data/lib/metanorma/collection_xref_process.rb +0 -217
  52. data/lib/metanorma/document.rb +0 -133
  53. data/lib/metanorma/files_lookup.rb +0 -224
  54. data/lib/metanorma/files_lookup_sectionsplit.rb +0 -84
  55. data/lib/metanorma/fontist_utils.rb +0 -122
  56. data/lib/metanorma/sectionsplit.rb +0 -216
  57. data/lib/metanorma/util.rb +0 -127
  58. data/lib/metanorma/worker_pool.rb +0 -29
@@ -1,257 +0,0 @@
1
- module Metanorma
2
- # XML collection renderer
3
- class CollectionRenderer
4
- # Resolves references to other files in the collection. Three routines:
5
- # 1. Eref to a document that has been split into multiple documents
6
- # (sectionsplit) are resolved to direct eref to the split document
7
- # 2. Indirect erefs to a file anchor in an unknwon file in the collection
8
- # (bibitem[@type = 'internal'] ) are resolved to direct eref to the
9
- # containing document
10
- # 3. Direct erefs to other files in collection
11
- # (repo(current-metanorma-collection/x) are resolved to hyperlinks
12
- # @param file [String] XML content
13
- # @param identifier [String] docid
14
- # @param internal_refs [Hash{String=>Hash{String=>String}] schema name to
15
- # anchor to filename
16
- # @return [String] XML content
17
- def update_xrefs(file, docid, internal_refs)
18
- xml, sso = update_xrefs_prep(file, docid)
19
- @nested || sso or Metanorma::XrefProcess::xref_process(xml, xml, nil, docid, @isodoc)
20
- @nested or update_indirect_refs_to_docs(xml, docid, internal_refs)
21
- @files.add_document_suffix(docid, xml)
22
- @nested or update_sectionsplit_refs_to_docs(xml, internal_refs)
23
- update_direct_refs_to_docs(xml, docid)
24
- hide_refs(xml)
25
- sso and eref2link(xml)
26
- svgmap_resolve(datauri_encode(xml), @files.get(docid, :ids))
27
- xml.to_xml
28
- end
29
-
30
- def update_xrefs_prep(file, docid)
31
- docxml = file.is_a?(String) ? Nokogiri::XML(file, &:huge) : file
32
- supply_repo_ids(docxml)
33
- sso = @files.get(docid, :sectionsplit_output)
34
- [docxml, sso]
35
- end
36
-
37
- def update_sectionsplit_refs_to_docs(docxml, internal_refs)
38
- Util::gather_citeases(docxml).each do |k, v|
39
- (@files.get(k) && @files.get(k, :sectionsplit)) or next
40
- opts = { key: @files.get(k, :indirect_key),
41
- source_suffix: docxml.root["document_suffix"],
42
- target_suffix: @files.get(k, :document_suffix) }
43
- refs = v.each_with_object({}) do |eref, m|
44
- update_sectionsplit_eref_to_doc(eref, internal_refs, m, opts)
45
- end
46
- add_hidden_bibliography(docxml, refs)
47
- end
48
- end
49
-
50
- def update_sectionsplit_eref_to_doc(eref, internal_refs, doclist, opts)
51
- a = eref.at(ns("./localityStack/locality[@type = 'anchor']/" \
52
- "referenceFrom")) or return
53
- doc = internal_refs[opts[:key]]["#{a.text}_#{opts[:target_suffix]}"]
54
- bibitemid = Metanorma::Utils::to_ncname("#{doc}_#{opts[:source_suffix]}")
55
- eref["bibitemid"] = bibitemid
56
- doclist[bibitemid] ||= doc
57
- doclist
58
- end
59
-
60
- def new_hidden_ref(xmldoc)
61
- ins = xmldoc.at(ns("bibliography")) or
62
- xmldoc.root << "<bibliography/>" and ins = xmldoc.at(ns("bibliography"))
63
- ins.at(ns("./referenced[@hidden = 'true']")) or
64
- ins.add_child("<references hidden='true' normative='false'/>").first
65
- end
66
-
67
- def add_hidden_bibliography(xmldoc, refs)
68
- ins = new_hidden_ref(xmldoc)
69
- refs.each do |k, v|
70
- url = @files.url(v, {})
71
- ins << <<~XML
72
- <bibitem id="#{k}">
73
- <docidentifier type="repository">current-metanorma-collection/#{v}</docidentifier>
74
- <uri type='citation'>#{url}</uri>
75
- </bibitem>
76
- XML
77
- end
78
- end
79
-
80
- def eref2link(docxml)
81
- isodoc = IsoDoc::PresentationXMLConvert.new({})
82
- isodoc.bibitem_lookup(docxml)
83
- isodoc.eref2link(docxml)
84
- end
85
-
86
- BIBITEM_NOT_REPO_XPATH = "//bibitem[not(ancestor::bibitem)]" \
87
- "[not(./docidentifier[@type = 'repository'])]".freeze
88
-
89
- def supply_repo_ids(doc)
90
- doc.xpath(ns(BIBITEM_NOT_REPO_XPATH)).each do |b|
91
- b.xpath(ns("./docidentifier")).each do |docid|
92
- id = @isodoc.docid_prefix(docid["type"], docid.children.to_xml)
93
- @files.get(id) or next
94
- @files.get(id, :indirect_key) and next # will resolve as indirect key
95
- docid.next = "<docidentifier type='repository'>" \
96
- "current-metanorma-collection/#{id}</docidentifier>"
97
- end
98
- end
99
- end
100
-
101
- def svgmap_resolve(docxml, ids)
102
- isodoc = IsoDoc::PresentationXMLConvert.new({})
103
- isodoc.bibitem_lookup(docxml)
104
- docxml.xpath(ns("//svgmap//eref")).each do |e|
105
- svgmap_resolve1(e, isodoc, docxml, ids)
106
- end
107
- Vectory::SvgMapping.new(docxml, "").call
108
- docxml.xpath(ns("//svgmap")).each { |s| isodoc.svgmap_extract(s) }
109
- end
110
-
111
- def svgmap_resolve1(eref, isodoc, _docxml, ids)
112
- href = isodoc.eref_target(eref) or return
113
- href == "##{eref['bibitemid']}" ||
114
- (href =~ /^#/ && !ids[href.sub(/^#/, "")]) and return
115
- eref["target"] = href.strip
116
- eref.name = "link"
117
- eref.elements&.remove
118
- end
119
-
120
- # repo(current-metanorma-collection/ISO 17301-1:2016)
121
- # replaced by bibdata of "ISO 17301-1:2016" in situ as bibitem.
122
- # Any erefs to that bibitem id are replaced with relative URL
123
- # Preferably with anchor, and is a job to realise dynamic lookup
124
- # of localities.
125
- def update_direct_refs_to_docs(docxml, identifier)
126
- erefs, erefs1 = update_direct_refs_to_docs_prep(docxml)
127
- docxml.xpath(ns("//bibitem")).each do |b|
128
- docid = b.at(ns("./docidentifier[@type = 'repository']")) or next
129
- strip_unresolved_repo_erefs(identifier, docid, erefs1, b) or next
130
- update_bibitem(b, identifier)
131
- docid = docid_to_citeas(b) or next
132
- erefs[docid] and update_anchors(b, docid, erefs[docid])
133
- end
134
- end
135
-
136
- def update_direct_refs_to_docs_prep(docxml)
137
- @ncnames = {}
138
- [Util::gather_citeases(docxml), Util::gather_bibitemids(docxml)]
139
- end
140
-
141
- # strip erefs if they are repository erefs, but do not point to a document
142
- # within the current collection. This can happen if a collection consists
143
- # of many documents, but not all are included in the current collection.
144
- # Do not do this if this is a sectionsplit collection or a nested manifest.
145
- # Return false if bibitem is not to be further processed
146
- def strip_unresolved_repo_erefs(_document_id, bib_docid, erefs, bibitem)
147
- %r{^current-metanorma-collection/(?!Missing:)}.match?(bib_docid.text) and
148
- return true
149
- @nested and return false
150
- erefs[bibitem["id"]]&.each { |x| x.parent and strip_eref(x) }
151
- false
152
- end
153
-
154
- # Resolve erefs to a container of ids in another doc,
155
- # to an anchor eref (direct link)
156
- def update_indirect_refs_to_docs(docxml, _docidentifier, internal_refs)
157
- bibitems, erefs = update_indirect_refs_to_docs_prep(docxml)
158
- internal_refs.each do |schema, ids|
159
- ids.each do |id, file|
160
- k = indirect_ref_key(schema, id, docxml)
161
- update_indirect_refs_to_docs1(docxml, k, file, bibitems, erefs)
162
- end
163
- end
164
- end
165
-
166
- def update_indirect_refs_to_docs_prep(docxml)
167
- bibitems = Util::gather_bibitems(docxml)
168
- erefs = Util::gather_bibitemids(docxml)
169
- @updated_anchors = {}
170
- [bibitems, erefs]
171
- end
172
-
173
- def indirect_ref_key(schema, id, docxml)
174
- /^#{schema}_/.match?(id) and return id
175
- ret = "#{schema}_#{id}"
176
- suffix = docxml.root["document_suffix"]
177
- (k = docxml.root["type"]) && k != schema && suffix and
178
- ret = "#{ret}_#{suffix}"
179
- ret
180
- end
181
-
182
- def update_indirect_refs_to_docs1(_docxml, key, file, bibitems, erefs)
183
- erefs[key]&.each do |e|
184
- e["citeas"] = file
185
- update_indirect_refs_to_docs_anchor(e, file)
186
- end
187
- update_indirect_refs_to_docs_docid(bibitems[key], file)
188
- end
189
-
190
- def update_indirect_refs_to_docs_anchor(eref, file)
191
- a = eref.at(ns(".//locality[@type = 'anchor']/referenceFrom")) or return
192
- suffix = file
193
- @files.get(file) && p = @files.get(file, :parentid) and
194
- suffix = "#{p}_#{suffix}"
195
- existing = a.text
196
- anchor = existing
197
- @files.url?(file) or
198
- anchor = Metanorma::Utils::to_ncname("#{anchor}_#{suffix}")
199
- @updated_anchors[existing] or a.children = anchor
200
- @updated_anchors[anchor] = true
201
- end
202
-
203
- def update_indirect_refs_to_docs_docid(bibitem, file)
204
- docid = bibitem&.at(ns("./docidentifier[@type = 'repository']")) or
205
- return
206
- docid.children = "current-metanorma-collection/#{file}"
207
- docid.previous =
208
- "<docidentifier type='metanorma-collection'>#{file}</docidentifier>"
209
- end
210
-
211
- # update crossrefences to other documents, to include
212
- # disambiguating document suffix on id
213
- def update_anchors(bib, docid, erefs)
214
- erefs.each do |e|
215
- if @files.get(docid) then update_anchor_loc(bib, e, docid)
216
- else
217
- msg = "<strong>** Unresolved reference to document #{docid} " \
218
- "from eref</strong>"
219
- e << msg
220
- strip_eref(e)
221
- @log&.add("Cross-References", e, msg)
222
- end
223
- end
224
- end
225
-
226
- def update_anchor_loc(bib, eref, docid)
227
- loc = eref.at(".//xmlns:locality[@type = 'anchor']") or
228
- return update_anchor_create_loc(bib, eref, docid)
229
- ref = loc.at("./xmlns:referenceFrom") or return
230
- anchor = suffix_anchor(ref, docid)
231
- a = @files.get(docid, :anchors) or return
232
- a.inject([]) do |m, (_, x)|
233
- m += x.values
234
- end.include?(anchor) or return
235
- ref.content = anchor
236
- end
237
-
238
- def suffix_anchor(ref, docid)
239
- @ncnames[docid] ||= Metanorma::Utils::to_ncname(docid)
240
- anchor = ref.text
241
- @files.url?(docid) or anchor = "#{@ncnames[docid]}_#{anchor}"
242
- anchor
243
- end
244
-
245
- # if there is a crossref to another document, with no anchor, retrieve the
246
- # anchor given the locality, and insert it into the crossref
247
- def update_anchor_create_loc(_bib, eref, docid)
248
- ins = eref.at(ns("./localityStack")) or return
249
- type = ins.at(ns("./locality/@type"))&.text
250
- type = "clause" if type == "annex"
251
- ref = ins.at(ns("./locality/referenceFrom"))&.text
252
- anchor = @files.get(docid, :anchors).dig(type, ref) or return
253
- ins << "<locality type='anchor'><referenceFrom>#{anchor.sub(/^_/, '')}" \
254
- "</referenceFrom></locality>"
255
- end
256
- end
257
- end
@@ -1,168 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "isodoc"
4
- require "metanorma-utils"
5
- require_relative "collection_fileparse"
6
-
7
- module Metanorma
8
- # XML collection renderer
9
- class CollectionRenderer
10
- # compile and output individual file in collection
11
- # warn "metanorma compile -x html #{f.path}"
12
- def file_compile(file, filename, identifier)
13
- return if @files.get(identifier, :sectionsplit) == "true"
14
-
15
- opts = {
16
- format: :asciidoc,
17
- extension_keys: @format,
18
- output_dir: @outdir,
19
- }.merge(compile_options_update(identifier))
20
-
21
- @compile.compile file, opts
22
- @files.set(identifier, :outputs, {})
23
- file_compile_formats(filename, identifier)
24
- end
25
-
26
- def compile_options_update(identifier)
27
- ret = @compile_options.dup
28
- Array(@directives).include?("presentation-xml") ||
29
- @files.get(identifier, :presentationxml) and
30
- ret.merge!(passthrough_presentation_xml: true)
31
- @files.get(identifier, :sectionsplit) == "true" and
32
- ret.merge!(sectionsplit: "true")
33
- @files.get(identifier, :bare) == true and
34
- ret.merge!(bare: true)
35
- ret
36
- end
37
-
38
- def file_compile_formats(filename, identifier)
39
- f = @files.get(identifier, :outputs)
40
- @format << :presentation if @format.include?(:pdf)
41
- @format.each do |e|
42
- ext = @compile.processor.output_formats[e]
43
- fn = File.basename(filename).sub(/(?<=\.)[^.]+$/, ext.to_s)
44
- (/html$/.match?(ext) && @files.get(identifier, :sectionsplit)) or
45
- f[e] = File.join(@outdir, fn)
46
- end
47
- @files.set(identifier, :outputs, f)
48
- end
49
-
50
- def copy_file_to_dest(identifier)
51
- dest = File.join(@outdir, @files.get(identifier, :out_path))
52
- FileUtils.mkdir_p(File.dirname(dest))
53
- FileUtils.cp @files.get(identifier, :ref), dest
54
- end
55
-
56
- # process each file in the collection
57
- # files are held in memory, and altered as postprocessing
58
- def files # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
59
- warn "\n\n\n\n\nRender Files: #{DateTime.now.strftime('%H:%M:%S')}"
60
- internal_refs = locate_internal_refs
61
- @files.keys.each_with_index do |ident, i|
62
- i.positive? && Array(@directives).include?("bare-after-first") and
63
- @compile_options.merge!(bare: true)
64
- if @files.get(ident, :attachment) then copy_file_to_dest(ident)
65
- else
66
- file, filename = @files.targetfile_id(ident, read: true)
67
- warn "\n\n\n\n\nProcess #{filename}: #{DateTime.now.strftime('%H:%M:%S')}"
68
- collection_xml = update_xrefs(file, ident, internal_refs)
69
- collection_filename = File.basename(filename, File.extname(filename))
70
- collection_xml_path = File.join(Dir.tmpdir,
71
- "#{collection_filename}.xml")
72
- File.write collection_xml_path, collection_xml, encoding: "UTF-8"
73
- file_compile(collection_xml_path, filename, ident)
74
- FileUtils.rm(collection_xml_path)
75
- end
76
- end
77
- end
78
-
79
- # gather internal bibitem references
80
- def gather_internal_refs
81
- @files.keys.each_with_object({}) do |i, refs|
82
- @files.get(i, :attachment) and next
83
- file, = @files.targetfile_id(i, read: true)
84
- gather_internal_refs1(file, i, refs)
85
- end
86
- end
87
-
88
- def gather_internal_refs1(file, ident, refs)
89
- f = Nokogiri::XML(file, &:huge)
90
- !@files.get(ident, :sectionsplit) and
91
- gather_internal_refs_indirect(f, refs)
92
- key = @files.get(ident, :indirect_key) and
93
- gather_internal_refs_sectionsplit(f, ident, key, refs)
94
- end
95
-
96
- def gather_internal_refs_indirect(doc, refs)
97
- doc.xpath(ns("//bibitem[@type = 'internal']/" \
98
- "docidentifier[@type = 'repository']")).each do |d|
99
- a = d.text.split(%r{/}, 2)
100
- a.size > 1 or next
101
- refs[a[0]] ||= {}
102
- refs[a[0]][a[1]] = false
103
- end
104
- end
105
-
106
- def gather_internal_refs_sectionsplit(_doc, ident, key, refs)
107
- refs[key] ||= {}
108
- @files.get(ident, :ids).each_key do |k|
109
- refs[key][k] = false
110
- end
111
- end
112
-
113
- def populate_internal_refs(refs)
114
- @files.keys.reject do |k|
115
- @files.get(k, :attachment) || @files.get(k, :sectionsplit)
116
- end.each do |ident|
117
- locate_internal_refs1(refs, ident, @isodoc.docid_prefix("", ident.dup))
118
- end
119
- refs
120
- end
121
-
122
- # resolve file location for the target of each internal reference
123
- def locate_internal_refs
124
- warn "\n\n\n\n\nInternal Refs: #{DateTime.now.strftime('%H:%M:%S')}"
125
- refs = populate_internal_refs(gather_internal_refs)
126
- refs.each do |schema, ids|
127
- ids.each do |id, key|
128
- key and next
129
- refs[schema][id] = "Missing:#{schema}:#{id}"
130
- @log&.add("Cross-References", nil, refs[schema][id])
131
- end
132
- end
133
- refs
134
- end
135
-
136
- def locate_internal_refs1(refs, identifier, ident)
137
- file, = @files.targetfile_id(ident, read: true)
138
- t = locate_internal_refs1_prep(file)
139
- refs.each do |schema, ids|
140
- ids.keys.select { |id| t[id] }.each do |id|
141
- t[id].at("./ancestor-or-self::*[@type = '#{schema}']") and
142
- refs[schema][id] = identifier
143
- end
144
- end
145
- end
146
-
147
- def locate_internal_refs1_prep(file)
148
- xml = Nokogiri::XML(file, &:huge)
149
- r = xml.root["document_suffix"]
150
- xml.xpath("//*[@id]").each_with_object({}) do |i, x|
151
- /^semantic_/.match?(i.name) and next
152
- x[i["id"]] = i
153
- r and x[i["id"].sub(/_#{r}$/, "")] = i
154
- end
155
- end
156
-
157
- def update_bibitem(bib, identifier)
158
- docid = get_bibitem_docid(bib, identifier) or return
159
- newbib = dup_bibitem(docid, bib)
160
- url = @files.url(docid, relative: true,
161
- doc: !@files.get(docid, :attachment))
162
- dest = newbib.at("./docidentifier") || newbib.at(ns("./docidentifier"))
163
- dest or dest = newbib.elements[-1]
164
- dest.previous = "<uri type='citation'>#{url}</uri>"
165
- bib.replace(newbib)
166
- end
167
- end
168
- end
@@ -1,168 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "util"
4
-
5
- module Metanorma
6
- # Metanorma collection's manifest
7
- class CollectionManifest
8
- # @return [Metanorma::Collection]
9
- attr_reader :collection
10
-
11
- # @param level [String]
12
- # @param title [String, nil]
13
- # @param docref [Array<Hash{String=>String}>]
14
- # @param manifest [Array<Metanorma::CollectionManifest>]
15
- def initialize(level, title = nil, docref = [], manifest = [])
16
- @level = level
17
- @title = title
18
- @docref = docref
19
- @manifest = manifest
20
- @disambig = Util::DisambigFiles.new
21
- end
22
-
23
- class << self
24
- # @param mnf [Nokogiri::XML::Element]
25
- # @return [Metanorma::CollectionManifest]
26
- def from_yaml(mnf)
27
- manifest = RelatonBib.array(mnf["manifest"]).map do |m|
28
- from_yaml m
29
- end
30
- docref = RelatonBib.array mnf["docref"]
31
- new(mnf["level"], mnf["title"], parse_docrefs_yaml(docref), manifest)
32
- end
33
-
34
- # @param mnf [Nokogiri::XML::Element]
35
- # @return [Metanorma::CollectionManifest]
36
- def from_xml(mnf)
37
- level = mnf.at("level").text
38
- title = mnf.at("title")&.text
39
- manifest = mnf.xpath("xmlns:manifest").map { |m| from_xml(m) }
40
- new(level, title, parse_docrefs_xml(mnf), manifest)
41
- end
42
-
43
- private
44
-
45
- def parse_docrefs_yaml(docrefs)
46
- docrefs.map do |dr|
47
- h = {}
48
- h["identifier"] = dr["identifier"] ||
49
- UUIDTools::UUID.random_create.to_s
50
- dr["manifest"] and h["manifest"] = from_yaml(dr["manifest"].first)
51
- %w(fileref url attachment sectionsplit index presentation-xml).each do |k|
52
- dr.has_key?(k) and h[k] = dr[k]
53
- end
54
- h
55
- end
56
- end
57
-
58
- # @param mnf [Nokogiri::XML::Element]
59
- # @return [Hash{String=>String}]
60
- def parse_docrefs_xml(mnf)
61
- mnf.xpath("xmlns:docref").map do |dr|
62
- h = { "identifier" => parse_docrefs_xml_id(dr) }
63
- %i(fileref url attachment sectionsplit index).each do |s|
64
- h[s.to_s] = dr[s] if dr[s]
65
- end
66
- m = dr.at("manifest") and h["manifest"] = from_xml(m)
67
- h["presentation-xml"] = dr[:presentationxml] if dr[:presentationxml]
68
- h
69
- end
70
- end
71
-
72
- def parse_docrefs_xml_id(docref)
73
- if i = docref.at("identifier")
74
- i.children.to_xml
75
- else UUIDTools::UUID.random_create
76
- end
77
- end
78
- end
79
-
80
- # @param col [Metanorma::Collection]
81
- def collection=(col)
82
- @collection = col
83
- @manifest.each { |mnf| mnf.collection = col }
84
- end
85
-
86
- # @param dir [String] path to collection
87
- # @return [Hash<String, Metanorma::Document>]
88
- def documents(dir = "")
89
- docs = @docref.each_with_object({}) do |dr, m|
90
- if dr["fileref"]
91
- m[Util::key dr["identifier"]] = documents_add(dir, dr)
92
- elsif dr["manifest"]
93
- m.merge! dr["manifest"].documents(dir)
94
- end
95
- m
96
- end
97
- @manifest.reduce(docs) { |mem, mnf| mem.merge mnf.documents(dir) }
98
- end
99
-
100
- def documents_add(dir, docref)
101
- Document.parse_file(
102
- Util::rel_path_resolve(dir, docref["fileref"]),
103
- docref["attachment"], docref["identifier"], docref["index"]
104
- )
105
- end
106
-
107
- # @param builder [Nokogiri::XML::Builder]
108
- def to_xml(builder)
109
- builder.manifest do |b|
110
- b.level @level
111
- b.title @title if @title
112
- docref_to_xml b
113
- @manifest&.each { |m| m.to_xml b }
114
- end
115
- end
116
-
117
- # @return [Array<Hash{String=>String}>]
118
- def docrefs
119
- return @docrefs if @docrefs
120
-
121
- drfs = @docref.map { |dr| dr }
122
- @manifest.reduce(drfs) { |mem, mnf| mem + mnf.docrefs }
123
- end
124
-
125
- def docref_by_id(docid)
126
- refs = docrefs
127
- dref = refs.detect { |k| k["identifier"] == docid }
128
- dref || docrefs.detect { |k| /^#{k['identifier']}/ =~ docid }
129
- end
130
-
131
- private
132
-
133
- # @param builder [Nokogiri::XML::Builder]
134
- def docref_to_xml(builder)
135
- @disambig = Util::DisambigFiles.new
136
- @docref.each do |dr|
137
- drf = builder.docref do |b|
138
- b.identifier { |i| i << dr["identifier"] }
139
- !dr["attachment"] && !dr["sectionsplit"] && @collection &&
140
- d = @collection.bibdatas[Util::key dr["identifier"]] and
141
- b.parent.add_child(d.bibitem.to_xml(bibdata: true))
142
- m = dr["manifest"] and m.to_xml b
143
- end
144
- docref_to_xml_attrs(drf, dr)
145
- end
146
- end
147
-
148
- def docref_to_xml_attrs(elem, docref)
149
- f = docref["fileref"] and elem[:fileref] = @disambig.strip_root(f)
150
- %i(attachment sectionsplit url).each do |i|
151
- elem[i] = docref[i.to_s] if docref[i.to_s]
152
- end
153
- elem[:index] = docref.has_key?("index") ? docref["index"] : "true"
154
- elem[:presentationxml] = "true" if docref["presentation-xml"] &&
155
- [true, "true"].include?(docref["presentation-xml"])
156
- docref_to_xml_attrs_id(elem, docref)
157
- end
158
-
159
- def docref_to_xml_attrs_id(elem, docref)
160
- if collection&.directives&.include?("documents-inline")
161
- id = collection.documents.find_index do |k, _|
162
- k == docref["identifier"]
163
- end
164
- id and elem[:id] = format("doc%<index>09d", index: id)
165
- end
166
- end
167
- end
168
- end