class IsoDoc::Ietf::RfcConvert

Constants

OL_STYLE

Private Class Methods

new(options) click to toggle source
Calls superclass method
# File lib/isodoc/ietf/rfc_convert.rb, line 86
def initialize(options)
  super
  @xinclude = options[:use_xinclude] == "true"
  @format = :rfc
  @suffix = "rfc.xml"
end

Private Instance Methods

abstract(isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 223
def abstract(isoxml, front)
  a = isoxml.at(ns("//preface/abstract | //preface/foreword")) || return
  front.abstract **attr_code(anchor: a["id"]) do |abs|
    a.children.reject { |c1| %w(title note).include? c1.name }.each do |c1|
      parse(c1, abs)
    end
  end
end
address(addr, phone, fax, email, uri, out) click to toggle source
# File lib/isodoc/ietf/front.rb, line 135
def address(addr, phone, fax, email, uri, out)
  return unless addr || phone || fax || email || uri

  out.address do |a|
    addr and postal(addr, a)
    phone and a.phone phone.text
    fax and a.facsimile fax.text
    email and email(email, a)
    uri and a.uri uri.text
  end
end
admitted_term_parse(node, out) click to toggle source
# File lib/isodoc/ietf/terms.rb, line 20
def admitted_term_parse(node, out)
  out.t do |p|
    node.children.each { |c| parse(c, p) }
  end
end
admonition_name_parse(_node, div, name) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 182
def admonition_name_parse(_node, div, name)
  div.t **{ keepWithNext: "true" } do |p|
    name.children.each { |n| parse(n, p) }
  end
end
admonition_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 188
def admonition_parse(node, out)
  type = node["type"]
  name = admonition_name(node, type)
  out.aside **{ anchor: node["id"] } do |t|
    admonition_name_parse(node, t, name) if name
    node.children.each { |n| parse(n, t) unless n.name == "name" }
  end
end
annex(isoxml, out) click to toggle source
# File lib/isodoc/ietf/section.rb, line 173
def annex(isoxml, out)
  isoxml.xpath(ns("//annex")).each do |c|
    clause_parse(c, out)
  end
end
annotation_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 186
def annotation_cleanup(docxml)
  docxml.xpath("//reference").each do |r|
    next unless r&.next_element&.name == "aside"

    aside = r.next_element
    aside.name = "annotation"
    aside.traverse do |n|
      n.name == "t" and n.replace(n.children)
    end
    r << aside
  end
  docxml.xpath("//references/aside").each(&:remove)
end
annotation_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 131
def annotation_parse(node, out)
  @sourcecode = false
  @annotation = true
  node.at("./preceding-sibling::*[local-name() = 'annotation']") or
    out << "\n\n"
  callout = node.at(ns("//callout[@target='#{node['id']}']"))
  out << "\n&lt;#{callout.text}&gt; "
  out << node&.children&.text&.strip
  @annotation = false
end
area(_isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 205
def area(_isoxml, front)
  @meta.get[:areas].each do |w|
    front.area w
  end
end
aside_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 227
def aside_cleanup(docxml)
  docxml.xpath("//t[descendant::aside] | //table[descendant::aside] | "\
               "//figure[descendant::aside]").each do |p|
    insert = p
    p.xpath(".//aside").each do |a|
      insert.next = a.remove
      insert = insert.next_element
    end
  end
end
author(isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 71
def author(isoxml, front)
  isoxml.xpath(("//xmlns:bibdata/xmlns:contributor[xmlns:role/@type = "\
                "'author' or xmlns:role/@type = 'editor']")).each do |c|
    role = c.at(ns("./role/@type")).text == "editor" ? "editor" : nil
    c.at("./organization") and org_author(c, role, front) or
      person_author(c, role, front)
  end
end
bcp14_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 35
def bcp14_parse(node, out)
  out.bcp14 do |e|
    node.children.each { |n| parse(n, e) }
  end
end
biblio_list(node, div, biblio) click to toggle source
# File lib/isodoc/ietf/references.rb, line 34
def biblio_list(node, div, biblio)
  i = 0
  node.xpath(ns("./bibitem | ./note")).each do |b|
    next if implicit_reference(b)

    i += 1 if b.name == "bibitem"
    if b.name == "note" then note_parse(b, div)
    elsif ietf?(b) then ietf_bibitem_entry(div, b, i)
    else
      nonstd_bibitem(div, b, i, biblio)
    end
  end
end
bibliography(isoxml, out) click to toggle source

TODO displayreference will be implemented as combination of autofetch and user-provided citations

# File lib/isodoc/ietf/references.rb, line 6
def bibliography(isoxml, out)
  isoxml.xpath(ns("//references/bibitem/docidentifier")).each do |i|
    i.children = docid_prefix(i["type"], i.text)
  end
  isoxml.xpath(ns("//bibliography/references | "\
                  "//bibliography/clause[.//references] | "\
                  "//annex/clause[.//references] | "\
                  "//annex/references | "\
                  "//sections/clause[.//references]")).each do |f|
    bibliography1(f, out)
  end
end
bibliography1(node, out) click to toggle source
# File lib/isodoc/ietf/references.rb, line 19
def bibliography1(node, out)
  out.references **attr_code(anchor: node["id"]) do |div|
    title = node.at(ns("./title")) and div.name do |name|
      title.children.each { |n| parse(n, name) }
    end
    node.elements.select do |e|
      %w(references clause).include? e.name
    end.each { |e| bibliography1(e, out) }
    node.elements.reject do |e|
      %w(references title bibitem note).include? e.name
    end.each { |e| parse(e, div) }
    biblio_list(node, div, true)
  end
end
boilerplate(isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 245
def boilerplate(isoxml, front); end
bookmark_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 223
def bookmark_cleanup(docxml)
  docxml.xpath("//bookmark").each(&:remove)
end
bookmark_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 163
def bookmark_parse(node, out)
  out.bookmark nil, **attr_code(anchor: node["id"])
end
br_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 74
def br_parse(node, out)
  if @sourcecode
    out.br
  end
end
clause(isoxml, out) click to toggle source
# File lib/isodoc/ietf/section.rb, line 162
def clause(isoxml, out)
  isoxml.xpath("//xmlns:preface/child::*"\
               "[not(name() = 'abstract' or name() = 'foreword')] "\
               "| //xmlns:sections/child::*").each do |c|
    # cdup = c.dup
    # cdup.xpath(ns(".//references")).each { |r| r.remove }
    # cdup.at("./*[local-name() != 'title'][normalize-space(text()) != '']") or next
    clause_parse(c, out)
  end
end
clause_parse(node, out) click to toggle source
# File lib/isodoc/ietf/section.rb, line 148
def clause_parse(node, out)
  return if node.at(ns(".//references"))

  out.section **attr_code(
    anchor: node["id"], numbered: node["numbered"],
    removeInRFC: node["removeInRFC"], toc: node["toc"]
  ) do |div|
    clause_parse_title(node, div, node.at(ns("./title")), out)
    node.children.reject { |c1| c1.name == "title" }.each do |c1|
      parse(c1, div)
    end
  end
end
clause_parse_title(_node, div, clause, _out, _heading_attrs = {}) click to toggle source
# File lib/isodoc/ietf/section.rb, line 140
def clause_parse_title(_node, div, clause, _out, _heading_attrs = {})
  return unless clause

  div.name do |n|
    clause&.children&.each { |c2| parse(c2, n) }
  end
end
cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 3
def cleanup(docxml)
  image_cleanup(docxml)
  figure_cleanup(docxml)
  table_cleanup(docxml)
  footnote_cleanup(docxml)
  sourcecode_cleanup(docxml)
  annotation_cleanup(docxml)
  deflist_cleanup(docxml)
  bookmark_cleanup(docxml)
  aside_cleanup(docxml)
  front_cleanup(docxml)
  docxml
end
common_rfc_pis(node) click to toggle source
# File lib/isodoc/ietf/section.rb, line 3
def common_rfc_pis(node)
  rfc_pis = {
    artworkdelimiter: node&.at(ns("//pi/artworkdelimiter"))&.text,
    artworklines: node&.at(ns("//pi/artworklines"))&.text,
    authorship: node&.at(ns("//pi/authorship"))&.text,
    autobreaks: node&.at(ns("//pi/autobreaks"))&.text,
    background: node&.at(ns("//pi/background"))&.text,
    colonspace: node&.at(ns("//pi/colonspace"))&.text,
    comments: node&.at(ns("//pi/comments"))&.text,
    docmapping: node&.at(ns("//pi/docmapping"))&.text,
    editing: node&.at(ns("//pi/editing"))&.text,
    emoticonic: node&.at(ns("//pi/emoticonic"))&.text,
    footer: node&.at(ns("//pi/footer"))&.text,
    header: node&.at(ns("//pi/header"))&.text,
    inline: node&.at(ns("//pi/inline"))&.text,
    iprnotified: node&.at(ns("//pi/iprnotified"))&.text,
    linkmailto: node&.at(ns("//pi/linkmailto"))&.text,
    linefile: node&.at(ns("//pi/linefile"))&.text,
    notedraftinprogress: node&.at(ns("//pi/notedraftinprogress"))&.text,
    private: node&.at(ns("//pi/private"))&.text,
    refparent: node&.at(ns("//pi/refparent"))&.text,
    rfcedstyle: node&.at(ns("//pi/rfcedstyle"))&.text,
    slides: node&.at(ns("//pi/slides"))&.text,
    "text-list-symbols": node&.at(ns("//pi/text-list-symbols"))&.text,
    tocappendix: node&.at(ns("//pi/tocappendix"))&.text,
    tocindent: node&.at(ns("//pi/tocindent"))&.text,
    tocnarrow: node&.at(ns("//pi/tocnarrow"))&.text,
    tocompact: node&.at(ns("//pi/tocompact"))&.text,
    topblock: node&.at(ns("//pi/topblock"))&.text,
    useobject: node&.at(ns("//pi/useobject"))&.text,
    strict: node&.at(ns("//pi/strict"))&.text || "yes",
    compact: node&.at(ns("//pi/compact"))&.text || "yes",
    subcompact: node&.at(ns("//pi/subcompact"))&.text || "no",
    toc: node&.at(ns("//pi/tocinclude"))&.text,
    tocdepth: node&.at(ns("//pi/toc-depth"))&.text || "4",
    symrefs: node&.at(ns("//pi/sym-refs"))&.text || "yes",
    sortrefs: node&.at(ns("//pi/sort-refs"))&.text || "yes",
  }
  attr_code(rfc_pis)
end
concept_parse(node, out) click to toggle source
# File lib/isodoc/ietf/terms.rb, line 50
def concept_parse(node, out)
  if d = node.at(ns("./renderterm"))
    out.em do |em|
      d.children.each { |n| parse(n, em) }
    end
    out << " "
  end
  out << "[term defined in "
  r = node.at(ns("./xref | ./eref | ./termref"))
  parse(r, out)
  out << "]"
end
content_validate(xml, filename) click to toggle source
# File lib/isodoc/ietf/validation.rb, line 18
def content_validate(xml, filename)
  err = []
  err += numbered_sections_check(xml)
  err += toc_sections_check(xml)
  err += references_check(xml)
  err += xref_check(xml)
  err += metadata_check(xml)
  return if err.empty?

  FileUtils.mv(filename, "#{filename}.err")
  err.each { |e| warn "RFC XML: #{e}" }
  warn "Cannot continue processing"
end
convert1(docxml, _filename, _dir) click to toggle source
# File lib/isodoc/ietf/rfc_convert.rb, line 18
def convert1(docxml, _filename, _dir)
  @xrefs.parse docxml
  info docxml, nil
  xml = noko do |xml|
    xml.rfc **attr_code(rfc_attributes(docxml)) do |html|
      make_link(html, docxml)
      make_front(html, docxml)
      make_middle(html, docxml)
      make_back(html, docxml)
    end
  end.join("\n").sub(/<!DOCTYPE[^>]+>\n/, "")
  set_pis(docxml, Nokogiri::XML(xml))
end
date(_isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 180
def date(_isoxml, front)
  date = @meta.get[:publisheddate] || @meta.get[:circulateddate] || return
  date = date.gsub(/T.*$/, "")
  attr = date_attr(date) || return
  front.date **attr_code(attr)
end
date_attr(date) click to toggle source
# File lib/isodoc/ietf/front.rb, line 187
def date_attr(date)
  return nil if date.nil?

  if date.length == 4 && date =~ /^\d\d\d\d$/ then { year: date }
  elsif /^\d\d\d\d-?\d\d$/.match?(date)
    m = /^(?<year>\d\d\d\d)-(?<month>\d\d)$/.match date
    { month: Date::MONTHNAMES[(m[:month]).to_i], year: m[:year] }
  else
    begin
      d = Date.iso8601 date
      { day: d.day.to_s.gsub(/^0/, ""), year: d.year,
        month: Date::MONTHNAMES[d.month] }
    rescue StandardError
      nil
    end
  end
end
dd_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 216
def dd_cleanup(docxml)
  docxml.xpath("//dd").each do |d|
    d&.first_element_child&.name == "bookmark" and
      d["anchor"] ||= d.first_element_child["anchor"]
  end
end
definition_parse(node, out) click to toggle source
# File lib/isodoc/ietf/terms.rb, line 3
def definition_parse(node, out)
  node.children.each { |n| parse(n, out) }
end
deflist_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 200
def deflist_cleanup(docxml)
  dt_cleanup(docxml)
  dd_cleanup(docxml)
end
deprecated_term_parse(node, out) click to toggle source
# File lib/isodoc/ietf/terms.rb, line 13
def deprecated_term_parse(node, out)
  out.t do |p|
    p << l10n("#{@i18n.deprecated}: ")
    node.children.each { |c| parse(c, p) }
  end
end
dl_attrs(node) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 60
def dl_attrs(node)
  attr_code(anchor: node["id"],
            newline: node["newline"],
            indent: node["indent"],
            spacing: node["spacing"])
end
dt_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 205
def dt_cleanup(docxml)
  docxml.xpath("//dt").each do |d|
    d&.first_element_child&.name == "bookmark" and
      d["anchor"] ||= d.first_element_child["anchor"]
    d.xpath(".//t").each do |t|
      d["anchor"] ||= t["anchor"]
      t.replace(t.children)
    end
  end
end
dt_parse(dt, term) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 67
def dt_parse(dt, term)
  if dt.elements.empty?
    term << dt.text
  else
    dt.children.each { |n| parse(n, term) }
  end
end
em_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 5
def em_parse(node, out)
  out.em do |e|
    node.children.each { |n| parse(n, e) }
  end
end
email(email, out) click to toggle source
# File lib/isodoc/ietf/front.rb, line 174
def email(email, out)
  ascii = email.text.transliterate
  out.email email.text,
            **attr_code(ascii: ascii == email.text ? nil : ascii)
end
eref_clause(refs, target) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 134
def eref_clause(refs, target)
  ret = []
  ret1 = ""
  refs.each do |l|
    if l.name == "localityStack"
      ret << ret1
      ret1 = ""
      ret << eref_clause1(l.elements, target)
    else
      ret1 += eref_clause1([l], target)
    end
  end
  ret << ret1
  ret.reject { |c| c.nil? || c.empty? }.join("; ")
end
eref_clause1(refs, target) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 150
def eref_clause1(refs, target)
  refs.each do |l|
    next unless %w(clause section).include? l["type"]
    return l&.at(ns("./referenceFrom"))&.text
  end
  return ""
end
eref_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 121
def eref_parse(node, out)
  linkend = node.children.reject { |c| %w{locality localityStack}.include? c.name }
  relative = node["relative"] ||
    node.at(ns(".//locality[@type = 'anchor']/referenceFrom"))&.text || ""
  section = eref_clause(node.xpath(ns("./locality | ./localityStack")), nil) || ""
  section = "" if relative.empty?
  out.relref **attr_code(target: node["bibitemid"], section: section,
                         relative: relative,
                         displayFormat: node["displayFormat"]) do |l|
                           linkend.each { |n| parse(n, l) }
                         end
end
error_parse(node, out) click to toggle source
# File lib/isodoc/ietf/rfc_convert.rb, line 51
def error_parse(node, out)
  case node.name
  when "bcp14" then bcp14_parse(node, out)
  when "concept" then concept_parse(node, out)
  else
    text = node.to_xml.gsub(/</, "&lt;").gsub(/>/, "&gt;")
    out.t { |p| p << text }
  end
end
example_label(node, div, name) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 101
def example_label(node, div, name)
  n = @xrefs.get[node["id"]]
  div.t **attr_code(anchor: node["id"], keepWithNext: "true") do |p|
    lbl = if n.nil? || n[:label].nil? || n[:label].empty?
            @i18n.example
          else
            l10n("#{@i18n.example} #{n[:label]}")
          end
    p << lbl
    name and !lbl.nil? and p << ": "
    name and name.children.each { |n| parse(n, p) }
  end
end
example_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 96
def example_parse(node, out)
  example_label(node, out, node.at(ns("./name")))
  node.elements.each { |n| parse(n, out) unless n.name == "name" }
end
extract_delims(text) click to toggle source
# File lib/isodoc/ietf/rfc_convert.rb, line 40
def extract_delims(text)
  @openmathdelim = "$$"
  @closemathdelim = "$$"
  while %r{#{Regexp.escape(@openmathdelim)}}m.match(text) ||
      %r{#{Regexp.escape(@closemathdelim)}}m.match(text)
    @openmathdelim += "$"
    @closemathdelim += "$"
  end
  [@openmathdelim, @closemathdelim]
end
figure_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 47
def figure_cleanup(docxml)
  figure_postamble(docxml)
  figure_unnest(docxml)
  figure_footnote_cleanup(docxml)
  figure_data_uri(docxml)
end
figure_data_uri(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 54
def figure_data_uri(docxml)
  docxml.xpath("//artwork").each do |a|
    next unless %r{^data:image/svg\+xml;base64}.match?(a["src"])

    f = Metanorma::Utils::save_dataimage(a["src"])
    a.delete("src")
    a.children = File.read(f).sub(%r{<\?.+\?>}, "")
  end
end
figure_footnote_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 35
def figure_footnote_cleanup(docxml)
  docxml.xpath("//figure[descendant::fn]").each do |t|
    t.xpath(".//fn").each do |a|
      t << "<aside>#{a.remove.children}</aside>"
    end
  end
end
figure_name_parse(_node, div, name) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 207
def figure_name_parse(_node, div, name)
  return if name.nil?

  div.name do |_n|
    name.children.each { |n| parse(n, div) }
  end
end
figure_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 219
def figure_parse(node, out)
  return pseudocode_parse(node, out) if node["class"] == "pseudocode" ||
    node["type"] == "pseudocode"

  @in_figure = true
  out.figure **attr_code(anchor: node["id"]) do |div|
    figure_name_parse(node, div, node.at(ns("./name")))
    node.children.each do |n|
      parse(n, div) unless n.name == "name"
    end
  end
  @in_figure = false
end
figure_postamble(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 76
def figure_postamble(docxml)
  make_postamble(docxml)
  move_postamble(docxml)
  move_preamble(docxml)
end
figure_unnest(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 64
def figure_unnest(docxml)
  docxml.xpath("//figure[descendant::figure]").each do |f|
    insert = f
    f.xpath(".//figure").each do |a|
      title = f.at("./name") and a.children.first.previous = title.remove
      insert.next = a.remove
      insert = insert.next_element
    end
    f.remove
  end
end
footnote_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 115
def footnote_cleanup(docxml)
  fn = footnote_refs_cleanup(docxml)
  endnotes = make_endnotes(docxml)
  docxml.xpath("//section[descendant::fn] | "\
               "//abstract[descendant::fn]").each do |s|
    s.xpath(".//fn").each do |f|
      ref = f.at(".//ref") and ref.replace("[#{fn[ref.text]}] ")
      endnotes << f.remove.children
    end
  end
end
footnote_parse(node, out) click to toggle source
# File lib/isodoc/ietf/footnotes.rb, line 3
def footnote_parse(node, out)
  return table_footnote_parse(node, out) if @in_table || @in_figure
  fn = node["reference"]
  out.fnref fn
  make_local_footnote(node, fn, out)
end
footnote_refs_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 127
def footnote_refs_cleanup(docxml)
  i = 0
  fn = {}
  docxml.xpath("//fnref").each do |f|
    unless fn[f.text]
      i = i + 1
      fn[f.text] = i.to_s
    end
    f.replace(" [#{fn[f.text]}]")
  end
  fn
end
formula_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 158
def formula_parse(node, out)
  formula_parse1(node, out)
  formula_where(node.at(ns("./dl")), out)
  node.children.each do |n|
    next if %w(stem dl).include? n.name

    parse(n, out)
  end
end
formula_parse1(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 149
def formula_parse1(node, out)
  out.t **attr_code(anchor: node["id"]) do |p|
    parse(node.at(ns("./stem")), p)
    lbl = @xrefs.anchor(node["id"], :label, false)
    lbl.nil? or
      p << "    (#{lbl})"
  end
end
formula_where(dl, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 142
def formula_where(dl, out)
  return unless dl

  out.t { |p| p << @i18n.where }
  parse(dl, out)
end
front_cleanup(xmldoc) click to toggle source

TODO: insert <u>

# File lib/isodoc/ietf/cleanup.rb, line 19
def front_cleanup(xmldoc)
  xmldoc.xpath("//title").each { |s| s.children = s.text }
  xmldoc.xpath("//reference/front[not(author)]").each do |f|
    insert = f.at("./seriesInfo[last()]") || f.at("./title")
    insert.next = "<author surname='Unknown'/>"
  end
end
get_linkend(node) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 113
def get_linkend(node)
  contents = node.children.select { |c| !%w{locality localityStack}.include? c.name }.
    select { |c| !c.text? || /\S/.match(c) }
  !contents.empty? and
    return Nokogiri::XML::NodeSet.new(node.document, contents).to_xml
  ""
end
get_table_ancestor_id(node) click to toggle source
# File lib/isodoc/ietf/footnotes.rb, line 64
def get_table_ancestor_id(node)
  table = node.ancestors("table") || node.ancestors("figure")
  return UUIDTools::UUID.random_create.to_s if table.empty?
  table.last["id"]
end
hr_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 80
def hr_parse(node, out)
end
id_seriesinfo(isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 62
def id_seriesinfo(isoxml, front)
  front.seriesInfo nil,
                   **seriesinfo_attr(isoxml)
                     .merge({ name: "Internet-Draft",
                              asciiName: "Internet-Draft" })
  i = isoxml&.at(ns("//bibdata/series[@type = 'intended']/title"))&.text and
    front.seriesInfo **attr_code(name: "", value: "", status: i)
end
ietf?(bib) click to toggle source
# File lib/isodoc/ietf/references.rb, line 166
def ietf?(bib)
  return false if !@xinclude

  url = bib.at(ns("./uri[@type = 'xml']")) or return false
  /xml2rfc\.tools\.ietf\.org/.match(url)
end
ietf_bibitem_entry(div, bib, _idx) click to toggle source
# File lib/isodoc/ietf/references.rb, line 161
def ietf_bibitem_entry(div, bib, _idx)
  url = bib&.at(ns("./uri[@type = 'xml']"))&.text
  div << "<xi:include href='#{url}'/>"
end
image_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 150
def image_cleanup(docxml)
  docxml.xpath("//t[descendant::artwork]").each do |t|
    insert = t
    t.xpath(".//artwork").each_with_index do |a, i|
      insert.next = a.dup
      insert = insert.next
      a.replace("[IMAGE #{i + 1}]")
    end
  end
end
image_parse(node, out, caption) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 89
def image_parse(node, out, caption)
  attrs = { src: node["src"], title: node["title"],
            align: node["align"], name: node["filename"],
            anchor: node["id"], type: "svg",
            alt: node["alt"] }
  out.artwork **attr_code(attrs)
  image_title_parse(out, caption)
end
image_title_parse(out, caption) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 98
def image_title_parse(out, caption)
  unless caption.nil?
    out.t **{ align: "center", keepWithPrevious: "true" } do |p|
      p << caption.to_s
    end
  end
end
index_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 158
def index_parse(node, out)
  out.iref nil, **attr_code(item: node.at(ns("./primary")).text, primary: node["primary"],
                            subitem: node&.at(ns("./secondary"))&.text)
end
info(isoxml, out) click to toggle source
Calls superclass method
# File lib/isodoc/ietf/front.rb, line 21
def info(isoxml, out)
  @meta.areas isoxml, out
  super
end
init_file(filename, debug) click to toggle source
Calls superclass method
# File lib/isodoc/ietf/rfc_convert.rb, line 81
def init_file(filename, debug)
  filename = filename.sub(/\.rfc\.xml$/, ".rfc")
  super
end
inline?(node) click to toggle source
# File lib/isodoc/ietf/reqt.rb, line 58
def inline?(node)
  return true if node.first_element_child.nil?
  %w(em link eref xref strong tt sup sub strike keyword smallcap
     br hr bookmark pagebreak stem origin term preferred admitted
     deprecates domain termsource modification).include? node.first_element_child.name
end
ipr_check(xml) click to toggle source

5.4.2.3. “Copyright Notice” Insertion

# File lib/isodoc/ietf/validation.rb, line 182
def ipr_check(xml)
  xml.root["ipr"] or
    return ["Missing ipr attribute on <rfc> element (:ipr:)"]
  /trust200902$/.match(xml.root["ipr"]) or
    return ["Unknown ipr attribute on <rfc> element (:ipr:): "\
            "#{xml.root['ipr']}"]
  []
end
keyword(_isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 217
def keyword(_isoxml, front)
  @meta.get[:keywords].each do |kw|
    front.keyword kw
  end
end
keyword_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 49
def keyword_parse(node, out)
  node.children.each { |n| parse(n, out) }
end
label(sect) click to toggle source
# File lib/isodoc/ietf/validation.rb, line 32
def label(sect)
  sect&.at("./name")&.text ||
    sect["name"] || sect["anchor"]
end
make_back(out, isoxml) click to toggle source
# File lib/isodoc/ietf/section.rb, line 133
def make_back(out, isoxml)
  out.back do |back|
    bibliography isoxml, back
    annex isoxml, back
  end
end
make_endnotes(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 140
def make_endnotes(docxml)
  return unless docxml.at("//fn")

  unless endnotes = docxml.at("//back")
    docxml << "<back/>" and endnotes = docxml.at("//back")
  end
  endnotes << "<section><name>Endnotes</name></section>"
  docxml.at("//back/section[last()]")
end
make_front(out, isoxml) click to toggle source
# File lib/isodoc/ietf/front.rb, line 5
def make_front(out, isoxml)
  info(isoxml, out)
  out.front do |front|
    title isoxml, front
    seriesinfo isoxml, front
    author isoxml, front
    date isoxml, front
    area isoxml, front
    workgroup isoxml, front
    keyword isoxml, front
    abstract isoxml, front
    note isoxml, front
    boilerplate isoxml, front
  end
end
make_generic_footnote_text(node, fnref) click to toggle source
# File lib/isodoc/ietf/footnotes.rb, line 18
def make_generic_footnote_text(node, fnref)
  first = node.first_element_child
  noko do |xml|
    xml.fn do |div|
      xml.t **attr_code(anchor: first ? first["id"] : nil) do |div|
        div.ref fnref
        first.name == "p" and first.children.each { |n| parse(n, div) }
      end
      first.name == "p" and
        node.elements.drop(1).each { |n| parse(n, xml) } or
        node.children.each { |n| parse(n, xml) }
    end
  end.join
end
make_local_footnote(node, fn, out) click to toggle source
# File lib/isodoc/ietf/footnotes.rb, line 10
def make_local_footnote(node, fn, out)
  return if @seen_footnote.include?(fn)
  @in_footnote = true
  out << make_generic_footnote_text(node, fn)
  @in_footnote = false
  @seen_footnote << fn
end
make_middle(out, isoxml) click to toggle source
# File lib/isodoc/ietf/section.rb, line 127
def make_middle(out, isoxml)
  out.middle do |middle|
    clause isoxml, middle
  end
end
make_postamble(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 82
def make_postamble(docxml)
  docxml.xpath("//figure").each do |f|
    a = f&.at("./artwork | ./sourcecode") || next
    name = f&.at("./name")&.remove
    b = a&.xpath("./preceding-sibling::*")&.remove
    c = a&.xpath("./following-sibling::*")&.remove
    a = a.remove
    name and f << name
    b.empty? or f << "<preamble>#{b.to_xml}</preamble>"
    a and f << a
    c.empty? or f << "<postamble>#{c.to_xml}</postamble>"
  end
end
make_table_footnote_text(node, fnid, fnref) click to toggle source
# File lib/isodoc/ietf/footnotes.rb, line 51
def make_table_footnote_text(node, fnid, fnref)
  first = node.first_element_child
  noko do |xml|
    xml.t **attr_code(anchor: first ? first["id"] : nil) do |div|
      div << "[#{fnref}]  "
      first.name == "p" and first.children.each { |n| parse(n, div) }
    end
    first.name == "p" and
      node.elements.drop(1).each { |n| parse(n, xml) } or
      node.children.each { |n| parse(n, xml) }
  end.join
end
make_tr_attr(td, row, totalrows, header) click to toggle source
# File lib/isodoc/ietf/table.rb, line 38
def make_tr_attr(td, row, totalrows, header)
  attr_code(rowspan: td["rowspan"], colspan: td["colspan"],
            align: td["align"] )
end
metadata_check(xml) click to toggle source
# File lib/isodoc/ietf/validation.rb, line 146
def metadata_check(xml)
  ret = []
  ret += link_check(xml)
  ret += seriesInfo_check(xml)
  ret += ipr_check(xml)
  ret
end
metadata_init(lang, script, i18n) click to toggle source
# File lib/isodoc/ietf/rfc_convert.rb, line 32
def metadata_init(lang, script, i18n)
  @meta = Metadata.new(lang, script, i18n)
end
modification_parse(node, out) click to toggle source
# File lib/isodoc/ietf/terms.rb, line 7
def modification_parse(node, out)
  para = node.at(ns("./p"))
  out << " -- "
  para.children.each { |n| parse(n, out) }
end
move_postamble(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 96
def move_postamble(docxml)
  docxml.xpath("//postamble").each do |p|
    insert = p.parent
    p.remove.elements.each do |e|
      insert.next = e
      insert = insert.next_element
    end
  end
end
move_preamble(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 106
def move_preamble(docxml)
  docxml.xpath("//preamble").each do |p|
    insert = p.parent
    p.remove.elements.each do |e|
      insert.previous = e
    end
  end
end
nonstd_bibitem(list, bib, _ordinal, _bibliography) click to toggle source
# File lib/isodoc/ietf/references.rb, line 48
def nonstd_bibitem(list, bib, _ordinal, _bibliography)
  uris = bib.xpath(ns("./uri"))
  target = nil
  uris&.each { |u| target = u.text if u["type"] == "src" }
  list.reference **attr_code(target: target,
                             anchor: bib["id"]) do |r|
    nonstd_bibitem_front(r, bib)
    uris&.each do |u|
      r.format nil, **attr_code(target: u.text, type: u["type"])
    end
    docidentifiers = bib.xpath(ns("./docidentifier"))
    id = render_identifier(bibitem_ref_code(bib))
    !id[1].nil? && id[1] != "(NO ID)" and r.refcontent id[1]
    docidentifiers&.each do |u|
      if %w(DOI IETF).include? u["type"]
        r.seriesInfo nil, **attr_code(value: u.text.sub(/^DOI /, ""),
                                      name: u["type"])
      end
    end
  end
end
nonstd_bibitem_front(ref, bib) click to toggle source
# File lib/isodoc/ietf/references.rb, line 70
def nonstd_bibitem_front(ref, bib)
  ref.front do |f|
    relaton_to_title(bib, f)
    relaton_to_author(bib, f)
    relaton_to_date(bib, f)
    relaton_to_keyword(bib, f)
    relaton_to_abstract(bib, f)
  end
end
note(isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 232
def note(isoxml, front)
  a = isoxml.at(ns("//preface/abstract/note | //preface/foreword/note")) or
    return
  front.note **attr_code(removeInRFC: a["removeInRFC"]) do |n|
    title = a.at(ns("./name")) and n.name do |t|
      title.children.each { |tt| parse(tt, t) }
    end
    a.children.reject { |c1| c1.name == "name" }.each do |c1|
      parse(c1, n)
    end
  end
end
note_label(node) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 75
def note_label(node)
  n = @xrefs.get[node["id"]]
  return l10n("#{@i18n.note}: ") if n.nil? || n[:label].nil? ||
    n[:label].empty?

  l10n("#{@i18n.note} #{n[:label]}: ")
end
note_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 83
def note_parse(node, out)
  first = node.first_element_child
  out.aside **attr_code(anchor: node["id"] || first["id"]) do |a|
    a.t do |p|
      p << note_label(node)
      first.name == "p" and first.children.each { |n| parse(n, p) }
    end
    first.name == "p" and
      node.elements.drop(1).each { |n| parse(n, out) } or
      node.children.each { |n| parse(n, out) }
  end
end
numbered_sections_check(xml) click to toggle source

2.46.2. “numbered” Attribute

# File lib/isodoc/ietf/validation.rb, line 38
def numbered_sections_check(xml)
  ret = []
  xml.xpath("//section[@numbered = 'false']").each do |s1|
    s1.xpath("./section[not(@numbered) or @numbered = 'true']")
      .each do |s2|
      ret << "Numbered section #{label(s2)} under unnumbered section "\
             "#{label(s1)}"
    end
    s1.xpath("./following-sibling::*[name() = 'section']"\
             "[not(@numbered) or @numbered = 'true']").each do |s2|
      ret << "Numbered section #{label(s2)} following unnumbered "\
             "section #{label(s1)}"
    end
  end
  ret
end
ol_attrs(node) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 46
def ol_attrs(node)
  { anchor: node["id"],
    spacing: node["spacing"],
    type: ol_style(node["type"]),
    group: node["group"],
    start: node["start"] }
end
ol_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 54
def ol_parse(node, out)
  out.ol **attr_code(ol_attrs(node)) do |ol|
    node.children.each { |n| parse(n, ol) }
  end
end
ol_style(type) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 42
def ol_style(type)
  OL_STYLE[type&.to_sym] || type
end
omit_docid_prefix(prefix) click to toggle source
Calls superclass method
# File lib/isodoc/ietf/rfc_convert.rb, line 61
def omit_docid_prefix(prefix)
  return true if prefix == "IETF"

  super
end
org_author(contrib, role, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 115
def org_author(contrib, role, front)
  front.author **attr_code(role: role) do |a|
    organization(contrib.at(ns("./organization")), a,
                 contrib.document.at(ns("//showOnFrontPage")))
    address(contrib.at(ns(".//address")),
            contrib.at(ns(".//phone[not(@type = 'fax')]")),
            contrib.at(ns(".//phone[@type = 'fax']")),
            contrib.at(ns(".//email")), contrib.at(ns(".//uri")), a)
  end
end
organization(org, out, show) click to toggle source
# File lib/isodoc/ietf/front.rb, line 126
def organization(org, out, show)
  name = org.at(ns("./name"))&.text
  out.organization name, **attr_code(
    showOnFrontPage: show&.text, ascii: output_if_translit(name),
    asciiAbbrev: output_if_translit(org.at(ns("./abbreviation"))),
    abbrev: org.at(ns("./abbreviation"))
  )
end
output_if_translit(text) click to toggle source
# File lib/isodoc/ietf/front.rb, line 26
def output_if_translit(text)
  return nil if text.nil?

  text.transliterate != text ? text.transliterate : nil
end
page_break(_out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 68
def page_break(_out)
end
pagebreak_parse(_node, _out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 71
def pagebreak_parse(_node, _out)
end
para_attrs(node) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 4
def para_attrs(node)
  { keepWithNext: node["keep-with-next"],
    keepWithPrevious: node["keep-with-previous"],
    anchor: node["id"] }
end
para_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 10
def para_parse(node, out)
  out.t **attr_code(para_attrs(node)) do |p|
    unless @termdomain.empty?
      p << "&lt;#{@termdomain}&gt; "
      @termdomain = ""
    end
    node.children.each { |n| parse(n, p) unless n.name == "note" }
  end
  node.xpath(ns("./note")).each { |n| parse(n, out) }
end
permission_parse(node, out) click to toggle source
# File lib/isodoc/ietf/reqt.rb, line 50
def permission_parse(node, out)
  recommendation_name(node, out, @i18n.permission)
  recommendation_attributes(node, out)
  node.children.each do |n|
    parse(n, out) unless %w(label title).include? n.name
  end
end
pers_author_attrs1(ret, full, init, contrib) click to toggle source
# File lib/isodoc/ietf/front.rb, line 92
def pers_author_attrs1(ret, full, init, contrib)
  full and ret.merge!(
    attr_code(
      asciiFullname: output_if_translit(full),
      asciiInitials: output_if_translit(init),
      asciiSurname: output_if_translit(contrib&.at(ns("./surname"))),
    ),
  )
  ret
end
person_author(contrib, role, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 103
def person_author(contrib, role, front)
  attrs = person_author_attrs(contrib.at(ns("./person/name")), role)
  front.author **attrs do |a|
    org = contrib.at(ns("./person/affiliation/organization")) and
      organization(org, a, contrib.document.at(ns("//showOnFrontPage")))
    address(contrib.xpath(ns(".//address")),
            contrib.at(ns(".//phone[not(@type = 'fax')]")),
            contrib.at(ns(".//phone[@type = 'fax']")),
            contrib.xpath(ns(".//email")), contrib.xpath(ns(".//uri")), a)
  end
end
person_author_attrs(contrib, role) click to toggle source
# File lib/isodoc/ietf/front.rb, line 80
def person_author_attrs(contrib, role)
  return {} if contrib.nil?

  full = contrib&.at(ns("./completename"))&.text
  init = contrib&.at(ns("./initial"))&.text ||
    contrib&.xpath(ns("./forename"))&.map { |n| n.text[0] }&.join(".")
  init = nil if init.empty?
  ret = attr_code(role: role, fullname: full, initials: init,
                  surname: contrib&.at(ns("./surname"))&.text)
  pers_author_attrs1(ret, full, init, contrib)
end
postal(addr, out) click to toggle source
# File lib/isodoc/ietf/front.rb, line 147
def postal(addr, out)
  out.postal do |p|
    if line = addr.at(ns("./formattedAddress"))
      line.xpath(ns(".//br")).each { |br| br.replace("\n") }
      line.text.split(/\n/).each do |l|
        p.postalLine l, **attr_code(ascii: l.transliterate)
      end
    else
      postal_detailed(addr, p)
    end
  end
end
postal_detailed(addr, out) click to toggle source
# File lib/isodoc/ietf/front.rb, line 160
def postal_detailed(addr, out)
  addr.xpath(ns("./street")).each do |s|
    out.street s.text, **attr_code(ascii: s.text.transliterate)
  end
  s = addr.at(ns("./city")) and
    out.city s.text, **attr_code(ascii: s.text.transliterate)
  s = addr.at(ns("./state")) and
    out.region s.text, **attr_code(ascii: s.text.transliterate)
  s = addr.at(ns("./country")) and
    out.country s.text, **attr_code(ascii: s.text.transliterate)
  s = addr.at(ns("./postcode")) and
    out.code s.text, **attr_code(ascii: s.text.transliterate)
end
postprocess(result, filename, _dir) click to toggle source
# File lib/isodoc/ietf/rfc_convert.rb, line 71
def postprocess(result, filename, _dir)
  result = from_xhtml(cleanup(to_xhtml(textcleanup(result))))
    .sub(/<!DOCTYPE[^>]+>\n/, "")
    .sub(/(<rfc[^<]+? )lang="[^"]+"/, "\\1")
  File.open(filename, "w:UTF-8") { |f| f.write(result) }
  schema_validate(filename)
  @files_to_delete.each { |f| FileUtils.rm_rf f }
  content_validate(to_xhtml(result), filename)
end
pre_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 124
def pre_parse(node, out)
  out.artwork **attr_code(anchor: node["id"], align: node["align"],
                          alt: node["alt"], type: "ascii-art") do |s|
    s.cdata node.text.sub(/^\n/, "").gsub(/\t/, "    ")
  end
end
pseudocode_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 215
def pseudocode_parse(node, out)
  sourcecode_parse(node, out)
end
quote_attribution(node) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 168
def quote_attribution(node)
  author = node&.at(ns("./author"))&.text
  source = node&.at(ns("./source/@uri"))&.text
  attr_code(quotedFrom: author, cite: source)
end
quote_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 174
def quote_parse(node, out)
  out.blockquote **quote_attribution(node) do |p|
    node.children.each do |n|
      parse(n, p) unless ["author", "source"].include? n.name
    end
  end
end
recommendation_attributes(node, out) click to toggle source
# File lib/isodoc/ietf/reqt.rb, line 22
def recommendation_attributes(node, out)
  ret = recommendation_attributes1(node)
  return if ret.empty?
  out.ul do |p|
    ret.each do |l|
      p.li do |i|
        i.em { |e| i << l }
      end
    end
  end
end
recommendation_labels(node) click to toggle source
# File lib/isodoc/ietf/reqt.rb, line 3
def recommendation_labels(node)
  [node.at(ns("./label")), node.at(ns("./title")), 
   @xrefs.anchor(node['id'], :label, false)]
end
recommendation_name(node, out, type) click to toggle source
# File lib/isodoc/ietf/reqt.rb, line 8
def recommendation_name(node, out, type)
  label, title, lbl = recommendation_labels(node)
  out.t **{ keepWithNext: "true" }  do |b|
    b << (lbl.nil? ? l10n("#{type}:") : l10n("#{type} #{lbl}:"))
  end
  if label || title
    out.t **{ keepWithNext: "true" }  do |b|
      label and label.children.each { |n| parse(n,b) }
      b << "#{clausedelim} " if label && title
      title and title.children.each { |n| parse(n,b) }
    end
  end
end
recommendation_parse(node, out) click to toggle source
# File lib/isodoc/ietf/reqt.rb, line 34
def recommendation_parse(node, out)
  recommendation_name(node, out, @i18n.recommendation)
  recommendation_attributes(node, out)
  node.children.each do |n|
    parse(n, out) unless %w(label title).include? n.name
  end
end
references_check(xml) click to toggle source

5.4.3 <reference> “target” Insertion 5.4.2.4 “Table of Contents” Insertion

# File lib/isodoc/ietf/validation.rb, line 69
def references_check(xml)
  ret = []
  xml.xpath("//reference[not(@target)]").each do |s|
    s.xpath(".//seriesInfo[@name = 'RFC' or @name = 'Internet-Draft' "\
            "or @name = 'DOI'][not(@value)]").each do |s1|
      ret << "for reference #{s['anchor']}, the seriesInfo with "\
             "name=#{s1['name']} has been given no value"
    end
  end
  xml.xpath("//references | //section").each do |s|
    s.at("./name") or ret << "Cannot generate table of contents entry "\
                             "for #{label(s)}, as it has no title"
  end
  ret
end
rel2iana(type) click to toggle source
# File lib/isodoc/ietf/section.rb, line 116
def rel2iana(type)
  case type
  when "includedIn" then "item"
  when "describedBy" then "describedby"
  when "derivedFrom" then "convertedfrom"
  when "instance" then "alternate"
  else
    "alternate"
  end
end
relaton_org_to_author(org, _role, node) click to toggle source
# File lib/isodoc/ietf/references.rb, line 120
def relaton_org_to_author(org, _role, node)
  name = org&.at(ns("./name"))&.text
  abbrev = org&.at(ns("./abbreviation"))&.text
  node.author do |_a|
    node.organization name, **attr_code(ascii: name&.transliterate,
                                        abbrev: abbrev)
  end
end
relaton_person_to_author(pers, role, node) click to toggle source
# File lib/isodoc/ietf/references.rb, line 102
def relaton_person_to_author(pers, role, node)
  full = pers&.at(ns("./completename"))&.text
  surname = pers&.at(ns("./surname"))&.text
  initials = pers&.xpath(ns("./initial"))&.map do |i|
               i.text
             end&.join(" ") ||
    pers&.xpath(ns("./forename"))&.map { |i| i.text[0] }&.join(" ")
  initials = nil if initials.empty?
  node.author nil, **attr_code(
    fullname: full,
    asciiFullname: full&.transliterate,
    role: role, surname: surname,
    initials: initials,
    asciiSurname: full ? surname&.transliterate : nil,
    asciiInitials: full ? initials&.transliterate : nil
  )
end
relaton_to_abstract(bib, node) click to toggle source
# File lib/isodoc/ietf/references.rb, line 147
def relaton_to_abstract(bib, node)
  bib.xpath(ns("./abstract")).each do |k|
    node.abstract do |abstract|
      if k.at(ns("./p"))
        k.children.each { |n| parse(n, abstract) }
      else
        abstract.t do |t|
          k.children.each { |n| parse(n, t) }
        end
      end
    end
  end
end
relaton_to_author(bib, node) click to toggle source
# File lib/isodoc/ietf/references.rb, line 88
def relaton_to_author(bib, node)
  auths = bib.xpath(ns("./contributor[xmlns:role/@type = 'author' or "\
                       "xmlns:role/@type = 'editor']"))
  auths.empty? and
    auths = bib.xpath(ns("./contributor[xmlns:role/@type = "\
                         "'publisher']"))
  auths.each do |a|
    role = a.at(ns("./role[@type = 'editor']")) ? "editor" : nil
    p = a&.at(ns("./person/name")) and
      relaton_person_to_author(p, role, node) or
      relaton_org_to_author(a&.at(ns("./organization")), role, node)
  end
end
relaton_to_date(bib, node) click to toggle source
# File lib/isodoc/ietf/references.rb, line 129
def relaton_to_date(bib, node)
  date = bib.at(ns("./date[@type = 'published']")) ||
    bib.at(ns("./date[@type = 'issued']")) ||
    bib.at(ns("./date[@type = 'circulated']"))
  return unless date

  attr = date_attr(date&.at(ns("./on | ./from"))&.text) || return
  node.date **attr_code(attr)
end
relaton_to_keyword(bib, node) click to toggle source
# File lib/isodoc/ietf/references.rb, line 139
def relaton_to_keyword(bib, node)
  bib.xpath(ns("./keyword")).each do |k|
    node.keyword do |keyword|
      k.children.each { |n| parse(n, keyword) }
    end
  end
end
relaton_to_title(bib, node) click to toggle source
# File lib/isodoc/ietf/references.rb, line 80
def relaton_to_title(bib, node)
  title = bib&.at(ns("./title")) || bib&.at(ns("./formattedref")) or
    return
  node.title do |t|
    title.children.each { |n| parse(n, t) }
  end
end
requirement_component_parse(node, out) click to toggle source
# File lib/isodoc/ietf/reqt.rb, line 65
def requirement_component_parse(node, out)
  return if node["exclude"] == "true"
  out1 = out
  if inline?(node)
    out.t do |p|
      p << "INHERIT: " if node.name == "inherit"
      node.children.each { |n| parse(n, p) }
    end
  else
    node.children.each { |n| parse(n, out) }
  end
end
requirement_parse(node, out) click to toggle source
# File lib/isodoc/ietf/reqt.rb, line 42
def requirement_parse(node, out)
  recommendation_name(node, out, @i18n.requirement)
  recommendation_attributes(node, out)
  node.children.each do |n|
    parse(n, out) unless %w(label title).include? n.name
  end
end
review_note_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 197
def review_note_parse(node, out)
  out.cref **attr_code(anchor: node["id"], display: node["display"],
                       source: node["reviewer"]) do |c|
    name = node.at(ns("./name")) and c.name do |div|
      name.children.each { |n| parse(n, div) }
    end
    node.children.each { |n| parse(n, c) unless n.name == "name" }
  end
end
rfc_attributes(docxml) click to toggle source
# File lib/isodoc/ietf/section.rb, line 54
def rfc_attributes(docxml)
  t = Time.now.getutc
  obs = xpath_comma(docxml
    .xpath(ns("//bibdata/relation[@type = 'obsoletes']/bibitem/docidentifier")))
  upd = xpath_comma(docxml
    .xpath(ns("//bibdata/relation[@type = 'updates']/bibitem/docidentifier")))
  {
    docName: @meta.get[:doctype] == "Internet Draft" ? @meta.get[:docnumber] : nil,
    number: @meta.get[:doctype].casecmp?("rfc") ? @meta.get[:docnumber] : nil,
    category: series2category(
      docxml&.at(ns("//bibdata/series[@type = 'intended']/title"))&.text,
    ),
    ipr: docxml&.at(ns("//bibdata/ext/ipr"))&.text,
    consensus: docxml&.at(ns("//bibdata/ext/consensus"))&.text,
    obsoletes: obs,
    updates: upd,
    indexInclude: docxml&.at(ns("//bibdata/ext/indexInclude"))&.text,
    iprExtract: docxml&.at(ns("//bibdata/ext/iprExtract"))&.text,
    sortRefs: docxml&.at(ns("//bibdata/ext/sortRefs"))&.text,
    symRefs: docxml&.at(ns("//bibdata/ext/symRefs"))&.text,
    tocInclude: docxml&.at(ns("//bibdata/ext/tocInclude"))&.text,
    tocDepth: docxml&.at(ns("//bibdata/ext/tocDepth"))&.text,
    submissionType: docxml&.at(ns(
      "//bibdata/series[@type = 'stream']/title",
    ))&.text || "IETF",
    'xml:lang': docxml&.at(ns("//bibdata/language"))&.text,
    version: "3",
    'xmlns:xi': "http://www.w3.org/2001/XInclude",
  }
end
rfc_seriesinfo(isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 52
def rfc_seriesinfo(isoxml, front)
  front.seriesInfo **seriesinfo_attr(isoxml).merge({ name: "RFC",
                                                     asciiName: "RFC" })
  i = isoxml&.at(ns("//bibdata/series[@type = 'intended']")) and
    front.seriesInfo nil,
                     **attr_code(name: "",
                                 status: i&.at(ns("./title"))&.text,
                                 value: i&.at(ns("./number"))&.text || "")
end
schema_validate(filename) click to toggle source
# File lib/isodoc/ietf/validation.rb, line 7
def schema_validate(filename)
  errors = Jing.new(File.join(File.dirname(__FILE__), "v3.rng"))
    .validate(filename)
  errors.each do |error|
    warn "RFC XML: Line #{'%06d' % error[:line]}:#{error[:column]} "\
         "#{error[:message]}"
  end
rescue Jing::Error => e
  abort "Jing failed with error: #{e}"
end
series2category(series) click to toggle source
# File lib/isodoc/ietf/section.rb, line 85
def series2category(series)
  case series&.downcase
  when "standard", "std" then "std"
  when "informational", "info" then "info"
  when "experimental", "exp" then "exp"
  when "bcp" then "bcp"
  when "fyi" then "info"
  when "full-standard" then "std"
  when "historic" then "historic"
  else
    "std"
  end
end
seriesInfo_check(xml) click to toggle source

5.2.2. “seriesInfo” Insertion

# File lib/isodoc/ietf/validation.rb, line 165
def seriesInfo_check(xml)
  ret = []
  xml.root["ipr"] == "none" and return []
  rfcinfo = xml.at("//seriesInfo[@name = 'RFC']")
  rfcnumber = xml.root["number"]
  rfcinfo && rfcnumber && rfcnumber != rfcinfo["value"] and
    ret << "Mismatch between <rfc number='#{rfcnumber}'> "\
           "(:docnumber: NUMBER) "\
           "and <seriesInfo name='RFC' value='#{rfcinfo['value']}'> "\
           "(:intended-series: TYPE NUMBER)"
  rfcinfo && !/^\d+$/.match(rfcnumber) and
    ret << "RFC identifier <rfc number='#{rfcnumber}'> "\
           "(:docnumber: NUMBER) must be a number"
  ret
end
seriesinfo(isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 39
def seriesinfo(isoxml, front)
  rfc_seriesinfo(isoxml, front) if @meta.get[:doctype] == "Rfc"
  id_seriesinfo(isoxml, front) if @meta.get[:doctype] == "Internet Draft"
end
seriesinfo_attr(isoxml) click to toggle source
# File lib/isodoc/ietf/front.rb, line 44
def seriesinfo_attr(isoxml)
  attr_code(value: @meta.get[:docnumber] || "",
            asciiValue: output_if_translit(@meta.get[:docnumber]),
            status: @meta.get[:stage],
            stream: isoxml&.at(ns("//bibdata/series[@type = 'stream']/"\
                                  "title"))&.text)
end
set_pis(node, doc) click to toggle source
# File lib/isodoc/ietf/section.rb, line 44
def set_pis(node, doc)
  rfc_pis = common_rfc_pis(node)
  rfc_pis.each_pair do |k, v|
    pi = Nokogiri::XML::ProcessingInstruction.new(doc, "rfc",
                                                  "#{k}=\"#{v}\"")
    doc.root.add_previous_sibling(pi)
  end
  doc.to_xml
end
smallcap_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 45
def smallcap_parse(node, out)
  node.children.each { |n| parse(n, out) }
end
sourcecode_cleanup(docxml) click to toggle source

for markup in pseudocode

# File lib/isodoc/ietf/cleanup.rb, line 162
def sourcecode_cleanup(docxml)
  docxml.xpath("//sourcecode").each do |s|
    s.children = s.children.to_xml.gsub(%r{<br/>\n}, "\n")
      .gsub(%r{\s+(<t[ >])}, "\\1").gsub(%r{</t>\s+}, "</t>")
    sourcecode_remove_markup(s)
    s.children = "<![CDATA[#{HTMLEntities.new.decode(s
    .children.to_xml.sub(/\A\n+/, ''))}]]>"
  end
end
sourcecode_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 115
def sourcecode_parse(node, out)
  out.sourcecode **attr_code(
    anchor: node["id"], type: node["lang"], name: node["filename"],
    markers: node["markers"], src: node["src"]
  ) do |s|
    node.children.each { |x| parse(x, s) unless x.name == "name" }
  end
end
sourcecode_remove_markup(node) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 172
def sourcecode_remove_markup(node)
  node.traverse do |n|
    next if n.text?
    next if %w(name callout annotation note sourcecode).include? n.name

    case n.name
    when "br" then n.replace("\n")
    when "t" then n.replace("\n\n#{n.children}")
    else
      n.replace(n.children)
    end
  end
end
stem_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 59
def stem_parse(node, out)
  stem = case node["type"]
         when "MathML" then MathML2AsciiMath.m2a(node.children.to_xml)
         else
           HTMLEntities.new.encode(node.text)
         end
  out << "#{@openmathdelim} #{stem} #{@closemathdelim}"
end
strike_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 41
def strike_parse(node, out)
  node.children.each { |n| parse(n, out) }
end
strong_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 29
def strong_parse(node, out)
  out.strong do |e|
    node.children.each { |n| parse(n, e) }
  end
end
sub_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 17
def sub_parse(node, out)
  out.sub do |e|
    node.children.each { |n| parse(n, e) }
  end
end
sup_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 11
def sup_parse(node, out)
  out.sup do |e|
    node.children.each { |n| parse(n, e) }
  end
end
table_attrs(node) click to toggle source
# File lib/isodoc/ietf/table.rb, line 3
def table_attrs(node)
  attr_code(anchor: node["id"], align: node["align"])
end
table_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 43
def table_cleanup(docxml)
  table_footnote_cleanup(docxml)
end
table_footnote_cleanup(docxml) click to toggle source
# File lib/isodoc/ietf/cleanup.rb, line 27
def table_footnote_cleanup(docxml)
  docxml.xpath("//table[descendant::fn]").each do |t|
    t.xpath(".//fn").each do |a|
      t << "<aside>#{a.remove.children}</aside>"
    end
  end
end
table_footnote_parse(node, out) click to toggle source
# File lib/isodoc/ietf/footnotes.rb, line 33
def table_footnote_parse(node, out)
  fn = node["reference"]
  tid = get_table_ancestor_id(node)
  make_table_footnote_link(out, tid + fn, fn)
  # do not output footnote text if we have already seen it for this table
  return if @seen_footnote.include?(tid + fn)
  @in_footnote = true
  out.fn do |a|
    a << make_table_footnote_text(node, tid + fn, fn)
  end
  @in_footnote = false
  @seen_footnote << (tid + fn)
end
table_parse(node, out) click to toggle source
# File lib/isodoc/ietf/table.rb, line 7
def table_parse(node, out)
  @in_table = true
  out.table **table_attrs(node) do |t|
    table_title_parse(node, out)
    thead_parse(node, t)
    tbody_parse(node, t)
    tfoot_parse(node, t)
  end
  (dl = node.at(ns("./dl"))) && parse(dl, out)
  node.xpath(ns("./note")).each { |n| parse(n, out) }
  @in_table = false
end
table_title_parse(node, out) click to toggle source
# File lib/isodoc/ietf/table.rb, line 20
def table_title_parse(node, out)
  name = node.at(ns("./name")) || return
  out.name do |p|
    name.children.each { |n| parse(n, p) }
  end
end
term_parse(node, out) click to toggle source
# File lib/isodoc/ietf/terms.rb, line 26
def term_parse(node, out)
  out.name do |p|
    node.children.each { |n| parse(n, p) }
  end
end
termdef_parse(node, out) click to toggle source
# File lib/isodoc/ietf/terms.rb, line 43
def termdef_parse(node, out)
  set_termdomain("")
  clause_parse(node, out)
end
termdocsource_parse(_node, _out) click to toggle source
# File lib/isodoc/ietf/terms.rb, line 48
def termdocsource_parse(_node, _out); end
termnote_parse(node, out) click to toggle source
# File lib/isodoc/ietf/terms.rb, line 32
def termnote_parse(node, out)
  note_parse(node, out)
end
termref_parse(node, out) click to toggle source
# File lib/isodoc/ietf/terms.rb, line 36
def termref_parse(node, out)
  out.t do |p|
    p << "SOURCE: "
    node.children.each { |n| parse(n, p) }
  end
end
text_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 53
def text_parse(node, out)
  return if node.nil? || node.text.nil?
  text = node.to_s
  out << text
end
textcleanup(docxml) click to toggle source
# File lib/isodoc/ietf/rfc_convert.rb, line 67
def textcleanup(docxml)
  passthrough_cleanup(docxml)
end
title(_isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 32
def title(_isoxml, front)
  title = @meta.get[:doctitle] or return
  front.title title, **attr_code(abbrev: @meta.get[:docabbrev],
                                 ascii: (@meta.get[:docascii] ||
                                 output_if_translit(title)))
end
toc_parse(_node, _out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 233
def toc_parse(_node, _out); end
toc_sections_check(xml) click to toggle source

5.2.7. Section “toc” attribute

# File lib/isodoc/ietf/validation.rb, line 56
def toc_sections_check(xml)
  ret = []
  xml.xpath("//section[@toc = 'exclude']").each do |s1|
    s1.xpath(".//section[@toc = 'include']").each do |s2|
      ret << "Section #{label(s2)} with toc=include is included in "\
             "section #{label(s1)} with toc=exclude"
    end
  end
  ret
end
tr_parse(node, out, ord, totalrows, header) click to toggle source
# File lib/isodoc/ietf/table.rb, line 27
def tr_parse(node, out, ord, totalrows, header)
  out.tr do |r|
    node.elements.each do |td|
      attrs = make_tr_attr(td, ord, totalrows - 1, header)
      r.send td.name, **attrs do |entry|
        td.children.each { |n| parse(n, entry) }
      end
    end
  end
end
tt_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 23
def tt_parse(node, out)
  out.tt do |e|
    node.children.each { |n| parse(n, e) }
  end
end
ul_attrs(node) click to toggle source

NOTE ignoring “bare” attribute, which is tantamount to “empty”

# File lib/isodoc/ietf/blocks.rb, line 22
def ul_attrs(node)
  { anchor: node["id"],
    empty: node["nobullet"],
    spacing: node["spacing"] }
end
ul_parse(node, out) click to toggle source
# File lib/isodoc/ietf/blocks.rb, line 28
def ul_parse(node, out)
  out.ul **attr_code(ul_attrs(node)) do |ul|
    node.children.each { |n| parse(n, ul) }
  end
end
workgroup(_isoxml, front) click to toggle source
# File lib/isodoc/ietf/front.rb, line 211
def workgroup(_isoxml, front)
  @meta.get[:wg].each do |w|
    front.workgroup w
  end
end
xpath_comma(xpath) click to toggle source
# File lib/isodoc/ietf/section.rb, line 99
def xpath_comma(xpath)
  return nil if xpath.empty?

  xpath.map(&:text).join(", ")
end
xref_check(xml) click to toggle source

5.4.8.2. “derivedContent” Insertion (without Content)

# File lib/isodoc/ietf/validation.rb, line 86
def xref_check(xml)
  ret = []
  xml.xpath("//xref | //relref").each do |x|
    t = xml.at(".//*[@anchor = '#{x['target']}']") ||
      xml.at(".//*[@pn = '#{x['target']}']") or
      ret << "#{x.name} target #{x['target']} does not exist in the document"
    next unless t

    x.delete("relative") if x["relative"] && x["relative"].empty?
    x.delete("section") if x["section"] && x["section"].empty?
    if x["format"] == "title" && t.name == "reference"
      t.at("./front/title") or
        ret << "reference #{t['anchor']} has been referenced by #{x.name} "\
               "with format=title, but the reference has no title"
    end
    if x["format"] == "counter" && !%w(section table figure li
                                       reference references t dt).include?(t.name)
      ret << "#{x.to_xml} with format=counter is only allowed for "\
             "clauses, tables, figures, list entries, definition terms, "\
             "paragraphs, bibliographies, and bibliographic entries"
    end
    if x["format"] == "counter" && t.name == "reference" && !x["section"]
      ret << "reference #{t['anchor']} has been referenced by xref "\
             "#{x.to_xml} with format=counter, which requires a "\
             "section attribute"
    end
    if x["format"] == "counter" && t.name == "li" && t.parent.name != "ol"
      ret << "#{x.to_xml} with format=counter refers to an unnumbered "\
             "list entry"
    end
    if x["format"] == "title" && %w(u author contact).include?(t.name)
      ret << "#{x.to_xml} with format=title cannot reference a "\
             "<#{t.name}> element"
    end
    if x["relative"] && !x["section"]
      ret << "#{x.to_xml} with relative attribute requires a section "\
             "attribute"
    end
    if (x["section"]) && t.name != "reference"
      ret << "#{x.to_xml} has a section attribute, but #{x['target']} "\
             "points to a #{t.name}"
    end
    if (x["relative"]) && t.name != "reference"
      ret << "#{x.to_xml} has a relative attribute, but #{x['target']} "\
             "points to a #{t.name}"
    end
    if !x["relative"] && x["section"] && !t.at(".//seriesInfo[@name = 'RFC' or @name = "\
                                               "'Internet-Draft']")
      ret << "#{x.to_xml} must use a relative attribute, "\
             "since it does not point to a RFC or Internet-Draft reference"
    end
    if x["relative"] && !(t.at(".//seriesInfo[@name = 'RFC' or @name = "\
                               "'Internet-Draft']") || t["target"])
      ret << "need an explicit target= URL attribute in the reference "\
             "pointed to by #{x.to_xml}"
    end
  end
  ret
end
xref_init(lang, script, klass, i18n, options) click to toggle source
# File lib/isodoc/ietf/rfc_convert.rb, line 36
def xref_init(lang, script, klass, i18n, options)
  @xrefs = Xref.new(lang, script, klass, i18n, options)
end
xref_parse(node, out) click to toggle source
# File lib/isodoc/ietf/inline.rb, line 106
def xref_parse(node, out)
  out.xref **attr_code(target: node["target"], format: node["format"],
                       relative: node["relative"]) do |l|
                         l << get_linkend(node)
                       end
end