metanorma 1.7.7 → 2.0.0

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 (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