Module: Asciidoctor::ISO::Validate
- Included in:
- Converter
- Defined in:
- lib/asciidoctor/iso/validate.rb,
lib/asciidoctor/iso/validate_style.rb,
lib/asciidoctor/iso/validate_section.rb,
lib/asciidoctor/iso/validate_requirements.rb
Constant Summary collapse
- 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
- ONE_SYMBOLS_WARNING =
"ISO style: only one Symbols and Abbreviated "\ "Terms section in the standard".freeze
- NON_DL_SYMBOLS_WARNING =
"ISO style: 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: [{ tag: "foreword", title: "Foreword" }], }, { msg: "Prefatory material must be followed by (clause) Scope", val: [{ tag: "introduction", title: "Introduction" }, { tag: "clause", title: "Scope" }], }, { msg: "Prefatory material must be followed by (clause) Scope", val: [{ tag: "clause", title: "Scope" }], }, { msg: "Normative References must be followed by "\ "Terms and Definitions", val: [ { tag: "terms", title: "Terms and Definitions" }, { tag: "terms", title: "Terms, Definitions, Symbols and Abbreviated Terms", }, ], }, ].freeze
- SECTIONS_XPATH =
" //foreword | //introduction | //sections/terms | "\ "//symbols-abbrevs | "\ "//sections/clause | ./references | ./annex".freeze
- NORM_ISO_WARN =
"non-ISO/IEC reference not expected as normative".freeze
- SCOPE_WARN =
"Scope contains subsections: should be succint".freeze
- ASSETS_TO_STYLE =
"//termsource | //formula | //termnote | //p | //li[not(p)] | "\ "//dt | //dd[not(p)] | //td[not(p)] | //th[not(p)]".freeze
- NORM_BIBITEMS =
"//references[title = 'Normative References']/bibitem".freeze
- REQUIREMENT_RE_STR =
<<~REGEXP.freeze \\b ( shall | (is|are)_to | (is|are)_required_(not_)?to | has_to | only\\b[^.,]+\\b(is|are)_permitted | it_is_necessary | (needs|need)_to | (is|are)_not_(allowed | permitted | acceptable | permissible) | (is|are)_not_to_be | (need|needs)_not | do_not ) \\b REGEXP
- REQUIREMENT_RE =
Regexp.new(REQUIREMENT_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"), Regexp::IGNORECASE)
- RECOMMENDATION_RE_STR =
<<~REGEXP.freeze \\b should | ought_(not_)?to | it_is_(not_)?recommended_that \\b REGEXP
- RECOMMENDATION_RE =
Regexp.new(RECOMMENDATION_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"), Regexp::IGNORECASE)
- 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
- PERMISSION_RE =
Regexp.new(PERMISSION_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"), Regexp::IGNORECASE)
- 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
- POSSIBILITY_RE =
Regexp.new(POSSIBILITY_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"), Regexp::IGNORECASE)
Instance Method Summary collapse
- #asset_style(root) ⇒ Object
- #asset_title_style(root) ⇒ Object
- #content_validate(doc) ⇒ Object
- #example_style(node) ⇒ Object
- #external_constraint(text) ⇒ Object
- #extract_text(node) ⇒ Object
- #footnote_style(node) ⇒ Object
- #foreword_style(node) ⇒ Object
- #foreword_validate(root) ⇒ Object
-
#formattedstr_strip(doc) ⇒ Object
RelaxNG cannot cope well with wildcard attributes.
- #introduction_style(node) ⇒ Object
- #isosubgroup_validate(root) ⇒ Object
- #norm_bibitem_style(root) ⇒ Object
- #normref_validate(root) ⇒ Object
- #note_style(node) ⇒ Object
- #onlychild_clause_validate(root) ⇒ Object
- #permission(text) ⇒ Object
- #possibility(text) ⇒ Object
- #recommendation(text) ⇒ Object
- #requirement(text) ⇒ Object
- #schema_validate(doc, filename) ⇒ Object
- #scope_style(node) ⇒ Object
- #section_style(root) ⇒ Object
- #section_validate(doc) ⇒ Object
- #sections_sequence_validate(root) ⇒ Object
- #see_erefs_validate(root) ⇒ Object
- #see_xrefs_validate(root) ⇒ Object
- #seqcheck(names, msg, accepted) ⇒ Object
- #sourcecode_style(root) ⇒ Object
- #style(n, t) ⇒ Object
- #style_abbrev(n, t) ⇒ Object
- #style_no_guidance(node, text, docpart) ⇒ Object
- #style_non_std_units(n, t) ⇒ Object
- #style_number(n, t) ⇒ Object
- #style_percent(n, t) ⇒ Object
- #style_regex(re, warning, n, text) ⇒ Object
-
#style_two_regex_not_prev(n, text, re, re_prev, warning) ⇒ Object
style check with a regex on a token and a negative match on its preceding token.
- #style_units(n, t) ⇒ Object
- #style_warning(node, msg, text) ⇒ Object
- #symbols_validate(root) ⇒ Object
- #termdef_style(xmldoc) ⇒ Object
- #termdef_warn(text, re, term, msg) ⇒ Object
- #title_all_siblings(xpath, label) ⇒ Object
- #title_first_level_validate(root) ⇒ Object
- #title_intro_validate(root) ⇒ Object
- #title_main_validate(root) ⇒ Object
- #title_names_type_validate(root) ⇒ Object
- #title_part_validate(root) ⇒ Object
- #title_subpart_validate(root) ⇒ Object
- #title_validate(root) ⇒ Object
- #validate(doc) ⇒ Object
Instance Method Details
#asset_style(root) ⇒ Object
185 186 187 188 189 190 191 192 |
# File 'lib/asciidoctor/iso/validate_section.rb', line 185 def asset_style(root) root.xpath("//example | //termexample").each { |e| example_style(e) } root.xpath("//note").each { |e| note_style(e) } root.xpath("//fn").each { |e| footnote_style(e) } root.xpath(ASSETS_TO_STYLE).each { |e| style(e, extract_text(e)) } asset_title_style(root) norm_bibitem_style(root) end |
#asset_title_style(root) ⇒ Object
168 169 170 171 172 173 174 175 |
# File 'lib/asciidoctor/iso/validate_section.rb', line 168 def asset_title_style(root) root.xpath("//figure[image][not(title)]").each do |node| style_warning(node, "Figure should have title", nil) end root.xpath("//table[not(title)]").each do |node| style_warning(node, "Table should have title", nil) end end |
#content_validate(doc) ⇒ Object
161 162 163 164 165 166 167 168 169 |
# File 'lib/asciidoctor/iso/validate.rb', line 161 def content_validate(doc) title_validate(doc.root) isosubgroup_validate(doc.root) section_validate(doc) onlychild_clause_validate(doc.root) termdef_style(doc.root) see_xrefs_validate(doc.root) see_erefs_validate(doc.root) end |
#example_style(node) ⇒ Object
33 34 35 36 37 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 33 def example_style(node) return if @novalid style_no_guidance(node, extract_text(node), "Term Example") style(node, extract_text(node)) end |
#external_constraint(text) ⇒ Object
89 90 91 92 93 94 |
# File 'lib/asciidoctor/iso/validate_requirements.rb', line 89 def external_constraint(text) text.split(/\.\s+/).each do |t| return t if /\b(must)\b/xi.match? t end nil end |
#extract_text(node) ⇒ Object
8 9 10 11 12 13 14 15 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 8 def extract_text(node) return "" if node.nil? node1 = node.dup node1.xpath("//link | //locality").each(&:remove) ret = "" node1.traverse { |x| ret += x.text if x.text? } ret end |
#footnote_style(node) ⇒ Object
45 46 47 48 49 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 45 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
17 18 19 20 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 17 def foreword_style(node) return if @novalid style_no_guidance(node, extract_text(node), "Foreword") end |
#foreword_validate(root) ⇒ Object
16 17 18 19 20 |
# File 'lib/asciidoctor/iso/validate_section.rb', line 16 def foreword_validate(root) f = root.at("//foreword") || return s = f.at("./subsection") warn "ISO style: foreword contains subsections" unless s.nil? end |
#formattedstr_strip(doc) ⇒ Object
RelaxNG cannot cope well with wildcard attributes. So we strip any attributes from FormattedString instances (which can contain xs:any markup, and are signalled with @format) before validation.
187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/asciidoctor/iso/validate.rb', line 187 def formattedstr_strip(doc) doc.xpath("//*[@format]").each do |n| n.elements.each do |e| e.traverse do |e1| next unless e1.element? e1.each { |k, _v| e.delete(k) } end end end doc end |
#introduction_style(node) ⇒ Object
27 28 29 30 31 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 27 def introduction_style(node) return if @novalid r = requirement(extract_text(node)) style_warning(node, "Introduction may contain requirement", r) if r end |
#isosubgroup_validate(root) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/asciidoctor/iso/validate.rb', line 109 def isosubgroup_validate(root) root.xpath("//technical-committee/@type").each do |t| unless %w{TC PC JTC JPC}.include? t.text warn "ISO: invalid technical committee type #{t}" end end root.xpath("//subcommittee/@type").each do |t| unless %w{SC JSC}.include? t.text warn "ISO: invalid subcommittee type #{t}" end end end |
#norm_bibitem_style(root) ⇒ Object
177 178 179 180 181 182 183 |
# File 'lib/asciidoctor/iso/validate_section.rb', line 177 def norm_bibitem_style(root) root.xpath(NORM_BIBITEMS).each do |b| if b.at(Cleanup::ISO_PUBLISHER_XPATH).nil? Utils::warning(b, NORM_ISO_WARN, b.text) end end end |
#normref_validate(root) ⇒ Object
22 23 24 25 26 |
# File 'lib/asciidoctor/iso/validate_section.rb', line 22 def normref_validate(root) f = root.at("//references[title = 'Normative References']") || return f.at("./references") && warn("ISO style: normative references contains subsections") end |
#note_style(node) ⇒ Object
39 40 41 42 43 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 39 def note_style(node) return if @novalid style_no_guidance(node, extract_text(node), "Note") style(node, extract_text(node)) end |
#onlychild_clause_validate(root) ⇒ Object
99 100 101 102 103 104 105 106 107 |
# File 'lib/asciidoctor/iso/validate.rb', line 99 def onlychild_clause_validate(root) root.xpath("//subsection").each do |c| next unless c.xpath("../subsection").size == 1 title = c.at("./title") location = c["id"] || c.text[0..60] + "..." location += ":#{title.text}" if c["id"] && !title.nil? warn "ISO style: #{location}: subsection is only child" end end |
#permission(text) ⇒ Object
64 65 66 67 68 69 |
# File 'lib/asciidoctor/iso/validate_requirements.rb', line 64 def (text) text.split(/\.\s+/).each do |t| return t if PERMISSION_RE.match? t end nil end |
#possibility(text) ⇒ Object
84 85 86 87 |
# File 'lib/asciidoctor/iso/validate_requirements.rb', line 84 def possibility(text) text.split(/\.\s+/).each { |t| return t if POSSIBILITY_RE.match? t } nil end |
#recommendation(text) ⇒ Object
45 46 47 48 49 50 |
# File 'lib/asciidoctor/iso/validate_requirements.rb', line 45 def recommendation(text) text.split(/\.\s+/).each do |t| return t if RECOMMENDATION_RE.match? t end nil end |
#requirement(text) ⇒ Object
27 28 29 30 31 32 |
# File 'lib/asciidoctor/iso/validate_requirements.rb', line 27 def requirement(text) text.split(/\.\s+/).each do |t| return t if REQUIREMENT_RE.match? t end nil end |
#schema_validate(doc, filename) ⇒ Object
171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/asciidoctor/iso/validate.rb', line 171 def schema_validate(doc, filename) File.open(".tmp.xml", "w") { |f| f.write(doc.to_xml) } begin errors = Jing.new(filename).validate(".tmp.xml") rescue Jing::Error => e abort "what what what #{e}" end warn "Valid!" if errors.none? errors.each do |error| warn "#{error[:message]} @ #{error[:line]}:#{error[:column]}" end end |
#scope_style(node) ⇒ Object
22 23 24 25 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 22 def scope_style(node) return if @novalid style_no_guidance(node, extract_text(node), "Scope") end |
#section_style(root) ⇒ Object
143 144 145 146 147 148 149 |
# File 'lib/asciidoctor/iso/validate_section.rb', line 143 def section_style(root) foreword_style(root.at("//foreword")) introduction_style(root.at("//introduction")) scope_style(root.at("//clause[title = 'Scope']")) scope = root.at("//clause[title = 'Scope']/subsection") scope.nil? || style_warning(scope, SCOPE_WARN, nil) end |
#section_validate(doc) ⇒ Object
6 7 8 9 10 11 12 13 14 |
# File 'lib/asciidoctor/iso/validate_section.rb', line 6 def section_validate(doc) foreword_validate(doc.root) normref_validate(doc.root) symbols_validate(doc.root) sections_sequence_validate(doc.root) section_style(doc.root) sourcecode_style(doc.root) asset_style(doc.root) end |
#sections_sequence_validate(root) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/asciidoctor/iso/validate_section.rb', line 90 def sections_sequence_validate(root) f = root.xpath(SECTIONS_XPATH) names = f.map { |s| { tag: s.name, title: s&.at("./title")&.text } } names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val]) || return n = names[0] names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val]) || return if n == { tag: "introduction", title: "Introduction" } names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val]) || return end names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val]) || return n = names.shift if n == { tag: "symbols-abbrevs", title: nil } n = names.shift || return end unless n warn "ISO style: Document must contain at least one clause" return end n[:tag] == "clause" || warn("ISO style: Document must contain clause after "\ "Terms and Definitions") n == { tag: "clause", title: "Scope" } && warn("ISO style: Scope must occur before Terms and Definitions") n = names.shift || return while n[:tag] == "clause" n[:title] == "Scope" && warn("ISO style: Scope must occur before Terms and Definitions") n = names.shift || return end unless n[:tag] == "annex" || n[:tag] == "references" warn "ISO style: Only annexes and references can follow clauses" end while n[:tag] == "annex" n = names.shift if n.nil? warn("ISO style: Document must include (references) "\ "Normative References") return end end n == { tag: "references", title: "Normative References" } || warn("ISO style: Document must include (references) "\ "Normative References") n = names.shift n == { tag: "references", title: "Bibliography" } || warn("ISO style: Final section must be (references) Bibliography") names.empty? || warn("ISO style: There are sections after the final Bibliography") end |
#see_erefs_validate(root) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/asciidoctor/iso/validate.rb', line 134 def see_erefs_validate(root) root.xpath("//eref").each do |t| preceding = t.at("./preceding-sibling::text()[last()]") next unless !preceding.nil? && /\bsee\s*$/mi.match?(preceding) target = root.at("//*[@id = '#{t['bibitemid']}']") if target.at("./ancestor::references"\ "[title = 'Normative References']") warn "ISO: 'see #{t}' is pointing to a normative reference" end end end |
#see_xrefs_validate(root) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/asciidoctor/iso/validate.rb', line 122 def see_xrefs_validate(root) root.xpath("//xref").each do |t| # does not deal with preceding text marked up preceding = t.at("./preceding-sibling::text()[last()]") next unless !preceding.nil? && /\bsee\s*$/mi.match?(preceding) (target = root.at("//*[@id = '#{t['target']}']")) || next if target&.at("./ancestor-or-self::*[@obligation = 'normative']") warn "ISO: 'see #{t['target']}' is pointing to a normative section" end end end |
#seqcheck(names, msg, accepted) ⇒ Object
46 47 48 49 50 51 52 53 |
# File 'lib/asciidoctor/iso/validate_section.rb', line 46 def seqcheck(names, msg, accepted) n = names.shift unless accepted.include? n warn "ISO style: #{msg}" names = [] end names end |
#sourcecode_style(root) ⇒ Object
151 152 153 154 155 156 157 158 159 |
# File 'lib/asciidoctor/iso/validate_section.rb', line 151 def sourcecode_style(root) root.xpath("//sourcecode").each do |x| callouts = x.elements.select { |e| e.name == "callout" } annotations = x.elements.select { |e| e.name == "annotation" } if callouts.size != annotations.size warn "#{x['id']}: mismatch of callouts and annotations" end end end |
#style(n, t) ⇒ Object
76 77 78 79 80 81 82 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 76 def style(n, t) return if @novalid style_number(n, t) style_percent(n, t) style_abbrev(n, t) style_units(n, t) end |
#style_abbrev(n, t) ⇒ Object
101 102 103 104 105 106 107 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 101 def style_abbrev(n, t) style_regex(/(^|\s)(?!e\.g\.|i\.e\.) (?<num>[a-z]{1,2}\.([a-z]{1,2}|\.))\b/ix, "no dots in abbreviations", n, t) style_regex(/\b(?<num>ppm)\b/i, "language-specific abbreviation", n, t) end |
#style_no_guidance(node, text, docpart) ⇒ Object
96 97 98 99 100 101 102 103 |
# File 'lib/asciidoctor/iso/validate_requirements.rb', line 96 def style_no_guidance(node, text, docpart) r = requirement(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(text) style_warning(node, "#{docpart} may contain recommendation", r) if r end |
#style_non_std_units(n, t) ⇒ Object
127 128 129 130 131 132 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 127 def style_non_std_units(n, t) NONSTD_UNITS.each do |k, v| style_regex(/\b(?<num>[0-9][0-9,]*\s+#{k})\b/, "non-standard unit (should be #{v})", n, t) end end |
#style_number(n, t) ⇒ Object
84 85 86 87 88 89 90 91 92 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 84 def style_number(n, t) style_two_regex_not_prev(n, t, /^(?<num>-?[0-9]{4,}[,0-9]*)$/, %r{(\bISO|\bIEC|\bIEEE/)$}, "number not broken up in threes") style_regex(/\b(?<num>[0-9]+\.[0-9]+)/i, "possible decimal point", n, t) style_regex(/\b(?<num>billion[s]?)\b/i, "ambiguous number", n, t) end |
#style_percent(n, t) ⇒ Object
94 95 96 97 98 99 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 94 def style_percent(n, t) style_regex(/\b(?<num>[0-9.,]+%)/, "no space before percent sign", n, t) style_regex(/\b(?<num>[0-9.,]+ \u00b1 [0-9,.]+ %)/, "unbracketed tolerance before percent sign", n, t) end |
#style_regex(re, warning, n, text) ⇒ Object
58 59 60 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 58 def style_regex(re, warning, n, text) (m = re.match(text)) && style_warning(n, warning, m[:num]) end |
#style_two_regex_not_prev(n, text, re, re_prev, warning) ⇒ Object
style check with a regex on a token and a negative match on its preceding token
64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 64 def style_two_regex_not_prev(n, text, re, re_prev, warning) return if text.nil? arr = text.split(/\W+/) arr.each_index do |i| m = re.match arr[i] m_prev = i.zero? ? nil : re_prev.match(arr[i - 1]) if !m.nil? && m_prev.nil? style_warning(n, warning, m[:num]) end end end |
#style_units(n, t) ⇒ Object
114 115 116 117 118 119 120 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 114 def style_units(n, t) style_regex(/\b(?<num>[0-9][0-9,]*\s+[\u00b0\u2032\u2033])/, "space between number and degrees/minutes/seconds", n, t) style_regex(/\b(?<num>[0-9][0-9,]*#{SI_UNIT})\b/, "no space between number and SI unit", n, t) style_non_std_units(n, t) end |
#style_warning(node, msg, text) ⇒ Object
51 52 53 54 55 56 |
# File 'lib/asciidoctor/iso/validate_style.rb', line 51 def style_warning(node, msg, text) return if @novalid w = "ISO style: WARNING (#{Utils::current_location(node)}): #{msg}" w += ": #{text}" if text warn w end |
#symbols_validate(root) ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/asciidoctor/iso/validate_section.rb', line 34 def symbols_validate(root) f = root.xpath("//symbols-abbrevs") f.empty? && return (f.size == 1) || warn(ONE_SYMBOLS_WARNING) f.first.elements.each do |e| unless e.name == "dl" warn(NON_DL_SYMBOLS_WARNING) return end end end |
#termdef_style(xmldoc) ⇒ Object
150 151 152 153 154 155 156 157 158 159 |
# File 'lib/asciidoctor/iso/validate.rb', line 150 def termdef_style(xmldoc) xmldoc.xpath("//term").each do |t| para = t.at("./definition") || return term = t.at("./preferred").text termdef_warn(para.text, /^(the|a)\b/i, term, "term definition starts with article") termdef_warn(para.text, /\.$/i, term, "term definition ends with period") end end |
#termdef_warn(text, re, term, msg) ⇒ Object
146 147 148 |
# File 'lib/asciidoctor/iso/validate.rb', line 146 def termdef_warn(text, re, term, msg) re.match?(text) && warn("ISO style: #{term}: #{msg}") end |
#title_all_siblings(xpath, label) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/asciidoctor/iso/validate.rb', line 75 def title_all_siblings(xpath, label) notitle = false withtitle = false xpath.each do |s| title_all_siblings(s.xpath("./subsection | ./terms"), s&.at("./title")&.text || s["id"]) subtitle = s.at("./title") notitle = notitle || (!subtitle || subtitle.text.empty?) withtitle = withtitle || !subtitle&.text&.empty? end notitle && withtitle && warn("#{label}: all subclauses must have a title, or none") end |
#title_first_level_validate(root) ⇒ Object
64 65 66 67 68 69 70 71 72 73 |
# File 'lib/asciidoctor/iso/validate.rb', line 64 def title_first_level_validate(root) root.xpath(SECTIONS_XPATH).each do |s| title = s&.at("./title")&.text || s.name s.xpath("./subsection | ./terms").each do |ss| subtitle = ss.at("./title") !subtitle.nil? && !subtitle&.text&.empty? || warn("#{title}: each first-level subclause must have a title") end end end |
#title_intro_validate(root) ⇒ Object
12 13 14 15 16 17 18 19 20 21 |
# File 'lib/asciidoctor/iso/validate.rb', line 12 def title_intro_validate(root) title_intro_en = root.at("//title-intro[@language='en']") title_intro_fr = root.at("//title-intro[@language='fr']") if title_intro_en.nil? && !title_intro_fr.nil? warn "No English Title Intro!" end if !title_intro_en.nil? && title_intro_fr.nil? warn "No French Title Intro!" end end |
#title_main_validate(root) ⇒ Object
23 24 25 26 27 28 29 30 31 32 |
# File 'lib/asciidoctor/iso/validate.rb', line 23 def title_main_validate(root) title_main_en = root.at("//title-main[@language='en']") title_main_fr = root.at("//title-main[@language='fr']") if title_main_en.nil? && !title_main_fr.nil? warn "No English Title!" end if !title_main_en.nil? && title_main_fr.nil? warn "No French Title!" end end |
#title_names_type_validate(root) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/asciidoctor/iso/validate.rb', line 51 def title_names_type_validate(root) doctypes = /International\sStandard | Technical\sSpecification | Publicly\sAvailable\sSpecification | Technical\sReport | Guide /xi title_main_en = root.at("//title-main[@language='en']") if !title_main_en.nil? && doctypes.match?(title_main_en.text) warn "Main Title may name document type" end title_intro_en = root.at("//title-intro[@language='en']") if !title_intro_en.nil? && doctypes.match?(title_intro_en.text) warn "Title Intro may name document type" end end |
#title_part_validate(root) ⇒ Object
34 35 36 37 38 39 40 41 |
# File 'lib/asciidoctor/iso/validate.rb', line 34 def title_part_validate(root) title_part_en = root.at("//title-part[@language='en']") title_part_fr = root.at("//title-part[@language='fr']") (title_part_en.nil? && !title_part_fr.nil?) && warn("No English Title Part!") (!title_part_en.nil? && title_part_fr.nil?) && warn("No French Title Part!") end |
#title_subpart_validate(root) ⇒ Object
43 44 45 46 47 48 49 |
# File 'lib/asciidoctor/iso/validate.rb', line 43 def title_subpart_validate(root) subpart = root.at("//bibdata/docidentifier/project-number[@subpart]") iec = root.at("//bibdata/contributor[role/@type = 'publisher']/"\ "organization[abbreviation = 'IEC' or "\ "name = 'International Electrotechnical Commission']") warn("Subpart defined on non-IEC document!") if subpart && !iec end |
#title_validate(root) ⇒ Object
89 90 91 92 93 94 95 96 97 |
# File 'lib/asciidoctor/iso/validate.rb', line 89 def title_validate(root) title_intro_validate(root) title_main_validate(root) title_part_validate(root) title_subpart_validate(root) title_names_type_validate(root) title_first_level_validate(root) title_all_siblings(root.xpath(SECTIONS_XPATH), "(top level)") end |
#validate(doc) ⇒ Object
199 200 201 202 203 |
# File 'lib/asciidoctor/iso/validate.rb', line 199 def validate(doc) content_validate(doc) schema_validate(formattedstr_strip(doc.dup), File.join(File.dirname(__FILE__), "isostandard.rng")) end |