Class: Metanorma::Iso::Validate
- Inherits:
-
Standoc::Validate
- Object
- Standoc::Validate
- Metanorma::Iso::Validate
- Defined in:
- lib/metanorma/iso/validate.rb,
lib/metanorma/iso/validate_list.rb,
lib/metanorma/iso/validate_xref.rb,
lib/metanorma/iso/validate_style.rb,
lib/metanorma/iso/validate_title.rb,
lib/metanorma/iso/validate_numeric.rb,
lib/metanorma/iso/validate_section.rb,
lib/metanorma/iso/validate_requirements.rb
Constant Summary collapse
- COMMITTEE_XPATH =
<<~XPATH.freeze //contributor[role/description = 'committee']/organization/subdivision XPATH
- ASSETS_TO_STYLE =
"//term//source | //formula | //termnote | " \ "//p[not(ancestor::boilerplate)] | //li[not(p)] | //dt | " \ "//dd[not(p)] | //td[not(p)] | //th[not(p)]".freeze
- SI_UNIT =
leaving out as problematic: N J K C S T H h d B o E
"(m|cm|mm|km|μm|nm|g|kg|mgmol|cd|rad|sr|Hz|Hz|MHz|Pa|hPa|kJ|" \ "V|kV|W|MW|kW|F|μF|Ω|Wb|°C|lm|lx|Bq|Gy|Sv|kat|l|t|eV|u|Np|Bd|" \ "bit|kB|MB|Hart|nat|Sh|var)".freeze
- NONSTD_UNITS =
{ sec: "s", mins: "min", hrs: "h", hr: "h", cc: "cm^3", lit: "l", amp: "A", amps: "A", rpm: "r/min" }.freeze
- SEQ =
spec of permissible section sequence we skip normative references, it goes to end of list
[ { msg: "Initial section must be (content) Foreword", val: ["./self::foreword"] }, { msg: "Prefatory material must be followed by (clause) Scope", val: ["./self::introduction", "./self::clause[@type = 'scope']"] }, { msg: "Prefatory material must be followed by (clause) Scope", val: ["./self::clause[@type = 'scope']"] }, { msg: "Normative References must be followed by " \ "Terms and Definitions", val: ["./self::terms | .//terms"] }, ].freeze
- SECTIONS_XPATH =
"//foreword | //introduction | //sections/terms | .//annex | " \ "//sections/definitions | //sections/clause | " \ "//references[not(parent::clause)] | " \ "//clause[descendant::references][not(parent::clause)]".freeze
- NORM_BIBITEMS =
"//references[@normative = 'true']/bibitem".freeze
- ISO_PUBLISHER_XPATH =
<<~XPATH.freeze ./contributor[role/@type = 'publisher']/organization[abbreviation = 'ISO' or abbreviation = 'IEC' or name = 'International Organization for Standardization' or name = 'International Electrotechnical Commission'] XPATH
- REQUIREMENT_RE_STR =
<<~REGEXP.freeze \\b ( shall | (is|are)_to | (is|are)_required_(not_)?to | (is|are)_required_that | has_to | only\\b[^.,]+\\b(is|are)_permitted | it_is_necessary | (is|are)_not_(allowed | permitted | acceptable | permissible) | (is|are)_not_to_be | [.,:;]_do_not ) \\b REGEXP
- RECOMMENDATION_RE_STR =
<<~REGEXP.freeze \\b should | ought_(not_)?to | it_is_(not_)?recommended_that \\b REGEXP
- PERMISSION_RE_STR =
<<~REGEXP.freeze \\b may | (is|are)_(permitted | allowed | permissible ) | it_is_not_required_that | no\\b[^.,]+\\b(is|are)_required \\b REGEXP
- POSSIBILITY_RE_STR =
<<~REGEXP.freeze \\b can | cannot | be_able_to | there_is_a_possibility_of | it_is_possible_to | be_unable_to | there_is_no_possibility_of | it_is_not_possible_to \\b REGEXP
- AMBIG_WORDS_RE_STR =
<<~REGEXP.freeze \\b( need_to | needs_to | might | could | family_of_standards | suite_of_standards )\\b REGEXP
- MISSPELLED_WORDS_RE_STR =
<<~REGEXP.freeze \\b( on-line | cyber_security | cyber-security )\\b REGEXP
Instance Method Summary collapse
- #ambig_words_check(text) ⇒ Object
- #asset_style(root) ⇒ Object
- #bibdata_validate(doc) ⇒ Object
- #bibitem_validate(xmldoc) ⇒ Object
- #content_validate(doc) ⇒ Object
- #copied_instance_variables ⇒ Object
-
#definition_style(node) ⇒ Object
ISO/IEC DIR 2, 16.5.6.
- #doctype_validate(_xmldoc) ⇒ Object
- #eref_style_punct(node) ⇒ Object
-
#example_style(node) ⇒ Object
ISO/IEC DIR 2, 16.5.7 ISO/IEC DIR 2, 25.5.
- #external_constraint(text) ⇒ Object
- #extract_anchor_norm(root) ⇒ Object
- #extract_bibitem_anchors(root) ⇒ Object
- #extract_text(node) ⇒ Object
- #figure_validate(xmldoc) ⇒ Object
-
#footnote_style(node) ⇒ Object
ISO/IEC DIR 2, 26.5.
-
#foreword_style(_node) ⇒ Object
ISO/IEC DIR 2, 12.2 Annulled, ISO’s own foreword text fails this test.
-
#foreword_validate(root) ⇒ Object
ISO/IEC DIR 2, 12.4.
-
#introduction_style(node) ⇒ Object
ISO/IEC DIR 2, 13.2.
- #iso_xref_validate(doc) ⇒ Object
- #isosubgroup_validate(root) ⇒ Object
- #iteration_validate(xmldoc) ⇒ Object
- #li_depth_validate(doc) ⇒ Object
-
#list_after_colon_punctuation(list, entries) ⇒ Object
if first list entry starts lowercase, treat as sentence broken up.
- #list_full_sentence(elem) ⇒ Object
- #list_punctuation(doc) ⇒ Object
- #list_punctuation1(list, prectext) ⇒ Object
- #list_semicolon_phrase(elem, last) ⇒ Object
- #list_semicolon_phrase_punct(elem, text, last) ⇒ Object
- #list_validate(doc) ⇒ Object
- #listcount_validate(doc) ⇒ Object
-
#locality_erefs_validate(root) ⇒ Object
ISO/IEC DIR 2, 10.4.
- #misspelled_words_check(text) ⇒ Object
-
#norm_bibitem_style(root) ⇒ Object
ISO/IEC DIR 2, 10.2.
-
#normref_validate(root) ⇒ Object
ISO/IEC DIR 2, 15.4.
-
#note_style(node) ⇒ Object
ISO/IEC DIR 2, 24.5.
- #ol_count_validate(doc) ⇒ Object
-
#onlychild_clause_validate(root) ⇒ Object
ISO/IEC DIR 2, 22.3.2.
- #permission_check(text) ⇒ Object
- #possibility_check(text) ⇒ Object
- #recommendation_check(text) ⇒ Object
- #requirement_check(text) ⇒ Object
- #schema_file ⇒ Object
-
#scope_style(node) ⇒ Object
ISO/IEC DIR 2, 14.2.
- #section_style(root) ⇒ Object
- #section_validate(doc) ⇒ Object
- #sections_presence_validate(root) ⇒ Object
- #sections_sequence_validate(root) ⇒ Object
- #sections_sequence_validate_body(names, elem) ⇒ Object
- #sections_sequence_validate_body_vocab(names, elem) ⇒ Object
- #sections_sequence_validate_end(names, elem) ⇒ Object
- #sections_sequence_validate_start(root) ⇒ Object
-
#see_erefs_validate(root) ⇒ Object
ISO/IEC DIR 2, 15.5.3.
-
#see_xrefs_validate(root) ⇒ Object
ISO/IEC DIR 2, 15.5.3, 20.2 does not deal with preceding text marked up.
- #seqcheck(names, msg, accepted) ⇒ Object
- #skip_list_punctuation(list) ⇒ Object
-
#starts_lowercase?(text) ⇒ Boolean
allow that all-caps word (acronym) is agnostic as to lowercase.
- #starts_numeric?(elem) ⇒ Boolean
- #starts_uppercase?(text) ⇒ Boolean
- #str_to_regexp(str) ⇒ Object
- #style(node, text) ⇒ Object
-
#style_abbrev(node, text) ⇒ Object
ISO/IEC DIR 2, 8.4 ISO/IEC DIR 2, 9.3.
- #style_no_guidance(node, text, docpart) ⇒ Object
-
#style_non_std_units(node, text) ⇒ Object
ISO/IEC DIR 2, 9.3.
-
#style_number(node, text) ⇒ Object
ISO/IEC DIR 2, 9.1 ISO/IEC DIR 2, Table B.1 www.iso.org/ISO-house-style.html#iso-hs-s-text-r-n-numbers.
- #style_number_grouping(node, text) ⇒ Object
-
#style_percent(node, text) ⇒ Object
ISO/IEC DIR 2, 9.2.1.
- #style_problem_words(node, text) ⇒ Object
- #style_punct(node, text) ⇒ Object
- #style_regex(regex, warning, node, text) ⇒ Object
- #style_subscript(node) ⇒ Object
-
#style_subscript_mathml(node) ⇒ Object
Check MathML subscripts - only topmost level msubs (no msub ancestors).
-
#style_subscript_proper(node) ⇒ Object
Check HTML subscripts - only topmost level subs (no sub ancestors).
-
#style_two_regex_not_prev(n, text, regex, re_prev, warning) ⇒ Object
style check with a regex on a token and a negative match on its preceding token.
-
#style_units(node, text) ⇒ Object
ISO/IEC DIR 2, 9.3.
- #style_warning(node, msg, text = nil, display: true) ⇒ Object
- #subclause_validate(root) ⇒ Object
-
#subfigure_validate(xmldoc) ⇒ Object
DRG directives 3.7; but anticipated by standoc.
- #symbols_validate(root) ⇒ Object
- #tech_report_style(root) ⇒ Object
- #term_xrefs_validate(xmldoc) ⇒ Object
- #term_xrefs_validate1(xref, termids) ⇒ Object
-
#termdef_style(xmldoc) ⇒ Object
ISO/IEC DIR 2, 16.5.6.
- #termdef_warn(text, regex, elem, term, msg) ⇒ Object
-
#title_all_siblings(xpath, label) ⇒ Object
ISO/IEC DIR 2, 22.2.
-
#title_first_level_validate(root) ⇒ Object
ISO/IEC DIR 2, 22.2.
- #title_intro_validate(root) ⇒ Object
- #title_lang_part(doc, part, lang) ⇒ Object
- #title_main_validate(root) ⇒ Object
-
#title_names_type_validate(root) ⇒ Object
ISO/IEC DIR 2, 11.5.2.
- #title_no_full_stop_validate(root) ⇒ Object
- #title_part_validate(root) ⇒ Object
-
#title_subpart_validate(root) ⇒ Object
ISO/IEC DIR 2, 11.4.
- #title_validate(root) ⇒ Object
- #vocab_terms_titles_validate(root) ⇒ Object
-
#xrefs_mandate_validate(xmldoc) ⇒ Object
require that all assets of a particular type be cross-referenced within the document.
- #xrefs_mandate_validate1(xmldoc, xpath, name) ⇒ Object
Instance Method Details
#ambig_words_check(text) ⇒ Object
99 100 101 102 103 104 105 106 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 99 def ambig_words_check(text) @lang == "en" or return re = str_to_regexp(self.class::AMBIG_WORDS_RE_STR) text.gsub(/\s+/, " ").split(/\.\s+/).each do |t| return t if re.match t end nil end |
#asset_style(root) ⇒ Object
154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/metanorma/iso/validate_style.rb', line 154 def asset_style(root) root.xpath("//example | //termexample").each { |e| example_style(e) } root.xpath("//definition/verbal-definition").each do |e| definition_style(e) end 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 |
#bibdata_validate(doc) ⇒ Object
67 68 69 70 |
# File 'lib/metanorma/iso/validate.rb', line 67 def bibdata_validate(doc) doctype_validate(doc) iteration_validate(doc) end |
#bibitem_validate(xmldoc) ⇒ Object
106 107 108 109 110 111 112 |
# File 'lib/metanorma/iso/validate.rb', line 106 def bibitem_validate(xmldoc) xmldoc.xpath("//bibitem[date/on = '–']").each do |b| n = b.xpath("./note/@type").map { |n| n.text.split(",").map(&:strip) } .flatten n.include?("Unpublished-Status") or @log.add("ISO_8", b) end end |
#content_validate(doc) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/metanorma/iso/validate.rb', line 88 def content_validate(doc) super root = doc.root title_validate(root) isosubgroup_validate(root) termdef_style(root) iso_xref_validate(root) bibdata_validate(root) bibitem_validate(root) figure_validate(root) list_validate(doc) end |
#copied_instance_variables ⇒ Object
15 16 17 |
# File 'lib/metanorma/iso/validate.rb', line 15 def copied_instance_variables super + %i[amd vocab validate_years] end |
#definition_style(node) ⇒ Object
ISO/IEC DIR 2, 16.5.6
40 41 42 43 44 45 |
# File 'lib/metanorma/iso/validate_style.rb', line 40 def definition_style(node) @novalid and return r = requirement_check(extract_text(node)) and style_warning(node, "Definition may contain requirement", r, display: false) end |
#doctype_validate(_xmldoc) ⇒ Object
52 53 54 55 56 57 58 59 |
# File 'lib/metanorma/iso/validate.rb', line 52 def doctype_validate(_xmldoc) %w(international-standard technical-specification technical-report publicly-available-specification international-workshop-agreement guide amendment technical-corrigendum committee-document addendum recommendation) .include? @doctype or @log.add("ISO_5", nil, params: [@doctype]) end |
#eref_style_punct(node) ⇒ Object
134 135 136 137 138 139 140 |
# File 'lib/metanorma/iso/validate_style.rb', line 134 def eref_style_punct(node) node.xpath(".//eref[@type='footnote']").each do |e| /^\p{P}/.match?(e.next&.text) or next style_warning(node, "superscript cross-reference followed by punctuation", node.to_xml) end end |
#example_style(node) ⇒ Object
ISO/IEC DIR 2, 16.5.7 ISO/IEC DIR 2, 25.5
49 50 51 52 53 |
# File 'lib/metanorma/iso/validate_style.rb', line 49 def example_style(node) @novalid and return style_no_guidance(node, extract_text(node), "Example") style(node, extract_text(node)) end |
#external_constraint(text) ⇒ Object
86 87 88 89 90 91 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 86 def external_constraint(text) text.split(/\.\s+/).each do |t| return t if /\b(must)\b/xi.match? t end nil end |
#extract_anchor_norm(root) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/metanorma/iso/validate_xref.rb', line 18 def extract_anchor_norm(root) nodes = root.xpath("//annex[@obligation = 'normative'] | " \ "//references[@obligation = 'normative']") ret = nodes.each_with_object({}) do |n, m| n["anchor"] and m[n["anchor"]] = true end nodes.each do |n| n.xpath(".//*[@anchor]").each { |n1| ret[n1["anchor"]] = true } end ret end |
#extract_bibitem_anchors(root) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/metanorma/iso/validate_xref.rb', line 47 def extract_bibitem_anchors(root) ret = root.xpath("//references[@normative = 'true']//bibitem") .each_with_object({}) do |b, m| m[b["anchor"]] = { bib: b, norm: true } end root.xpath("//references[not(@normative = 'true')]//bibitem") .each do |b| ret[b["anchor"]] = { bib: b, norm: false } end ret end |
#extract_text(node) ⇒ Object
8 9 10 11 12 13 14 15 16 |
# File 'lib/metanorma/iso/validate_style.rb', line 8 def extract_text(node) node.nil? and return "" node1 = Nokogiri::XML.fragment(node.to_s) node1.xpath(".//link | .//locality | .//localityStack | " \ ".//stem | .//sourcecode").each(&:remove) ret = "" node1.traverse { |x| ret += x.text if x.text? } HTMLEntities.new.decode(ret) end |
#figure_validate(xmldoc) ⇒ Object
84 85 86 |
# File 'lib/metanorma/iso/validate.rb', line 84 def figure_validate(xmldoc) subfigure_validate(xmldoc) end |
#footnote_style(node) ⇒ Object
ISO/IEC DIR 2, 26.5
63 64 65 66 67 |
# File 'lib/metanorma/iso/validate_style.rb', line 63 def footnote_style(node) @novalid and return style_no_guidance(node, extract_text(node), "Footnote") style(node, extract_text(node)) end |
#foreword_style(_node) ⇒ Object
ISO/IEC DIR 2, 12.2 Annulled, ISO’s own foreword text fails this test
20 21 22 23 |
# File 'lib/metanorma/iso/validate_style.rb', line 20 def foreword_style(_node) @novalid and return # style_no_guidance(node, extract_text(node), "Foreword") end |
#foreword_validate(root) ⇒ Object
ISO/IEC DIR 2, 12.4
22 23 24 25 26 |
# File 'lib/metanorma/iso/validate_section.rb', line 22 def foreword_validate(root) f = root.at("//foreword") || return s = f.at("./clause") @log.add("ISO_23", f) unless s.nil? end |
#introduction_style(node) ⇒ Object
ISO/IEC DIR 2, 13.2
32 33 34 35 36 37 |
# File 'lib/metanorma/iso/validate_style.rb', line 32 def introduction_style(node) @novalid and return r = requirement_check(extract_text(node)) and style_warning(node, "Introduction may contain requirement", r, display: false) end |
#iso_xref_validate(doc) ⇒ Object
111 112 113 114 115 116 117 |
# File 'lib/metanorma/iso/validate_xref.rb', line 111 def iso_xref_validate(doc) see_xrefs_validate(doc) term_xrefs_validate(doc) xrefs_mandate_validate(doc) see_erefs_validate(doc) locality_erefs_validate(doc) end |
#isosubgroup_validate(root) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/metanorma/iso/validate.rb', line 23 def isosubgroup_validate(root) root.xpath("#{COMMITTEE_XPATH}[@type = 'Technical committee']/@subtype") .each do |t| %w{TC PC JTC JPC}.include?(t.text) or @log.add("ISO_2", nil, params: [t.text]) end root.xpath("#{COMMITTEE_XPATH}[@type = 'Subcommittee']/@subtype") .each do |t| %w{SC JSC}.include?(t.text) or @log.add("ISO_3", nil, params: [t.text]) end end |
#iteration_validate(xmldoc) ⇒ Object
61 62 63 64 65 |
# File 'lib/metanorma/iso/validate.rb', line 61 def iteration_validate(xmldoc) iteration = xmldoc&.at("//bibdata/status/iteration")&.text or return /^\d+/.match(iteration) or @log.add("ISO_6", nil, params: [iteration]) end |
#li_depth_validate(doc) ⇒ Object
24 25 26 27 28 29 |
# File 'lib/metanorma/iso/validate_list.rb', line 24 def li_depth_validate(doc) doc.xpath("//li//li//li//li").each do |l| l.at(".//li") and style_warning(l, "List more than four levels deep", nil) end end |
#list_after_colon_punctuation(list, entries) ⇒ Object
if first list entry starts lowercase, treat as sentence broken up
69 70 71 72 73 74 75 76 77 78 |
# File 'lib/metanorma/iso/validate_list.rb', line 69 def list_after_colon_punctuation(list, entries) lower = starts_lowercase?(list.at(".//li").text) entries.each_with_index do |li, i| if lower list_semicolon_phrase(li, i == entries.size - 1) else list_full_sentence(li) end end end |
#list_full_sentence(elem) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/metanorma/iso/validate_list.rb', line 102 def list_full_sentence(elem) %w(Cyrl Latn Grek).include?(@script) or return text = elem.text.strip starts_uppercase?(text) || starts_numeric?(elem) or style_warning(elem, "List entry of separate sentences must start " \ "with uppercase letter", text, display: false) punct = text.strip.sub(/^.*?(\S)\z/m, "\\1") punct == "." or style_warning(elem, "List entry of separate sentences must " \ "end with full stop", text, display: false) end |
#list_punctuation(doc) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/metanorma/iso/validate_list.rb', line 32 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| next if skip_list_punctuation(list) prec = list.at("./preceding::text()[normalize-space(.) != ''][1]") list_punctuation1(list, prec&.text) end end |
#list_punctuation1(list, prectext) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/metanorma/iso/validate_list.rb', line 56 def list_punctuation1(list, prectext) prectext ||= "" entries = list.xpath(".//li") %w(Cyrl Latn Grek).include?(@script) or return case prectext.strip[-1] when ":", "" then list_after_colon_punctuation(list, entries) when "." then entries.each { |li| list_full_sentence(li) } else style_warning(list, "All lists must be preceded by " \ "colon or full stop", prectext, display: false) end end |
#list_semicolon_phrase(elem, last) ⇒ Object
80 81 82 83 84 85 86 |
# File 'lib/metanorma/iso/validate_list.rb', line 80 def list_semicolon_phrase(elem, last) text = elem.text.strip starts_lowercase?(text) or style_warning(elem, "List entry of broken up sentence must start " \ "with lowercase letter", text, display: false) list_semicolon_phrase_punct(elem, text, last) end |
#list_semicolon_phrase_punct(elem, text, last) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/metanorma/iso/validate_list.rb', line 88 def list_semicolon_phrase_punct(elem, text, last) punct = text.strip.sub(/^.*?(\S)\z/m, "\\1") if last punct == "." or style_warning(elem, "Final list entry of broken up " \ "sentence must end with full stop", text, display: false) else punct == ";" or style_warning(elem, "List entry of broken up sentence must " \ "end with semicolon", text, display: false) end end |
#list_validate(doc) ⇒ Object
101 102 103 104 |
# File 'lib/metanorma/iso/validate.rb', line 101 def list_validate(doc) listcount_validate(doc) list_punctuation(doc) end |
#listcount_validate(doc) ⇒ Object
5 6 7 8 9 10 |
# File 'lib/metanorma/iso/validate_list.rb', line 5 def listcount_validate(doc) return if @novalid ol_count_validate(doc) li_depth_validate(doc) end |
#locality_erefs_validate(root) ⇒ Object
ISO/IEC DIR 2, 10.4
60 61 62 63 64 65 66 67 |
# File 'lib/metanorma/iso/validate_xref.rb', line 60 def locality_erefs_validate(root) root.xpath("//eref[descendant::locality]").each do |t| if /^(ISO|IEC)/.match?(t["citeas"]) && !/: ?(\d+{4}|–)$/.match?(t["citeas"]) @log.add("ISO_49", t, params: [t["citeas"]]) end end end |
#misspelled_words_check(text) ⇒ Object
114 115 116 117 118 119 120 121 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 114 def misspelled_words_check(text) @lang == "en" or return re = str_to_regexp(self.class::MISSPELLED_WORDS_RE_STR) text.gsub(/\s+/, " ").split(/\.\s+/).each do |t| return t if re.match t end nil end |
#norm_bibitem_style(root) ⇒ Object
ISO/IEC DIR 2, 10.2
185 186 187 188 189 190 191 |
# File 'lib/metanorma/iso/validate_section.rb', line 185 def norm_bibitem_style(root) root.xpath(NORM_BIBITEMS).each do |b| if b.at(ISO_PUBLISHER_XPATH).nil? @log.add("ISO_42", b, params: [b.text]) end end end |
#normref_validate(root) ⇒ Object
ISO/IEC DIR 2, 15.4
29 30 31 32 33 |
# File 'lib/metanorma/iso/validate_section.rb', line 29 def normref_validate(root) f = root.at("//references[@normative = 'true']") || return f.at("./references | ./clause") && @log.add("ISO_24", f) end |
#note_style(node) ⇒ Object
ISO/IEC DIR 2, 24.5
56 57 58 59 60 |
# File 'lib/metanorma/iso/validate_style.rb', line 56 def note_style(node) @novalid and return style_no_guidance(node, extract_text(node), "Note") style(node, extract_text(node)) end |
#ol_count_validate(doc) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/metanorma/iso/validate_list.rb', line 12 def ol_count_validate(doc) doc.xpath("//clause | //annex").each do |c| next if c.xpath(".//ol").empty? ols = c.xpath(".//ol") - c.xpath(".//ul//ol | .//ol//ol | .//clause//ol") ols.size > 1 and style_warning(c, "More than 1 ordered list in a numbered clause", nil) end end |
#onlychild_clause_validate(root) ⇒ Object
ISO/IEC DIR 2, 22.3.2
201 202 203 204 205 206 |
# File 'lib/metanorma/iso/validate_section.rb', line 201 def onlychild_clause_validate(root) root.xpath(Standoc::Utils::SUBCLAUSE_XPATH).each do |c| c.xpath("../clause").size == 1 or next @log.add("ISO_43", c) end end |
#permission_check(text) ⇒ Object
60 61 62 63 64 65 66 67 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 60 def (text) @lang == "en" or return re = str_to_regexp(self.class::PERMISSION_RE_STR) text.gsub(/\s+/, " ").split(/\.\s+/).each do |t| return t if re.match t end nil end |
#possibility_check(text) ⇒ Object
79 80 81 82 83 84 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 79 def possibility_check(text) @lang == "en" or return re = str_to_regexp(self.class::POSSIBILITY_RE_STR) text.gsub(/\s+/, " ").split(/\.\s+/).each { |t| return t if re.match t } nil end |
#recommendation_check(text) ⇒ Object
42 43 44 45 46 47 48 49 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 42 def recommendation_check(text) @lang == "en" or return re = str_to_regexp(self.class::RECOMMENDATION_RE_STR) text.gsub(/\s+/, " ").split(/\.\s+/).each do |t| return t if re.match t end nil end |
#requirement_check(text) ⇒ Object
25 26 27 28 29 30 31 32 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 25 def requirement_check(text) @lang == "en" or return re = str_to_regexp(self.class::REQUIREMENT_RE_STR) text.gsub(/\s+/, " ").split(/\.\s+/).each do |t| return t if re.match t end nil end |
#schema_file ⇒ Object
114 115 116 117 118 119 120 |
# File 'lib/metanorma/iso/validate.rb', line 114 def schema_file case @doctype when "amendment", "technical-corrigendum" # @amd "isostandard-amd.rng" else "isostandard-compile.rng" end end |
#scope_style(node) ⇒ Object
ISO/IEC DIR 2, 14.2
26 27 28 29 |
# File 'lib/metanorma/iso/validate_style.rb', line 26 def scope_style(node) @novalid and return style_no_guidance(node, extract_text(node), "Scope") end |
#section_style(root) ⇒ Object
157 158 159 160 161 162 163 164 165 |
# File 'lib/metanorma/iso/validate_section.rb', line 157 def section_style(root) foreword_style(root.at("//foreword")) introduction_style(root.at("//introduction")) scope_style(root.at("//clause[@type = 'scope']")) scope = root.at("//clause[@type = 'scope']/clause") # ISO/IEC DIR 2, 14.4 scope.nil? || @log.add("ISO_39", scope) tech_report_style(root) end |
#section_validate(doc) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/metanorma/iso/validate_section.rb', line 6 def section_validate(doc) unless %w(amendment technical-corrigendum).include? @doctype foreword_validate(doc.root) normref_validate(doc.root) symbols_validate(doc.root) sections_presence_validate(doc.root) sections_sequence_validate(doc.root) end section_style(doc.root) subclause_validate(doc.root) onlychild_clause_validate(doc.root) @vocab and vocab_terms_titles_validate(doc.root) super end |
#sections_presence_validate(root) ⇒ Object
59 60 61 62 63 64 65 66 |
# File 'lib/metanorma/iso/validate_section.rb', line 59 def sections_presence_validate(root) root.at("//sections/clause[@type = 'scope']") or @log.add("ISO_29", nil) root.at("//references[@normative = 'true']") or @log.add("ISO_30", nil) root.at("//terms") or @log.add("ISO_31", nil) end |
#sections_sequence_validate(root) ⇒ Object
88 89 90 91 92 93 94 95 96 |
# File 'lib/metanorma/iso/validate_section.rb', line 88 def sections_sequence_validate(root) names, n = sections_sequence_validate_start(root) if @vocab names, n = sections_sequence_validate_body_vocab(names, n) else names, n = sections_sequence_validate_body(names, n) end sections_sequence_validate_end(names, n) end |
#sections_sequence_validate_body(names, elem) ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/metanorma/iso/validate_section.rb', line 111 def sections_sequence_validate_body(names, elem) if elem.nil? || elem.name != "clause" @log.add("ISO_32", elem) end elem&.at("./self::clause") or @log.add("ISO_33", elem) elem&.at("./self::clause[@type = 'scope']") and @log.add("ISO_34", elem) elem = names.shift while elem&.name == "clause" elem&.at("./self::clause[@type = 'scope']") and @log.add("ISO_34", elem) elem = names.shift end %w(annex references).include? elem&.name or @log.add("ISO_36", elem) [names, elem] end |
#sections_sequence_validate_body_vocab(names, elem) ⇒ Object
130 131 132 133 134 135 136 137 |
# File 'lib/metanorma/iso/validate_section.rb', line 130 def sections_sequence_validate_body_vocab(names, elem) while elem && %w(clause terms).include?(elem.name) elem = names.shift end %w(annex references).include? elem&.name or @log.add("ISO_37", elem) [names, elem] end |
#sections_sequence_validate_end(names, elem) ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/metanorma/iso/validate_section.rb', line 139 def sections_sequence_validate_end(names, elem) while elem&.name == "annex" elem = names.shift if elem.nil? @log.add("ISO_38", nil) end end elem.nil? and return elem&.at("./self::references[@normative = 'true']") || @log.add("ISO_38", nil) elem = names&.shift elem.nil? and return elem&.at("./self::references[@normative = 'false']") || @log.add("ISO_40", elem) names.empty? || @log.add("ISO_41", elem) end |
#sections_sequence_validate_start(root) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/metanorma/iso/validate_section.rb', line 98 def sections_sequence_validate_start(root) names = root.xpath(SECTIONS_XPATH) names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val]) n = names[0] names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val]) n&.at("./self::introduction") and names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val]) names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val]) n = names.shift n = names.shift if n&.at("./self::definitions") [names, n] end |
#see_erefs_validate(root) ⇒ Object
ISO/IEC DIR 2, 15.5.3
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/metanorma/iso/validate_xref.rb', line 31 def see_erefs_validate(root) @lang == "en" or return bibitemids = extract_bibitem_anchors(root) root.xpath("//eref").each do |t| prec = t.at("./preceding-sibling::text()[last()]") !prec.nil? && /\b(see|refer to)\p{Zs}*\Z/mi.match(prec) or next unless target = bibitemids[t["bibitemid"]] # unless target = root.at("//bibitem[@anchor = '#{t['bibitemid']}']") @log.add("ISO_47", t, params: [t]) next end target[:norm] and @log.add("ISO_48", t, params: [t]) end end |
#see_xrefs_validate(root) ⇒ Object
ISO/IEC DIR 2, 15.5.3, 20.2 does not deal with preceding text marked up
6 7 8 9 10 11 12 13 14 15 16 |
# File 'lib/metanorma/iso/validate_xref.rb', line 6 def see_xrefs_validate(root) @lang == "en" or return anchors = extract_anchor_norm(root) root.xpath("//xref").each do |t| preceding = t.at("./preceding-sibling::text()[last()]") !preceding.nil? && /\b(see| refer to)\p{Zs}*\Z/mi.match(preceding) or next anchors[t["target"]] and @log.add("ISO_46", t, params: [t["target"]]) end end |
#seqcheck(names, msg, accepted) ⇒ Object
48 49 50 51 52 53 54 55 56 57 |
# File 'lib/metanorma/iso/validate_section.rb', line 48 def seqcheck(names, msg, accepted) n = names.shift return [] if n.nil? test = accepted.map { |a| n.at(a) } if test.all?(&:nil?) @log.add("ISO_28", nil, params: [msg]) end names end |
#skip_list_punctuation(list) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/metanorma/iso/validate_list.rb', line 44 def skip_list_punctuation(list) return true if list.at("./ancestor::table") return true if list.at("./following-sibling::term") # terms boilerplate list.xpath(".//li").each do |entry| l = entry.dup l.xpath(".//ol | .//ul").each(&:remove) l.text.split.size > 2 and return false end true end |
#starts_lowercase?(text) ⇒ Boolean
allow that all-caps word (acronym) is agnostic as to lowercase
115 116 117 118 |
# File 'lib/metanorma/iso/validate_list.rb', line 115 def starts_lowercase?(text) text.match?(/^[^[[:upper:]][[:lower:]]]*[[:lower:]]/) || text.match?(/^[^[[:upper:]][[:lower:]]]*[[:upper:]][[:upper:]]+[^[[:alpha:]]]/) end |
#starts_numeric?(elem) ⇒ Boolean
124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/metanorma/iso/validate_list.rb', line 124 def starts_numeric?(elem) traverse_breadth_first(elem) do |n| n.name == "stem" and return true %w(xref eref).include?(n.name) && n.text.strip.empty? and return true n.text? or next t = n.text.strip t.empty? and next return /^\d/.match?(t) end false end |
#starts_uppercase?(text) ⇒ Boolean
120 121 122 |
# File 'lib/metanorma/iso/validate_list.rb', line 120 def starts_uppercase?(text) text.match?(/^[^[[:upper:]][[:lower:]]]*[[:upper:]]/) end |
#str_to_regexp(str) ⇒ Object
21 22 23 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 21 def str_to_regexp(str) Regexp.new(str.gsub(/\s/, "").gsub("_", "\\s"), Regexp::IGNORECASE) end |
#style(node, text) ⇒ Object
87 88 89 90 91 92 93 94 95 96 |
# File 'lib/metanorma/iso/validate_style.rb', line 87 def style(node, text) @novalid and return @novalid_number or style_number(node, text) style_percent(node, text) style_abbrev(node, text) style_units(node, text) style_punct(node, text) style_subscript(node) style_problem_words(node, text) end |
#style_abbrev(node, text) ⇒ Object
ISO/IEC DIR 2, 8.4 ISO/IEC DIR 2, 9.3
115 116 117 118 119 120 121 |
# File 'lib/metanorma/iso/validate_style.rb', line 115 def style_abbrev(node, text) style_regex(/(?:\A|\p{Zs})(?!e\.g\.|i\.e\.) (?<num>[a-z]{1,2}\.(?:[a-z]{1,2}|\.))\b/ix, "no dots in abbreviations", node, text) style_regex(/\d\s*(?<num>ppm)\b/i, "language-specific abbreviation of unit (ppm): ISO/IEC DIR 2, 9.3", node, text) end |
#style_no_guidance(node, text, docpart) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 123 def style_no_guidance(node, text, docpart) @lang == "en" or return r = requirement_check(text) and style_warning(node, "#{docpart} may contain requirement", r, display: false) r = (text) and style_warning(node, "#{docpart} may contain permission", r, display: false) r = recommendation_check(text) and style_warning(node, "#{docpart} may contain recommendation", r, display: false) end |
#style_non_std_units(node, text) ⇒ Object
ISO/IEC DIR 2, 9.3
98 99 100 101 102 103 |
# File 'lib/metanorma/iso/validate_numeric.rb', line 98 def style_non_std_units(node, text) NONSTD_UNITS.each do |k, v| style_regex(/\b(?<num>[0-9][0-9,]*\p{Zs}+#{k})\b/, "non-standard unit (should be #{v})", node, text) end end |
#style_number(node, text) ⇒ Object
ISO/IEC DIR 2, 9.1 ISO/IEC DIR 2, Table B.1 www.iso.org/ISO-house-style.html#iso-hs-s-text-r-n-numbers
42 43 44 45 46 47 48 49 50 51 |
# File 'lib/metanorma/iso/validate_numeric.rb', line 42 def style_number(node, text) style_number_grouping(node, text) style_regex(/(?:^|\p{Zs})(?<num>[0-9]+\.[0-9]+)(?!\.[0-9])/i, "possible decimal point: mark up numbers with stem:[]", node, text) @lang == "en" and style_regex(/\b(?<num>billions?)\b/i, "ambiguous number", node, text) style_regex(/(?:^|\p{Zs})(?<num>-[0-9][0-9,.]*)/i, "hyphen instead of minus sign U+2212", node, text) @novalid_number = true end |
#style_number_grouping(node, text) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/metanorma/iso/validate_numeric.rb', line 53 def style_number_grouping(node, text) if @validate_years style_two_regex_not_prev( node, text, /^(?<num>-?[0-9]{4,}[,0-9]*)\Z/, %r{\b(ISO|IEC|IEEE|(in|January|February|March|April|May|June|August|September|October|November|December)\b)\Z}, "number not broken up in threes: mark up numbers with stem:[]" ) else style_two_regex_not_prev( node, text, /^(?<num>-?(?:[0-9]{5,}[,0-9]*|[03-9]\d\d\d|1[0-8]\d\d|2[1-9]\d\d|20[5-9]\d))\Z/, %r{\b(ISO|IEC|IEEE|\b)\Z}, "number not broken up in threes: mark up numbers with stem:[]" ) end end |
#style_percent(node, text) ⇒ Object
ISO/IEC DIR 2, 9.2.1
70 71 72 73 74 75 |
# File 'lib/metanorma/iso/validate_numeric.rb', line 70 def style_percent(node, text) style_regex(/\b(?<num>[0-9.,]+%)/, "no space before percent sign", node, text) style_regex(/\b(?<num>[0-9.,]+ \u00b1 [0-9,.]+ %)/, "unbracketed tolerance before percent sign", node, text) end |
#style_problem_words(node, text) ⇒ Object
103 104 105 106 107 108 109 110 111 |
# File 'lib/metanorma/iso/validate_style.rb', line 103 def style_problem_words(node, text) r = ambig_words_check(text) and style_warning(node, "may contain ambiguous provision", r, display: false) r = misspelled_words_check(text) and style_warning(node, "dispreferred spelling", r, display: false) style_regex(/\b(?<num>billions?)\b/i, "ambiguous number", node, text) end |
#style_punct(node, text) ⇒ Object
125 126 127 128 129 130 131 |
# File 'lib/metanorma/iso/validate_style.rb', line 125 def style_punct(node, text) @lang == "en" and style_regex(/\b(?<num>and\/?or)\b/i, "Use 'either x or y, or both'", node, text) style_regex(/\p{Zs}(?<num>&)\p{Zs}/i, "Avoid ampersand in ordinary text'", node, text) eref_style_punct(node) end |
#style_regex(regex, warning, node, text) ⇒ Object
69 70 71 |
# File 'lib/metanorma/iso/validate_style.rb', line 69 def style_regex(regex, warning, node, text) (m = regex.match(text)) && style_warning(node, warning, m[:num]) end |
#style_subscript(node) ⇒ Object
5 6 7 8 |
# File 'lib/metanorma/iso/validate_numeric.rb', line 5 def style_subscript(node) style_subscript_proper(node) style_subscript_mathml(node) end |
#style_subscript_mathml(node) ⇒ Object
Check MathML subscripts - only topmost level msubs (no msub ancestors)
25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/metanorma/iso/validate_numeric.rb', line 25 def style_subscript_mathml(node) node.xpath(".//m:msub[not(ancestor::m:msub)]", "m" => MATHML_NS).each do |x| depth = calculate_mathml_subscript_depth(x) depth < 2 and next # No warning for single level subscripts if [2, 3].include?(depth) style_warning(node, "may contain nested subscripts", x.to_xml) else # depth > 3 style_warning(node, "no more than 3 levels of subscript nesting allowed", x.to_xml) end end end |
#style_subscript_proper(node) ⇒ Object
Check HTML subscripts - only topmost level subs (no sub ancestors)
11 12 13 14 15 16 17 18 19 20 21 22 |
# File 'lib/metanorma/iso/validate_numeric.rb', line 11 def style_subscript_proper(node) node.xpath(".//sub[not(ancestor::sub)]").each do |x| depth = calculate_subscript_depth(x) depth < 2 and next # No warning for single level subscripts if [2, 3].include?(depth) style_warning(node, "may contain nested subscripts", x.to_xml) else # depth >= 3 style_warning(node, "no more than 3 levels of subscript nesting allowed", x.to_xml) end end end |
#style_two_regex_not_prev(n, text, regex, re_prev, warning) ⇒ Object
style check with a regex on a token and a negative match on its preceding token
75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/metanorma/iso/validate_style.rb', line 75 def style_two_regex_not_prev(n, text, regex, re_prev, warning) text.nil? and return arr = Tokenizer::WhitespaceTokenizer.new.tokenize(text) arr.each_index do |i| m = regex.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(node, text) ⇒ Object
ISO/IEC DIR 2, 9.3
83 84 85 86 87 88 89 90 |
# File 'lib/metanorma/iso/validate_numeric.rb', line 83 def style_units(node, text) style_regex(/\b(?<num>[0-9][0-9,]*\p{Zs}+[\u00b0\u2032\u2033])/, "space between number and degrees/minutes/seconds", node, text) style_regex(/(?<![A-Za-z0-9])(?<num>[1-9][0-9,]*#{SI_UNIT})\b/o, "no space between number and SI unit", node, text) style_non_std_units(node, text) end |
#style_warning(node, msg, text = nil, display: true) ⇒ Object
142 143 144 145 146 147 |
# File 'lib/metanorma/iso/validate_style.rb', line 142 def style_warning(node, msg, text = nil, display: true) @novalid and return w = msg w += ": #{text}" if text @log.add("STANDOC_48", node, params: [w], display:) end |
#subclause_validate(root) ⇒ Object
193 194 195 196 197 198 |
# File 'lib/metanorma/iso/validate_section.rb', line 193 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 |
#subfigure_validate(xmldoc) ⇒ Object
DRG directives 3.7; but anticipated by standoc
73 74 75 76 77 78 79 80 81 82 |
# File 'lib/metanorma/iso/validate.rb', line 73 def subfigure_validate(xmldoc) elems = { footnote: "fn", note: "note", key: "key" } xmldoc.xpath("//figure//figure").each do |f| elems.each do |k, v| f.xpath(".//#{v}").each do |n| @log.add("ISO_7", n, params: [k]) end end end end |
#symbols_validate(root) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/metanorma/iso/validate_section.rb', line 35 def symbols_validate(root) f = root.xpath("//definitions") f.empty? && return (f.size == 1 || @vocab) or @log.add("ISO_25", f.first) f.first.elements.reject { |e| %w(title dl).include? e.name }.empty? or @log.add("ISO_26", f.first) @vocab and f.each do |f1| f1.at("./ancestor::annex") or @log.add("ISO_27", f1) end end |
#tech_report_style(root) ⇒ Object
167 168 169 170 171 172 173 174 175 |
# File 'lib/metanorma/iso/validate_section.rb', line 167 def tech_report_style(root) @doctype == "technical-report" or return root.xpath("//sections/clause[not(@type = 'scope')] | //annex") .each do |s| r = requirement_check(extract_text(s)) and style_warning(s, "Technical Report clause may contain requirement", r) end end |
#term_xrefs_validate(xmldoc) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/metanorma/iso/validate_xref.rb', line 70 def term_xrefs_validate(xmldoc) termids = xmldoc .xpath("//sections/terms | //sections/clause[.//terms] | " \ "//annex[.//terms]").each_with_object({}) do |t, m| t.xpath(".//*/@anchor").each { |a| m[a.text] = true } t.xpath(".//*/@id").each { |a| m[a.text] = true } t.name == "terms" and m[t["anchor"] || t["id"]] = true end xmldoc.xpath(".//xref").each do |x| term_xrefs_validate1(x, termids) end end |
#term_xrefs_validate1(xref, termids) ⇒ Object
83 84 85 86 87 88 89 |
# File 'lib/metanorma/iso/validate_xref.rb', line 83 def term_xrefs_validate1(xref, termids) closest_id = xref.xpath("./ancestor::*[@id]")&.last or return termids[xref["target"]] && !termids[closest_id["id"]] and @log.add("ISO_50", xref, params: [xref["target"]]) !termids[xref["target"]] && termids[closest_id["id"]] and @log.add("ISO_51", xref, params: [xref["target"]]) end |
#termdef_style(xmldoc) ⇒ Object
ISO/IEC DIR 2, 16.5.6
41 42 43 44 45 46 47 48 49 50 |
# File 'lib/metanorma/iso/validate.rb', line 41 def termdef_style(xmldoc) xmldoc.xpath("//term").each do |t| para = t.at("./definition/verbal-definition") || return term = t.at("./preferred//name").text @lang == "en" and termdef_warn(para.text, /\A(the|a)\b/i, t, term, "ISO_4") %(Cyrl Latn).include?(@script) and termdef_warn(para.text, /\.\Z/i, t, term, "ISO_35") end end |
#termdef_warn(text, regex, elem, term, msg) ⇒ Object
36 37 38 |
# File 'lib/metanorma/iso/validate.rb', line 36 def termdef_warn(text, regex, elem, term, msg) regex.match(text) && @log.add(msg, elem, params: [term]) end |
#title_all_siblings(xpath, label) ⇒ Object
ISO/IEC DIR 2, 22.2
78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/metanorma/iso/validate_title.rb', line 78 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["anchor"]) subtitle = s.at("./title") notitle = notitle || (!subtitle || subtitle.text.empty?) withtitle = withtitle || (subtitle && !subtitle.text.empty?) end notitle && withtitle && @log.add("ISO_20", nil, params: [label]) end |
#title_first_level_validate(root) ⇒ Object
ISO/IEC DIR 2, 22.2
66 67 68 69 70 71 72 73 74 75 |
# File 'lib/metanorma/iso/validate_title.rb', line 66 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?) or @log.add("ISO_19", ss, params: [title]) end end end |
#title_intro_validate(root) ⇒ Object
10 11 12 13 14 15 16 17 18 19 |
# File 'lib/metanorma/iso/validate_title.rb', line 10 def title_intro_validate(root) title_intro_en = title_lang_part(root, "intro", "en") title_intro_fr = title_lang_part(root, "intro", "fr") if title_intro_en.nil? && !title_intro_fr.nil? @log.add("ISO_10", title_intro_fr) end if !title_intro_en.nil? && title_intro_fr.nil? @log.add("ISO_11", title_intro_en) end end |
#title_lang_part(doc, part, lang) ⇒ Object
6 7 8 |
# File 'lib/metanorma/iso/validate_title.rb', line 6 def title_lang_part(doc, part, lang) doc.at("//bibdata/title[@type='title-#{part}' and @language='#{lang}']") end |
#title_main_validate(root) ⇒ Object
21 22 23 24 25 26 27 28 29 30 |
# File 'lib/metanorma/iso/validate_title.rb', line 21 def title_main_validate(root) title_main_en = title_lang_part(root, "main", "en") title_main_fr = title_lang_part(root, "main", "fr") if title_main_en.nil? && !title_main_fr.nil? @log.add("ISO_12", title_main_fr) end if !title_main_en.nil? && title_main_fr.nil? @log.add("ISO_13", title_main_en) end end |
#title_names_type_validate(root) ⇒ Object
ISO/IEC DIR 2, 11.5.2
53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/metanorma/iso/validate_title.rb', line 53 def title_names_type_validate(root) @lang == "en" or return doctypes = /International\sStandard | Technical\sSpecification | Publicly\sAvailable\sSpecification | Technical\sReport | Guide /xi title_main_en = title_lang_part(root, "main", "en") !title_main_en.nil? && doctypes.match(title_main_en.text) and @log.add("ISO_17", title_main_en) title_intro_en = title_lang_part(root, "intro", "en") !title_intro_en.nil? && doctypes.match(title_intro_en.text) and @log.add("ISO_18", title_intro_en) end |
#title_no_full_stop_validate(root) ⇒ Object
93 94 95 96 97 98 99 100 101 |
# File 'lib/metanorma/iso/validate_title.rb', line 93 def title_no_full_stop_validate(root) root.xpath("//preface//title | //sections//title | //annex//title | " \ "//references/title | //preface//name | //sections//name | " \ "//annex//name").each do |t| style_regex(/\A(?<num>.+\.\Z)/i, "No full stop at end of title or caption", t, t.text.strip) end end |
#title_part_validate(root) ⇒ Object
32 33 34 35 36 37 38 39 |
# File 'lib/metanorma/iso/validate_title.rb', line 32 def title_part_validate(root) title_part_en = title_lang_part(root, "part", "en") title_part_fr = title_lang_part(root, "part", "fr") title_part_en.nil? && !title_part_fr.nil? && @log.add("ISO_14", title_part_fr) !title_part_en.nil? && title_part_fr.nil? && @log.add("ISO_15", title_part_en) end |
#title_subpart_validate(root) ⇒ Object
ISO/IEC DIR 2, 11.4
42 43 44 45 46 47 48 49 50 |
# File 'lib/metanorma/iso/validate_title.rb', line 42 def title_subpart_validate(root) docid = root.at("//bibdata/docidentifier[@type = 'ISO']") subpart = /-\d+-\d+/.match docid iec = root.at("//bibdata/contributor[role/@type = 'publisher']/" \ "organization[abbreviation = 'IEC' or " \ "name = 'International Electrotechnical Commission']") subpart && !iec and @log.add("ISO_16", docid) end |
#title_validate(root) ⇒ Object
103 104 105 106 107 108 109 110 111 112 |
# File 'lib/metanorma/iso/validate_title.rb', line 103 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)") title_no_full_stop_validate(root) end |
#vocab_terms_titles_validate(root) ⇒ Object
209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/metanorma/iso/validate_section.rb', line 209 def vocab_terms_titles_validate(root) terms = root.xpath("//sections/terms | //sections/clause[.//terms]") if terms.size == 1 ((t = terms.first.at("./title")) && (t&.text == @i18n.termsdef)) or @log.add("ISO_44", terms.first) elsif terms.size > 1 terms.each do |x| ((t = x.at("./title")) && /^#{@i18n.}/.match?(t&.text)) or @log.add("ISO_45", x) end end end |
#xrefs_mandate_validate(xmldoc) ⇒ Object
require that all assets of a particular type be cross-referenced within the document
93 94 95 96 97 98 |
# File 'lib/metanorma/iso/validate_xref.rb', line 93 def xrefs_mandate_validate(xmldoc) xrefs_mandate_validate1(xmldoc, "//annex", "Annex") xrefs_mandate_validate1(xmldoc, "//table", "Table") xrefs_mandate_validate1(xmldoc, "//figure", "Figure") xrefs_mandate_validate1(xmldoc, "//formula", "Formula") end |
#xrefs_mandate_validate1(xmldoc, xpath, name) ⇒ Object
100 101 102 103 104 105 106 107 108 109 |
# File 'lib/metanorma/iso/validate_xref.rb', line 100 def xrefs_mandate_validate1(xmldoc, xpath, name) exc = %w(table note example figure).map { |x| "//#{x}#{xpath}" } .join(" | ") (xmldoc.xpath(xpath) - xmldoc.xpath(exc)).each do |x| x["unnumbered"] == "true" and next @doc_xrefs[x["anchor"]] or @log.add(xpath == "//formula" ? "ISO_22" : "ISO_21", x, params: [name, x["anchor"]]) end end |