class Asciidoctor::BSI::Converter

Constants

BSI_PUBLISHER_XPATH
NORM_BSI_WARN
PARENT_PARA
PERMISSION_RE_STR
POSSIBILITY_RE_STR
RECOMMENDATION_RE_STR
REQUIREMENT_RE_STR

Rules for Structure 7.1

XML_NAMESPACE
XML_ROOT_TAG

Public Instance Methods

admonition_style(node, text) click to toggle source

Rules for Structure 24.8

# File lib/asciidoctor/bsi/validate_requirement.rb, line 70
def admonition_style(node, text)
  r = requirement_check(text) and
    style_warning(node, "admonition may contain requirement", r)
  r = permission_check(text) and
    style_warning(node, "admonition may contain permission", r)
  r = recommendation_check(text) and
    style_warning(node, "admonition may contain recommendation", r)
  r = possibility_check(text) and
    style_warning(node, "admonition may contain possibility", r)
end
annex_normative_validate(root) click to toggle source

Rules for Structure 20.2

# File lib/asciidoctor/bsi/validate.rb, line 95
def annex_normative_validate(root)
  @doctype == "guide" and root.xpath("//annex[@obligation = 'normative']")
    .each do |s|
    style_warning(s, "Guide contains normative annex",
                  s&.at("./title")&.text)
  end
end
annex_ordering_validate(root) click to toggle source

Rules for Structure 20.4

# File lib/asciidoctor/bsi/validate.rb, line 104
def annex_ordering_validate(root)
  ids = citation_order(root.xpath("//annex"))
  cite_order = ids.keys.sort_by { |a| ids[a] || 999999 }
  annex_order = root.xpath("//annex").map { |x| x["id"] }
  cite_order.each_with_index do |a, i|
    next if annex_order[i] == a || ids[a].nil?

    annex = root.at("//annex[@id = '#{a}']")
    title = annex&.at("./title")&.text || "Annex #{a}"
    style_warning(annex, "#{title} should be annex ##{i + 1}", nil)
  end
end
annex_validate(root) click to toggle source
# File lib/asciidoctor/bsi/validate.rb, line 89
def annex_validate(root)
  annex_normative_validate(root)
  annex_ordering_validate(root)
end
asset_style(root) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/validate_requirement.rb, line 62
def asset_style(root)
  root.xpath("//admonition[not(@type = 'commentary')]").each do |e|
    admonition_style(e, extract_text(e))
  end
  super
end
avoid_must(root) click to toggle source

Rules for Structure 7.1

# File lib/asciidoctor/bsi/validate_requirement.rb, line 16
def avoid_must(root)
  root.xpath("//sections/clause[not(@type = 'scope')] | //annex")
    .each do |s|
    r = avoid_must_check(extract_text(s))
    style_warning(s, "text contains ambiguous 'must'", r) if r
  end
end
avoid_must_check(text) click to toggle source
# File lib/asciidoctor/bsi/validate_requirement.rb, line 24
def avoid_must_check(text)
  text.split(/\.\s+/).each do |t|
    return t if /\b(must|will)\b/xi.match? t
  end
  nil
end
bibdata_cleanup(xmldoc) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/cleanup.rb, line 64
def bibdata_cleanup(xmldoc)
  super
  xmldoc.xpath("//bibdata/relation[@type = 'bsi-related']").each do |r|
    r["type"] = "related"
  end
end
biblio_cleanup(xmldoc) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 4
def biblio_cleanup(xmldoc)
  biblio_metanorma_ids_informative(xmldoc)
  super
end
biblio_key_title(bib) click to toggle source
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 98
def biblio_key_title(bib)
  bib&.at("./title[@type = 'main']")&.text ||
    bib&.at("./title")&.text || bib&.at("./formattedref")&.text
end
biblio_metanorma_ids1(bib, idx) click to toggle source
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 17
def biblio_metanorma_ids1(bib, idx)
  bib.at("./docidentifier[@type][not(@type = 'DOI' or "\
         "@type = 'ISSN' or @type = 'ISBN')]") and return
  bib&.at("./docidentifier[@type = 'metanorma']")&.remove
  bib.at("./docidentifier").previous =
    "<docidentifier type='metanorma'>[#{idx}]</docidentifier>"
end
biblio_metanorma_ids_informative(xmldoc) click to toggle source

Rules for Structure 21.4

# File lib/asciidoctor/bsi/cleanup_ref.rb, line 26
def biblio_metanorma_ids_informative(xmldoc)
  xmldoc.xpath("//references[@normative = 'false']/bibitem")
    .each_with_index do |b, i|
    biblio_metanorma_ids1(b, i)
  end
end
biblio_metanorma_ids_normative(xmldoc) click to toggle source

Rules for Structure 15.4

# File lib/asciidoctor/bsi/cleanup_ref.rb, line 10
def biblio_metanorma_ids_normative(xmldoc)
  xmldoc.xpath("//references[@normative = 'true']/bibitem")
    .each_with_index do |b, i|
    biblio_metanorma_ids1(b, i)
  end
end
biblio_preface(ref) click to toggle source

Rules for Structure 21.5

# File lib/asciidoctor/bsi/cleanup_ref.rb, line 152
def biblio_preface(ref)
  ref.at("./title").next = "<p>#{@i18n.biblio_pref}</p>"
end
biblio_renumber(xmldoc) click to toggle source
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 103
def biblio_renumber(xmldoc)
  ["true", "false"].each do |norm|
    i = 0
    xmldoc.xpath("//bibliography//references | //clause//references | "\
                 "//annex//references").each do |r|
      next if r["normative"] != norm

      r.xpath("./bibitem").each do |b|
        next unless docid = b.at("./docidentifier[@type = 'metanorma']")
        next unless /^\[\d+\]$/.match?(docid.text)

        i += 1
        docid.children = "[#{norm == 'true' ? 'N' : ''}#{i}]"
      end
    end
  end
end
biblio_reorder(xmldoc) click to toggle source
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 33
def biblio_reorder(xmldoc)
  xmldoc.xpath("//references[@normative = 'false']").each do |r|
    biblio_reorder1(r)
  end
  xmldoc.xpath("//references[@normative = 'true']").each do |r|
    biblio_reorder1(r)
  end
end
boilerplate_cleanup(xmldoc) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 144
def boilerplate_cleanup(xmldoc)
  super
  f = xmldoc.at("//bibliography//references[@normative = 'false']"\
                "[not(references)]")
  f and biblio_preface(f)
end
boilerplate_file(_x_orig) click to toggle source
# File lib/asciidoctor/bsi/converter.rb, line 15
def boilerplate_file(_x_orig)
  File.join(@libdir, "bsi_intro_en.xml")
end
citation_order(bib) click to toggle source
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 46
def citation_order(bib)
  return {} if bib.empty?

  ids = bib.each_with_object({}) { |b, m| m[b["id"]] = nil }
  bib.first.document.xpath(".//xref").each_with_index do |b, i|
    next unless ids.has_key?(b["target"])

    ids[b["target"]] ||= i + 1
  end
  ids
end
cleanup(xmldoc) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/cleanup.rb, line 6
def cleanup(xmldoc)
  super
  ol_cleanup(xmldoc)
  commentary_cleanup(xmldoc)
  xmldoc
end
commentary(node) click to toggle source
# File lib/asciidoctor/bsi/converter.rb, line 39
def commentary(node)
  noko do |xml|
    xml.admonition **commentary_attrs(node) do |a|
      node.title.nil? or a.name { |name| name << node.title }
      wrap_in_para(node, a)
    end
  end.join("\n")
end
commentary_attrs(node) click to toggle source
# File lib/asciidoctor/bsi/converter.rb, line 29
def commentary_attrs(node)
  b = node.attr("beforeclauses") == "true" ? "true" : nil
  attr_code(keep_attrs(node).merge(
              id: Metanorma::Utils::anchor_or_uuid(node),
              type: "commentary",
              target: node.attr("target"),
              beforeclauses: b,
            ))
end
commentary_cleanup(xmldoc) click to toggle source
# File lib/asciidoctor/bsi/cleanup.rb, line 31
def commentary_cleanup(xmldoc)
  @isodoc ||= isodoc(@lang, @script)
  xmldoc.xpath("//admonition[@type = 'commentary'][not(@target)]")
    .each do |a|
    a["target"] = @isodoc.get_clause_id(a)
  end
end
content_validate(doc) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/validate.rb, line 167
def content_validate(doc)
  super
  symbol_style(doc)
  table_validate(doc)
  listcount_validate(doc)
  list_punctuation(doc)
end
docidentifier_cleanup(xmldoc) click to toggle source

BS as a prefix goes first

# File lib/asciidoctor/bsi/cleanup.rb, line 50
def docidentifier_cleanup(xmldoc)
  prefix = get_id_prefix(xmldoc)
  id = xmldoc.at("//bibdata/docidentifier[@type = 'BS']") or return
  id.content = id_prefix(prefix, id)
  id = xmldoc.at("//bibdata/ext/structuredidentifier/project-number") and
    id.content = id_prefix(prefix, id)
end
doctype_validate(xmldoc) click to toggle source

BSI 0:2016 9.4.1

# File lib/asciidoctor/bsi/validate.rb, line 8
def doctype_validate(xmldoc)
  doctype = xmldoc&.at("//bibdata/ext/doctype")&.text
  %w(specification management-systems-standard code-of-practice
     guide method-of-test method-of-specifying vocabulary
     classification).include? doctype or
    @log.add("Document Attributes", nil,
             "#{doctype} is not a recognised document type")
end
example_style(node) click to toggle source

Rules for Structure 25.5

# File lib/asciidoctor/bsi/validate_requirement.rb, line 54
def example_style(node)
  return if @novalid

  r = requirement_check(extract_text(node)) and
    style_warning(node, "Example may contain requirement", r)
  style(node, extract_text(node))
end
external_constraint(text) click to toggle source
# File lib/asciidoctor/bsi/validate_requirement.rb, line 4
def external_constraint(text); end
get_id_prefix(xmldoc) click to toggle source
# File lib/asciidoctor/bsi/cleanup.rb, line 39
def get_id_prefix(xmldoc)
  prefix = []
  xmldoc.xpath("//bibdata/contributor[role/@type = 'publisher']"\
               "/organization").each do |x|
    x1 = x.at("abbreviation")&.text || x.at("name")&.text
    x1 == "BSI" and prefix.unshift("BS") or prefix << x1
  end
  prefix
end
get_typeabbr(node, amd = false) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/front.rb, line 64
def get_typeabbr(node, amd = false)
  case doctype(node)
  when "publicly-available-specification" then "PAS "
  when "british-standard" then "BS "
  when "draft-for-development" then "DD "
  when "privately-subscribed-standard" then "PSS "
  when "flex-standard" then "Flex "
  else
    super
  end
end
html_converter(node) click to toggle source
# File lib/asciidoctor/bsi/converter.rb, line 48
def html_converter(node)
  if node.nil?
    IsoDoc::BSI::HtmlConvert.new({})
  else
    IsoDoc::BSI::HtmlConvert.new(html_extract_attributes(node))
  end
end
id_prefix(prefix, id) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/cleanup.rb, line 58
def id_prefix(prefix, id)
  return id.text if prefix == ["BS"] && %r{^[^/]}.match?(id.text)

  super
end
id_stage_abbr(stage, substage, node, bare = false) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/front.rb, line 76
def id_stage_abbr(stage, substage, node, bare = false)
  ret = super
  if %w(publicly-available-specification).include?(doctype(node)) &&
      !%w(D FD).include?(ret)
    ret = "#{ret} "
  end
  ret
end
id_stage_prefix(docnum, node, force_year) click to toggle source
# File lib/asciidoctor/bsi/front.rb, line 85
def id_stage_prefix(docnum, node, force_year)
  stage = get_stage(node)
  typeabbr = get_typeabbr(node)
  typeabbr.nil? || typeabbr.empty? and typeabbr = "BS "
  docnum = if stage && (stage.to_i < 60)
             unpub_stage_prefix(docnum, stage, typeabbr, node)
           else "#{typeabbr}#{docnum}"
           end
  (force_year || !(stage && (stage.to_i < 60))) and
    docnum = id_add_year(docnum, node)
  docnum
end
id_to_num(bib, ids) click to toggle source

if this is a standard document, we ignore citation order (Rules for Structure 21.4). That is done by zeroing id_to_num

# File lib/asciidoctor/bsi/cleanup_ref.rb, line 61
def id_to_num(bib, ids)
  return "000000000" if bib["id"].nil?

  sprintf("%09d", ids[bib["id"]] || 0)
end
image_name_validate(xmldoc) click to toggle source
# File lib/asciidoctor/bsi/validate.rb, line 23
def image_name_validate(xmldoc); end
informative_text_style(root) click to toggle source

Rules for Structure 7.2, 7.3, 24.5

# File lib/asciidoctor/bsi/validate_requirement.rb, line 35
def informative_text_style(root)
  root.xpath("//note | //admonition[@type = 'commentary'] | "\
             "//annex[@obligation = 'informative']").each do |s|
    if r = requirement_check(extract_text(s))
      style_warning(s, "#{@type} clause may contain requirement", r)
    end
    if r = recommendation_check(extract_text(s))
      %w(code-of-practice guide).include?(@doctype) and
        style_warning(s, "#{@type} clause may contain recommendation", r)
    end
  end
end
iso_id(node, xml) click to toggle source
# File lib/asciidoctor/bsi/front.rb, line 47
def iso_id(node, xml)
  return unless node.attr("docnumber")

  part = node&.attr("partnumber")
  dn = add_id_parts(node.attr("docnumber"), part, nil)
  dn = id_stage_prefix(dn, node, false)
  xml.docidentifier dn, **attr_code(type: "BS")
end
list_full_sentence(elem) click to toggle source
# File lib/asciidoctor/bsi/validate_list.rb, line 60
def list_full_sentence(elem)
  text = elem.text.strip
  text.match?(/^[^A-Za-z]*[A-Z]/) or
    style_warning(elem, "List entry after full stop must start with "\
                  "uppercase letter", text)
  punct = text.sub(/^.*?(\S)\s*$/, "\\1")
  punct == "." or
    style_warning(elem, "List entry after full stop must "\
                  "end with full stop", text)
end
list_punctuation(doc) click to toggle source

Rules for Structure 23.5

# File lib/asciidoctor/bsi/validate_list.rb, line 19
def list_punctuation(doc)
  return if @novalid

  ((doc.xpath("//ol") - doc.xpath("//ul//ol | //ol//ol")) +
   (doc.xpath("//ul") - doc.xpath("//ul//ul | //ol//ul"))).each do |list|
    prec = list.previous_element
    prec&.name == "p" or
      style_warning(list, "All lists must be preceded by "\
                    "introductory phrase", nil)
    list_punctuation1(list, prec&.text)
  end
end
list_punctuation1(list, prectext) click to toggle source
# File lib/asciidoctor/bsi/validate_list.rb, line 32
def list_punctuation1(list, prectext)
  entries = list.xpath(".//li")
  case prectext&.sub(/^.*?(\S)\s*$/, "\\1")
  when ":"
    list.xpath(".//li").each_with_index do |li, i|
      list_semicolon_phrase(li, i == entries.size - 1)
    end
  when "." then entries.each { |li| list_full_sentence(li) }
  else style_warning(list, "All lists must be preceded by "\
                    "colon or full stop", prectext)
  end
end
list_semicolon_phrase(elem, last) click to toggle source
# File lib/asciidoctor/bsi/validate_list.rb, line 45
def list_semicolon_phrase(elem, last)
  text = elem.text.strip
  text.match?(/^[^A-Za-z]*[a-z]/) or
    style_warning(elem, "List entry after colon must start with "\
                  "lowercase letter", text)
  punct = text.sub(/^.*?(\S)\s*$/, "\\1")
  if last
    punct == "." or style_warning(elem, "Final list entry after colon "\
                                  "must end with full stop", text)
  else
    punct == ";" or style_warning(elem, "List entry after colon must "\
                                  "end with semicolon", text)
  end
end
listcount_validate(doc) click to toggle source

Rules for Structure 23.3

# File lib/asciidoctor/bsi/validate_list.rb, line 5
def listcount_validate(doc)
  return if @novalid

  doc.xpath("//clause[not(.//clause)] | //annex").each do |c|
    next if c.xpath(".//ol").empty?

    ols = c.xpath(".//ol") - c.xpath(".//ul//ol | .//ol//ol")
    ols.size > 3 and
      style_warning(c, "More than 3 ordered lists in a numbered clause",
                    nil)
  end
end
metadata_author(node, xml) click to toggle source
# File lib/asciidoctor/bsi/front.rb, line 8
def metadata_author(node, xml)
  publishers = node.attr("publisher") || "BSI"
  csv_split(publishers)&.each do |p|
    xml.contributor do |c|
      c.role **{ type: "author" }
      c.organization do |a|
        organization(a, p, false, node, !node.attr("publisher"))
      end
    end
  end
end
metadata_doctype(node, xml) click to toggle source
# File lib/asciidoctor/bsi/front.rb, line 56
def metadata_doctype(node, xml)
  xml.doctype doctype(node)
end
metadata_publisher(node, xml) click to toggle source
# File lib/asciidoctor/bsi/front.rb, line 20
def metadata_publisher(node, xml)
  publishers = node.attr("publisher") || "BSI"
  csv_split(publishers)&.each do |p|
    xml.contributor do |c|
      c.role **{ type: "publisher" }
      c.organization do |a|
        organization(a, p, true, node, !node.attr("publisher"))
      end
    end
  end
end
new_ref(title, norm) click to toggle source
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 138
def new_ref(title, norm)
  id = "_#{UUIDTools::UUID.random_create}"
  "<references id='#{id}' normative='#{norm}' unnumbered='true'>"\
    "<title>#{title}</title></references>"
end
norm_bibitem_style(root) click to toggle source

Rules for Structure 10.2

# File lib/asciidoctor/bsi/validate.rb, line 127
def norm_bibitem_style(root)
  root.xpath(NORM_BIBITEMS).each do |b|
    b.at(BSI_PUBLISHER_XPATH).nil? and
      @log.add("Style", b, "#{NORM_BSI_WARN}: #{b.text}")
    status = b&.at("./status/stage")&.text
    /^9.$/.match?(status) and
      @log.add("Style", b,
               "Do not cite withdrawn standards as normative: #{b.text}")
    /^[0-5].$/.match?(status) and
      @log.add("Style", b, "Do not cite unpublished standards "\
                           "as normative: #{b.text}")
  end
end
normative_text_style(root) click to toggle source

Rules for Structure 7.2

# File lib/asciidoctor/bsi/validate_requirement.rb, line 82
def normative_text_style(root)
  root.xpath("//sections/* | //annex[@obligation = 'normative']")
    .each do |s1|
    s = s1.dup
    s.xpath(".//note | .//admonition | .//example").each(&:remove)
    %w(code-of-practice guide).include?(@doctype) and
      r = requirement_check(extract_text(s)) and
      style_warning(s, "#{@type} clause may contain requirement", r)
    %w(specification method-of-specifying test-method)
      .include?(@doctype) and spec_normative_text_style(s)
  end
end
normref_cleanup(xmldoc) click to toggle source

Rules for Structure 15.4

Calls superclass method
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 122
def normref_cleanup(xmldoc)
  biblio_metanorma_ids_normative(xmldoc)
  xmldoc.xpath("//references[@normative = 'true']//references")
    .each do |ref|
    ref["unnumbered"] = true
  end
  super
end
normref_validate(xmldoc) click to toggle source

Generalise to all biblio: Standards Publications and Other Publications

# File lib/asciidoctor/bsi/validate.rb, line 211
def normref_validate(xmldoc)
  xmldoc.xpath("//references").each do |r|
    t = r.at("./title")
    case t.text.strip.downcase
    when "standards publications"
      r.xpath("./bibitem").each { |b| normref_validate1(b, true) }
    when "other publications"
      r.xpath("./bibitem").each { |b| normref_validate1(b, false) }
    end
  end
end
normref_validate1(bib, std_pub) click to toggle source
# File lib/asciidoctor/bsi/validate.rb, line 223
def normref_validate1(bib, std_pub)
  numbered = bib.at("./docidentifier[@type = 'metanorma']")
  numbered && std_pub and
    style_warning(bib, "Non-Standard reference included under "\
                       "Standards Publications", nil)
  !numbered && !std_pub and
    style_warning(bib, "Standard reference included under "\
                       "Other Publications", nil)
end
note(node) click to toggle source

TODO: we will not implement sections for now (Rules for Structure 6.4)

TODO: we will not implement access date for now (Rules for Structure 10.3)

Calls superclass method
# File lib/asciidoctor/bsi/converter.rb, line 23
def note(node)
  return commentary(node) if node.attr("type") == "commentary"

  super
end
note_style(node) click to toggle source

requirement language taken care of in informative_text_style

# File lib/asciidoctor/bsi/validate_requirement.rb, line 49
def note_style(node)
  style(node, extract_text(node))
end
ol_cleanup(doc) click to toggle source
# File lib/asciidoctor/bsi/cleanup.rb, line 13
def ol_cleanup(doc)
  doc.xpath("//clause[not(.//clause)] | //annex | //preface/*")
    .each do |c|
    (c.xpath(".//ol") - c.xpath(".//ul//ol | .//ol//ol"))
      .each_with_index do |l, i|
      ol_cleanup1(l, i)
    end
  end
end
ol_cleanup1(list, idx) click to toggle source
# File lib/asciidoctor/bsi/cleanup.rb, line 23
def ol_cleanup1(list, idx)
  styles = %w(alphabet arabic roman)
  list["type"] = styles[idx % styles.size]
  (list.xpath(".//ol") - list.xpath(".//ol//ol")).each do |l|
    ol_cleanup1(l, idx + 1)
  end
end
ordinal_check(node) click to toggle source

Rules for Structure 9.1

# File lib/asciidoctor/bsi/validate.rb, line 71
def ordinal_check(node)
  node.xpath(".//sup").each do |s|
    next unless %w(st nd rd th).include? s.text

    style_warning(s, "text contains ordinal superscript", s.text)
  end
end
org_abbrev() click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/front.rb, line 4
def org_abbrev
  super.merge("The British Standards Institution" => "BSI")
end
pdf_converter(node) click to toggle source
# File lib/asciidoctor/bsi/converter.rb, line 56
def pdf_converter(node)
  return if node.attr("no-pdf")

  if node.nil?
    IsoDoc::BSI::PdfConvert.new({})
  else
    IsoDoc::BSI::PdfConvert.new(doc_extract_attributes(node))
  end
end
presentation_xml_converter(node) click to toggle source
# File lib/asciidoctor/bsi/converter.rb, line 66
def presentation_xml_converter(node)
  if node.nil?
    IsoDoc::BSI::PresentationXMLConvert.new({})
  else
    IsoDoc::BSI::PresentationXMLConvert.new(doc_extract_attributes(node))
  end
end
relaton_relations() click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/front.rb, line 60
def relaton_relations
  super + %w(obsoletes adopted-from bsi-related)
end
section_names_refs_cleanup(xml) click to toggle source
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 131
def section_names_refs_cleanup(xml)
  replace_title(xml, "//bibliography/references[@normative = 'true']",
                @i18n&.normref, true)
  replace_title(xml, "//bibliography/references[@normative = 'false']",
                @i18n&.bibliography, true)
end
section_style(root) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/validate.rb, line 79
def section_style(root)
  super
  @doctype = root.at("//bibdata/ext/doctype")&.text
  @type = @doctype.gsub(/-/, " ").split.map(&:capitalize).join(" ")
  informative_text_style(root)
  normative_text_style(root)
  avoid_must(root)
  annex_validate(root)
end
see_xrefs_validate(root) click to toggle source
# File lib/asciidoctor/bsi/validate_requirement.rb, line 106
def see_xrefs_validate(root)
  root.xpath("//xref").each do |t|
    (target = root.at("//*[@id = '#{t['target']}']")) || next
    if target.at("./ancestor-or-self::annex")
      xrefs_annex_validate(t, target)
    else
      preceding = t.at("./preceding-sibling::text()[last()]")
      next unless !preceding.nil? &&
        /\b(see| refer to)\s*$/mi.match(preceding)

      if target&.at("./ancestor-or-self::*[@obligation = 'normative']")
        @log.add("Style", t, "'see #{t['target']}' is pointing "\
                 "to a normative section")
      end
    end
  end
end
sort_biblio(bib) click to toggle source
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 42
def sort_biblio(bib)
  sort_norm_appearance(bib)
end
sort_biblio_key(bib) click to toggle source

Rules for Structure 15.4 Normative references ordering sort by: alphanumeric prefix, then docnumber if present, numeric sort

else alphanumeric metanorma id (abbreviation)

then doc part number if present, numeric sort then doc id (not DOI &c) then title

# File lib/asciidoctor/bsi/cleanup_ref.rb, line 86
def sort_biblio_key(bib)
  num = bib&.at("./docnumber")&.text
  id = bib&.at("./docidentifier[not(#{OTHERIDS})]")
  metaid = bib&.at("./docidentifier[@type = 'metanorma']")&.text
  abbrid = metaid unless /^\[\d+\]$/.match?(metaid)
  /\d-(?<partid>\d+)/ =~ id&.text
  type = id["type"] if id
  "#{type} :: "\
    "#{num.nil? ? abbrid : sprintf('%09d', num.to_i)} :: "\
    "#{partid} :: #{id&.text} :: #{biblio_key_title(bib)}"
end
sort_norm_appearance(bib) click to toggle source
# File lib/asciidoctor/bsi/cleanup_ref.rb, line 67
def sort_norm_appearance(bib)
  ids = citation_order(bib)
  bib.each do |b|
    ids[b["id"]] = 0 unless b.at("./docidentifier[@type = 'metanorma']")
  end
  bib.sort do |a, b|
    "#{id_to_num(a, ids)} :: #{sort_biblio_key(a)}" <=>
    "#{id_to_num(b, ids)} :: #{sort_biblio_key(b)}"
  end
end
spec_normative_text_style(node) click to toggle source

Rules for Structure 7.3, 7.4, 7.5

# File lib/asciidoctor/bsi/validate_requirement.rb, line 96
def spec_normative_text_style(node)
  r = recommendation_check(extract_text(node))
  r and style_warning(node,
                      "#{@type} clause may contain recommendation", r)
  r = permission_check(extract_text(node))
  r and style_warning(node, "#{@type} clause may contain permission", r)
  r = possibility_check(extract_text(node))
  r and style_warning(node, "#{@type} clause may contain possibility", r)
end
sts_converter(node) click to toggle source
# File lib/asciidoctor/bsi/converter.rb, line 74
def sts_converter(node)
  return if node.attr("no-pdf")

  if node.nil?
    IsoDoc::BSI::StsConvert.new({})
  else
    IsoDoc::BSI::StsConvert.new(html_extract_attributes(node))
  end
end
style(node, text) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/validate.rb, line 25
def style(node, text)
  super
  style_plusminus(node, text)
  style_subscript(node)
end
style_number(node, text) click to toggle source

protest decimal comma not decimal point TODO we will not yet override decimal comma warning if this is a National Annex to Eurocode (Rules for Structure Annex B)

# File lib/asciidoctor/bsi/validate.rb, line 57
def style_number(node, text)
  style_two_regex_not_prev(
    node, text, /^(?<num>-?[0-9]{4,}[,0-9]*)$/,
    %r{\b(ISO|IEC|IEEE/|(in|January|February|March|April|May|June|August|September|October|November|December)\b)$},
    "number not broken up in threes"
  )
  style_regex(/\b(?<num>[0-9]+,[0-9]+)/i,
              "possible decimal comma", node, text)
  style_regex(/\b(?<num>billions?)\b/i,
              "ambiguous number", node, text)
  ordinal_check(node)
end
style_plusminus(node, text) click to toggle source

Rules for Structure 27.5

# File lib/asciidoctor/bsi/validate.rb, line 32
def style_plusminus(node, text)
  style_regex(/\s*(?<num>\S+\u00b1\s*\S+)/,
              "no space before plus-minus sign", node, text)
  style_regex(/\s*(?<num>\S+\s*\u00b1\s+\S+)/,
              "space after plus-minus sign", node, text)
end
style_subscript(node) click to toggle source

Rules for Structure 27.6

# File lib/asciidoctor/bsi/validate.rb, line 40
def style_subscript(node)
  node.xpath(".//sub[.//sub]").each do |r|
    style_warning(node, "Nested subscript", r)
  end
  node.xpath(".//m:msub[.//m:msub]", "m" => MATHML_NS).each do |r|
    style_warning(node, "Nested subscript", r)
  end
  node.xpath(".//sup[.//sup]").each do |r|
    style_warning(node, "Nested superscript", r)
  end
  node.xpath(".//m:msup[.//m:msup]", "m" => MATHML_NS).each do |r|
    style_warning(node, "Nested superscript", r)
  end
end
subclause_validate(root) click to toggle source

Rules for Structure 22.3.2

# File lib/asciidoctor/bsi/validate.rb, line 193
def subclause_validate(root)
  return if @novalid

  root.xpath("//clause/clause/clause/clause/clause/clause")
    .each do |c|
    style_warning(c, "Exceeds the maximum clause depth of 5", nil)
  end
end
symbol_style(xmldoc) click to toggle source

Rules for Structure 17.5

# File lib/asciidoctor/bsi/validate.rb, line 176
def symbol_style(xmldoc)
  return if @novalid

  xmldoc.xpath("//definitions//dd").each do |para|
    term = para&.at("./preceding::dt[1]")&.text&.strip || "[symbol]"
    termdef_warn(para.text, /^(the|a)\b/i, para, term,
                 "symbol definition starts with article")
    termdef_warn(para.text, /\.$/i, para, term,
                 "symbol definition ends with period")
    termdef_warn(para.text, /^[A-Z]/, para, term,
                 "symbol definition starts with upper case character")
    termdef_warn(para.text, /\b#{term.downcase}\b/i, para, term,
                 "symbol definition may be circular")
  end
end
table_footnote_renumber1(fnote, idx, seen) click to toggle source
# File lib/asciidoctor/bsi/cleanup.rb, line 71
def table_footnote_renumber1(fnote, idx, seen)
  content = footnote_content(fnote)
  if seen[content] then outnum = seen[content]
  else
    idx += 1
    outnum = idx
    seen[content] = outnum
  end
  fnote["reference"] = (outnum - 1 + "A".ord).chr
  fnote["table"] = true
  [idx, seen]
end
table_validate(xmldoc) click to toggle source

Rules for Structure 29.6

# File lib/asciidoctor/bsi/validate.rb, line 203
def table_validate(xmldoc)
  xmldoc.xpath("//td[not(./*) and normalize-space(.)=''] | "\
               "//th[not(./*) and normalize-space(.)='']").each do |td|
    style_warning(td, "Empty table cell", nil)
  end
end
tech_report_style(root) click to toggle source

Rules for Structure 7.2

# File lib/asciidoctor/bsi/validate_requirement.rb, line 32
def tech_report_style(root); end
termdef_style(xmldoc) click to toggle source

Rules for Structure 16.5.5

Calls superclass method
# File lib/asciidoctor/bsi/validate.rb, line 155
def termdef_style(xmldoc)
  super
  xmldoc.xpath("//term").each do |t|
    para = t.at("./definition") || return
    term = t.at("./preferred").text.strip
    termdef_warn(para.text, /^[A-Z]/, t, term,
                 "term definition starts with upper case character")
    termdef_warn(para.text, /\b#{term.downcase}\b/i, t, term,
                 "term definition may be circular")
  end
end
title_names_type_validate(root) click to toggle source

Rules for Structure 11.5.2

Calls superclass method
# File lib/asciidoctor/bsi/validate.rb, line 142
def title_names_type_validate(root)
  super
  doctypes = /British\sStandard/xi
  title_main_en = title_lang_part(root, "main", "en")
  !title_main_en.nil? && doctypes.match(title_main_en.text) and
    @log.add("Style", title_main_en, "Main Title may name document type")
  title_intro_en = title_lang_part(root, "intro", "en")
  !title_intro_en.nil? && doctypes.match(title_intro_en.text) and
    @log.add("Style", title_intro_en,
             "Title Intro may name document type")
end
unpub_stage_prefix(docnum, stage, typeabbr, node) click to toggle source
Calls superclass method
# File lib/asciidoctor/bsi/front.rb, line 98
def unpub_stage_prefix(docnum, stage, typeabbr, node)
  typeabbr = "" if typeabbr == "BS "
  super
end
validate(doc) click to toggle source
# File lib/asciidoctor/bsi/validate.rb, line 17
def validate(doc)
  content_validate(doc)
  schema_validate(formattedstr_strip(doc.dup),
                  File.join(File.dirname(__FILE__), "bsi.rng"))
end
xrefs_annex_validate(xref, target) click to toggle source

Rules for Structure 20.5

# File lib/asciidoctor/bsi/validate_requirement.rb, line 129
def xrefs_annex_validate(xref, target)
  normative = !target&.at("./ancestor-or-self::*"\
                          "[@obligation='normative']").nil?
  clause = xref.at(PARENT_PARA) or return
  prec = (clause&.children & xref&.xpath("./preceding::text()"))
  &.text&.split(/\.\s*(?=[A-Z])/m)[-1]&.strip
  foll = (clause.children & xref.xpath("./following::text()"))
  &.text&.split(/\.\s*(?=[A-Z])/m)[0]&.strip
  text = "#{prec} XREF #{foll}".strip
  if %w(specification method-of-specifying).include?(@doctype) && normative
    requirement_re.match?(text) or
      style_warning(xref, "#{@type} must cite normative "\
                    "annex as requirement", text)
  elsif @doctype == "code-of-practice" && normative
    recommendation_re.match?(text) or
      style_warning(xref, "#{@type} must cite normative "\
                    "annex as recommendation", text)
  elsif %w(specification method-of-specifying).include?(@doctype) && !normative
    (recommendation_re.match?(text) ||
     (!requirement_re.match?(text) && !permission_re.match?(text) &&
      !possibility_re.match?(text))) or
    style_warning(xref, "#{@type} must cite informative annex as "\
                  "recommendation or statement", text)
  elsif %w(code-of-practice guide).include?(@doctype) && !normative
    (!recommendation_re.match?(text) && !requirement_re.match?(text) &&
     !permission_re.match?(text) && !possibility_re.match?(text)) or
    style_warning(xref, "#{@type} must cite informative annex as "\
                  "statement", text)
  end
end