lib/metanorma/collection/renderer/fileparse.rb in metanorma-2.0.6 vs lib/metanorma/collection/renderer/fileparse.rb in metanorma-2.0.7

- old
+ new

@@ -17,10 +17,11 @@ def update_xrefs(file, docid, internal_refs) xml, sso = update_xrefs_prep(file, docid) @nested || sso or Metanorma::Collection::XrefProcess::xref_process(xml, xml, nil, docid, @isodoc) + @ncnames = {} @nested or update_indirect_refs_to_docs(xml, docid, internal_refs) @files.add_document_suffix(docid, xml) @nested or update_sectionsplit_refs_to_docs(xml, internal_refs) update_direct_refs_to_docs(xml, docid) hide_refs(xml) @@ -47,26 +48,22 @@ end add_hidden_bibliography(docxml, refs) end end + ANCHOR_XPATH = "xmlns:locality[@type = 'anchor']/xmlns:referenceFrom" + .freeze + def update_sectionsplit_eref_to_doc(eref, internal_refs, doclist, opts) - a = eref.at(ns("./localityStack/locality[@type = 'anchor']/" \ - "referenceFrom")) or return + a = eref.at("./xmlns:localityStack/#{ANCHOR_XPATH}") 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 - def eref2link(docxml) - isodoc = IsoDoc::PresentationXMLConvert.new({}) - isodoc.bibitem_lookup(docxml) - isodoc.eref2link(docxml) - end - BIBITEM_NOT_REPO_XPATH = "//bibitem[not(ancestor::bibitem)]" \ "[not(./docidentifier[@type = 'repository'])]".freeze def supply_repo_ids(doc) doc.xpath(ns(BIBITEM_NOT_REPO_XPATH)).each do |b| @@ -77,68 +74,41 @@ docid.next = docid_xml(id) end end end - def svg_datauri(docxml, docid) - rel = @files.get(docid, :rel_path) - parent = @files.get(docid, :parentid) and - rel = @files.get(parent, :rel_path) - # if sectionsplit, use orig file dir - dir = File.join(@dirname, File.dirname(rel)) - datauri_encode(docxml, dir) - end - - def svgmap_resolve(docxml, docid) - ids = @files.get(docid, :ids) - docxml = svg_unnest(svg_datauri(docxml, docid)) - isodoc = IsoDoc::PresentationXMLConvert.new({}) - isodoc.bibitem_lookup(docxml) - docxml.xpath(ns("//svgmap//eref")).each do |e| - svgmap_resolve_eref(e, isodoc, docxml, ids) - end - Vectory::SvgMapping.new(docxml, "").call - docxml.xpath(ns("//svgmap")).each { |s| isodoc.svgmap_extract(s) } - end - - def svg_unnest(docxml) - docxml.xpath(ns("//svgmap//image[.//*[name() = 'image']]")).each do |i| - s = i.elements.detect { |e| e.name == "svg" } and - i.replace(s) - end - docxml - end - - def svgmap_resolve_eref(eref, isodoc, _docxml, ids) - href = isodoc.eref_target(eref) or return - href = href[:link] - href == "##{eref['bibitemid']}" || - (href =~ /^#/ && !ids[href.sub(/^#/, "")]) and return - eref["target"] = href.strip - eref.name = "link" - eref.elements&.remove - end - # 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. def update_direct_refs_to_docs(docxml, identifier) - erefs, erefs1 = update_direct_refs_to_docs_prep(docxml) + erefs, erefs_no_anchor, anchors, 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]) + erefs[docid] and + update_anchors(b, docid, erefs[docid], erefs_no_anchor[docid], + anchors[docid]) end end + # Hash(docid) of arrays def update_direct_refs_to_docs_prep(docxml) - @ncnames = {} - [Util::gather_citeases(docxml), Util::gather_bibitemids(docxml)] + erefs = Util::gather_citeases(docxml) + no_anchor = erefs.keys.each_with_object({}) { |k, m| m[k] = [] } + anchors = erefs.keys.each_with_object({}) { |k, m| m[k] = [] } + erefs.each do |k, v| + v.each do |e| + if loc = e.at(".//#{ANCHOR_XPATH}") then anchors[k] << loc + else no_anchor[k] << e end + end + end + [erefs, no_anchor, anchors, Util::gather_bibitemids(docxml)] end # 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. @@ -153,60 +123,82 @@ end # Resolve erefs to a container of ids in another doc, # to an anchor eref (direct link) def update_indirect_refs_to_docs(docxml, _docidentifier, internal_refs) - bibitems, erefs = update_indirect_refs_to_docs_prep(docxml) + bib, erefs, doc_suffix, doc_type, f = update_indirect_refs_prep(docxml) internal_refs.each do |schema, ids| - s = "#{schema}_" + add_suffix = doc_suffix && doc_type && doc_type != schema ids.each do |id, file| - k = indirect_ref_key(s, schema, id, docxml) - update_indirect_refs_to_docs1(docxml, k, file, bibitems, erefs) + f[file] ||= { url: @files.url?(file), + parentid: @files.get(file) && @files.get(file, + :parentid) } + k = indirect_ref_key(schema, id, doc_suffix, add_suffix) + update_indirect_refs_to_docs1(f[file], k, file, bib, erefs) end end end - def update_indirect_refs_to_docs_prep(docxml) + def update_indirect_refs_prep(docxml) @updated_anchors = {} - [Util::gather_bibitems(docxml), Util::gather_bibitemids(docxml)] + @indirect_keys = {} + [Util::gather_bibitems(docxml), Util::gather_bibitemids(docxml), + docxml.root["document_suffix"], docxml.root["type"], {}] end - def indirect_ref_key(schema_, schema, id, docxml) - /^#{schema_}/.match?(id) and return id - ret = schema_ + id - suffix = docxml.root["document_suffix"] or return ret - (k = docxml.root["type"]) && k != schema or return ret - "#{ret}_#{suffix}" + def indirect_ref_key(schema, id, doc_suffix, doc_type) + /^#{schema}_/.match?(id) and return id + key = [schema, id, doc_suffix, doc_type].join("::") + x = @indirect_keys[key] and return x + ret = "#{schema}_#{id}" + doc_suffix && doc_type && doc_type != schema and + ret = "#{ret}_#{doc_suffix}" + @indirect_keys[key] = ret + ret end - #OLD - def indirect_ref_key1(schema, id, docxml) + def indirect_ref_key(schema, id, doc_suffix, add_suffix) /^#{schema}_/.match?(id) and return id + #key = "#{schema}_#{id}" + x = @indirect_keys.dig(schema, id) and return x + @indirect_keys[schema] ||= {} + @indirect_keys[schema][id] = if add_suffix + "#{schema}_#{id}_#{doc_suffix}" + else + "#{schema}_#{id}" + end + end + + def indirect_ref_keyx(schema, id, doc_suffix, doc_type) + /^#{schema}_/.match?(id) and return id ret = "#{schema}_#{id}" - suffix = docxml.root["document_suffix"] - (k = docxml.root["type"]) && k != schema && suffix and - ret = "#{ret}_#{suffix}" + doc_suffix && doc_type && doc_type != schema and + ret = "#{ret}_#{doc_suffix}" ret end - def update_indirect_refs_to_docs1(_docxml, key, file, bibitems, erefs) + def update_indirect_refs_to_docs1(filec, key, file, bibitems, erefs) erefs[key]&.each do |e| e["citeas"] = file - update_indirect_refs_to_docs_anchor(e, file) + update_indirect_refs_to_docs_anchor(e, file, filec[:url], + filec[:parentid]) end update_indirect_refs_to_docs_docid(bibitems[key], file) end - 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}" + def update_indirect_refs_to_docs_anchor(eref, file, url, parentid) + a = eref.at(".//#{ANCHOR_XPATH}") or return + parentid and file = "#{parentid}_#{file}" existing = a.text - anchor = existing - @files.url?(file) or - anchor = Metanorma::Utils::to_ncname("#{anchor}_#{suffix}") + anchor = if url then existing + else + #suffix_anchor_indirect(existing, suffix) + #k = "#{existing}_#{file}" + #@ncnames[k] ||= Metanorma::Utils::to_ncname(k) + @indirect_keys[existing] ||= {} + @indirect_keys[existing][file] ||= Metanorma::Utils::to_ncname("#{existing}_#{file}") + end @updated_anchors[existing] or a.children = anchor @updated_anchors[anchor] = true end def update_indirect_refs_to_docs_docid(bib, file) @@ -214,70 +206,51 @@ docid.children = "current-metanorma-collection/#{file}" docid.previous = "<docidentifier type='metanorma-collection'>#{file}</docidentifier>" end - # update crossrefences to other documents, to include - # disambiguating document suffix on id - 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 + # bottleneck + def update_anchors(bib, docid, erefs, erefs_no_anchor, erefs_anchors) + @files.get(docid) or error_anchor(erefs, docid) + has_anchors, url, ncn_docid = update_anchors_prep(docid) + erefs_no_anchor.each do |e| + update_anchor_create_loc(bib, e, docid) end + !url && has_anchors or return + erefs_anchors.each do |e| + update_anchors1(docid, ncn_docid, e) + end end - def update_anchor_loc(bib, eref, docid) - loc = eref.at(".//xmlns:locality[@type = 'anchor']") or - return update_anchor_create_loc(bib, eref, docid) - a = @files.get(docid, :anchors) or return - ref = loc.elements&.first or return - anchor = suffix_anchor(ref.text, docid) - a.values.detect { |x| x.value?(anchor) } or return - ref.content = anchor + def update_anchors1(docid, ncn_docid, anchor) + @concat_anchors[anchor.text] ||= "#{ncn_docid}_#{anchor.text}" + if @files.get(docid).dig(:anchors_lookup, @concat_anchors[anchor.text]) + anchor.content = @concat_anchors[anchor.text] + end end - #OLD - def update_anchor_loc1(bib, eref, docid) - loc = eref.at(".//xmlns:locality[@type = 'anchor']") or - return update_anchor_create_loc(bib, eref, docid) - ref = loc.at("./xmlns:referenceFrom") or return - anchor = suffix_anchor(ref, docid) - a = @files.get(docid, :anchors) or return - a.inject([]) { |m, (_, x)| m + x.values } - .include?(anchor) or return - ref.content = anchor + def update_anchors_prep(docid) + @concat_anchors = {} + [@files.get(docid)&.key?(:anchors_lookup), @files.url?(docid), + Metanorma::Utils::to_ncname(docid)] end - def suffix_anchor(ref, docid) - @ncnames[docid] ||= "#{Metanorma::Utils::to_ncname(docid)}_" - @files.url?(docid) or return ref - @ncnames[docid] + ref + # encode both prefix and suffix to NCName + def suffix_anchor_indirect(prefix, suffix) + k = "#{prefix}_#{suffix}" + @ncnames[k] ||= Metanorma::Utils::to_ncname(k) end - #OLD - def suffix_anchor1(ref, docid) - @ncnames[docid] ||= Metanorma::Utils::to_ncname(docid) - anchor = ref.text - @files.url?(docid) or anchor = "#{@ncnames[docid]}_#{anchor}" - anchor - end - # if there is a crossref to another document, with no anchor, retrieve the # anchor given the locality, and insert it into the crossref 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 a = @files.get(docid, :anchors).dig(type, ref) or return ins << "<locality type='anchor'><referenceFrom>#{a.sub(/^_/, '')}" \ - "</referenceFrom></locality>" + "</referenceFrom></locality>" end end end end