Class: Metanorma::CollectionRenderer
- Inherits:
-
Object
- Object
- Metanorma::CollectionRenderer
- Defined in:
- lib/metanorma/collection_renderer.rb,
lib/metanorma/collection_fileparse.rb,
lib/metanorma/collection_fileprocess.rb,
lib/metanorma/collection_render_utils.rb
Overview
XML collection renderer
Defined Under Namespace
Classes: Dummy, PdfOptionsNode
Constant Summary collapse
- FORMATS =
%i[html xml doc pdf].freeze
Instance Attribute Summary collapse
-
#compile ⇒ Object
readonly
Returns the value of attribute compile.
-
#compile_options ⇒ Object
readonly
Returns the value of attribute compile_options.
-
#documents ⇒ Object
readonly
Returns the value of attribute documents.
-
#isodoc ⇒ Object
Returns the value of attribute isodoc.
-
#nested ⇒ Object
Returns the value of attribute nested.
-
#xml ⇒ Object
readonly
Returns the value of attribute xml.
Class Method Summary collapse
Instance Method Summary collapse
- #add_hidden_bibliography(xmldoc, refs) ⇒ Object
- #collect_erefs(docxml) ⇒ Object
- #compile_options_update(identifier) ⇒ Object
- #concatenate(col, options) ⇒ Object
- #concatenate1(out, ext) ⇒ Object
- #copy_file_to_dest(identifier) ⇒ Object
-
#coverpage ⇒ Object
populate liquid template of ARGV with metadata extracted from collection manifest.
- #dir_name_cleanse(name) ⇒ Object
- #docid_to_citeas(bib) ⇒ Object
- #docrefs(elm, builder) ⇒ Object
-
#doctype ⇒ Object
infer the flavour from the first document identifier; relaton does that.
- #dup_bibitem(docid, bib) ⇒ Object
- #eref2link(docxml) ⇒ Object
-
#file_compile(file, filename, identifier) ⇒ Object
compile and output individual file in collection warn “metanorma compile -x html #ff.path”.
- #file_compile_formats(filename, identifier) ⇒ Object
-
#files ⇒ Object
process each file in the collection files are held in memory, and altered as postprocessing.
- #flush_files ⇒ Object
-
#gather_internal_refs ⇒ Object
gather internal bibitem references.
- #gather_internal_refs1(file, ident, refs) ⇒ Object
- #gather_internal_refs_indirect(doc, refs) ⇒ Object
- #gather_internal_refs_sectionsplit(_doc, ident, key, refs) ⇒ Object
- #get_bibitem_docid(bib, identifier) ⇒ Object
- #hide_refs(docxml) ⇒ Object
- #index_link(docref, ident) ⇒ Object
-
#index_object(elm) ⇒ Object
object to construct navigation out of in Liquid.
-
#indexfile(elm) ⇒ String
single level navigation list, with hierarchical nesting.
-
#indexfile_docref(elm, builder) ⇒ Object
uses the identifier to label documents; other attributes (title) can be looked up in @files[:bibdata].
- #indexfile_title(elm) ⇒ String
- #indirect_ref_key(schema, id, docxml) ⇒ Object
-
#initialize(collection, folder, options = {}) ⇒ CollectionRenderer
constructor
This is only going to render the HTML collection We presuppose that the bibdata of the document is equivalent to that of the collection, and that the flavour gem can sensibly process it.
- #liquid_docrefs ⇒ Object
-
#locate_internal_refs ⇒ Object
resolve file location for the target of each internal reference.
- #locate_internal_refs1(refs, identifier, ident) ⇒ Object
- #locate_internal_refs1_prep(ident) ⇒ Object
- #new_hidden_ref(xmldoc) ⇒ Object
- #populate_internal_refs(refs) ⇒ Object
- #strip_eref(eref) ⇒ Object
-
#strip_unresolved_repo_erefs(_document_id, bib_docid, erefs, bibitem) ⇒ Object
strip erefs if they are repository erefs, but do not point to a document within the current collection.
- #supply_repo_ids(doc) ⇒ Object
- #svgmap_resolve(docxml, ids) ⇒ Object
- #svgmap_resolve1(eref, isodoc, _docxml, ids) ⇒ Object
-
#update_anchor_create_loc(_bib, eref, docid) ⇒ Object
if there is a crossref to another document, with no anchor, retrieve the anchor given the locality, and insert it into the crossref.
- #update_anchor_loc(bib, eref, docid) ⇒ Object
-
#update_anchors(bib, docid, erefs) ⇒ Object
update crossrefences to other documents, to include disambiguating document suffix on id.
- #update_bibitem(bib, identifier) ⇒ Object
-
#update_direct_refs_to_docs(docxml, identifier) ⇒ Object
repo(current-metanorma-collection/ISO 17301-1:2016) replaced by bibdata of “ISO 17301-1:2016” in situ as bibitem.
- #update_direct_refs_to_docs_prep(docxml) ⇒ Object
-
#update_indirect_refs_to_docs(docxml, _docidentifier, internal_refs) ⇒ Object
Resolve erefs to a container of ids in another doc, to an anchor eref (direct link).
- #update_indirect_refs_to_docs1(_docxml, key, file, bibitems, erefs) ⇒ Object
- #update_indirect_refs_to_docs_anchor(eref, file) ⇒ Object
- #update_indirect_refs_to_docs_docid(bibitem, file) ⇒ Object
- #update_indirect_refs_to_docs_prep(docxml) ⇒ Object
- #update_sectionsplit_eref_to_doc(eref, internal_refs, doclist, opts) ⇒ Object
- #update_sectionsplit_refs_to_docs(docxml, internal_refs) ⇒ Object
-
#update_xrefs(file, docid, internal_refs) ⇒ String
Resolves references to other files in the collection.
Constructor Details
#initialize(collection, folder, options = {}) ⇒ CollectionRenderer
This is only going to render the HTML collection We presuppose that the bibdata of the document is equivalent to that of the collection, and that the flavour gem can sensibly process it. We may need to enhance metadata in the flavour gems isodoc/metadata.rb with collection metadata
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/metanorma/collection_renderer.rb', line 29 def initialize(collection, folder, = {}) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength @xml = Nokogiri::XML collection.to_xml # @xml is the collection manifest @lang = @xml.at("//xmlns:bibdata/xmlns:language")&.text || "en" @script = @xml.at("//xmlns:bibdata/xmlns:script")&.text || "Latn" @locale = @xml.at("//xmlns:bibdata/xmlns:locale")&.text @doctype = doctype require "metanorma-#{@doctype}" @isodoc = isodoc_create # output processor for flavour @outdir = dir_name_cleanse([:output_folder]) @coverpage = [:coverpage] || collection.coverpage @format = Util.sort_extensions_execution([:format]) @compile_options = [:compile] || {} @compile_options[:no_install_fonts] = true if [:no_install_fonts] @log = [:log] @documents = collection.documents @bibdata = collection.documents @directives = collection.directives @disambig = Util::DisambigFiles.new @compile = Compile.new @c = HTMLEntities.new @files_to_delete = [] @nested = [:nested] # if false, this is the root instance of Renderer # if true, then this is not the last time Renderer will be run # (e.g. this is sectionsplit) # list of files in the collection @files = Metanorma::FileLookup.new(folder, self) @files.add_section_split isodoc_populate create_non_existing_directory(@outdir) end |
Instance Attribute Details
#compile ⇒ Object (readonly)
Returns the value of attribute compile.
15 16 17 |
# File 'lib/metanorma/collection_renderer.rb', line 15 def compile @compile end |
#compile_options ⇒ Object (readonly)
Returns the value of attribute compile_options.
15 16 17 |
# File 'lib/metanorma/collection_renderer.rb', line 15 def @compile_options end |
#documents ⇒ Object (readonly)
Returns the value of attribute documents.
15 16 17 |
# File 'lib/metanorma/collection_renderer.rb', line 15 def documents @documents end |
#isodoc ⇒ Object
Returns the value of attribute isodoc.
14 15 16 |
# File 'lib/metanorma/collection_renderer.rb', line 14 def isodoc @isodoc end |
#nested ⇒ Object
Returns the value of attribute nested.
14 15 16 |
# File 'lib/metanorma/collection_renderer.rb', line 14 def nested @nested end |
#xml ⇒ Object (readonly)
Returns the value of attribute xml.
15 16 17 |
# File 'lib/metanorma/collection_renderer.rb', line 15 def xml @xml end |
Class Method Details
.render(col, options = {}) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/metanorma/collection_renderer.rb', line 74 def self.render(col, = {}) folder = File.dirname col.file warn "\n\n\n\n\nRender Init: #{DateTime.now.strftime('%H:%M:%S')}" cr = new(col, folder, ) warn "\n\n\n\n\nRender Files: #{DateTime.now.strftime('%H:%M:%S')}" cr.files warn "\n\n\n\n\nConcatenate: #{DateTime.now.strftime('%H:%M:%S')}" cr.concatenate(col, ) warn "\n\n\n\n\nCoverpage: #{DateTime.now.strftime('%H:%M:%S')}" cr.coverpage if [:format]&.include?(:html) warn "\n\n\n\n\nDone: #{DateTime.now.strftime('%H:%M:%S')}" cr.flush_files cr end |
Instance Method Details
#add_hidden_bibliography(xmldoc, refs) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/metanorma/collection_fileparse.rb', line 71 def add_hidden_bibliography(xmldoc, refs) ins = new_hidden_ref(xmldoc) refs.each do |k, v| _, url = @files.targetfile_id(v, {}) ins << <<~XML <bibitem id="#{k}"> <docidentifier type="repository">current-metanorma-collection/#{v}</docidentifier> <uri type='citation'>#{url}</uri> </bibitem> XML end end |
#collect_erefs(docxml) ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/metanorma/collection_render_utils.rb', line 52 def collect_erefs(docxml) docxml.xpath(ns("//eref")) .each_with_object({ citeas: {}, bibitemid: {} }) do |i, m| m[:citeas][i["citeas"]] = true m[:bibitemid][i["bibitemid"]] = true end end |
#compile_options_update(identifier) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/metanorma/collection_fileprocess.rb', line 26 def (identifier) ret = @compile_options.dup Array(@directives).include?("presentation-xml") || @files.get(identifier, :presentationxml) and ret.merge!(passthrough_presentation_xml: true) @files.get(identifier, :sectionsplit) == "true" and ret.merge!(sectionsplit: "true") @files.get(identifier, :bare) == true and ret.merge!(bare: true) ret end |
#concatenate(col, options) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/metanorma/collection_renderer.rb', line 89 def concatenate(col, ) [:format] << :presentation if [:format].include?(:pdf) [:format].uniq.each do |e| %i(presentation xml).include?(e) or next ext = e == :presentation ? "presentation.xml" : e.to_s File.open(File.join(@outdir, "collection.#{ext}"), "w:UTF-8") do |f| f.write(concatenate1(col.clone, e).to_xml) end end [:format].include?(:pdf) and pdfconv.convert(File.join(@outdir, "collection.presentation.xml")) end |
#concatenate1(out, ext) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/metanorma/collection_renderer.rb', line 102 def concatenate1(out, ext) out.directives << "documents-inline" out.bibdatas.each_key do |ident| id = @isodoc.docid_prefix(nil, ident.dup) @files.get(id, :attachment) || @files.get(id, :outputs).nil? and next out.documents[id] = Metanorma::Document.raw_file(@files.get(id, :outputs)[ext]) end out end |
#copy_file_to_dest(identifier) ⇒ Object
50 51 52 53 54 |
# File 'lib/metanorma/collection_fileprocess.rb', line 50 def copy_file_to_dest(identifier) dest = File.join(@outdir, @files.get(identifier, :out_path)) FileUtils.mkdir_p(File.dirname(dest)) FileUtils.cp @files.get(identifier, :ref), dest end |
#coverpage ⇒ Object
populate liquid template of ARGV with metadata extracted from collection manifest
128 129 130 131 132 133 |
# File 'lib/metanorma/collection_renderer.rb', line 128 def coverpage @coverpage or return File.open(File.join(@outdir, "index.html"), "w:UTF-8") do |f| f.write @isodoc.populate_template(File.read(@coverpage)) end end |
#dir_name_cleanse(name) ⇒ Object
3 4 5 6 7 8 9 10 11 |
# File 'lib/metanorma/collection_render_utils.rb', line 3 def dir_name_cleanse(name) path = Pathname.new(name) clean_regex = /[<>:"|?*]/ fallback_sym = "_" return name.gsub(clean_regex, fallback_sym) unless path.absolute? File.join(path.dirname, path.basename.to_s.gsub(clean_regex, fallback_sym)) end |
#docid_to_citeas(bib) ⇒ Object
46 47 48 49 50 |
# File 'lib/metanorma/collection_render_utils.rb', line 46 def docid_to_citeas(bib) docid = bib.at(ns("./docidentifier[@primary = 'true']")) || bib.at(ns("./docidentifier")) or return docid_prefix(docid) end |
#docrefs(elm, builder) ⇒ Object
154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/metanorma/collection_renderer.rb', line 154 def docrefs(elm, builder) elm.xpath(ns("./docref[@index = 'true']")).each do |d| ident = d.at(ns("./identifier")).children.to_xml ident = @c.decode(@isodoc.docid_prefix(nil, ident)) builder.li do |li| li.a href: index_link(d, ident) do |a| a << ident.split(/([<>&])/).map do |x| /[<>&]/.match?(x) ? x : @c.encode(x, :hexadecimal) end.join end end end end |
#doctype ⇒ Object
infer the flavour from the first document identifier; relaton does that
115 116 117 118 119 120 121 122 123 124 |
# File 'lib/metanorma/collection_renderer.rb', line 115 def doctype if (docid = @xml.at("//xmlns:bibdata/xmlns:docidentifier/@type")&.text) dt = docid.downcase elsif (docid = @xml.at("//xmlns:bibdata/xmlns:docidentifier")&.text) dt = docid.sub(/\s.*$/, "").lowercase else return "standoc" end @registry = Metanorma::Registry.instance @registry.alias(dt.to_sym)&.to_s || dt end |
#dup_bibitem(docid, bib) ⇒ Object
13 14 15 16 17 18 19 20 |
# File 'lib/metanorma/collection_render_utils.rb', line 13 def dup_bibitem(docid, bib) newbib = @files.get(docid, :bibdata).dup newbib.name = "bibitem" newbib["hidden"] = "true" newbib&.at("./*[local-name() = 'ext']")&.remove newbib["id"] = bib["id"] newbib end |
#eref2link(docxml) ⇒ Object
84 85 86 87 88 |
# File 'lib/metanorma/collection_fileparse.rb', line 84 def eref2link(docxml) isodoc = IsoDoc::PresentationXMLConvert.new({}) isodoc.bibitem_lookup(docxml) isodoc.eref2link(docxml) end |
#file_compile(file, filename, identifier) ⇒ Object
compile and output individual file in collection warn “metanorma compile -x html #Metanorma::CollectionRenderer.ff.path”
12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/metanorma/collection_fileprocess.rb', line 12 def file_compile(file, filename, identifier) return if @files.get(identifier, :sectionsplit) == "true" opts = { format: :asciidoc, extension_keys: @format, output_dir: @outdir, }.merge((identifier)) @compile.compile file, opts @files.set(identifier, :outputs, {}) file_compile_formats(filename, identifier) end |
#file_compile_formats(filename, identifier) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/metanorma/collection_fileprocess.rb', line 38 def file_compile_formats(filename, identifier) f = @files.get(identifier, :outputs) @format << :presentation if @format.include?(:pdf) @format.each do |e| ext = @compile.processor.output_formats[e] fn = File.basename(filename).sub(/(?<=\.)[^.]+$/, ext.to_s) (/html$/.match?(ext) && @files.get(identifier, :sectionsplit)) or f[e] = File.join(@outdir, fn) end @files.set(identifier, :outputs, f) end |
#files ⇒ Object
process each file in the collection files are held in memory, and altered as postprocessing
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/metanorma/collection_fileprocess.rb', line 58 def files # rubocop:disable Metrics/AbcSize, Metrics/MethodLength warn "\n\n\n\n\nInternal Refs: #{DateTime.now.strftime('%H:%M:%S')}" internal_refs = locate_internal_refs @files.keys.each_with_index do |ident, i| i.positive? && Array(@directives).include?("bare-after-first") and @compile_options.merge!(bare: true) if @files.get(ident, :attachment) then copy_file_to_dest(ident) else file, filename = @files.targetfile_id(ident, read: true) warn "\n\n\n\n\nProcess #{filename}: #{DateTime.now.strftime('%H:%M:%S')}" collection_xml = update_xrefs(file, ident, internal_refs) collection_filename = File.basename(filename, File.extname(filename)) collection_xml_path = File.join(Dir.tmpdir, "#{collection_filename}.xml") File.write collection_xml_path, collection_xml, encoding: "UTF-8" file_compile(collection_xml_path, filename, ident) FileUtils.rm(collection_xml_path) end end end |
#flush_files ⇒ Object
63 64 65 66 67 |
# File 'lib/metanorma/collection_renderer.rb', line 63 def flush_files warn @files.files_to_delete @files.files_to_delete.each { |f| FileUtils.rm_f(f) } @files_to_delete.each { |f| FileUtils.rm_f(f) } end |
#gather_internal_refs ⇒ Object
gather internal bibitem references
80 81 82 83 84 85 86 |
# File 'lib/metanorma/collection_fileprocess.rb', line 80 def gather_internal_refs @files.keys.each_with_object({}) do |i, refs| @files.get(i, :attachment) and next file, = @files.targetfile_id(i, read: true) gather_internal_refs1(file, i, refs) end end |
#gather_internal_refs1(file, ident, refs) ⇒ Object
88 89 90 91 92 93 94 |
# File 'lib/metanorma/collection_fileprocess.rb', line 88 def gather_internal_refs1(file, ident, refs) f = Nokogiri::XML(file, &:huge) !@files.get(ident, :sectionsplit) and gather_internal_refs_indirect(f, refs) key = @files.get(ident, :indirect_key) and gather_internal_refs_sectionsplit(f, ident, key, refs) end |
#gather_internal_refs_indirect(doc, refs) ⇒ Object
96 97 98 99 100 101 102 103 104 |
# File 'lib/metanorma/collection_fileprocess.rb', line 96 def gather_internal_refs_indirect(doc, refs) doc.xpath(ns("//bibitem[@type = 'internal']/" \ "docidentifier[@type = 'repository']")).each do |d| a = d.text.split(%r{/}, 2) a.size > 1 or next refs[a[0]] ||= {} refs[a[0]][a[1]] = false end end |
#gather_internal_refs_sectionsplit(_doc, ident, key, refs) ⇒ Object
106 107 108 109 110 111 |
# File 'lib/metanorma/collection_fileprocess.rb', line 106 def gather_internal_refs_sectionsplit(_doc, ident, key, refs) refs[key] ||= {} @files.get(ident, :ids).each_key do |k| refs[key][k] = false end end |
#get_bibitem_docid(bib, identifier) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/metanorma/collection_render_utils.rb', line 22 def get_bibitem_docid(bib, identifier) # IDs for repo references are untyped by default docid = bib.at(ns("./docidentifier[not(@type)]")) || bib.at(ns("./docidentifier")) docid &&= docid_prefix(docid) if @files.get(docid) then docid else fail_update_bibitem(docid, identifier) nil end end |
#hide_refs(docxml) ⇒ Object
34 35 36 37 38 39 |
# File 'lib/metanorma/collection_render_utils.rb', line 34 def hide_refs(docxml) docxml.xpath(ns("//references[bibitem][not(./bibitem[not(@hidden) or " \ "@hidden = 'false'])]")).each do |f| f["hidden"] = "true" end end |
#index_link(docref, ident) ⇒ Object
168 169 170 171 172 173 |
# File 'lib/metanorma/collection_renderer.rb', line 168 def index_link(docref, ident) if docref["fileref"] @files.get(ident, :out_path).sub(/\.xml$/, ".html") else "#{docref['id']}.html" end end |
#index_object(elm) ⇒ Object
object to construct navigation out of in Liquid
192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/metanorma/collection_renderer.rb', line 192 def index_object(elm) c = elm.xpath(ns("./manifest")).each_with_object([]) do |d, b| b << index_object(d) end c.empty? and c = nil r = Nokogiri::HTML::Builder.new do |b| indexfile_docref(elm, b) end r &&= r.doc.root&.to_html&.gsub("\n", " ") { title: indexfile_title(elm), docrefs: r, children: c }.compact end |
#indexfile(elm) ⇒ String
single level navigation list, with hierarchical nesting
179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/metanorma/collection_renderer.rb', line 179 def indexfile(elm) Nokogiri::HTML::Builder.new do |b| b.ul do b.li indexfile_title(elm) indexfile_docref(elm, b) elm.xpath(ns("./manifest")).each do |d| b << indexfile(d) end end end.doc.root.to_html end |
#indexfile_docref(elm, builder) ⇒ Object
uses the identifier to label documents; other attributes (title) can be looked up in @files[:bibdata]
146 147 148 149 150 |
# File 'lib/metanorma/collection_renderer.rb', line 146 def indexfile_docref(elm, builder) return "" unless elm.at(ns("./docref[@index = 'true']")) builder.ul { |b| docrefs(elm, b) } end |
#indexfile_title(elm) ⇒ String
137 138 139 |
# File 'lib/metanorma/collection_renderer.rb', line 137 def indexfile_title(elm) elm.at(ns("./title"))&.text end |
#indirect_ref_key(schema, id, docxml) ⇒ Object
178 179 180 181 182 183 184 |
# File 'lib/metanorma/collection_fileparse.rb', line 178 def indirect_ref_key(schema, id, docxml) /^#{schema}_/.match?(id) and return id ret = "#{schema}_#{id}" (k = docxml.root["type"]) && k != schema and ret = "#{ret}_#{docxml.root['document_suffix']}" ret end |
#liquid_docrefs ⇒ Object
205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/metanorma/collection_renderer.rb', line 205 def liquid_docrefs @xml.xpath(ns("//docref[@index = 'true']")).each_with_object([]) do |d, m| ident = d.at(ns("./identifier")).children.to_xml ident = @c.decode(@isodoc.docid_prefix(nil, ident)) title = d.at(ns("./bibdata/title[@type = 'main']")) || d.at(ns("./bibdata/title")) || d.at(ns("./title")) m << { "identifier" => ident, "file" => index_link(d, ident), "title" => title&.children&.to_xml, "level" => d.at(ns("./level"))&.text } end end |
#locate_internal_refs ⇒ Object
resolve file location for the target of each internal reference
123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/metanorma/collection_fileprocess.rb', line 123 def locate_internal_refs refs = populate_internal_refs(gather_internal_refs) refs.each do |schema, ids| ids.each do |id, key| key and next refs[schema][id] = "Missing:#{schema}:#{id}" @log&.add("Cross-References", nil, refs[schema][id]) end end refs end |
#locate_internal_refs1(refs, identifier, ident) ⇒ Object
135 136 137 138 139 140 141 142 143 |
# File 'lib/metanorma/collection_fileprocess.rb', line 135 def locate_internal_refs1(refs, identifier, ident) t = locate_internal_refs1_prep(ident) refs.each do |schema, ids| ids.keys.select { |id| t[id] }.each do |id| t[id].at("./ancestor-or-self::*[@type = '#{schema}']") and refs[schema][id] = identifier end end end |
#locate_internal_refs1_prep(ident) ⇒ Object
145 146 147 148 149 150 151 152 153 154 |
# File 'lib/metanorma/collection_fileprocess.rb', line 145 def locate_internal_refs1_prep(ident) file, = @files.targetfile_id(ident, read: true) xml = Nokogiri::XML(file, &:huge) r = xml.root["document_suffix"] xml.xpath("//*[@id]").each_with_object({}) do |i, x| /^semantic_/.match?(i.name) and next x[i["id"]] = i r and x[i["id"].sub(/_#{r}$/, "")] = i end end |
#new_hidden_ref(xmldoc) ⇒ Object
64 65 66 67 68 69 |
# File 'lib/metanorma/collection_fileparse.rb', line 64 def new_hidden_ref(xmldoc) ins = xmldoc.at(ns("bibliography")) or xmldoc.root << "<bibliography/>" and ins = xmldoc.at(ns("bibliography")) ins.at(ns("./referenced[@hidden = 'true']")) or ins.add_child("<references hidden='true' normative='false'/>").first end |
#populate_internal_refs(refs) ⇒ Object
113 114 115 116 117 118 119 120 |
# File 'lib/metanorma/collection_fileprocess.rb', line 113 def populate_internal_refs(refs) @files.keys.reject do |k| @files.get(k, :attachment) || @files.get(k, :sectionsplit) end.each do |ident| locate_internal_refs1(refs, ident, @isodoc.docid_prefix("", ident.dup)) end refs end |
#strip_eref(eref) ⇒ Object
41 42 43 44 |
# File 'lib/metanorma/collection_render_utils.rb', line 41 def strip_eref(eref) eref.xpath(ns("./locality | ./localityStack")).each(&:remove) eref.replace(eref.children) end |
#strip_unresolved_repo_erefs(_document_id, bib_docid, erefs, bibitem) ⇒ Object
strip erefs if they are repository erefs, but do not point to a document within the current collection. This can happen if a collection consists of many documents, but not all are included in the current collection. Do not do this if this is a sectionsplit collection or a nested manifest. Return false if bibitem is not to be further processed
150 151 152 153 154 155 156 |
# File 'lib/metanorma/collection_fileparse.rb', line 150 def strip_unresolved_repo_erefs(_document_id, bib_docid, erefs, bibitem) %r{^current-metanorma-collection/(?!Missing:)}.match?(bib_docid.text) and return true @nested and return false erefs[bibitem["id"]]&.each { |x| x.parent and strip_eref(x) } false end |
#supply_repo_ids(doc) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/metanorma/collection_fileparse.rb', line 90 def supply_repo_ids(doc) doc.xpath( ns("//bibitem[not(ancestor::bibitem)]" \ "[not(./docidentifier[@type = 'repository'])]"), ).each do |b| b.xpath(ns("./docidentifier")).each do |docid| id = @isodoc.docid_prefix(docid["type"], docid.children.to_xml) @files.get(id) or next @files.get(id, :indirect_key) and next # will resolve as indirect key docid.next = "<docidentifier type='repository'>" \ "current-metanorma-collection/#{id}</docidentifier>" end end end |
#svgmap_resolve(docxml, ids) ⇒ Object
105 106 107 108 109 110 111 112 113 |
# File 'lib/metanorma/collection_fileparse.rb', line 105 def svgmap_resolve(docxml, ids) isodoc = IsoDoc::PresentationXMLConvert.new({}) isodoc.bibitem_lookup(docxml) docxml.xpath(ns("//svgmap//eref")).each do |e| svgmap_resolve1(e, isodoc, docxml, ids) end Metanorma::Utils::svgmap_rewrite(docxml, "") docxml.xpath(ns("//svgmap")).each { |s| isodoc.svgmap_extract(s) } end |
#svgmap_resolve1(eref, isodoc, _docxml, ids) ⇒ Object
115 116 117 118 119 120 121 122 |
# File 'lib/metanorma/collection_fileparse.rb', line 115 def svgmap_resolve1(eref, isodoc, _docxml, ids) href = isodoc.eref_target(eref) or return href == "##{eref['bibitemid']}" || (href =~ /^#/ && !ids[href.sub(/^#/, "")]) and return eref["target"] = href.strip eref.name = "link" eref.elements&.remove end |
#update_anchor_create_loc(_bib, eref, docid) ⇒ Object
if there is a crossref to another document, with no anchor, retrieve the anchor given the locality, and insert it into the crossref
242 243 244 245 246 247 248 249 250 |
# File 'lib/metanorma/collection_fileparse.rb', line 242 def update_anchor_create_loc(_bib, eref, docid) ins = eref.at(ns("./localityStack")) or return type = ins.at(ns("./locality/@type"))&.text type = "clause" if type == "annex" ref = ins.at(ns("./locality/referenceFrom"))&.text anchor = @files.get(docid, :anchors).dig(type, ref) or return ins << "<locality type='anchor'><referenceFrom>#{anchor.sub(/^_/, '')}" \ "</referenceFrom></locality>" end |
#update_anchor_loc(bib, eref, docid) ⇒ Object
228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/metanorma/collection_fileparse.rb', line 228 def update_anchor_loc(bib, eref, docid) loc = eref.at(".//xmlns:locality[@type = 'anchor']") or return update_anchor_create_loc(bib, eref, docid) @ncnames[docid] ||= Metanorma::Utils::to_ncname(docid) ref = loc.at("./xmlns:referenceFrom") or return anchor = "#{ref.text}_#{@ncnames[docid]}" @files.get(docid, :anchors).inject([]) do |m, (_, x)| m += x.values end.include?(anchor) or return ref.content = anchor end |
#update_anchors(bib, docid, erefs) ⇒ Object
update crossrefences to other documents, to include disambiguating document suffix on id
215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/metanorma/collection_fileparse.rb', line 215 def update_anchors(bib, docid, erefs) erefs.each do |e| if @files.get(docid) then update_anchor_loc(bib, e, docid) else msg = "<strong>** Unresolved reference to document #{docid} " \ "from eref</strong>" e << msg strip_eref(e) @log&.add("Cross-References", e, msg) end end end |
#update_bibitem(bib, identifier) ⇒ Object
4 5 6 7 8 9 10 11 12 13 |
# File 'lib/metanorma/collection_fileparse.rb', line 4 def update_bibitem(bib, identifier) docid = get_bibitem_docid(bib, identifier) or return newbib = dup_bibitem(docid, bib) _file, url = @files .targetfile_id(docid, relative: true, read: false, doc: !@files.get(docid, :attachment)) dest = newbib.at("./docidentifier") || newbib.at(ns("./docidentifier")) dest.previous = "<uri type='citation'>#{url}</uri>" bib.replace(newbib) end |
#update_direct_refs_to_docs(docxml, identifier) ⇒ Object
repo(current-metanorma-collection/ISO 17301-1:2016) replaced by bibdata of “ISO 17301-1:2016” in situ as bibitem. Any erefs to that bibitem id are replaced with relative URL Preferably with anchor, and is a job to realise dynamic lookup of localities.
129 130 131 132 133 134 135 136 137 138 |
# File 'lib/metanorma/collection_fileparse.rb', line 129 def update_direct_refs_to_docs(docxml, identifier) erefs, erefs1 = update_direct_refs_to_docs_prep(docxml) docxml.xpath(ns("//bibitem")).each do |b| docid = b.at(ns("./docidentifier[@type = 'repository']")) or next strip_unresolved_repo_erefs(identifier, docid, erefs1, b) or next update_bibitem(b, identifier) docid = docid_to_citeas(b) or next erefs[docid] and update_anchors(b, docid, erefs[docid]) end end |
#update_direct_refs_to_docs_prep(docxml) ⇒ Object
140 141 142 143 |
# File 'lib/metanorma/collection_fileparse.rb', line 140 def update_direct_refs_to_docs_prep(docxml) @ncnames = {} [Util::gather_citeases(docxml), Util::gather_bibitemids(docxml)] end |
#update_indirect_refs_to_docs(docxml, _docidentifier, internal_refs) ⇒ Object
Resolve erefs to a container of ids in another doc, to an anchor eref (direct link)
160 161 162 163 164 165 166 167 168 169 |
# File 'lib/metanorma/collection_fileparse.rb', line 160 def update_indirect_refs_to_docs(docxml, _docidentifier, internal_refs) bibitems, erefs = update_indirect_refs_to_docs_prep(docxml) internal_refs.each do |schema, ids| ids.each do |id, file| k = indirect_ref_key(schema, id, docxml) update_indirect_refs_to_docs1(docxml, k, file, bibitems, erefs) end end end |
#update_indirect_refs_to_docs1(_docxml, key, file, bibitems, erefs) ⇒ Object
186 187 188 189 190 191 192 |
# File 'lib/metanorma/collection_fileparse.rb', line 186 def update_indirect_refs_to_docs1(_docxml, key, file, bibitems, erefs) erefs[key]&.each do |e| e["citeas"] = file update_indirect_refs_to_docs_anchor(e, file) end update_indirect_refs_to_docs_docid(bibitems[key], file) end |
#update_indirect_refs_to_docs_anchor(eref, file) ⇒ Object
194 195 196 197 198 199 200 201 202 203 |
# File 'lib/metanorma/collection_fileparse.rb', line 194 def update_indirect_refs_to_docs_anchor(eref, file) a = eref.at(ns(".//locality[@type = 'anchor']/referenceFrom")) or return suffix = file @files.get(file) && p = @files.get(file, :parentid) and suffix = "#{p}_#{suffix}" existing = a.text anchor = Metanorma::Utils::to_ncname("#{existing}_#{suffix}") @updated_anchors[existing] or a.children = anchor @updated_anchors[anchor] = true end |
#update_indirect_refs_to_docs_docid(bibitem, file) ⇒ Object
205 206 207 208 209 210 211 |
# File 'lib/metanorma/collection_fileparse.rb', line 205 def update_indirect_refs_to_docs_docid(bibitem, file) docid = bibitem&.at(ns("./docidentifier[@type = 'repository']")) or return docid.children = "current-metanorma-collection/#{file}" docid.previous = "<docidentifier type='metanorma-collection'>#{file}</docidentifier>" end |
#update_indirect_refs_to_docs_prep(docxml) ⇒ Object
171 172 173 174 175 176 |
# File 'lib/metanorma/collection_fileparse.rb', line 171 def update_indirect_refs_to_docs_prep(docxml) bibitems = Util::gather_bibitems(docxml) erefs = Util::gather_bibitemids(docxml) @updated_anchors = {} [bibitems, erefs] end |
#update_sectionsplit_eref_to_doc(eref, internal_refs, doclist, opts) ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'lib/metanorma/collection_fileparse.rb', line 54 def update_sectionsplit_eref_to_doc(eref, internal_refs, doclist, opts) a = eref.at(ns("./localityStack/locality[@type = 'anchor']/" \ "referenceFrom")) or return doc = internal_refs[opts[:key]]["#{a.text}_#{opts[:target_suffix]}"] bibitemid = Metanorma::Utils::to_ncname("#{doc}_#{opts[:source_suffix]}") eref["bibitemid"] = bibitemid doclist[bibitemid] ||= doc doclist end |
#update_sectionsplit_refs_to_docs(docxml, internal_refs) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/metanorma/collection_fileparse.rb', line 41 def update_sectionsplit_refs_to_docs(docxml, internal_refs) Util::gather_citeases(docxml).each do |k, v| (@files.get(k) && @files.get(k, :sectionsplit)) or next opts = { key: @files.get(k, :indirect_key), source_suffix: docxml.root["document_suffix"], target_suffix: @files.get(k, :document_suffix) } refs = v.each_with_object({}) do |eref, m| update_sectionsplit_eref_to_doc(eref, internal_refs, m, opts) end add_hidden_bibliography(docxml, refs) end end |
#update_xrefs(file, docid, internal_refs) ⇒ String
Resolves references to other files in the collection. Three routines:
-
Eref to a document that has been split into multiple documents
(sectionsplit) are resolved to direct eref to the split document
-
Indirect erefs to a file anchor in an unknwon file in the collection
(bibitem[@type = ‘internal’] ) are resolved to direct eref to the containing document
-
Direct erefs to other files in collection
(repo(current-metanorma-collection/x) are resolved to hyperlinks
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/metanorma/collection_fileparse.rb', line 28 def update_xrefs(file, docid, internal_refs) docxml = file.is_a?(String) ? Nokogiri::XML(file, &:huge) : file supply_repo_ids(docxml) @nested or update_indirect_refs_to_docs(docxml, docid, internal_refs) @files.add_document_suffix(docid, docxml) @nested or update_sectionsplit_refs_to_docs(docxml, internal_refs) update_direct_refs_to_docs(docxml, docid) hide_refs(docxml) @files.get(docid, :sectionsplit_output) and eref2link(docxml) svgmap_resolve(datauri_encode(docxml), @files.get(docid, :ids)) docxml.to_xml end |