Class: Metanorma::ISO::Converter
- Inherits:
-
Standoc::Converter
- Object
- Standoc::Converter
- Metanorma::ISO::Converter
- Defined in:
- lib/metanorma/iso/converter.rb,
lib/metanorma/iso/base.rb,
lib/metanorma/iso/front.rb,
lib/metanorma/iso/cleanup.rb,
lib/metanorma/iso/section.rb,
lib/metanorma/iso/front_id.rb,
lib/metanorma/iso/validate.rb,
lib/metanorma/iso/validate_list.rb,
lib/metanorma/iso/validate_image.rb,
lib/metanorma/iso/validate_style.rb,
lib/metanorma/iso/validate_title.rb,
lib/metanorma/iso/validate_section.rb,
lib/metanorma/iso/validate_requirements.rb
Overview
A Converter implementation that generates ISO output, and a document schema encapsulation of the document for validation
Constant Summary collapse
- XML_ROOT_TAG =
"iso-standard".freeze
- XML_NAMESPACE =
"https://www.metanorma.org/ns/iso".freeze
- PRE_NORMREF_FOOTNOTES =
"//preface//fn | "\ "//clause[@type = 'scope']//fn".freeze
- NORMREF_FOOTNOTES =
"//references[@normative = 'true']//fn".freeze
- POST_NORMREF_FOOTNOTES =
"//sections//clause[not(@type = 'scope')]//fn | "\ "//annex//fn | //references[@normative = 'false']//fn".freeze
- TERM_CLAUSE =
"//sections//terms | "\ "//sections//clause[descendant::terms][not(descendant::definitions)]" .freeze
- PUBLISHER =
"./contributor[role/@type = 'publisher']/organization".freeze
- OTHERIDS =
"@type = 'DOI' or @type = 'metanorma' or @type = 'ISSN' or "\ "@type = 'ISBN'".freeze
- DEFAULT_EDGROUP_TYPE =
{ "technical-committee": "TC", subcommittee: "SC", workgroup: "WG" }.freeze
- STAGE_ABBRS =
{ "00": "PWI", "10": "NP", "20": "WD", "30": "CD", "40": "DIS", "50": "FDIS", "60": "IS", "90": "(Review)", "95": "(Withdrawal)", }.freeze
- STAGE_NAMES =
{ "00": "Preliminary work item", "10": "New work item proposal", "20": "Working draft", "30": "Committee draft", "40": "Draft", "50": "Final draft", "60": "International standard", "90": "Review", "95": "Withdrawal", }.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
- ASSETS_TO_STYLE =
"//termsource | //formula | //termnote | "\ "//p[not(ancestor::boilerplate)] | //li[not(p)] | //dt | "\ "//dd[not(p)] | //td[not(p)] | //th[not(p)]".freeze
- ONE_SYMBOLS_WARNING =
"Only one Symbols and Abbreviated "\ "Terms section in the standard".freeze
- NON_DL_SYMBOLS_WARNING =
"Symbols and Abbreviated Terms can "\ "only contain a definition list".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_ISO_WARN =
"non-ISO/IEC reference not expected as normative".freeze
- SCOPE_WARN =
"Scope contains subclauses: should be succinct".freeze
- NORM_BIBITEMS =
"//references[@normative = 'true']/bibitem".freeze
- 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
Instance Method Summary collapse
- #add_amd_parts(docnum, node) ⇒ Object
- #add_id_parts(docnum, part, subpart) ⇒ Object
- #admonition_name(node) ⇒ Object
- #appendix_parse(attrs, xml, node) ⇒ Object
- #approval_groups_rename(xmldoc) ⇒ Object
- #asset_style(root) ⇒ Object
- #bibdata_cleanup(xmldoc) ⇒ Object
- #bibdata_validate(doc) ⇒ Object
- #bibitem_cleanup(xmldoc) ⇒ Object
- #bibitem_validate(xmldoc) ⇒ Object
- #boilerplate_file(_xmldoc) ⇒ Object
- #clause_parse(attrs, xml, node) ⇒ Object
- #content_validate(doc) ⇒ Object
- #cover_stage_abbr(node) ⇒ Object
-
#definition_style(node) ⇒ Object
ISO/IEC DIR 2, 16.5.6.
- #disjunct_error(img, cond1, cond2, msg1, msg2) ⇒ Object
- #doc_converter(node) ⇒ Object
- #doc_extract_attributes(node) ⇒ Object
-
#docidentifier_cleanup(xmldoc) ⇒ Object
ISO as a prefix goes first.
- #doctype_validate(xmldoc) ⇒ Object
- #editorial_group_types(xmldoc) ⇒ Object
- #editorial_groups_agency(xmldoc) ⇒ Object
-
#example_style(node) ⇒ Object
ISO/IEC DIR 2, 16.5.7 ISO/IEC DIR 2, 25.5.
- #external_constraint(text) ⇒ Object
- #extract_publishers(xmldoc) ⇒ Object
- #extract_text(node) ⇒ Object
- #figure_validate(xmldoc) ⇒ Object
- #footnote_cleanup(xmldoc) ⇒ Object
-
#footnote_style(node) ⇒ Object
ISO/IEC DIR 2, 26.5.
-
#foreword_style(node) ⇒ Object
ISO/IEC DIR 2, 12.2.
-
#foreword_validate(root) ⇒ Object
ISO/IEC DIR 2, 12.4.
- #format_ref(ref, type) ⇒ Object
- #get_id_prefix(xmldoc) ⇒ Object
- #get_stage(node) ⇒ Object
- #get_substage(node) ⇒ Object
- #get_typeabbr(node, amd: false) ⇒ Object
- #html_converter(node) ⇒ Object
- #html_converter_alt(node) ⇒ Object
- #id_add_year(docnum, node) ⇒ Object
- #id_langsuffix(docnum, node) ⇒ Object
- #id_prefix(prefix, id) ⇒ Object
- #id_stage_abbr(stage, substage, node, bare = false) ⇒ Object
- #id_stage_abbr1(stage, substage, node, bare) ⇒ Object
- #id_stage_prefix(docnum, node) ⇒ Object
- #id_year(docnum, node, mode: :default) ⇒ Object
- #image_name_parse(img, prefix) ⇒ Object
- #image_name_prefix(xmldoc) ⇒ Object
- #image_name_suffix(xmldoc) ⇒ Object
-
#image_name_validate(xmldoc) ⇒ Object
DRG directives 3.2.
- #image_name_validate1(i, prefix) ⇒ Object
- #init(node) ⇒ Object
- #insert_unpub_note(biblio, msg) ⇒ Object
-
#introduction_style(node) ⇒ Object
ISO/IEC DIR 2, 13.2.
- #iso_id(node, xml) ⇒ Object
-
#iso_id1(node) ⇒ Object
def get_typeabbr(node, amd: false) case doctype(node) when “directive” then “DIR” when “technical-report” then “TR” when “technical-specification” then “TS” else nil end end.
- #iso_id_out(node, xml, dns) ⇒ 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
- #listcount_validate(doc) ⇒ Object
-
#locality_erefs_validate(root) ⇒ Object
ISO/IEC DIR 2, 10.4.
- #metadata_approval_agency(xml, list) ⇒ Object
- #metadata_approval_committee(node, xml) ⇒ Object
- #metadata_approval_committee_types(node) ⇒ Object
- #metadata_author(node, xml) ⇒ Object
- #metadata_committee(node, xml) ⇒ Object
- #metadata_copyright(node, xml) ⇒ Object
- #metadata_editorial_committee(node, xml) ⇒ Object
- #metadata_ext(node, xml) ⇒ Object
- #metadata_id(node, xml) ⇒ Object
- #metadata_publisher(node, xml) ⇒ Object
- #metadata_status(node, xml) ⇒ Object
- #metadata_subdoctype(node, xml) ⇒ 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_attrs(node) ⇒ Object
- #ol_count_validate(doc) ⇒ Object
-
#onlychild_clause_validate(root) ⇒ Object
ISO/IEC DIR 2, 22.3.2.
- #org_abbrev ⇒ Object
- #other_footnote_renumber(xmldoc) ⇒ Object
- #outputs(node, ret) ⇒ Object
- #patent_notice_parse(xml, node) ⇒ Object
- #pdf_converter(node) ⇒ Object
- #permission_check(text) ⇒ Object
- #permission_re ⇒ Object
- #possibility_check(text) ⇒ Object
- #possibility_re ⇒ Object
- #presentation_xml_converter(node) ⇒ Object
- #pub_class(bib) ⇒ Object
- #recommendation_check(text) ⇒ Object
- #recommendation_re ⇒ Object
- #relaton_relation_descriptions ⇒ Object
- #relaton_relations ⇒ Object
- #replacement_standard(biblio) ⇒ Object
- #requirement_check(text) ⇒ Object
- #requirement_re ⇒ Object
- #requirements_processor ⇒ Object
- #scope_parse(attrs, xml, node) ⇒ Object
-
#scope_style(node) ⇒ Object
ISO/IEC DIR 2, 14.2.
- #script_validate(xmldoc) ⇒ Object
- #section_names_terms_cleanup(xml) ⇒ Object
- #section_style(root) ⇒ Object
- #section_validate(doc) ⇒ Object
- #sections_cleanup(xml) ⇒ 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
- #sectiontype(node, level = true) ⇒ 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 does not deal with preceding text marked up.
- #seqcheck(names, msg, accepted) ⇒ Object
- #skip_list_punctuation(list) ⇒ Object
- #sort_biblio(bib) ⇒ Object
-
#sort_biblio_key(bib) ⇒ Object
sort by: doc class (ISO, IEC, other standard (not DOI &c), other then standard class (docid class other than DOI &c) 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.
- #stage_abbr(stage, substage, doctype) ⇒ Object
- #stage_name(stage, substage, _doctype, iteration = nil) ⇒ Object
- #stage_validate(xmldoc) ⇒ Object
-
#starts_lowercase?(text) ⇒ Boolean
allow that all-caps word (acronym) is agnostic as to lowercase.
- #starts_uppercase?(text) ⇒ Boolean
- #structured_id(node, xml) ⇒ Object
- #sts_converter(node) ⇒ 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_percent(node, text) ⇒ Object
ISO/IEC DIR 2, 9.2.1.
- #style_punct(node, text) ⇒ Object
- #style_regex(regex, warning, node, text) ⇒ Object
-
#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) ⇒ Object
- #subclause_validate(root) ⇒ Object
-
#subfigure_validate(xmldoc) ⇒ Object
DRG directives 3.7; but anticipated by standoc.
- #substage_validate(xmldoc) ⇒ Object
- #symbols_validate(root) ⇒ Object
- #tech_report_style(root) ⇒ Object
- #term_children_cleanup(xmldoc) ⇒ Object
- #term_contains_subclauses(node) ⇒ Object
- #term_def_subclause_parse(attrs, xml, node) ⇒ Object
- #term_defs_boilerplate_cont(src, term, isodoc) ⇒ Object
- #term_xrefs_validate(xmldoc) ⇒ Object
- #term_xrefs_validate1(xref, termids) ⇒ Object
- #termdef_boilerplate_insert(xmldoc, isodoc, once = false) ⇒ Object
-
#termdef_style(xmldoc) ⇒ Object
ISO/IEC DIR 2, 16.5.6.
- #termdef_warn(text, regex, elem, term, msg) ⇒ Object
- #title(node, xml) ⇒ Object
-
#title_all_siblings(xpath, label) ⇒ Object
ISO/IEC DIR 2, 22.2.
- #title_amd(node, xml, lang, at) ⇒ Object
-
#title_first_level_validate(root) ⇒ Object
ISO/IEC DIR 2, 22.2.
- #title_full(node, xml, lang, at) ⇒ Object
- #title_intro(node, xml, lang, at) ⇒ Object
- #title_intro_validate(root) ⇒ Object
- #title_lang_part(doc, part, lang) ⇒ Object
- #title_main(node, xml, lang, at) ⇒ 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(node, xml, lang, at) ⇒ Object
- #title_part_validate(root) ⇒ Object
-
#title_subpart_validate(root) ⇒ Object
ISO/IEC DIR 2, 11.4.
- #title_validate(root) ⇒ Object
- #unpub_footnotes(xmldoc) ⇒ Object
- #unpub_stage_prefix(docnum, stage, typeabbr, node) ⇒ Object
- #unpublished_note(xmldoc) ⇒ Object
- #validate(doc) ⇒ Object
- #vocab_terms_titles_validate(root) ⇒ Object
- #withdrawn_note(xmldoc) ⇒ Object
- #withdrawn_ref?(biblio) ⇒ Boolean
Instance Method Details
#add_amd_parts(docnum, node) ⇒ Object
165 166 167 168 169 170 171 172 |
# File 'lib/metanorma/iso/front_id.rb', line 165 def add_amd_parts(docnum, node) case doctype(node) when "amendment" "#{docnum}/Amd #{node.attr('amendment-number')}" when "technical-corrigendum" "#{docnum}/Cor.#{node.attr('corrigendum-number')}" end end |
#add_id_parts(docnum, part, subpart) ⇒ Object
200 201 202 203 204 |
# File 'lib/metanorma/iso/front_id.rb', line 200 def add_id_parts(docnum, part, subpart) docnum += "-#{part}" if part docnum += "-#{subpart}" if subpart docnum end |
#admonition_name(node) ⇒ Object
64 65 66 67 68 69 70 |
# File 'lib/metanorma/iso/base.rb', line 64 def admonition_name(node) name = super a = node.attr("type") and ["editorial"].each do |t| name = t if a.casecmp(t).zero? end name end |
#appendix_parse(attrs, xml, node) ⇒ Object
17 18 19 20 21 22 23 24 |
# File 'lib/metanorma/iso/section.rb', line 17 def appendix_parse(attrs, xml, node) attrs[:"inline-header"] = 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 |
#approval_groups_rename(xmldoc) ⇒ Object
219 220 221 222 223 |
# File 'lib/metanorma/iso/cleanup.rb', line 219 def approval_groups_rename(xmldoc) %w(technical-committee subcommittee workgroup).each do |v| xmldoc.xpath("//bibdata//approval-#{v}").each { |a| a.name = v } end end |
#asset_style(root) ⇒ Object
187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/metanorma/iso/validate_style.rb', line 187 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_cleanup(xmldoc) ⇒ Object
212 213 214 215 216 217 |
# File 'lib/metanorma/iso/cleanup.rb', line 212 def bibdata_cleanup(xmldoc) super approval_groups_rename(xmldoc) editorial_groups_agency(xmldoc) editorial_group_types(xmldoc) end |
#bibdata_validate(doc) ⇒ Object
153 154 155 156 157 158 159 |
# File 'lib/metanorma/iso/validate.rb', line 153 def bibdata_validate(doc) doctype_validate(doc) script_validate(doc) stage_validate(doc) substage_validate(doc) iteration_validate(doc) end |
#bibitem_cleanup(xmldoc) ⇒ Object
144 145 146 147 148 |
# File 'lib/metanorma/iso/cleanup.rb', line 144 def bibitem_cleanup(xmldoc) super unpublished_note(xmldoc) withdrawn_note(xmldoc) end |
#bibitem_validate(xmldoc) ⇒ Object
178 179 180 181 182 183 184 185 |
# File 'lib/metanorma/iso/validate.rb', line 178 def bibitem_validate(xmldoc) xmldoc.xpath("//bibitem[date/on = '–']").each do |b| b.at("./note[@type = 'Unpublished-Status']") or @log.add("Style", b, "Reference #{b&.at('./@id')&.text} does not have an "\ "associated footnote indicating unpublished status") end end |
#boilerplate_file(_xmldoc) ⇒ Object
121 122 123 124 125 126 127 128 |
# File 'lib/metanorma/iso/cleanup.rb', line 121 def boilerplate_file(_xmldoc) file = case @lang when "fr" then "boilerplate-fr.xml" when "ru" then "boilerplate-ru.xml" else "boilerplate.xml" end File.join(@libdir, file) end |
#clause_parse(attrs, xml, node) ⇒ Object
7 8 9 10 |
# File 'lib/metanorma/iso/section.rb', line 7 def clause_parse(attrs, xml, node) node.option? "appendix" and return appendix_parse(attrs, xml, node) super end |
#content_validate(doc) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/metanorma/iso/validate.rb', line 161 def content_validate(doc) super title_validate(doc.root) isosubgroup_validate(doc.root) onlychild_clause_validate(doc.root) termdef_style(doc.root) see_xrefs_validate(doc.root) term_xrefs_validate(doc.root) see_erefs_validate(doc.root) locality_erefs_validate(doc.root) bibdata_validate(doc.root) bibitem_validate(doc.root) figure_validate(doc.root) listcount_validate(doc) list_punctuation(doc) end |
#cover_stage_abbr(node) ⇒ Object
229 230 231 232 233 234 235 236 237 |
# File 'lib/metanorma/iso/front_id.rb', line 229 def cover_stage_abbr(node) stage = get_stage(node) abbr = id_stage_abbr(get_stage(node), get_substage(node), node, true) typeabbr = get_typeabbr(node, amd: true) if stage.to_i > 50 || (stage.to_i == 60 && get_substage(node).to_i < 60) typeabbr = "" end "#{abbr}#{typeabbr}".strip end |
#definition_style(node) ⇒ Object
ISO/IEC DIR 2, 16.5.6
41 42 43 44 45 46 |
# File 'lib/metanorma/iso/validate_style.rb', line 41 def definition_style(node) return if @novalid r = requirement_check(extract_text(node)) style_warning(node, "Definition may contain requirement", r) if r end |
#disjunct_error(img, cond1, cond2, msg1, msg2) ⇒ Object
40 41 42 43 44 45 |
# File 'lib/metanorma/iso/validate_image.rb', line 40 def disjunct_error(img, cond1, cond2, msg1, msg2) cond1 && !cond2 and @log.add("Style", img, "image name #{img['src']} #{msg1}") !cond1 && cond2 and @log.add("Style", img, "image name #{img['src']} #{msg2}") end |
#doc_converter(node) ⇒ Object
28 29 30 |
# File 'lib/metanorma/iso/base.rb', line 28 def doc_converter(node) IsoDoc::Iso::WordConvert.new(doc_extract_attributes(node)) end |
#doc_extract_attributes(node) ⇒ Object
32 33 34 |
# File 'lib/metanorma/iso/base.rb', line 32 def doc_extract_attributes(node) super.merge(isowordtemplate: node.attr("iso-word-template")) end |
#docidentifier_cleanup(xmldoc) ⇒ Object
ISO as a prefix goes first
45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/metanorma/iso/cleanup.rb', line 45 def docidentifier_cleanup(xmldoc) prefix = get_id_prefix(xmldoc) id = xmldoc.at("//bibdata/docidentifier[@type = 'ISO']") or return id.content = id_prefix(prefix, id) id = xmldoc.at("//bibdata/ext/structuredidentifier/project-number") and id.content = id_prefix(prefix, id) %w(iso-with-lang iso-reference iso-undated).each do |t| id = xmldoc.at("//bibdata/docidentifier[@type = '#{t}']") and id.content = id_prefix(prefix, id) end end |
#doctype_validate(xmldoc) ⇒ Object
116 117 118 119 120 121 122 123 |
# File 'lib/metanorma/iso/validate.rb', line 116 def doctype_validate(xmldoc) doctype = xmldoc&.at("//bibdata/ext/doctype")&.text %w(international-standard technical-specification technical-report publicly-available-specification international-workshop-agreement guide amendment technical-corrigendum).include? doctype or @log.add("Document Attributes", nil, "#{doctype} is not a recognised document type") end |
#editorial_group_types(xmldoc) ⇒ Object
247 248 249 250 251 252 253 254 255 |
# File 'lib/metanorma/iso/cleanup.rb', line 247 def editorial_group_types(xmldoc) %w(technical-committee subcommittee workgroup).each do |v| xmldoc.xpath("//bibdata//#{v} | //bibdata//approval-#{v}").each do |g| next if g["type"] g["type"] = DEFAULT_EDGROUP_TYPE[v.to_sym] end end end |
#editorial_groups_agency(xmldoc) ⇒ Object
225 226 227 228 229 230 231 232 233 234 |
# File 'lib/metanorma/iso/cleanup.rb', line 225 def editorial_groups_agency(xmldoc) pubs = extract_publishers(xmldoc) xmldoc.xpath("//bibdata/ext/editorialgroup").each do |e| pubs.reverse.each do |p| if e.children.empty? then e << "<agency>#{p}</agency>" else e.children.first.previous = "<agency>#{p}</agency>" end end end end |
#example_style(node) ⇒ Object
ISO/IEC DIR 2, 16.5.7 ISO/IEC DIR 2, 25.5
50 51 52 53 54 55 |
# File 'lib/metanorma/iso/validate_style.rb', line 50 def example_style(node) return if @novalid style_no_guidance(node, extract_text(node), "Example") style(node, extract_text(node)) end |
#external_constraint(text) ⇒ Object
94 95 96 97 98 99 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 94 def external_constraint(text) text.split(/\.\s+/).each do |t| return t if /\b(must)\b/xi.match? t end nil end |
#extract_publishers(xmldoc) ⇒ Object
236 237 238 239 240 241 242 |
# File 'lib/metanorma/iso/cleanup.rb', line 236 def extract_publishers(xmldoc) xmldoc.xpath("//bibdata/contributor[role/@type = 'publisher']/"\ "organization").each_with_object([]) do |p, m| x = p.at("./abbreviation") || p.at("./name") or next m << x.text end 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) return "" if node.nil? node1 = Nokogiri::XML.fragment(node.to_s) node1.xpath("//link | //locality | //localityStack").each(&:remove) ret = "" node1.traverse { |x| ret += x.text if x.text? } HTMLEntities.new.decode(ret) end |
#figure_validate(xmldoc) ⇒ Object
91 92 93 94 |
# File 'lib/metanorma/iso/validate_image.rb', line 91 def figure_validate(xmldoc) image_name_validate(xmldoc) subfigure_validate(xmldoc) end |
#footnote_cleanup(xmldoc) ⇒ Object
130 131 132 133 |
# File 'lib/metanorma/iso/cleanup.rb', line 130 def footnote_cleanup(xmldoc) unpub_footnotes(xmldoc) super end |
#footnote_style(node) ⇒ Object
ISO/IEC DIR 2, 26.5
66 67 68 69 70 71 |
# File 'lib/metanorma/iso/validate_style.rb', line 66 def footnote_style(node) return if @novalid style_no_guidance(node, extract_text(node), "Footnote") style(node, extract_text(node)) end |
#foreword_style(node) ⇒ Object
ISO/IEC DIR 2, 12.2
19 20 21 22 23 |
# File 'lib/metanorma/iso/validate_style.rb', line 19 def foreword_style(node) return if @novalid 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("Style", f, "foreword contains subclauses") unless s.nil? end |
#format_ref(ref, type) ⇒ Object
57 58 59 60 |
# File 'lib/metanorma/iso/cleanup.rb', line 57 def format_ref(ref, type) ref = ref.sub(/ \(All Parts\)/i, "") super end |
#get_id_prefix(xmldoc) ⇒ Object
35 36 37 38 39 40 41 42 |
# File 'lib/metanorma/iso/cleanup.rb', line 35 def get_id_prefix(xmldoc) xmldoc.xpath("//bibdata/contributor[role/@type = 'publisher']"\ "/organization").each_with_object([]) do |x, prefix| x1 = x.at("abbreviation")&.text || x.at("name")&.text # (x1 == "ISO" and prefix.unshift("ISO")) or prefix << x1 prefix << x1 end end |
#get_stage(node) ⇒ Object
284 285 286 287 288 289 |
# File 'lib/metanorma/iso/front_id.rb', line 284 def get_stage(node) a = node.attr("status") a = node.attr("docstage") if a.nil? || a.empty? a = "60" if a.nil? || a.empty? a end |
#get_substage(node) ⇒ Object
291 292 293 294 295 296 |
# File 'lib/metanorma/iso/front_id.rb', line 291 def get_substage(node) stage = get_stage(node) ret = node.attr("docsubstage") ret = (stage == "60" ? "60" : "00") if ret.nil? || ret.empty? ret end |
#get_typeabbr(node, amd: false) ⇒ Object
92 93 94 95 96 97 98 99 100 |
# File 'lib/metanorma/iso/front_id.rb', line 92 def get_typeabbr(node, amd: false) case doctype(node) when "directive" then "DIR " when "technical-report" then "TR " when "technical-specification" then "TS " when "amendment" then (amd ? "Amd " : "") when "technical-corrigendum" then (amd ? "Cor " : "") end end |
#html_converter(node) ⇒ Object
19 20 21 |
# File 'lib/metanorma/iso/base.rb', line 19 def html_converter(node) IsoDoc::Iso::HtmlConvert.new(html_extract_attributes(node)) end |
#html_converter_alt(node) ⇒ Object
23 24 25 26 |
# File 'lib/metanorma/iso/base.rb', line 23 def html_converter_alt(node) IsoDoc::Iso::HtmlConvert.new(html_extract_attributes(node) .merge(alt: true)) end |
#id_add_year(docnum, node) ⇒ Object
277 278 279 280 281 282 |
# File 'lib/metanorma/iso/front_id.rb', line 277 def id_add_year(docnum, node) year = node.attr("copyright-year") @amd and year ||= node.attr("updated-date")&.sub(/-.*$/, "") docnum += ":#{year}" if year docnum end |
#id_langsuffix(docnum, node) ⇒ Object
174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/metanorma/iso/front_id.rb', line 174 def id_langsuffix(docnum, node) lang = node.attr("language") || "en" suffix = case lang when "en" then "(E)" when "fr" then "(F)" when "ru" then "(R)" else "(X)" end "#{docnum}#{suffix}" end |
#id_prefix(prefix, id) ⇒ Object
28 29 30 31 32 33 |
# File 'lib/metanorma/iso/cleanup.rb', line 28 def id_prefix(prefix, id) # we're just inheriting the prefixes from parent doc return id.text if @amd prefix.join("/") + (id.text.match?(%{^/}) ? "" : " ") + id.text end |
#id_stage_abbr(stage, substage, node, bare = false) ⇒ Object
206 207 208 209 210 211 212 213 214 |
# File 'lib/metanorma/iso/front_id.rb', line 206 def id_stage_abbr(stage, substage, node, = false) ret = id_stage_abbr1(stage, substage, node, ) if %w(amendment technical-corrigendum technical-report technical-specification).include?(doctype(node)) && !%w(D FD).include?(ret) ret = "#{ret} " end ret end |
#id_stage_abbr1(stage, substage, node, bare) ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/metanorma/iso/front_id.rb', line 216 def id_stage_abbr1(stage, substage, node, ) if IsoDoc::Iso::Metadata.new("en", "Latn", @i18n) .status_abbrev(stage_abbr(stage, substage, doctype(node)), substage, nil, nil, doctype(node)) else IsoDoc::Iso::Metadata.new("en", "Latn", @i18n) .status_abbrev(stage_abbr(stage, substage, doctype(node)), substage, node.attr("iteration"), node.attr("draft"), doctype(node)) end end |
#id_stage_prefix(docnum, node) ⇒ Object
239 240 241 242 243 244 245 246 247 248 |
# File 'lib/metanorma/iso/front_id.rb', line 239 def id_stage_prefix(docnum, node) stage = get_stage(node) typeabbr = get_typeabbr(node) if stage && (stage.to_i < 60) docnum = unpub_stage_prefix(docnum, stage, typeabbr, node) elsif typeabbr == "DIR " then docnum = "#{typeabbr}#{docnum}" elsif typeabbr && !@amd then docnum = "/#{typeabbr}#{docnum}" end docnum end |
#id_year(docnum, node, mode: :default) ⇒ Object
250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/metanorma/iso/front_id.rb', line 250 def id_year(docnum, node, mode: :default) case mode when :strip then docnum.sub(/:(19|20)\d\d(?!\d)/, "") when :force then id_add_year(docnum, node) else stage = get_stage(node) if stage && (stage.to_i < 60) docnum else id_add_year(docnum, node) end end end |
#image_name_parse(img, prefix) ⇒ Object
47 48 49 50 51 52 53 54 55 |
# File 'lib/metanorma/iso/validate_image.rb', line 47 def image_name_parse(img, prefix) m = %r[(SL)?#{prefix}fig(?<tab>Tab)?(?<annex>[A-Z])?(Text)?(?<num>\d+) (?<subfig>[a-z])?(?<key>_key\d+)?(?<lang>_[a-z])?$]x .match(File.basename(img["src"], ".*")) m.nil? and @log.add("Style", img, "image name #{img['src']} does not match DRG requirements") m end |
#image_name_prefix(xmldoc) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/metanorma/iso/validate_image.rb', line 15 def image_name_prefix(xmldoc) std = xmldoc&.at("//bibdata/ext/structuredidentifier/project-number") or return num = xmldoc&.at("//bibdata/docnumber")&.text or return ed = xmldoc&.at("//bibdata/edition")&.text || "1" prefix = num std["part"] and prefix += "-#{std['part']}" prefix += "_ed#{ed}" amd = std["amendment"] and prefix += "amd#{amd}" prefix end |
#image_name_suffix(xmldoc) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/metanorma/iso/validate_image.rb', line 27 def image_name_suffix(xmldoc) case xmldoc&.at("//bibdata/language")&.text when "fr" then "_f" when "de" then "_d" when "ru" then "_r" when "es" then "_s" when "ar" then "_a" # when "en" then "_e" else "_e" end end |
#image_name_validate(xmldoc) ⇒ Object
DRG directives 3.2
76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/metanorma/iso/validate_image.rb', line 76 def image_name_validate(xmldoc) prefix = image_name_prefix(xmldoc) or return xmldoc.xpath("//image").each do |i| next if i["src"].start_with?("data:") case File.basename(i["src"]) when /^ISO_\d+_/ when /^(SL)?#{prefix}fig/ then image_name_validate1(i, prefix) else @log.add("Style", i, "image name #{i['src']} does not match DRG requirements: expect #{prefix}fig") end end end |
#image_name_validate1(i, prefix) ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/metanorma/iso/validate_image.rb', line 57 def image_name_validate1(i, prefix) m = image_name_parse(i, prefix) or return warn i["src"] disjunct_error(i, i.at("./ancestor::table"), !m[:tab].nil?, "is under a table but is not so labelled", "is labelled as under a table but is not") disjunct_error(i, i.at("./ancestor::annex"), !m[:annex].nil?, "is under an annex but is not so labelled", "is labelled as under an annex but is not") disjunct_error(i, i.xpath("./ancestor::figure").size > 1, !m[:subfig].nil?, "does not have a subfigure letter but is a subfigure", "has a subfigure letter but is not a subfigure") lang = image_name_suffix(i.document.root) (m[:lang] || "_e") == lang or @log.add("Style", i, "image name #{i['src']} expected to have suffix #{lang}") end |
#init(node) ⇒ Object
52 53 54 55 56 |
# File 'lib/metanorma/iso/base.rb', line 52 def init(node) super @amd = %w(amendment technical-corrigendum).include? doctype(node) @vocab = node.attr("docsubtype") == "vocabulary" end |
#insert_unpub_note(biblio, msg) ⇒ Object
187 188 189 190 |
# File 'lib/metanorma/iso/cleanup.rb', line 187 def insert_unpub_note(biblio, msg) biblio.at("./language | ./script | ./abstract | ./status") .previous = %(<note type="Unpublished-Status"><p>#{msg}</p></note>) end |
#introduction_style(node) ⇒ Object
ISO/IEC DIR 2, 13.2
33 34 35 36 37 38 |
# File 'lib/metanorma/iso/validate_style.rb', line 33 def introduction_style(node) return if @novalid r = requirement_check(extract_text(node)) style_warning(node, "Introduction may contain requirement", r) if r end |
#iso_id(node, xml) ⇒ Object
73 74 75 76 77 78 79 80 81 |
# File 'lib/metanorma/iso/front_id.rb', line 73 def iso_id(node, xml) (!@amd && node.attr("docnumber")) || (@amd && node.attr("updates")) or return dn = id_stage_prefix(iso_id1(node), node) dns = [id_year(dn, node, mode: :default), id_year(dn, node, mode: :force), id_year(dn, node, mode: :strip)] iso_id_out(node, xml, dns) end |
#iso_id1(node) ⇒ Object
def get_typeabbr(node, amd: false)
case doctype(node)
when "directive" then "DIR"
when "technical-report" then "TR"
when "technical-specification" then "TS"
else nil
end
end
def iso_id(node, xml)
(!@amd && node.attr("docnumber")) || (@amd && node.attr("updates")) or
return
stage = id_stage_abbr(get_stage(node), get_substage(node), node, true)&.strip
stage = nil if %w{IS (Review) (Withdrwal)}.include?(stage.strip)
urn_stage = "#{get_stage(node)}.#{get_substage(node)}"
pub = (node.attr(“publisher”) || “ISO”).split(//)
params = {
number: node.attr("docnumber"), # (@amd ? node.attr("updates") : node.attr("docnumber")),
part: node.attr("partnumber"),
language: node.attr("language") || "en",
type: get_typeabbr(node),
year: node.attr("copyright-year") || node.attr("updated-date")&.sub(/-.*$/, ""),
publisher: pub[0],
copublisher: pub[1..-1],
}.compact
if a = node.attr("amendment-number")
params[:amendments] = { number: a, stage: stage }
elsif a = node.attr("corrigendum-number")
params[:corrigendums] = { number: a, stage: stage }
else
params.merge!( { stage: stage, urn_stage: urn_stage }.compact )
end
iso_id_out(xml, params)
end
def iso_id_out(xml, params)
params_nolang = params.dup.tap { |hs| hs.delete(:language) }
unpub = /^[0-5]/.match?(params[:urn_stage])
params1 = unpub ? params_nolang.dup.tap { |hs| hs.delete(:year) } : params_nolang
xml.docidentifier Pubid::Iso::Identifier.new(**params1), **attr_code(type: "ISO")
params2 = params_nolang.dup.tap { |hs| hs.delete(:year) }
xml.docidentifier Pubid::Iso::Identifier.new(**params2), **attr_code(type: "iso-undated")
params1 = unpub ? params.dup.tap { |hs| hs.delete(:year) } : params
xml.docidentifier(Pubid::Iso::Identifier.new(**params1),
**attr_code(type: "iso-with-lang"))
warn params
warn "Generated: #{Pubid::Iso::Identifier.new(**params).to_s}"
xml.docidentifier(Pubid::Iso::Identifier.new(**params),
**attr_code(type: "iso-reference"))
end
155 156 157 158 159 160 161 162 163 |
# File 'lib/metanorma/iso/front_id.rb', line 155 def iso_id1(node) if @amd dn = node.attr("updates") add_amd_parts(dn, node) else part, subpart = node&.attr("partnumber")&.split(/-/) add_id_parts(node.attr("docnumber"), part, subpart) end end |
#iso_id_out(node, xml, dns) ⇒ Object
83 84 85 86 87 88 89 90 |
# File 'lib/metanorma/iso/front_id.rb', line 83 def iso_id_out(node, xml, dns) xml.docidentifier dns[0], **attr_code(type: "ISO") xml.docidentifier dns[2], **attr_code(type: "iso-undated") xml.docidentifier(id_langsuffix(dns[0], node), **attr_code(type: "iso-with-lang")) xml.docidentifier(id_langsuffix(dns[1], node), **attr_code(type: "iso-reference")) end |
#isosubgroup_validate(root) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/metanorma/iso/validate.rb', line 15 def isosubgroup_validate(root) root.xpath("//technical-committee/@type").each do |t| unless %w{TC PC JTC JPC}.include? t.text @log.add("Document Attributes", nil, "invalid technical committee type #{t}") end end root.xpath("//subcommittee/@type").each do |t| unless %w{SC JSC}.include? t.text @log.add("Document Attributes", nil, "invalid subcommittee type #{t}") end end end |
#iteration_validate(xmldoc) ⇒ Object
146 147 148 149 150 151 |
# File 'lib/metanorma/iso/validate.rb', line 146 def iteration_validate(xmldoc) iteration = xmldoc&.at("//bibdata/status/iteration")&.text or return /^\d+/.match(iteration) or @log.add("Document Attributes", nil, "#{iteration} is not a recognised 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
68 69 70 71 72 73 74 75 76 77 |
# File 'lib/metanorma/iso/validate_list.rb', line 68 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
100 101 102 103 104 105 106 107 108 109 |
# File 'lib/metanorma/iso/validate_list.rb', line 100 def list_full_sentence(elem) text = elem.text.strip starts_uppercase?(text) or style_warning(elem, "List entry of separate sentences must start "\ "with uppercase letter", text) punct = text.strip.sub(/^.*?(\S)$/m, "\\1") punct == "." or style_warning(elem, "List entry of separate sentences must "\ "end with full stop", text) 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 |
# File 'lib/metanorma/iso/validate_list.rb', line 56 def list_punctuation1(list, prectext) prectext ||= "" entries = list.xpath(".//li") case prectext.strip.chars.last 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) end end |
#list_semicolon_phrase(elem, last) ⇒ Object
79 80 81 82 83 84 85 |
# File 'lib/metanorma/iso/validate_list.rb', line 79 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) list_semicolon_phrase_punct(elem, text, last) end |
#list_semicolon_phrase_punct(elem, text, last) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/metanorma/iso/validate_list.rb', line 87 def list_semicolon_phrase_punct(elem, text, last) punct = text.strip.sub(/^.*?(\S)$/m, "\\1") if last punct == "." or style_warning(elem, "Final list entry of broken up "\ "sentence must end with full stop", text) else punct == ";" or style_warning(elem, "List entry of broken up sentence must "\ "end with semicolon", text) end 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
64 65 66 67 68 69 70 71 72 73 |
# File 'lib/metanorma/iso/validate.rb', line 64 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("Style", t, "undated reference #{t['citeas']} should not contain "\ "specific elements") end end end |
#metadata_approval_agency(xml, list) ⇒ Object
116 117 118 119 120 121 |
# File 'lib/metanorma/iso/front.rb', line 116 def (xml, list) list = ["ISO"] if list.nil? || list.empty? list.each do |v| xml.agency v end end |
#metadata_approval_committee(node, xml) ⇒ Object
97 98 99 100 101 102 103 104 105 106 |
# File 'lib/metanorma/iso/front.rb', line 97 def (node, xml) types = (node) xml.approvalgroup do |a| (a, node.attr("approval-agency") &.split(%r{[/,;]})) types.each do |v| node.attr("#{v}-number") and committee_component(v, node, a) end end end |
#metadata_approval_committee_types(node) ⇒ Object
108 109 110 111 112 113 114 |
# File 'lib/metanorma/iso/front.rb', line 108 def (node) types = %w(technical-committee subcommittee workgroup) node.attr("approval-technical-committee-number") and types = %w(approval-technical-committee approval-subcommittee approval-workgroup) types end |
#metadata_author(node, xml) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/metanorma/iso/front.rb', line 31 def (node, xml) publishers = node.attr("publisher") || "ISO" 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_committee(node, xml) ⇒ Object
83 84 85 86 |
# File 'lib/metanorma/iso/front.rb', line 83 def (node, xml) (node, xml) (node, xml) end |
#metadata_copyright(node, xml) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/metanorma/iso/front.rb', line 55 def (node, xml) publishers = node.attr("copyright-holder") || node.attr("publisher") || "ISO" csv_split(publishers).each do |p| xml.copyright do |c| c.from (node.attr("copyright-year") || Date.today.year) c.owner do |owner| owner.organization do |o| organization( o, p, true, node, !(node.attr("copyright-holder") || node.attr("publisher")) ) end end end end end |
#metadata_editorial_committee(node, xml) ⇒ Object
88 89 90 91 92 93 94 95 |
# File 'lib/metanorma/iso/front.rb', line 88 def (node, xml) xml.editorialgroup do |a| %w(technical-committee subcommittee workgroup).each do |v| node.attr("#{v}-number") and committee_component(v, node, a) end node.attr("secretariat") and a.secretariat(node.attr("secretariat")) end end |
#metadata_ext(node, xml) ⇒ Object
12 13 14 15 16 17 18 19 |
# File 'lib/metanorma/iso/front.rb', line 12 def (node, xml) super structured_id(node, xml) xml.stagename stage_name(get_stage(node), get_substage(node), doctype(node), node.attr("iteration")) @amd && a = node.attr("updates-document-type") and xml.updates_document_type a end |
#metadata_id(node, xml) ⇒ Object
65 66 67 68 69 70 71 |
# File 'lib/metanorma/iso/front_id.rb', line 65 def (node, xml) iso_id(node, xml) node&.attr("tc-docnumber")&.split(/,\s*/)&.each do |n| xml.docidentifier(n, **attr_code(type: "iso-tc")) end xml.docnumber node&.attr("docnumber") end |
#metadata_publisher(node, xml) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/metanorma/iso/front.rb', line 43 def (node, xml) publishers = node.attr("publisher") || "ISO" 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 |
#metadata_status(node, xml) ⇒ Object
73 74 75 76 77 78 79 80 81 |
# File 'lib/metanorma/iso/front.rb', line 73 def (node, xml) stage = get_stage(node) substage = get_substage(node) xml.status do |s| s.stage stage, **attr_code(abbreviation: cover_stage_abbr(node)) s.substage substage node.attr("iteration") && (s.iteration node.attr("iteration")) end end |
#metadata_subdoctype(node, xml) ⇒ Object
21 22 23 24 |
# File 'lib/metanorma/iso/front.rb', line 21 def (node, xml) super a = node.attr("horizontal") and xml.horizontal a end |
#norm_bibitem_style(root) ⇒ Object
ISO/IEC DIR 2, 10.2
197 198 199 200 201 202 203 |
# File 'lib/metanorma/iso/validate_section.rb', line 197 def norm_bibitem_style(root) root.xpath(NORM_BIBITEMS).each do |b| if b.at(Standoc::Converter::ISO_PUBLISHER_XPATH).nil? @log.add("Style", b, "#{NORM_ISO_WARN}: #{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("Style", f, "normative references contains subclauses") end |
#note_style(node) ⇒ Object
ISO/IEC DIR 2, 24.5
58 59 60 61 62 63 |
# File 'lib/metanorma/iso/validate_style.rb', line 58 def note_style(node) return if @novalid style_no_guidance(node, extract_text(node), "Note") style(node, extract_text(node)) end |
#ol_attrs(node) ⇒ Object
58 59 60 61 62 |
# File 'lib/metanorma/iso/base.rb', line 58 def ol_attrs(node) attr_code(keep_attrs(node) .merge(id: ::Metanorma::Utils::anchor_or_uuid(node), start: node.attr("start"))) 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
213 214 215 216 217 218 219 220 221 222 |
# File 'lib/metanorma/iso/validate_section.rb', line 213 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? @log.add("Style", nil, "#{location}: subclause is only child") end end |
#org_abbrev ⇒ Object
26 27 28 29 |
# File 'lib/metanorma/iso/front.rb', line 26 def org_abbrev { "International Organization for Standardization" => "ISO", "International Electrotechnical Commission" => "IEC" } end |
#other_footnote_renumber(xmldoc) ⇒ Object
17 18 19 20 21 22 23 24 25 26 |
# File 'lib/metanorma/iso/cleanup.rb', line 17 def other_footnote_renumber(xmldoc) seen = {} i = 0 [PRE_NORMREF_FOOTNOTES, NORMREF_FOOTNOTES, POST_NORMREF_FOOTNOTES].each do |xpath| xmldoc.xpath(xpath).each do |fn| i, seen = other_footnote_renumber1(fn, i, seen) end end end |
#outputs(node, ret) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/metanorma/iso/base.rb', line 72 def outputs(node, ret) File.open("#{@filename}.xml", "w:UTF-8") { |f| f.write(ret) } presentation_xml_converter(node).convert("#{@filename}.xml") html_converter_alt(node).convert("#{@filename}.presentation.xml", nil, false, "#{@filename}_alt.html") html_converter(node).convert("#{@filename}.presentation.xml", nil, false, "#{@filename}.html") doc_converter(node).convert("#{@filename}.presentation.xml", nil, false, "#{@filename}.doc") pdf_converter(node)&.convert("#{@filename}.presentation.xml", nil, false, "#{@filename}.pdf") # sts_converter(node)&.convert(@filename + ".xml") end |
#patent_notice_parse(xml, node) ⇒ Object
26 27 28 29 30 31 |
# File 'lib/metanorma/iso/section.rb', line 26 def patent_notice_parse(xml, node) # xml.patent_notice do |xml_section| # xml_section << node.content # end xml << node.content end |
#pdf_converter(node) ⇒ Object
36 37 38 39 40 |
# File 'lib/metanorma/iso/base.rb', line 36 def pdf_converter(node) return nil if node.attr("no-pdf") IsoDoc::Iso::PdfConvert.new(pdf_extract_attributes(node)) end |
#permission_check(text) ⇒ Object
67 68 69 70 71 72 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 67 def (text) text.split(/\.\s+/).each do |t| return t if .match t end nil end |
#permission_re ⇒ Object
62 63 64 65 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 62 def Regexp.new(self.class::PERMISSION_RE_STR.gsub(/\s/, "") .gsub(/_/, "\\s"), Regexp::IGNORECASE) end |
#possibility_check(text) ⇒ Object
89 90 91 92 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 89 def possibility_check(text) text.split(/\.\s+/).each { |t| return t if possibility_re.match t } nil end |
#possibility_re ⇒ Object
84 85 86 87 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 84 def possibility_re Regexp.new(self.class::POSSIBILITY_RE_STR.gsub(/\s/, "") .gsub(/_/, "\\s"), Regexp::IGNORECASE) end |
#presentation_xml_converter(node) ⇒ Object
48 49 50 |
# File 'lib/metanorma/iso/base.rb', line 48 def presentation_xml_converter(node) IsoDoc::Iso::PresentationXMLConvert.new(html_extract_attributes(node)) end |
#pub_class(bib) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/metanorma/iso/cleanup.rb', line 72 def pub_class(bib) return 1 if bib.at("#{PUBLISHER}[abbreviation = 'ISO']") return 1 if bib.at("#{PUBLISHER}[name = 'International Organization "\ "for Standardization']") return 2 if bib.at("#{PUBLISHER}[abbreviation = 'IEC']") return 2 if bib.at("#{PUBLISHER}[name = 'International "\ "Electrotechnical Commission']") return 3 if bib.at("./docidentifier[@type][not(#{OTHERIDS})]") || bib.at("./docidentifier[not(@type)]") 4 end |
#recommendation_check(text) ⇒ Object
46 47 48 49 50 51 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 46 def recommendation_check(text) text.split(/\.\s+/).each do |t| return t if recommendation_re.match t end nil end |
#recommendation_re ⇒ Object
41 42 43 44 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 41 def recommendation_re Regexp.new(self.class::RECOMMENDATION_RE_STR.gsub(/\s/, "") .gsub(/_/, "\\s"), Regexp::IGNORECASE) end |
#relaton_relation_descriptions ⇒ Object
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/metanorma/iso/front.rb', line 184 def relaton_relation_descriptions super.merge( "amends" => "updates", "revises" => "updates", "replaces" => "obsoletes", "supersedes" => "obsoletes", "corrects" => "updates", "informatively-cited-in" => "isCitedIn", "informatively-cites" => "cites", "normatively-cited in" => "isCitedIn", "normatively-cites" => "cites", "identical-adopted-from" => "adoptedFrom", "modified-adopted-from" => "adoptedFrom", "related-directive" => "related", "related-mandate" => "related" ) end |
#relaton_relations ⇒ Object
179 180 181 182 |
# File 'lib/metanorma/iso/front.rb', line 179 def relaton_relations super + %w(obsoletes successor-of manifestation-of related annotation-of) end |
#replacement_standard(biblio) ⇒ Object
180 181 182 183 184 185 |
# File 'lib/metanorma/iso/cleanup.rb', line 180 def replacement_standard(biblio) r = biblio.at("./relation[@type = 'updates']/bibitem") or return nil id = r.at("./formattedref | ./docidentifier[@primary = 'true'] | "\ "./docidentifier | ./formattedref") or return nil id.text end |
#requirement_check(text) ⇒ Object
26 27 28 29 30 31 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 26 def requirement_check(text) text.split(/\.\s+/).each do |t| return t if requirement_re.match t end nil end |
#requirement_re ⇒ Object
21 22 23 24 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 21 def requirement_re Regexp.new(self.class::REQUIREMENT_RE_STR.gsub(/\s/, "") .gsub(/_/, "\\s"), Regexp::IGNORECASE) end |
#requirements_processor ⇒ Object
15 16 17 |
# File 'lib/metanorma/iso/base.rb', line 15 def requirements_processor ::Metanorma::Requirements::Iso end |
#scope_parse(attrs, xml, node) ⇒ Object
12 13 14 15 |
# File 'lib/metanorma/iso/section.rb', line 12 def scope_parse(attrs, xml, node) attrs = attrs.merge(type: "scope") unless @amd clause_parse(attrs, xml, node) end |
#scope_style(node) ⇒ Object
ISO/IEC DIR 2, 14.2
26 27 28 29 30 |
# File 'lib/metanorma/iso/validate_style.rb', line 26 def scope_style(node) return if @novalid style_no_guidance(node, extract_text(node), "Scope") end |
#script_validate(xmldoc) ⇒ Object
125 126 127 128 129 130 |
# File 'lib/metanorma/iso/validate.rb', line 125 def script_validate(xmldoc) script = xmldoc&.at("//bibdata/script")&.text %w(Cyrl Latn).include?(script) or @log.add("Document Attributes", nil, "#{script} is not a recognised script") end |
#section_names_terms_cleanup(xml) ⇒ Object
202 203 204 205 |
# File 'lib/metanorma/iso/cleanup.rb', line 202 def section_names_terms_cleanup(xml) @vocab and return super end |
#section_style(root) ⇒ Object
173 174 175 176 177 178 179 180 181 |
# File 'lib/metanorma/iso/validate_section.rb', line 173 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? || style_warning(scope, SCOPE_WARN, nil) 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) doctype = doc&.at("//bibdata/ext/doctype")&.text 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) @vocab and vocab_terms_titles_validate(doc.root) super end |
#sections_cleanup(xml) ⇒ Object
114 115 116 117 118 119 |
# File 'lib/metanorma/iso/cleanup.rb', line 114 def sections_cleanup(xml) super return unless @amd xml.xpath("//*[@inline-header]").each { |h| h.delete("inline-header") } end |
#sections_presence_validate(root) ⇒ Object
65 66 67 68 69 70 71 72 |
# File 'lib/metanorma/iso/validate_section.rb', line 65 def sections_presence_validate(root) root.at("//sections/clause[@type = 'scope']") or @log.add("Style", nil, "Scope clause missing") root.at("//references[@normative = 'true']") or @log.add("Style", nil, "Normative references missing") root.at("//terms") or @log.add("Style", nil, "Terms & definitions missing") end |
#sections_sequence_validate(root) ⇒ Object
94 95 96 97 98 99 100 101 102 |
# File 'lib/metanorma/iso/validate_section.rb', line 94 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
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/metanorma/iso/validate_section.rb', line 117 def sections_sequence_validate_body(names, elem) if elem.nil? || elem.name != "clause" @log.add("Style", elem, "Document must contain at least one clause") end elem&.at("./self::clause") || @log.add("Style", elem, "Document must contain clause after "\ "Terms and Definitions") elem&.at("./self::clause[@type = 'scope']") && @log.add("Style", elem, "Scope must occur before Terms and Definitions") elem = names.shift while elem&.name == "clause" elem&.at("./self::clause[@type = 'scope']") @log.add("Style", elem, "Scope must occur before Terms and Definitions") elem = names.shift end %w(annex references).include? elem&.name or @log.add("Style", elem, "Only annexes and references can follow clauses") [names, elem] end |
#sections_sequence_validate_body_vocab(names, elem) ⇒ Object
140 141 142 143 144 145 146 147 148 |
# File 'lib/metanorma/iso/validate_section.rb', line 140 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("Style", elem, "Only annexes and references can follow terms and clauses") [names, elem] end |
#sections_sequence_validate_end(names, elem) ⇒ Object
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/metanorma/iso/validate_section.rb', line 150 def sections_sequence_validate_end(names, elem) while elem&.name == "annex" elem = names.shift if elem.nil? @log.add("Style", nil, "Document must include (references) "\ "Normative References") end end elem&.at("./self::references[@normative = 'true']") || @log.add("Style", nil, "Document must include (references) "\ "Normative References") elem = names&.shift elem&.at("./self::references[@normative = 'false']") || @log.add("Style", elem, "Final section must be (references) Bibliography") names.empty? || @log.add("Style", elem, "There are sections after the final Bibliography") end |
#sections_sequence_validate_start(root) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/metanorma/iso/validate_section.rb', line 104 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 |
#sectiontype(node, level = true) ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/metanorma/iso/section.rb', line 33 def sectiontype(node, level = true) return nil if @amd ret = sectiontype_streamline(sectiontype1(node)) return ret if ret == "terms and definitions" && @vocab super end |
#see_erefs_validate(root) ⇒ Object
ISO/IEC DIR 2, 15.5.3
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/metanorma/iso/validate.rb', line 47 def see_erefs_validate(root) root.xpath("//eref").each do |t| prec = t.at("./preceding-sibling::text()[last()]") next unless !prec.nil? && /\b(see|refer to)\s*\Z/mi.match(prec) unless target = root.at("//*[@id = '#{t['bibitemid']}']") @log.add("Bibliography", t, "'#{t} is not pointing to a real reference") next end target.at("./ancestor::references[@normative = 'true']") and @log.add("Style", t, "'see #{t}' is pointing to a normative reference") end end |
#see_xrefs_validate(root) ⇒ Object
ISO/IEC DIR 2, 15.5.3 does not deal with preceding text marked up
32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/metanorma/iso/validate.rb', line 32 def see_xrefs_validate(root) root.xpath("//xref").each do |t| preceding = t.at("./preceding-sibling::text()[last()]") next unless !preceding.nil? && /\b(see| refer to)\s*\Z/mi.match(preceding) (target = root.at("//*[@id = '#{t['target']}']")) || next if target.at("./ancestor-or-self::*[@obligation = 'normative']") @log.add("Style", t, "'see #{t['target']}' is pointing to a normative section") end end end |
#seqcheck(names, msg, accepted) ⇒ Object
54 55 56 57 58 59 60 61 62 63 |
# File 'lib/metanorma/iso/validate_section.rb', line 54 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("Style", nil, 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 |
#sort_biblio(bib) ⇒ Object
85 86 87 88 89 |
# File 'lib/metanorma/iso/cleanup.rb', line 85 def sort_biblio(bib) bib.sort do |a, b| sort_biblio_key(a) <=> sort_biblio_key(b) end end |
#sort_biblio_key(bib) ⇒ Object
sort by: doc class (ISO, IEC, other standard (not DOI &c), other then standard class (docid class other than DOI &c) 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
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/metanorma/iso/cleanup.rb', line 98 def sort_biblio_key(bib) pubclass = pub_class(bib) num = bib&.at("./docnumber")&.text id = bib&.at("./docidentifier[@primary]") || bib&.at("./docidentifier[not(#{OTHERIDS})]") = bib&.at("./docidentifier[@type = 'metanorma']")&.text abbrid = unless /^\[\d+\]$/.match?() /\d-(?<partid>\d+)/ =~ id&.text type = id["type"] if id title = bib&.at("./title[@type = 'main']")&.text || bib&.at("./title")&.text || bib&.at("./formattedref")&.text "#{pubclass} :: #{type} :: "\ "#{num.nil? ? abbrid : sprintf('%09d', num.to_i)} :: "\ "#{sprintf('%09d', partid.to_i)} :: #{id&.text} :: #{title}" end |
#stage_abbr(stage, substage, doctype) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/metanorma/iso/front_id.rb', line 37 def stage_abbr(stage, substage, doctype) return nil if stage.to_i > 60 ret = STAGE_ABBRS[stage.to_sym] ret = "PRF" if stage == "60" && substage == "00" ret = "AWI" if stage == "10" && substage == "99" ret = "AWI" if stage == "20" && substage == "00" if %w(amendment technical-corrigendum technical-report technical-specification).include?(doctype) ret = "D" if stage == "40" && doctype == "amendment" ret = "FD" if stage == "50" && %w(amendment technical-corrigendum) .include?(doctype) end ret end |
#stage_name(stage, substage, _doctype, iteration = nil) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/metanorma/iso/front_id.rb', line 53 def stage_name(stage, substage, _doctype, iteration = nil) return "Proof" if stage == "60" && substage == "00" ret = STAGE_NAMES[stage.to_sym] if iteration && %w(20 30).include?(stage) prefix = iteration.to_i.localize(@lang.to_sym) .to_rbnf_s("SpelloutRules", "spellout-ordinal") ret = "#{prefix.capitalize} #{ret.downcase}" end ret end |
#stage_validate(xmldoc) ⇒ Object
132 133 134 135 136 137 |
# File 'lib/metanorma/iso/validate.rb', line 132 def stage_validate(xmldoc) stage = xmldoc&.at("//bibdata/status/stage")&.text %w(00 10 20 30 40 50 60 90 95).include? stage or @log.add("Document Attributes", nil, "#{stage} is not a recognised stage") end |
#starts_lowercase?(text) ⇒ Boolean
allow that all-caps word (acronym) is agnostic as to lowercase
112 113 114 115 |
# File 'lib/metanorma/iso/validate_list.rb', line 112 def starts_lowercase?(text) text.match?(/^[^[[:upper:]][[:lower:]]]*[[:lower:]]/) || text.match?(/^[^[[:upper:]][[:lower:]]]*[[:upper:]][[:upper:]]+[^[[:alpha:]]]/) end |
#starts_uppercase?(text) ⇒ Boolean
117 118 119 |
# File 'lib/metanorma/iso/validate_list.rb', line 117 def starts_uppercase?(text) text.match?(/^[^[[:upper:]][[:lower:]]]*[[:upper:]]/) end |
#structured_id(node, xml) ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/metanorma/iso/front_id.rb', line 186 def structured_id(node, xml) return unless node.attr("docnumber") part, subpart = node&.attr("partnumber")&.split(/-/) xml.structuredidentifier do |i| i.project_number(node.attr("docnumber"), **attr_code( part: part, subpart: subpart, amendment: node.attr("amendment-number"), corrigendum: node.attr("corrigendum-number"), origyr: node.attr("created-date") )) end end |
#sts_converter(node) ⇒ Object
42 43 44 45 46 |
# File 'lib/metanorma/iso/base.rb', line 42 def sts_converter(node) return nil if node.attr("no-pdf") IsoDoc::Iso::StsConvert.new(html_extract_attributes(node)) end |
#style(node, text) ⇒ Object
92 93 94 95 96 97 98 99 100 |
# File 'lib/metanorma/iso/validate_style.rb', line 92 def style(node, text) return if @novalid style_number(node, text) style_percent(node, text) style_abbrev(node, text) style_units(node, text) style_punct(node, text) end |
#style_abbrev(node, text) ⇒ Object
ISO/IEC DIR 2, 8.4 ISO/IEC DIR 2, 9.3
129 130 131 132 133 134 135 |
# File 'lib/metanorma/iso/validate_style.rb', line 129 def style_abbrev(node, text) style_regex(/(\A|\s)(?!e\.g\.|i\.e\.) (?<num>[a-z]{1,2}\.([a-z]{1,2}|\.))\b/ix, "no dots in abbreviations", node, text) style_regex(/\b(?<num>ppm)\b/i, "language-specific abbreviation", node, text) end |
#style_no_guidance(node, text, docpart) ⇒ Object
101 102 103 104 105 106 107 108 |
# File 'lib/metanorma/iso/validate_requirements.rb', line 101 def style_no_guidance(node, text, docpart) r = requirement_check(text) style_warning(node, "#{docpart} may contain requirement", r) if r r = (text) style_warning(node, "#{docpart} may contain permission", r) if r r = recommendation_check(text) style_warning(node, "#{docpart} may contain recommendation", r) if r end |
#style_non_std_units(node, text) ⇒ Object
ISO/IEC DIR 2, 9.3
158 159 160 161 162 163 |
# File 'lib/metanorma/iso/validate_style.rb', line 158 def style_non_std_units(node, text) NONSTD_UNITS.each do |k, v| style_regex(/\b(?<num>[0-9][0-9,]*\s+#{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
105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/metanorma/iso/validate_style.rb', line 105 def style_number(node, text) 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" ) style_regex(/\b(?<num>[0-9]+\.[0-9]+)/i, "possible decimal point", node, text) style_regex(/\b(?<num>billions?)\b/i, "ambiguous number", node, text) style_regex(/(^|\s)(?<num>-[0-9][0-9,.]*)/i, "hyphen instead of minus sign U+2212", node, text) end |
#style_percent(node, text) ⇒ Object
ISO/IEC DIR 2, 9.2.1
120 121 122 123 124 125 |
# File 'lib/metanorma/iso/validate_style.rb', line 120 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_punct(node, text) ⇒ Object
167 168 169 170 171 172 |
# File 'lib/metanorma/iso/validate_style.rb', line 167 def style_punct(node, text) style_regex(/\b(?<num>and\/?or)\b/i, "Use 'either x or y, or both'", node, text) style_regex(/\s(?<num>&)\s/i, "Avoid ampersand in ordinary text'", node, text) end |
#style_regex(regex, warning, node, text) ⇒ Object
73 74 75 |
# File 'lib/metanorma/iso/validate_style.rb', line 73 def style_regex(regex, warning, node, text) (m = regex.match(text)) && style_warning(node, warning, m[:num]) 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
79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/metanorma/iso/validate_style.rb', line 79 def style_two_regex_not_prev(n, text, regex, re_prev, warning) return if text.nil? 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
143 144 145 146 147 148 149 150 |
# File 'lib/metanorma/iso/validate_style.rb', line 143 def style_units(node, text) style_regex(/\b(?<num>[0-9][0-9,]*\s+[\u00b0\u2032\u2033])/, "space between number and degrees/minutes/seconds", node, text) style_regex(/\b(?<num>[0-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) ⇒ Object
174 175 176 177 178 179 180 |
# File 'lib/metanorma/iso/validate_style.rb', line 174 def style_warning(node, msg, text = nil) return if @novalid w = msg w += ": #{text}" if text @log.add("Style", node, w) end |
#subclause_validate(root) ⇒ Object
205 206 207 208 209 210 |
# File 'lib/metanorma/iso/validate_section.rb', line 205 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
5 6 7 8 9 10 11 12 13 |
# File 'lib/metanorma/iso/validate_image.rb', line 5 def subfigure_validate(xmldoc) xmldoc.xpath("//figure//figure").each do |f| { footnote: "fn", note: "note", key: "dl" }.each do |k, v| f.xpath(".//#{v}").each do |n| @log.add("Style", n, "#{k} is not permitted in a subfigure") end end end end |
#substage_validate(xmldoc) ⇒ Object
139 140 141 142 143 144 |
# File 'lib/metanorma/iso/validate.rb', line 139 def substage_validate(xmldoc) substage = xmldoc&.at("//bibdata/status/substage")&.text or return %w(00 20 60 90 92 93 98 99).include? substage or @log.add("Document Attributes", nil, "#{substage} is not a recognised substage") end |
#symbols_validate(root) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/metanorma/iso/validate_section.rb', line 40 def symbols_validate(root) f = root.xpath("//definitions") f.empty? && return (f.size == 1 || @vocab) or @log.add("Style", f.first, ONE_SYMBOLS_WARNING) f.first.elements.reject { |e| %w(title dl).include? e.name }.empty? or @log.add("Style", f.first, NON_DL_SYMBOLS_WARNING) @vocab and f.each do |f1| f1.at("./ancestor::annex") or @log.add("Style", f1, "In vocabulary documents, Symbols and "\ "Abbreviated Terms are only permitted in annexes") end end |
#tech_report_style(root) ⇒ Object
183 184 185 186 187 188 189 190 191 |
# File 'lib/metanorma/iso/validate_section.rb', line 183 def tech_report_style(root) root.at("//bibdata/ext/doctype")&.text == "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_children_cleanup(xmldoc) ⇒ Object
207 208 209 210 |
# File 'lib/metanorma/iso/cleanup.rb', line 207 def term_children_cleanup(xmldoc) @vocab and return super end |
#term_contains_subclauses(node) ⇒ Object
48 49 50 51 |
# File 'lib/metanorma/iso/section.rb', line 48 def term_contains_subclauses(node) @vocab and return false # treat this as a term super end |
#term_def_subclause_parse(attrs, xml, node) ⇒ Object
42 43 44 45 46 |
# File 'lib/metanorma/iso/section.rb', line 42 def term_def_subclause_parse(attrs, xml, node) node.role == "term" and return term_def_subclause_parse1(attrs, xml, node) super end |
#term_defs_boilerplate_cont(src, term, isodoc) ⇒ Object
197 198 199 200 |
# File 'lib/metanorma/iso/cleanup.rb', line 197 def term_defs_boilerplate_cont(src, term, isodoc) @vocab and src.empty? and return super end |
#term_xrefs_validate(xmldoc) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/metanorma/iso/validate.rb', line 80 def term_xrefs_validate(xmldoc) termids = xmldoc .xpath("//sections/terms | //sections/clause[.//terms] | "\ "//annex[.//terms]").each_with_object({}) do |t, m| t.xpath(".//*/@id").each { |a| m[a.text] = true } t.name == "terms" and m[t["id"]] = true end xmldoc.xpath(".//xref").each do |x| term_xrefs_validate1(x, termids) end end |
#term_xrefs_validate1(xref, termids) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/metanorma/iso/validate.rb', line 92 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("Style", xref, "only terms clauses can cross-reference terms clause "\ "(#{xref['target']})") (!termids[xref["target"]] && termids[closest_id["id"]]) and @log.add("Style", xref, "non-terms clauses cannot cross-reference terms clause "\ "(#{xref['target']})") end |
#termdef_boilerplate_insert(xmldoc, isodoc, once = false) ⇒ Object
192 193 194 195 |
# File 'lib/metanorma/iso/cleanup.rb', line 192 def termdef_boilerplate_insert(xmldoc, isodoc, once = false) once = true super end |
#termdef_style(xmldoc) ⇒ Object
ISO/IEC DIR 2, 16.5.6
105 106 107 108 109 110 111 112 113 114 |
# File 'lib/metanorma/iso/validate.rb', line 105 def termdef_style(xmldoc) xmldoc.xpath("//term").each do |t| para = t.at("./definition/verbal-definition") || return term = t.at("./preferred//name").text termdef_warn(para.text, /\A(the|a)\b/i, t, term, "term definition starts with article") termdef_warn(para.text, /\.\Z/i, t, term, "term definition ends with period") end end |
#termdef_warn(text, regex, elem, term, msg) ⇒ Object
75 76 77 |
# File 'lib/metanorma/iso/validate.rb', line 75 def termdef_warn(text, regex, elem, term, msg) regex.match(text) && @log.add("Style", elem, "#{term}: #{msg}") end |
#title(node, xml) ⇒ Object
168 169 170 171 172 173 174 175 176 177 |
# File 'lib/metanorma/iso/front.rb', line 168 def title(node, xml) %w(en ru fr).each do |lang| at = { language: lang, format: "text/plain" } title_full(node, xml, lang, at) title_intro(node, xml, lang, at) title_main(node, xml, lang, at) title_part(node, xml, lang, at) title_amd(node, xml, lang, at) if @amd end end |
#title_all_siblings(xpath, label) ⇒ Object
ISO/IEC DIR 2, 22.2
79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/metanorma/iso/validate_title.rb', line 79 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 && @log.add("Style", nil, "#{label}: all subclauses must have a title, or none") end |
#title_amd(node, xml, lang, at) ⇒ Object
145 146 147 148 149 150 151 152 153 |
# File 'lib/metanorma/iso/front.rb', line 145 def title_amd(node, xml, lang, at) return unless node.attr("title-amendment-#{lang}") xml.title(**attr_code(at.merge(type: "title-amd"))) do |t1| t1 << Metanorma::Utils::asciidoc_sub( node.attr("title-amendment-#{lang}"), ) end end |
#title_first_level_validate(root) ⇒ Object
ISO/IEC DIR 2, 22.2
66 67 68 69 70 71 72 73 74 75 76 |
# 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("Style", ss, "#{title}: each first-level subclause must have a title") end end end |
#title_full(node, xml, lang, at) ⇒ Object
155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/metanorma/iso/front.rb', line 155 def title_full(node, xml, lang, at) title = node.attr("title-main-#{lang}") intro = node.attr("title-intro-#{lang}") part = node.attr("title-part-#{lang}") amd = node.attr("title-amendment-#{lang}") title = "#{intro} -- #{title}" if intro title = "#{title} -- #{part}" if part title = "#{title} -- #{amd}" if amd && @amd xml.title **attr_code(at.merge(type: "main")) do |t1| t1 << Metanorma::Utils::asciidoc_sub(title) end end |
#title_intro(node, xml, lang, at) ⇒ Object
123 124 125 126 127 128 129 |
# File 'lib/metanorma/iso/front.rb', line 123 def title_intro(node, xml, lang, at) return unless node.attr("title-intro-#{lang}") xml.title(**attr_code(at.merge(type: "title-intro"))) do |t1| t1 << Metanorma::Utils::asciidoc_sub(node.attr("title-intro-#{lang}")) 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("Style", title_intro_fr, "No English Title Intro!") end if !title_intro_en.nil? && title_intro_fr.nil? @log.add("Style", title_intro_en, "No French Title Intro!") 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(node, xml, lang, at) ⇒ Object
131 132 133 134 135 |
# File 'lib/metanorma/iso/front.rb', line 131 def title_main(node, xml, lang, at) xml.title **attr_code(at.merge(type: "title-main")) do |t1| t1 << Metanorma::Utils::asciidoc_sub(node.attr("title-main-#{lang}")) end 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("Style", title_main_fr, "No English Title!") end if !title_main_en.nil? && title_main_fr.nil? @log.add("Style", title_main_en, "No French Title!") 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) 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("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 |
#title_no_full_stop_validate(root) ⇒ Object
95 96 97 98 99 100 101 102 103 |
# File 'lib/metanorma/iso/validate_title.rb', line 95 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(node, xml, lang, at) ⇒ Object
137 138 139 140 141 142 143 |
# File 'lib/metanorma/iso/front.rb', line 137 def title_part(node, xml, lang, at) return unless node.attr("title-part-#{lang}") xml.title(**attr_code(at.merge(type: "title-part"))) do |t1| t1 << Metanorma::Utils::asciidoc_sub(node.attr("title-part-#{lang}")) 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("Style", title_part_fr, "No English Title Part!") (!title_part_en.nil? && title_part_fr.nil?) && @log.add("Style", title_part_en, "No French Title Part!") 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("Style", docid, "Subpart defined on non-IEC document!") end |
#title_validate(root) ⇒ Object
105 106 107 108 109 110 111 112 113 114 |
# File 'lib/metanorma/iso/validate_title.rb', line 105 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 |
#unpub_footnotes(xmldoc) ⇒ Object
135 136 137 138 139 140 141 142 |
# File 'lib/metanorma/iso/cleanup.rb', line 135 def unpub_footnotes(xmldoc) xmldoc.xpath("//bibitem/note[@type = 'Unpublished-Status']").each do |n| e = xmldoc.at("//eref[@bibitemid = '#{n.parent['id']}']") or next fn = n.children.to_xml n.elements&.first&.name == "p" or fn = "<p>#{fn}</p>" e.next = "<fn>#{fn}</fn>" end end |
#unpub_stage_prefix(docnum, stage, typeabbr, node) ⇒ Object
263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/metanorma/iso/front_id.rb', line 263 def unpub_stage_prefix(docnum, stage, typeabbr, node) abbr = id_stage_abbr(stage, get_substage(node), node) %w(40 50).include?(stage) && i = node.attr("iteration") and itersuffix = ".#{i}" return docnum if abbr.nil? || abbr.empty? # prefixes added in cleanup typeabbr = "" if %w(DTS FDTS).include?(abbr.sub(/\s+$/, "")) return "/#{abbr}#{typeabbr} #{docnum}#{itersuffix}" unless @amd a = docnum.split(%r{/}) a[-1] = "#{abbr}#{a[-1]}#{itersuffix}" a.join("/") end |
#unpublished_note(xmldoc) ⇒ Object
150 151 152 153 154 155 156 157 158 159 |
# File 'lib/metanorma/iso/cleanup.rb', line 150 def unpublished_note(xmldoc) xmldoc.xpath("//bibitem[not(./ancestor::bibitem)]"\ "[not(note[@type = 'Unpublished-Status'])]").each do |b| next if pub_class(b) > 2 next unless (s = b.at("./status/stage")) && (s.text.to_i < 60) id = b.at("docidentifier").text insert_unpub_note(b, @i18n.under_preparation.sub(/%/, id)) end end |
#validate(doc) ⇒ Object
187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/metanorma/iso/validate.rb', line 187 def validate(doc) content_validate(doc) doctype = doc&.at("//bibdata/ext/doctype")&.text schema = case doctype when "amendment", "technical-corrigendum" # @amd "isostandard-amd.rng" else "isostandard.rng" end schema_validate(formattedstr_strip(doc.dup), File.join(File.dirname(__FILE__), schema)) end |
#vocab_terms_titles_validate(root) ⇒ Object
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/metanorma/iso/validate_section.rb', line 225 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("Style", terms.first, "Single terms clause in vocabulary document "\ "should have normal Terms and definitions heading") elsif terms.size > 1 terms.each do |x| ((t = x.at("./title")) && /^#{@i18n.}/.match?(t&.text)) or @log.add("Style", x, "Multiple terms clauses in vocabulary document "\ "should have 'Terms related to' heading") end end end |
#withdrawn_note(xmldoc) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/metanorma/iso/cleanup.rb', line 161 def withdrawn_note(xmldoc) xmldoc.xpath("//bibitem[not(note[@type = 'Unpublished-Status'])]") .each do |b| next unless withdrawn_ref?(b) if id = replacement_standard(b) insert_unpub_note(b, @i18n.cancelled_and_replaced.sub(/%/, id)) else insert_unpub_note(b, @i18n.withdrawn) end end end |
#withdrawn_ref?(biblio) ⇒ Boolean
173 174 175 176 177 178 |
# File 'lib/metanorma/iso/cleanup.rb', line 173 def withdrawn_ref?(biblio) return false if pub_class(biblio) > 2 (s = biblio.at("./status/stage")) && (s.text.to_i == 95) && (t = biblio.at("./status/substage")) && (t.text.to_i == 99) end |