class Asciidoctor::ISO::Converter

A {Converter} implementation that generates ISO output, and a document schema encapsulation of the document for validation

Constants

ASSETS_TO_STYLE
NONSTD_UNITS
NON_DL_SYMBOLS_WARNING
NORMREF_FOOTNOTES
NORM_BIBITEMS
NORM_ISO_WARN
ONE_SYMBOLS_WARNING
PERMISSION_RE
PERMISSION_RE_STR
POSSIBILITY_RE
POSSIBILITY_RE_STR
POST_NORMREF_FOOTNOTES
PRE_NORMREF_FOOTNOTES
RECOMMENDATION_RE
RECOMMENDATION_RE_STR
REQUIREMENT_RE
REQUIREMENT_RE_STR
SCOPE_WARN
SECTIONS_XPATH
SEQ

spec of permissible section sequence we skip normative references, it goes to end of list

SI_UNIT

leaving out as problematic: N J K C S T H h d B o E

Public Instance Methods

appendix_parse(attrs, xml, node) click to toggle source
# File lib/asciidoctor/iso/section.rb, line 47
def appendix_parse(attrs, xml, node)
  attrs["inline-header".to_sym] = node.option? "inline-header"
  set_obligation(attrs, node)
  xml.appendix **attr_code(attrs) do |xml_section|
    xml_section.title { |name| name << node.title }
    xml_section << node.content
  end
end
asset_style(root) click to toggle source
Calls superclass method
# File lib/asciidoctor/iso/validate_section.rb, line 197
def asset_style(root)
  root.xpath("//example | //termexample").each { |e| example_style(e) }
  root.xpath("//definition").each { |e| definition_style(e) }
  root.xpath("//note").each { |e| note_style(e) }
  root.xpath("//fn").each { |e| footnote_style(e) }
  root.xpath(ASSETS_TO_STYLE).each { |e| style(e, extract_text(e)) }
  norm_bibitem_style(root)
  super
end
asset_title_style(root) click to toggle source
# File lib/asciidoctor/iso/validate_section.rb, line 180
def asset_title_style(root)
  root.xpath("//figure[image][not(title)]").each do |node|
    style_warning(node, "Figure should have title", nil)
  end
  root.xpath("//table[not(title)]").each do |node|
    style_warning(node, "Table should have title", nil)
  end
end
content_validate(doc) click to toggle source
Calls superclass method
# File lib/asciidoctor/iso/validate.rb, line 171
def content_validate(doc)
  super
  title_validate(doc.root)
  isosubgroup_validate(doc.root)
  onlychild_clause_validate(doc.root)
  termdef_style(doc.root)
  iev_validate(doc.root)
  see_xrefs_validate(doc.root)
  see_erefs_validate(doc.root)
  locality_erefs_validate(doc.root)
end
definition_style(node) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 33
def definition_style(node)
  return if @novalid
  r = requirement(extract_text(node))
  style_warning(node, "Definition may contain requirement", r) if r
end
doc_converter(node) click to toggle source
# File lib/asciidoctor/iso/base.rb, line 43
def doc_converter(node)
  IsoDoc::Iso::WordConvert.new(
    script: node.attr("script"),
    bodyfont: node.attr("body-font"),
    headerfont: node.attr("header-font"),
    monospacefont: node.attr("monospace-font"),
    i18nyaml: node.attr("i18nyaml"),
    scope: node.attr("scope"),
    wordstylesheet: node.attr("wordstylesheet"),
    standardstylesheet: node.attr("standardstylesheet"),
    header: node.attr("header"),
    wordcoverpage: node.attr("wordcoverpage"),
    wordintropage: node.attr("wordintropage"),
    ulstyle: node.attr("ulstyle"),
    olstyle: node.attr("olstyle"),
  )
end
document(node) click to toggle source
# File lib/asciidoctor/iso/base.rb, line 61
def document(node)
  init(node)
  ret = makexml(node).to_xml(indent: 2)
  unless node.attr("nodoc") || !node.attr("docfile")
    File.open(@filename + ".xml", "w:UTF-8") { |f| f.write(ret) }
    html_converter_alt(node).convert(@filename + ".xml")
    system "mv #{@filename}.html #{@filename}_alt.html"
    html_converter(node).convert(@filename + ".xml")
    doc_converter(node).convert(@filename + ".xml")
  end
  @files_to_delete.each { |f| system "rm #{f}" }
  ret
end
example_style(node) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 39
def example_style(node)
  return if @novalid
  style_no_guidance(node, extract_text(node), "Term Example")
  style(node, extract_text(node))
end
external_constraint(text) click to toggle source
# File lib/asciidoctor/iso/validate_requirements.rb, line 88
def external_constraint(text)
  text.split(/\.\s+/).each do |t|
    return t if /\b(must)\b/xi.match t
  end
  nil
end
extract_text(node) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 8
def extract_text(node)
  return "" if node.nil?
  node1 = Nokogiri::XML.fragment(node.to_s)
  node1.xpath("//link | //locality").each(&:remove)
  ret = ""
  node1.traverse { |x| ret += x.text if x.text? }
  ret
end
footnote_style(node) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 51
def footnote_style(node)
  return if @novalid
  style_no_guidance(node, extract_text(node), "Footnote")
  style(node, extract_text(node))
end
foreword_style(node) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 17
def foreword_style(node)
  return if @novalid
  style_no_guidance(node, extract_text(node), "Foreword")
end
foreword_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate_section.rb, line 16
def foreword_validate(root)
  f = root.at("//foreword") || return
  s = f.at("./clause")
  warn "ISO style: foreword contains subclauses" unless s.nil?
end
html_converter(node) click to toggle source
# File lib/asciidoctor/iso/base.rb, line 12
def html_converter(node)
  IsoDoc::Iso::HtmlConvert.new(
    script: node.attr("script"),
    bodyfont: node.attr("body-font"),
    headerfont: node.attr("header-font"),
    monospacefont: node.attr("monospace-font"),
    i18nyaml: node.attr("i18nyaml"),
    scope: node.attr("scope"),
    htmlstylesheet: node.attr("htmlstylesheet"),
    htmlcoverpage: node.attr("htmlcoverpage"),
    htmlintropage: node.attr("htmlintropage"),
    scripts: node.attr("scripts"),
  )
end
html_converter_alt(node) click to toggle source
# File lib/asciidoctor/iso/base.rb, line 27
def html_converter_alt(node)
  IsoDoc::Iso::HtmlConvert.new(
    script: node.attr("script"),
    bodyfont: node.attr("body-font"),
    headerfont: node.attr("header-font"),
    monospacefont: node.attr("monospace-font"),
    i18nyaml: node.attr("i18nyaml"),
    alt: true,
    scope: node.attr("scope"),
    htmlstylesheet: node.attr("htmlstylesheet"),
    htmlcoverpage: node.attr("htmlcoverpage"),
    htmlintropage: node.attr("htmlintropage"),
    scripts: node.attr("scripts"),
  )
end
introduction_style(node) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 27
def introduction_style(node)
  return if @novalid
  r = requirement(extract_text(node))
  style_warning(node, "Introduction may contain requirement", r) if r
end
isosubgroup_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 110
def isosubgroup_validate(root)
  root.xpath("//technical-committee/@type").each do |t|
    unless %w{TC PC JTC JPC}.include? t.text
      warn "ISO: invalid technical committee type #{t}"
    end
  end
  root.xpath("//subcommittee/@type").each do |t|
    unless %w{SC JSC}.include? t.text
      warn "ISO: invalid subcommittee type #{t}"
    end
  end
end
locality_erefs_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 147
def locality_erefs_validate(root)
  root.xpath("//eref[locality]").each do |t|
    unless /:[ ]?\d+{4}$/.match t["citeas"]
      warn "ISO: undated reference #{t['citeas']} should not contain "\
        "specific elements"
    end
  end
end
makexml1(node) click to toggle source
# File lib/asciidoctor/iso/base.rb, line 75
def makexml1(node)
  result = ["<?xml version='1.0' encoding='UTF-8'?>\n<iso-standard>"]
  result << noko { |ixml| front node, ixml }
  result << noko { |ixml| middle node, ixml }
  result << "</iso-standard>"
  textcleanup(result.flatten * "\n")
end
metadata(node, xml) click to toggle source
# File lib/asciidoctor/iso/front.rb, line 86
def metadata(node, xml)
  title node, xml
  metadata_id(node, xml)
  metadata_author(node, xml)
  metadata_publisher(node, xml)
  xml.language (node.attr("language") || "en")
  xml.script (node.attr("script") || "Latn")
  metadata_status(node, xml)
  metadata_copyright(node, xml)
  metadata_committee(node, xml)
  metadata_ics(node, xml)
end
metadata_author(node, xml) click to toggle source
# File lib/asciidoctor/iso/front.rb, line 37
def metadata_author(node, xml)
  publishers = node.attr("publisher") || "ISO"
  publishers.split(/,[ ]?/).each do |p|
    xml.contributor do |c|
      c.role **{ type: "author" }
      c.organization { |a| organization(a, p) }
    end
  end
end
metadata_committee(node, xml) click to toggle source
# File lib/asciidoctor/iso/front.rb, line 77
def metadata_committee(node, xml)
  xml.editorialgroup do |a|
    committee_component("technical-committee", node, a)
    committee_component("subcommittee", node, a)
    committee_component("workgroup", node, a)
    node.attr("secretariat") && a.secretariat(node.attr("secretariat"))
  end
end
metadata_id(node, xml) click to toggle source
# File lib/asciidoctor/iso/front.rb, line 12
def metadata_id(node, xml)
  part, subpart = node&.attr("partnumber")&.split(/-/)
  xml.docidentifier do |i|
    i.project_number node.attr("docnumber"),
      **attr_code(part: part, subpart: subpart)
    if node.attr("tc-docnumber")
      i.tc_document_number node.attr("tc-docnumber")
    end
  end
end
metadata_publisher(node, xml) click to toggle source
# File lib/asciidoctor/iso/front.rb, line 47
def metadata_publisher(node, xml)
  publishers = node.attr("publisher") || "ISO"
  publishers.split(/,[ ]?/).each do |p|
    xml.contributor do |c|
      c.role **{ type: "publisher" }
      c.organization { |a| organization(a, p) }
    end
  end
end
metadata_status(node, xml) click to toggle source
# File lib/asciidoctor/iso/front.rb, line 69
def metadata_status(node, xml)
  xml.status do |s|
    s.stage (node.attr("docstage") || "60")
    s.substage (node.attr("docsubstage") || "60")
    node.attr("iteration") && (s.iteration node.attr("iteration"))
  end
end
norm_bibitem_style(root) click to toggle source
# File lib/asciidoctor/iso/validate_section.rb, line 189
def norm_bibitem_style(root)
  root.xpath(NORM_BIBITEMS).each do |b|
    if b.at(Standoc::Converter::ISO_PUBLISHER_XPATH).nil?
      Standoc::Utils::warning(b, NORM_ISO_WARN, b.text)
    end
  end
end
normref_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate_section.rb, line 22
def normref_validate(root)
  f = root.at("//references[title = 'Normative References']") || return
  f.at("./references | ./clause") &&
    warn("ISO style: normative references contains subclauses")
end
note_style(node) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 45
def note_style(node)
  return if @novalid
  style_no_guidance(node, extract_text(node), "Note")
  style(node, extract_text(node))
end
onlychild_clause_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 100
def onlychild_clause_validate(root)
  root.xpath(Standoc::Utils::SUBCLAUSE_XPATH).each do |c|
    next unless c.xpath("../clause").size == 1
    title = c.at("./title")
    location = c["id"] || c.text[0..60] + "..."
    location += ":#{title.text}" if c["id"] && !title.nil?
    warn "ISO style: #{location}: subclause is only child"
  end
end
organization(org, orgname) click to toggle source
# File lib/asciidoctor/iso/front.rb, line 23
def organization(org, orgname)
  if ["ISO",
      "International Organization for Standardization"].include? orgname
    org.name "International Organization for Standardization"
    org.abbreviation "ISO"
  elsif ["IEC",
           "International Electrotechnical Commission"].include? orgname
    org.name "International Electrotechnical Commission"
    org.abbreviation "IEC"
  else
    org.name orgname
  end
end
other_footnote_renumber(xmldoc) click to toggle source
# File lib/asciidoctor/iso/cleanup.rb, line 24
def other_footnote_renumber(xmldoc)
  seen = {}
  i = 0
  xmldoc.xpath(PRE_NORMREF_FOOTNOTES).each do |fn|
    i, seen = other_footnote_renumber1(fn, i, seen)
  end
  xmldoc.xpath(NORMREF_FOOTNOTES).each do |fn|
    i, seen = other_footnote_renumber1(fn, i, seen)
  end
  xmldoc.xpath(POST_NORMREF_FOOTNOTES).each do |fn|
    i, seen = other_footnote_renumber1(fn, i, seen)
  end
end
patent_notice_parse(xml, node) click to toggle source
# File lib/asciidoctor/iso/section.rb, line 56
def patent_notice_parse(xml, node)
  # xml.patent_notice do |xml_section|
  #  xml_section << node.content
  # end
  xml << node.content
end
permission(text) click to toggle source
# File lib/asciidoctor/iso/validate_requirements.rb, line 63
def permission(text)
  text.split(/\.\s+/).each do |t|
    return t if PERMISSION_RE.match t
  end
  nil
end
possibility(text) click to toggle source
# File lib/asciidoctor/iso/validate_requirements.rb, line 83
def possibility(text)
  text.split(/\.\s+/).each { |t| return t if POSSIBILITY_RE.match t }
  nil
end
recommendation(text) click to toggle source
# File lib/asciidoctor/iso/validate_requirements.rb, line 44
def recommendation(text)
  text.split(/\.\s+/).each do |t|
    return t if RECOMMENDATION_RE.match t
  end
  nil
end
requirement(text) click to toggle source
# File lib/asciidoctor/iso/validate_requirements.rb, line 26
def requirement(text)
  text.split(/\.\s+/).each do |t|
    return t if REQUIREMENT_RE.match t
  end
  nil
end
scope_parse(attrs, xml, node) click to toggle source
# File lib/asciidoctor/iso/section.rb, line 63
def scope_parse(attrs, xml, node)
  xml.clause **attr_code(attrs) do |xml_section|
    xml_section.title { |t| t << "Scope" }
    content = node.content
    xml_section << content
  end
end
scope_style(node) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 22
def scope_style(node)
  return if @novalid
  style_no_guidance(node, extract_text(node), "Scope")
end
section(node) click to toggle source
# File lib/asciidoctor/iso/section.rb, line 7
def section(node)
  a = { id: Standoc::Utils::anchor_or_uuid(node) }
  noko do |xml|
    case sectiontype(node)
    when "introduction" then
      if node.level == 1 then introduction_parse(a, xml, node)
      else
        clause_parse(a, xml, node)
      end
    when "patent notice" then patent_notice_parse(xml, node)
    when "scope" then scope_parse(a, xml, node)
    when "normative references" then norm_ref_parse(a, xml, node)
    when "terms and definitions",
      "terms, definitions, symbols and abbreviated terms",
      "terms, definitions, symbols and abbreviations",
      "terms, definitions and symbols",
      "terms, definitions and abbreviations",
      "terms, definitions and abbreviated terms"
      @term_def = true
      term_def_parse(a, xml, node, true)
      @term_def = false
    when "symbols and abbreviated terms"
      symbols_parse(a, xml, node)
    when "bibliography" then bibliography_parse(a, xml, node)
    else
      if @term_def then term_def_subclause_parse(a, xml, node)
      elsif @biblio then bibliography_parse(a, xml, node)
      elsif node.attr("style") == "bibliography" && node.level == 1
        bibliography_parse(a, xml, node)
      elsif node.attr("style") == "appendix" && node.level == 1
        annex_parse(a, xml, node)
      elsif node.option? "appendix"
        appendix_parse(a, xml, node)
      else
        clause_parse(a, xml, node)
      end
    end
  end.join("\n")
end
section_style(root) click to toggle source
# File lib/asciidoctor/iso/validate_section.rb, line 155
def section_style(root)
  foreword_style(root.at("//foreword"))
  introduction_style(root.at("//introduction"))
  scope_style(root.at("//clause[title = 'Scope']"))
  scope = root.at("//clause[title = 'Scope']/clause")
  scope.nil? || style_warning(scope, SCOPE_WARN, nil)
end
section_validate(doc) click to toggle source
Calls superclass method
# File lib/asciidoctor/iso/validate_section.rb, line 6
def section_validate(doc)
  foreword_validate(doc.root)
  normref_validate(doc.root)
  symbols_validate(doc.root)
  sections_sequence_validate(doc.root)
  section_style(doc.root)
  subclause_validate(doc.root)
  super
end
sections_sequence_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate_section.rb, line 95
def sections_sequence_validate(root)
  f = root.xpath(SECTIONS_XPATH)
  names = f.map { |s| { tag: s.name, title: s&.at("./title")&.text } }
  names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val]) || return
  n = names[0]
  names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val]) || return
  if n == { tag: "introduction", title: "Introduction" }
    names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val]) || return
  end
  names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val]) || return
  n = names.shift
  if n == { tag: "definitions", title: nil }
    n = names.shift || return
  end
  unless n
    warn "ISO style: Document must contain at least one clause"
    return
  end
  n[:tag] == "clause" ||
    warn("ISO style: Document must contain clause after "\
         "Terms and Definitions")
  n == { tag: "clause", title: "Scope" } &&
    warn("ISO style: Scope must occur before Terms and Definitions")
  n = names.shift || return
  while n[:tag] == "clause"
    n[:title] == "Scope" &&
      warn("ISO style: Scope must occur before Terms and Definitions")
    n = names.shift || return
  end
  unless n[:tag] == "annex" || n[:tag] == "references"
    warn "ISO style: Only annexes and references can follow clauses"
  end
  while n[:tag] == "annex"
    n = names.shift
    if n.nil?
      warn("ISO style: Document must include (references) "\
           "Normative References")
      return
    end
  end
  n == { tag: "references", title: "Normative References" } ||
    warn("ISO style: Document must include (references) "\
         "Normative References")
  n = names.shift
  n == { tag: "references", title: "Bibliography" } ||
    warn("ISO style: Final section must be (references) Bibliography")
  names.empty? ||
    warn("ISO style: There are sections after the final Bibliography")
end
see_erefs_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 135
def see_erefs_validate(root)
  root.xpath("//eref").each do |t|
    preceding = t.at("./preceding-sibling::text()[last()]")
    next unless !preceding.nil? && /\bsee\s*$/mi.match(preceding)
    target = root.at("//*[@id = '#{t['bibitemid']}']")
    if target.at("./ancestor::references"\
        "[title = 'Normative References']")
      warn "ISO: 'see #{t}' is pointing to a normative reference"
    end
  end
end
see_xrefs_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 123
def see_xrefs_validate(root)
  root.xpath("//xref").each do |t|
    # does not deal with preceding text marked up
    preceding = t.at("./preceding-sibling::text()[last()]")
    next unless !preceding.nil? && /\bsee\s*$/mi.match(preceding)
    (target = root.at("//*[@id = '#{t['target']}']")) || next
    if target&.at("./ancestor-or-self::*[@obligation = 'normative']")
      warn "ISO: 'see #{t['target']}' is pointing to a normative section"
    end
  end
end
seqcheck(names, msg, accepted) click to toggle source
# File lib/asciidoctor/iso/validate_section.rb, line 46
def seqcheck(names, msg, accepted)
  n = names.shift
  unless accepted.include? n
    warn "ISO style: #{msg}"
    names = []
  end
  names
end
sourcecode_style(root) click to toggle source
# File lib/asciidoctor/iso/validate_section.rb, line 163
def sourcecode_style(root)
  root.xpath("//sourcecode").each do |x|
    callouts = x.elements.select { |e| e.name == "callout" }
    annotations = x.elements.select { |e| e.name == "annotation" }
    if callouts.size != annotations.size
      warn "#{x['id']}: mismatch of callouts and annotations"
    end
  end
end
style(n, t) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 75
def style(n, t)
  return if @novalid
  style_number(n, t)
  style_percent(n, t)
  style_abbrev(n, t)
  style_units(n, t)
end
style_abbrev(n, t) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 100
def style_abbrev(n, t)
  style_regex(/(^|\s)(?!e\.g\.|i\.e\.)
              (?<num>[a-z]{1,2}\.([a-z]{1,2}|\.))\b/ix,
                "no dots in abbreviations", n, t)
  style_regex(/\b(?<num>ppm)\b/i,
              "language-specific abbreviation", n, t)
end
style_no_guidance(node, text, docpart) click to toggle source
# File lib/asciidoctor/iso/validate_requirements.rb, line 95
def style_no_guidance(node, text, docpart)
  r = requirement(text)
  style_warning(node, "#{docpart} may contain requirement", r) if r
  r = permission(text)
  style_warning(node, "#{docpart} may contain permission", r) if r
  r = recommendation(text)
  style_warning(node, "#{docpart} may contain recommendation", r) if r
end
style_non_std_units(n, t) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 126
def style_non_std_units(n, t)
  NONSTD_UNITS.each do |k, v|
    style_regex(/\b(?<num>[0-9][0-9,]*\s+#{k})\b/,
                "non-standard unit (should be #{v})", n, t)
  end
end
style_number(n, t) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 83
def style_number(n, t)
  style_two_regex_not_prev(n, t, /^(?<num>-?[0-9]{4,}[,0-9]*)$/,
                           %r{(\bISO|\bIEC|\bIEEE/)$},
                           "number not broken up in threes")
  style_regex(/\b(?<num>[0-9]+\.[0-9]+)/i,
              "possible decimal point", n, t)
  style_regex(/\b(?<num>billion[s]?)\b/i,
              "ambiguous number", n, t)
end
style_percent(n, t) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 93
def style_percent(n, t)
  style_regex(/\b(?<num>[0-9.,]+%)/,
              "no space before percent sign", n, t)
  style_regex(/\b(?<num>[0-9.,]+ \u00b1 [0-9,.]+ %)/,
              "unbracketed tolerance before percent sign", n, t)
end
style_regex(re, warning, n, text) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 57
def style_regex(re, warning, n, text)
  (m = re.match(text)) && style_warning(n, warning, m[:num])
end
style_two_regex_not_prev(n, text, re, re_prev, warning) click to toggle source

style check with a regex on a token and a negative match on its preceding token

# File lib/asciidoctor/iso/validate_style.rb, line 63
def style_two_regex_not_prev(n, text, re, re_prev, warning)
  return if text.nil?
  arr = text.split(/\W+/)
  arr.each_index do |i|
    m = re.match arr[i]
    m_prev = i.zero? ? nil : re_prev.match(arr[i - 1])
    if !m.nil? && m_prev.nil?
      style_warning(n, warning, m[:num])
    end
  end
end
style_units(n, t) click to toggle source
# File lib/asciidoctor/iso/validate_style.rb, line 113
def style_units(n, t)
  style_regex(/\b(?<num>[0-9][0-9,]*\s+[\u00b0\u2032\u2033])/,
              "space between number and degrees/minutes/seconds", n, t)
  style_regex(/\b(?<num>[0-9][0-9,]*#{SI_UNIT})\b/,
              "no space between number and SI unit", n, t)
  style_non_std_units(n, t)
end
style_warning(node, msg, text) click to toggle source
# File lib/asciidoctor/iso/validate_section.rb, line 145
def style_warning(node, msg, text)
  return if @novalid
  w = "ISO style: WARNING (#{Standoc::Utils::current_location(node)}): #{msg}"
  w += ": #{text}" if text
  warn w
end
subclause_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate_section.rb, line 207
def subclause_validate(root)
  root.xpath("//clause/clause/clause/clause/clause/clause/clause/clause").each do |c|
    style_warning(c, "Exceeds the maximum clause depth of 7", nil)
  end
end
symbols_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate_section.rb, line 34
def symbols_validate(root)
  f = root.xpath("//definitions")
  f.empty? && return
  (f.size == 1) || warn(ONE_SYMBOLS_WARNING)
  f.first.elements.each do |e|
    unless e.name == "dl"
      warn(NON_DL_SYMBOLS_WARNING)
      return
    end
  end
end
termdef_style(xmldoc) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 160
def termdef_style(xmldoc)
  xmldoc.xpath("//term").each do |t|
    para = t.at("./definition") || return
    term = t.at("./preferred").text
    termdef_warn(para.text, /^(the|a)\b/i, term,
                 "term definition starts with article")
    termdef_warn(para.text, /\.$/i, term,
                 "term definition ends with period")
  end
end
termdef_warn(text, re, term, msg) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 156
def termdef_warn(text, re, term, msg)
  re.match(text) && warn("ISO style: #{term}: #{msg}")
end
title(node, xml) click to toggle source
# File lib/asciidoctor/iso/front.rb, line 119
def title(node, xml)
  ["en", "fr"].each do |lang|
    xml.title do |t|
      at = { language: lang, format: "text/plain" }
      title_intro(node, t, lang, at)
      title_main(node, t, lang, at)
      title_part(node, t, lang, at)
    end
  end
end
title_all_siblings(xpath, label) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 76
def title_all_siblings(xpath, label)
  notitle = false
  withtitle = false
  xpath.each do |s|
    title_all_siblings(s.xpath("./clause | ./terms | ./references"),
                       s&.at("./title")&.text || s["id"])
    subtitle = s.at("./title")
    notitle = notitle || (!subtitle || subtitle.text.empty?)
    withtitle = withtitle || (subtitle && !subtitle.text.empty?)
  end
  notitle && withtitle &&
    warn("#{label}: all subclauses must have a title, or none")
end
title_first_level_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 65
    def title_first_level_validate(root)
      root.xpath(SECTIONS_XPATH).each do |s|
        title = s&.at("./title")&.text || s.name
        s.xpath("./clause | ./terms | ./references").each do |ss|
          subtitle = ss.at("./title")
          !subtitle.nil? && !subtitle&.text&.empty? ||
            warn("#{title}: each first-level subclause must have a title")
    end
  end
end
title_intro(node, t, lang, at) click to toggle source
# File lib/asciidoctor/iso/front.rb, line 99
def title_intro(node, t, lang, at)
  return unless node.attr("title-intro-#{lang}")
  t.title_intro(**attr_code(at)) do |t1|
    t1 << asciidoc_sub(node.attr("title-intro-#{lang}"))
  end
end
title_intro_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 13
def title_intro_validate(root)
  title_intro_en = root.at("//title-intro[@language='en']")
  title_intro_fr = root.at("//title-intro[@language='fr']")
  if title_intro_en.nil? && !title_intro_fr.nil?
    warn "No English Title Intro!"
  end
  if !title_intro_en.nil? && title_intro_fr.nil?
    warn "No French Title Intro!"
  end
end
title_main(node, t, lang, at) click to toggle source
# File lib/asciidoctor/iso/front.rb, line 106
def title_main(node, t, lang, at)
  t.title_main **attr_code(at) do |t1|
    t1 << asciidoc_sub(node.attr("title-main-#{lang}"))
  end
end
title_main_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 24
def title_main_validate(root)
  title_main_en = root.at("//title-main[@language='en']")
  title_main_fr = root.at("//title-main[@language='fr']")
  if title_main_en.nil? && !title_main_fr.nil?
    warn "No English Title!"
  end
  if !title_main_en.nil? && title_main_fr.nil?
    warn "No French Title!"
  end
end
title_names_type_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 52
def title_names_type_validate(root)
  doctypes = /International\sStandard | Technical\sSpecification |
  Publicly\sAvailable\sSpecification | Technical\sReport | Guide /xi
  title_main_en = root.at("//title-main[@language='en']")
  if !title_main_en.nil? && doctypes.match(title_main_en.text)
    warn "Main Title may name document type"
  end
  title_intro_en = root.at("//title-intro[@language='en']")
  if !title_intro_en.nil? && doctypes.match(title_intro_en.text)
    warn "Title Intro may name document type"
  end
end
title_part(node, t, lang, at) click to toggle source
# File lib/asciidoctor/iso/front.rb, line 112
def title_part(node, t, lang, at)
  return unless node.attr("title-part-#{lang}")
  t.title_part(**attr_code(at)) do |t1|
    t1 << asciidoc_sub(node.attr("title-part-#{lang}"))
  end
end
title_part_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 35
def title_part_validate(root)
  title_part_en = root.at("//title-part[@language='en']")
  title_part_fr = root.at("//title-part[@language='fr']")
  (title_part_en.nil? && !title_part_fr.nil?) &&
    warn("No English Title Part!")
  (!title_part_en.nil? && title_part_fr.nil?) &&
    warn("No French Title Part!")
end
title_subpart_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 44
def title_subpart_validate(root)
  subpart = root.at("//bibdata/docidentifier/project-number[@subpart]")
  iec = root.at("//bibdata/contributor[role/@type = 'publisher']/"\
                "organization[abbreviation = 'IEC' or "\
                "name = 'International Electrotechnical Commission']")
  warn("Subpart defined on non-IEC document!") if subpart && !iec
end
title_validate(root) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 90
def title_validate(root)
  title_intro_validate(root)
  title_main_validate(root)
  title_part_validate(root)
  title_subpart_validate(root)
  title_names_type_validate(root)
  title_first_level_validate(root)
  title_all_siblings(root.xpath(SECTIONS_XPATH), "(top level)")
end
validate(doc) click to toggle source
# File lib/asciidoctor/iso/validate.rb, line 183
def validate(doc)
  content_validate(doc)
  schema_validate(formattedstr_strip(doc.dup),
                  File.join(File.dirname(__FILE__), "isostandard.rng"))
end