class Metanorma::CollectionRenderer

XML collection renderer

XML collection renderer

XML collection renderer

Constants

FORMATS

Public Class Methods

new(collection, folder, options = {}) click to toggle source

This is only going to render the HTML collection @param xml [Metanorma::Collection] input XML collection @param folder [String] input folder @param options [Hash] @option options [String] :coverpage cover page HTML (Liquid template) @option options [Array<Symbol>] :format list of formats (xml,html,doc,pdf) @option options [String] :ourput_folder output directory

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

# File lib/metanorma/collection_renderer.rb, line 25
def initialize(collection, folder, options = {}) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  check_options options
  @xml = Nokogiri::XML collection.to_xml # @xml is the collection manifest
  @lang = @xml&.at(ns("//bibdata/language"))&.text || "en"
  @script = @xml&.at(ns("//bibdata/script"))&.text || "Latn"
  @doctype = doctype
  require "metanorma-#{@doctype}"

  # output processor for flavour
  @isodoc = isodoc

  @outdir = dir_name_cleanse(options[:output_folder])
  @coverpage = options[:coverpage]
  @format = Util.sort_extensions_execution(options[:format])
  @compile_options = options[:compile] || {}
  @compile_options[:no_install_fonts] = true if options[:no_install_fonts]
  @log = options[:log]
  @documents = collection.documents
  @directives = collection.directives
  @disambig = Util::DisambigFiles.new
  @compile = Compile.new

  # list of files in the collection
  @files = read_files folder
  isodoc_populate(@isodoc)
  FileUtils.rm_rf @outdir
  FileUtils.mkdir_p @outdir
end
render(col, options = {}) click to toggle source

@param col [Metanorma::Collection] XML collection @param options [Hash] @option options [String] :coverpage cover page HTML (Liquid template) @option options [Array<Symbol>] :format list of formats @option options [Strong] :ourput_folder output directory

# File lib/metanorma/collection_renderer.rb, line 63
def self.render(col, options = {})
  folder = File.dirname col.file
  # require "byebug"; byebug
  warn "\n\n\n\n\nRender Init: #{DateTime.now.strftime('%H:%M:%S')}"
  cr = new(col, folder, options)
  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, options)
  warn "\n\n\n\n\nCoverpage: #{DateTime.now.strftime('%H:%M:%S')}"
  cr.coverpage if options[:format]&.include?(:html)
  warn "\n\n\n\n\nDone: #{DateTime.now.strftime('%H:%M:%S')}"
end

Public Instance Methods

add_document_suffix(identifier, doc) click to toggle source
# File lib/metanorma/collection_fileprocess.rb, line 122
def add_document_suffix(identifier, doc)
  document_suffix = Metanorma::Utils::to_ncname(identifier)
  [%w[* id], %w[* bibitemid], %w[review from],
   %w[review to], %w[index to], %w[xref target],
   %w[callout target]]
    .each do |(tag_name, attribute_name)|
    add_suffix_to_attributes(doc, document_suffix, tag_name, attribute_name)
  end
end
add_section_split(files) click to toggle source
# File lib/metanorma/collection_fileprocess.rb, line 38
def add_section_split(files)
  files.keys.each_with_object({}) do |k, m|
    if files[k][:sectionsplit] == "true" && !files[k]["attachment"]
      s, manifest = sectionsplit(files[k][:ref])
      s.each_with_index do |f1, i|
        add_section_split_instance(f1, m, k, i, files)
      end
      m["#{k}:index.html"] = add_section_split_cover(files, manifest, k)
    end
    m[k] = files[k]
  end
end
add_section_split_cover(files, manifest, ident) click to toggle source
# File lib/metanorma/collection_fileprocess.rb, line 51
def add_section_split_cover(files, manifest, ident)
  cover = section_split_cover(manifest, dir_name_cleanse(ident))
  files[ident][:out_path] = cover
  { attachment: true, index: false, out_path: cover,
    ref: File.join(File.dirname(manifest.file), cover) }
end
add_section_split_instance(file, manifest, key, idx, files) click to toggle source
# File lib/metanorma/collection_fileprocess.rb, line 71
def add_section_split_instance(file, manifest, key, idx, files)
  dir = File.dirname(files[key][:ref])
  presfile = File.join(dir, File.basename(file[:url]))
  manifest["#{key} #{file[:title]}"] =
    { parentid: key, presentationxml: true, type: "fileref",
      rel_path: file[:url], out_path: File.basename(file[:url]),
      anchors: read_anchors(Nokogiri::XML(File.read(presfile))),
      bibdata: files[key][:bibdata], ref: presfile }
  manifest["#{key} #{file[:title]}"][:bare] = true unless idx.zero?
end
add_suffix_to_attributes(doc, suffix, tag_name, attribute_name) click to toggle source
# File lib/metanorma/collection_fileprocess.rb, line 115
def add_suffix_to_attributes(doc, suffix, tag_name, attribute_name)
  doc.xpath(ns("//#{tag_name}[@#{attribute_name}]")).each do |elem|
    elem.attributes[attribute_name].value =
      "#{elem.attributes[attribute_name].value}_#{suffix}"
  end
end
compile_options(identifier) click to toggle source
# File lib/metanorma/collection_fileprocess.rb, line 173
def compile_options(identifier)
  ret = @compile_options.dup
  Array(@directives).include?("presentation-xml") ||
    @files[identifier][:presentationxml] and
    ret.merge!(passthrough_presentation_xml: true)
  @files[identifier][:sectionsplit] == "true" and
    ret.merge!(sectionsplit: "true")
  @files[identifier][:bare] == true and
    ret.merge!(bare: true)
  ret
end
concatenate(col, options) click to toggle source
# File lib/metanorma/collection_renderer.rb, line 77
def concatenate(col, options)
  options[:format] << :presentation if options[:format].include?(:pdf)
  options[:format].uniq.each do |e|
    next unless %i(presentation xml).include?(e)

    ext = e == :presentation ? "presentation.xml" : e.to_s
    out = col.clone
    out.directives << "documents-inline"
    out.documents.each_key do |id|
      next if @files[id][:attachment] || @files[id][:outputs].nil?

      filename = @files[id][:outputs][e]
      out.documents[id] = Metanorma::Document.raw_file(filename)
    end
    File.open(File.join(@outdir, "collection.#{ext}"), "w:UTF-8") do |f|
      f.write(out.to_xml)
    end
  end
  options[:format].include?(:pdf) and
    pdfconv.convert(File.join(@outdir, "collection.presentation.xml"))
end
copy_file_to_dest(fileref) click to toggle source
# File lib/metanorma/collection_fileprocess.rb, line 208
def copy_file_to_dest(fileref)
  dest = File.join(@outdir, fileref[:out_path])
  FileUtils.mkdir_p(File.dirname(dest))
  FileUtils.cp fileref[:ref], dest
end
coverpage() click to toggle source

populate liquid template of ARGV with metadata extracted from collection manifest

# File lib/metanorma/collection_renderer.rb, line 164
def coverpage
  return unless @coverpage

  File.open(File.join(@outdir, "index.html"), "w:UTF-8") do |f|
    f.write @isodoc.populate_template(File.read(@coverpage))
  end
end
datauri_encode(docxml) click to toggle source
# File lib/metanorma/collection_fileparse.rb, line 92
def datauri_encode(docxml)
  docxml.xpath(ns("//image")).each do |i|
    i["src"] = Metanorma::Utils::datauri(i["src"])
  end
  docxml
end
dir_name_cleanse(name) click to toggle source
# File lib/metanorma/collection_renderer.rb, line 54
def dir_name_cleanse(name)
  name.gsub(/[<>:"|?*]/, "_")
end
docrefs(elm, builder) click to toggle source

@param elm [Nokogiri::XML::Element] @param builder [Nokogiri::XML::Builder]

# File lib/metanorma/collection_renderer.rb, line 193
def docrefs(elm, builder)
  elm.xpath(ns("./docref[@index = 'true']")).each do |d|
    ident = d.at(ns("./identifier")).children.to_xml
    builder.li do |li|
      li.a **{ href: index_link(d, ident) } do |a|
        a << ident
      end
    end
  end
end
doctype() click to toggle source

infer the flavour from the first document identifier; relaton does that

# File lib/metanorma/collection_renderer.rb, line 147
def doctype
  if (docid = @xml&.at(ns("//bibdata/docidentifier/@type"))&.text)
    dt = docid.downcase
  elsif (docid = @xml&.at(ns("//bibdata/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) click to toggle source
# File lib/metanorma/collection_fileparse.rb, line 61
def dup_bibitem(docid, bib)
  newbib = @files[docid][:bibdata].dup
  newbib.name = "bibitem"
  newbib["hidden"] = "true"
  newbib&.at("./*[local-name() = 'ext']")&.remove
  newbib["id"] = bib["id"]
  newbib
end
fail_update_bibitem(docid, identifier) click to toggle source
# File lib/metanorma/collection_fileparse.rb, line 54
def fail_update_bibitem(docid, identifier)
  error = "[metanorma] Cannot find crossreference to document #{docid} "\
    "in document #{identifier}."
  @log.add("Cross-References", nil, error)
  Util.log(error, :warning)
end
file_compile(file, filename, identifier) click to toggle source

compile and output individual file in collection warn “metanorma compile -x html #{f.path}”

# File lib/metanorma/collection_fileprocess.rb, line 164
def file_compile(file, filename, identifier)
  return if @files[identifier][:sectionsplit] == "true"

  @compile.compile file.path, { format: :asciidoc, extension_keys: @format }
    .merge(compile_options(identifier))
  @files[identifier][:outputs] = {}
  file_compile_formats(file, filename, identifier)
end
file_compile_formats(file, filename, identifier) click to toggle source
# File lib/metanorma/collection_fileprocess.rb, line 185
def file_compile_formats(file, filename, identifier)
  @format.each do |e|
    ext = @compile.processor.output_formats[e]
    fn = File.basename(filename).sub(/(?<=\.)[^.]+$/, ext.to_s)
    if /html$/.match?(ext) && @files[identifier][:sectionsplit]
      # file_sectionsplit_copy(file, fn, identifier, ext, e)
    else
      FileUtils.cp file.path.sub(/\.xml$/, ".#{ext}"),
                   File.join(@outdir, fn)
      @files[identifier][:outputs][e] = File.join(@outdir, fn)
    end
  end
end
file_entry(ref, identifier, _path) click to toggle source

rel_path is the source file address, determined relative to the YAML. out_path is the destination file address, with any references outside the working directory (../../…) truncated

# File lib/metanorma/collection_fileprocess.rb, line 98
def file_entry(ref, identifier, _path)
  out = ref["attachment"] ? ref["fileref"] : File.basename(ref["fileref"])
  ret = if ref["fileref"]
          { type: "fileref", ref: @documents[identifier].file,
            rel_path: ref["fileref"],
            out_path: out }
        else
          { type: "id", ref: ref["id"] }
        end
  %i(attachment sectionsplit index).each do |s|
    ret[s] = ref[s.to_s] if ref[s.to_s]
  end
  ret[:presentationxml] = ref["presentation-xml"] if ref["presentation-xml"]
  ret[:bareafterfirst] = ref["bare-after-first"] if ref["bare-after-first"]
  ret
end
file_sectionsplit_copy(file, base, identifier, ext, format) click to toggle source
# File lib/metanorma/collection_fileprocess.rb, line 199
def file_sectionsplit_copy(file, base, identifier, ext, format)
  dir = file.path.sub(/\.xml$/, ".#{ext}_collection")
  files = Dir.glob("#{dir}/*.#{ext}")
  FileUtils.cp files, @outdir
  cover = File.join(@outdir, base.sub(/\.html$/, ".index.html"))
  FileUtils.cp File.join(dir, "index.html"), cover
  @files[identifier][:outputs][format] = cover
end
files() click to toggle source

process each file in the collection files are held in memory, and altered as postprocessing

# File lib/metanorma/collection_fileprocess.rb, line 216
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.each_with_index do |(identifier, x), i|
    i.positive? && Array(@directives).include?("bare-after-first") and
      @compile_options.merge!(bare: true)
    if x[:attachment] then copy_file_to_dest(x)
    else
      file, filename = targetfile(x, read: true)
      warn "\n\n\n\n\nProcess #{filename}: #{DateTime.now.strftime('%H:%M:%S')}"
      file = update_xrefs(file, identifier, internal_refs)
      Tempfile.open(["collection", ".xml"], encoding: "utf-8") do |f|
        f.write(file)
        f.close
        file_compile(f, filename, identifier)
      end
    end
  end
end
gather_internal_refs() click to toggle source

gather internal bibitem references

# File lib/metanorma/collection_fileparse.rb, line 195
def gather_internal_refs
  @files.each_with_object({}) do |(_, x), refs|
    next if x[:attachment]

    file, = targetfile(x, read: true)
    Nokogiri::XML(file)
      .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]] = true
    end
  end
end
indexfile(elm) click to toggle source

single level navigation list, with hierarchical nesting if multiple lists are needed as separate HTML fragments, multiple instances of this function will be needed, and associated to different variables in the call to @isodoc.metadata_init (including possibly an array of HTML fragments)

@param elm [Nokogiri::XML::Element] @return [String] XML

# File lib/metanorma/collection_renderer.rb, line 219
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) click to toggle source

uses the identifier to label documents; other attributes (title) can be looked up in @files[:bibdata]

@param elm [Nokogiri::XML::Element] @param builder [Nokogiri::XML::Builder]

# File lib/metanorma/collection_renderer.rb, line 185
def indexfile_docref(elm, builder)
  return "" unless elm.at(ns("./docref[@index = 'true']"))

  builder.ul { |b| docrefs(elm, b) }
end
indexfile_title(elm) click to toggle source

@param elm [Nokogiri::XML::Element] @return [String]

# File lib/metanorma/collection_renderer.rb, line 174
def indexfile_title(elm)
  lvl = elm&.at(ns("./level"))&.text&.capitalize
  lbl = elm&.at(ns("./title"))&.text
  "#{lvl}#{lvl && lbl ? ': ' : ''}#{lbl}"
end
isodoc() click to toggle source

The isodoc class for the metanorma flavour we are using

# File lib/metanorma/collection_renderer.rb, line 124
def isodoc
  x = Asciidoctor.load nil, backend: @doctype.to_sym
  isodoc = x.converter.html_converter(Dummy.new)
  isodoc.i18n_init(@lang, @script) # read in internationalisation
  isodoc.metadata_init(@lang, @script, isodoc.i18n)
  isodoc.info(@xml, nil)
  isodoc
end
isodoc_populate(isodoc) click to toggle source
# File lib/metanorma/collection_renderer.rb, line 133
def isodoc_populate(isodoc)
  # create the @meta class of isodoc, with "navigation" set to the index bar
  # extracted from the manifest
  nav = indexfile(@xml.at(ns("//manifest")))
  i18n = isodoc.i18n
  i18n.set("navigation", nav)
  isodoc.metadata_init(@lang, @script, i18n)
  # populate the @meta class of isodoc with the various metadata fields
  # native to the flavour; used to populate Liquid
  isodoc.info(@xml, nil)
  isodoc
end
locate_internal_refs() click to toggle source

resolve file location for the target of each internal reference

# File lib/metanorma/collection_fileparse.rb, line 212
def locate_internal_refs
  refs = gather_internal_refs
  @files.keys.reject { |k| @files[k][:attachment] }.each do |identifier|
    locate_internal_refs1(refs, identifier, @files[identifier])
  end
  refs.each do |schema, ids|
    ids.each do |id, key|
      key == true and refs[schema][id] = "Missing:#{schema}:#{id}"
    end
  end
  refs
end
locate_internal_refs1(refs, identifier, filedesc) click to toggle source
# File lib/metanorma/collection_fileparse.rb, line 225
def locate_internal_refs1(refs, identifier, filedesc)
  file, _filename = targetfile(filedesc, read: true)
  xml = Nokogiri::XML(file) { |config| config.huge }
  t = xml.xpath("//*/@id").each_with_object({}) { |i, x| x[i.text] = true }
  refs.each do |schema, ids|
    ids.keys.select { |id| t[id] }.each do |id|
      n = xml.at("//*[@id = '#{id}']") and
        n.at("./ancestor-or-self::*[@type = '#{schema}']") and
        refs[schema][id] = identifier
    end
  end
end
ns(xpath) click to toggle source
# File lib/metanorma/collection_renderer.rb, line 158
def ns(xpath)
  IsoDoc::Convert.new({}).ns(xpath)
end
pdfconv() click to toggle source
# File lib/metanorma/collection_renderer.rb, line 99
def pdfconv
  doctype = @doctype.to_sym
  x = Asciidoctor.load nil, backend: doctype
  x.converter.pdf_converter(PdfOptionsNode.new(doctype, @compile_options))
end
read_anchors(xml) click to toggle source

map locality type and label (e.g. “clause” “1”) to id = anchor for a document Note: will only key clauses, which have unambiguous reference label in locality. Notes, examples etc with containers are just plunked against UUIDs, so that their IDs can at least be registered to be tracked as existing.

# File lib/metanorma/collection_fileparse.rb, line 10
def read_anchors(xml)
  xrefs = @isodoc.xref_init(@lang, @script, @isodoc, @isodoc.i18n, {})
  xrefs.parse xml
  xrefs.get.each_with_object({}) do |(k, v), ret|
    read_anchors1(k, v, ret)
  end
end
read_anchors1(key, val, ret) click to toggle source
# File lib/metanorma/collection_fileparse.rb, line 18
def read_anchors1(key, val, ret)
  val[:type] ||= "clause"
  ret[val[:type]] ||= {}
  index = if val[:container] || val[:label].nil? || val[:label].empty?
            UUIDTools::UUID.random_create.to_s
          else val[:label]
          end
  ret[val[:type]][index] = key
  ret[val[:type]][val[:value]] = key if val[:value]
end
read_files(path) click to toggle source

hash for each document in collection of document identifier to: document reference (fileref or id), type of document reference, and bibdata entry for that file @param path [String] path to collection @return [Hash{String=>Hash}]

# File lib/metanorma/collection_fileprocess.rb, line 15
def read_files(path) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
  files = {}
  @xml.xpath(ns("//docref")).each do |d|
    identifier = d.at(ns("./identifier")).children.to_xml
    files[identifier] = file_entry(d, identifier, path)
    if files[identifier][:attachment]
      files[identifier][:bibdata] = Metanorma::Document
        .attachment_bibitem(identifier).root
    else
      file, _filename = targetfile(files[identifier], read: true)
      xml = Nokogiri::XML(file)
      add_document_suffix(identifier, xml)
      files[identifier][:anchors] = read_anchors(xml)
      files[identifier][:bibdata] = xml.at(ns("//bibdata"))
    end
    files[identifier][:bibitem] = files[identifier][:bibdata].dup
    files[identifier][:bibitem].name = "bibitem"
    files[identifier][:bibitem]["hidden"] = "true"
    files[identifier][:bibitem]&.at("./*[local-name() = 'ext']")&.remove
  end
  add_section_split(files)
end
ref_file(ref, out, read, doc) click to toggle source

@param ref [String] @param read [Boolean] @param doc [Boolean] @return [Array<String, nil>]

# File lib/metanorma/collection_fileprocess.rb, line 155
def ref_file(ref, out, read, doc)
  file = File.read(ref, encoding: "utf-8") if read
  filename = out.dup
  filename.sub!(/\.xml$/, ".html") if doc
  [file, filename]
end
section_split_cover(col, ident) click to toggle source
# File lib/metanorma/collection_fileprocess.rb, line 58
def section_split_cover(col, ident)
  dir = File.dirname(col.file)
  @compile.collection_setup(nil, dir)
  CollectionRenderer.new(col, dir,
                         output_folder: "#{ident}_collection",
                         format: %i(html),
                         coverpage: File.join(dir, "cover.html")).coverpage
  FileUtils.mv "#{ident}_collection/index.html",
               File.join(dir, "#{ident}_index.html")
  FileUtils.rm_rf "#{ident}_collection"
  "#{ident}_index.html"
end
sectionsplit(file) click to toggle source
# File lib/metanorma/collection_fileprocess.rb, line 82
def sectionsplit(file)
  @compile.compile(
    file, { format: :asciidoc, extension_keys: [:presentation] }
    .merge(@compile_options)
  )
  r = file.sub(/\.xml$/, ".presentation.xml")
  xml = Nokogiri::XML(File.read(r))
  s = @compile.sectionsplit(xml, File.basename(r), File.dirname(r))
    .sort_by { |f| f[:order] }
  [s, @compile.collection_manifest(File.basename(r), s, xml, nil,
                                   File.dirname(r))]
end
svgmap_resolve(docxml) click to toggle source
# File lib/metanorma/collection_fileparse.rb, line 99
def svgmap_resolve(docxml)
  isodoc = IsoDoc::Convert.new({})
  docxml.xpath(ns("//svgmap//eref")).each do |e|
    href = isodoc.eref_target(e)
    next if href == "##{e['bibitemid']}" ||
      href =~ /^#/ && !docxml.at("//*[@id = '#{href.sub(/^#/, '')}']")

    e["target"] = href.strip
    e.name = "link"
    e&.elements&.remove
  end
  Metanorma::Utils::svgmap_rewrite(docxml, "")
end
targetfile(data, options) click to toggle source

return file contents + output filename for each file in the collection, given a docref entry @param data [Hash] docref entry @param read [Boolean] read the file in and return it @param doc [Boolean] I am a Metanorma document, so my URL should end with html or pdf or whatever @param relative [Boolean] Return output path, formed relative to YAML file, not input path, relative to calling function @return [Array<String, nil>]

# File lib/metanorma/collection_fileprocess.rb, line 141
def targetfile(data, options)
  options = { read: false, doc: true, relative: false }.merge(options)
  path = options[:relative] ? data[:rel_path] : data[:ref]
  if data[:type] == "fileref"
    ref_file path, data[:out_path], options[:read], options[:doc]
  else
    xml_file data[:id], options[:read]
  end
end
update_anchor_create_loc(_bib, eref, docid) click to toggle source

if there is a crossref to another document, with no anchor, retrieve the anchor given the locality, and insert it into the crossref

# File lib/metanorma/collection_fileparse.rb, line 184
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[docid][:anchors].dig(type, ref) or return
  ins << "<locality type='anchor'><referenceFrom>#{anchor.sub(/^_/, '')}"\
    "</referenceFrom></locality>"
end
update_anchor_loc(bib, eref, docid) click to toggle source
# File lib/metanorma/collection_fileparse.rb, line 169
def update_anchor_loc(bib, eref, docid)
  loc = eref.at(ns(".//locality[@type = 'anchor']")) or
    return update_anchor_create_loc(bib, eref, docid)
  document_suffix = Metanorma::Utils::to_ncname(docid)
  ref = loc.at(ns("./referenceFrom")) || return
  anchor = "#{ref.text}_#{document_suffix}"
  return unless @files[docid][:anchors].inject([]) do |m, (_, x)|
    m += x.values
  end.include?(anchor)

  ref.content = anchor
end
update_anchors(bib, docxml, docid) click to toggle source

update crossrefences to other documents, to include disambiguating document suffix on id

# File lib/metanorma/collection_fileparse.rb, line 159
def update_anchors(bib, docxml, docid) # rubocop:disable Metrics/AbcSize
  docxml.xpath("//xmlns:eref[@citeas = '#{docid}']").each do |e|
    if @files[docid] then update_anchor_loc(bib, e, docid)
    else
      e << "<strong>** Unresolved reference to document #{docid} "\
        "from eref</strong>"
    end
  end
end
update_bibitem(bib, identifier) click to toggle source

@param bib [Nokogiri::XML::Element] @param identifier [String]

# File lib/metanorma/collection_fileparse.rb, line 40
def update_bibitem(bib, identifier) # rubocop:disable Metrics/AbcSize
  docid = bib&.at(ns("./docidentifier"))&.children&.to_xml
  return fail_update_bibitem(docid, identifier) unless @files[docid]

  newbib = dup_bibitem(docid, bib)
  bib.replace(newbib)
  _file, url = targetfile(@files[docid], relative: true, read: false,
                          doc: !@files[docid][:attachment])
  uri_node = Nokogiri::XML::Node.new "uri", newbib
  uri_node[:type] = "citation"
  uri_node.content = url
  newbib.at(ns("./docidentifier")).previous = uri_node
end
update_direct_refs_to_docs(docxml, identifier) click to toggle source

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.

# File lib/metanorma/collection_fileparse.rb, line 118
def update_direct_refs_to_docs(docxml, identifier)
  erefs = docxml.xpath(ns("//eref"))
    .each_with_object({ citeas: {}, bibitemid: {} }) do |i, m|
    m[:citeas][i["citeas"]] = true
    m[:bibitemid][i["bibitemid"]] = true
  end
  docxml.xpath(ns("//bibitem[not(ancestor::bibitem)]")).each do |b|
    docid = b&.at(ns("./docidentifier[@type = 'repository']"))&.text
    next unless docid && %r{^current-metanorma-collection/}.match(docid)

    update_bibitem(b, identifier)
    docid = b&.at(ns("./docidentifier"))&.children&.to_xml or next
    erefs[:citeas][docid] and update_anchors(b, docxml, docid)
  end
end
update_indirect_refs_to_docs(docxml, internal_refs) click to toggle source

Resolve erefs to a container of ids in another doc, to an anchor eref (direct link)

# File lib/metanorma/collection_fileparse.rb, line 136
def update_indirect_refs_to_docs(docxml, internal_refs)
  internal_refs.each do |schema, ids|
    ids.each do |id, file|
      update_indirect_refs_to_docs1(docxml, schema, id, file)
    end
  end
end
update_indirect_refs_to_docs1(docxml, schema, id, file) click to toggle source
# File lib/metanorma/collection_fileparse.rb, line 144
def update_indirect_refs_to_docs1(docxml, schema, id, file)
  docxml.xpath(ns("//eref[@bibitemid = '#{schema}_#{id}']")).each do |e|
    e["citeas"] = file
    if a = e.at(ns(".//locality[@type = 'anchor']/referenceFrom"))
      a.children = "#{a.text}_#{Metanorma::Utils::to_ncname(file)}"
    end
  end
  docid = docxml.at(ns("//bibitem[@id = '#{schema}_#{id}']/"\
                       "docidentifier[@type = 'repository']")) or return
  docid.children = "current-metanorma-collection/#{file}"
  docid.previous = "<docidentifier type='X'>#{file}</docidentifier>"
end
update_xrefs(file, identifier, internal_refs) click to toggle source

Resolves direct links to other files in collection (repo(current-metanorma-collection/x), and indirect links to other files in collection (bibitem[@type = 'internal'] pointing to a file anchor in another file in the collection) @param file [String] XML content @param identifier [String] docid @param internal_refs [Hash{String=>Hash{String=>String}] schema name to anchor to filename @return [String] XML content

# File lib/metanorma/collection_fileparse.rb, line 79
def update_xrefs(file, identifier, internal_refs)
  docxml = Nokogiri::XML(file) { |config| config.huge }
  update_indirect_refs_to_docs(docxml, internal_refs)
  add_document_suffix(identifier, docxml)
  update_direct_refs_to_docs(docxml, identifier)
  svgmap_resolve(datauri_encode(docxml))
  docxml.xpath(ns("//references[bibitem][not(./bibitem[not(@hidden) or "\
                  "@hidden = 'false'])]")).each do |f|
    f["hidden"] = "true"
  end
  docxml.to_xml
end
xml_file(id, read) click to toggle source

@param id [String] @param read [Boolean] @return [Array<String, nil>]

# File lib/metanorma/collection_fileparse.rb, line 32
def xml_file(id, read)
  file = @xml.at(ns("//doc-container[@id = '#{id}']")).to_xml if read
  filename = "#{id}.html"
  [file, filename]
end

Private Instance Methods

check_options(options) click to toggle source

@param options [Hash] @raise [ArgumentError]

# File lib/metanorma/collection_renderer.rb, line 243
def check_options(options)
  unless options[:format].is_a?(Array) && (FORMATS & options[:format]).any?
    raise ArgumentError, "Need to specify formats (xml,html,pdf,doc)"
  end
end
format_sort(formats) click to toggle source
# File lib/metanorma/collection_renderer.rb, line 233
def format_sort(formats)
  ret = []
  formats.include?(:xml) and ret << :xml
  formats.include?(:presentation) and ret << :presentation
  a = %i(presentation xml)
  ret + formats.reject { |i| a.include? i }
end