Module: Asciidoctor::Standoc::Validate
- Included in:
- Converter
- Defined in:
- lib/asciidoctor/standoc/validate.rb,
lib/asciidoctor/standoc/validate_section.rb
Constant Summary collapse
- SOURCELOCALITY =
"./origin//locality[@type = 'clause']/"\ "referenceFrom".freeze
Instance Method Summary collapse
- #asset_style(root) ⇒ Object
- #asset_title_style(root) ⇒ Object
- #concept_validate(doc, tag, refterm) ⇒ Object
- #content_validate(doc) ⇒ Object
-
#formattedstr_strip(doc) ⇒ Object
RelaxNG cannot cope well with wildcard attributes.
- #hanging_para_style(root) ⇒ Object
- #iev_validate(xmldoc) ⇒ Object
- #iev_validate1(term, loc, xmldoc) ⇒ Object
- #init_iev ⇒ Object
- #norm_ref_validate(doc) ⇒ Object
- #repeat_id_validate(doc) ⇒ Object
- #repeat_id_validate1(ids, elem) ⇒ Object
- #schema_validate(doc, schema) ⇒ Object
- #schema_validate1(file, doc, schema) ⇒ Object
- #section_validate(doc) ⇒ Object
- #sourcecode_style(root) ⇒ Object
- #style_warning(node, msg, text = nil) ⇒ Object
- #validate(doc) ⇒ Object
-
#xref_validate(doc) ⇒ Object
manually check for xref/@target, xref/@to integrity.
Instance Method Details
#asset_style(root) ⇒ Object
38 39 40 |
# File 'lib/asciidoctor/standoc/validate_section.rb', line 38 def asset_style(root) asset_title_style(root) end |
#asset_title_style(root) ⇒ Object
29 30 31 32 33 34 35 36 |
# File 'lib/asciidoctor/standoc/validate_section.rb', line 29 def asset_title_style(root) root.xpath("//figure[image][not(name)]").each do |node| style_warning(node, "Figure should have title", nil) end root.xpath("//table[not(name)]").each do |node| style_warning(node, "Table should have title", nil) end end |
#concept_validate(doc, tag, refterm) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/asciidoctor/standoc/validate.rb', line 68 def concept_validate(doc, tag, refterm) found = false doc.xpath("//#{tag}/xref").each do |x| next if doc.at("//term[@id = '#{x['target']}']") next if doc.at("//definitions//dt[@id = '#{x['target']}']") ref = x&.at("../#{refterm}")&.text @log.add("Anchors", x, "#{tag.capitalize} #{ref} is pointing to "\ "#{x['target']}, which is not a term or symbol") found = true end found and @fatalerror << "#{tag.capitalize} not cross-referencing term or symbol" end |
#content_validate(doc) ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/asciidoctor/standoc/validate.rb', line 43 def content_validate(doc) @fatalerror = [] xref_validate(doc) section_validate(doc) norm_ref_validate(doc) repeat_id_validate(doc.root) iev_validate(doc.root) concept_validate(doc, "concept", "refterm") concept_validate(doc, "related", "preferred//name") @fatalerror.empty? or clean_abort(@fatalerror.join("\n"), doc.to_xml) 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.
126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/asciidoctor/standoc/validate.rb', line 126 def formattedstr_strip(doc) doc.xpath("//*[@format] | //stem | //bibdata//description | "\ "//formattedref | //bibdata//note | //bibdata/abstract | "\ "//bibitem/abstract | //bibitem/note | //misc-container") .each do |n| n.elements.each do |e| e.traverse do |e1| e1.element? and e1.each { |k, _v| e1.delete(k) } end end end doc end |
#hanging_para_style(root) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/asciidoctor/standoc/validate_section.rb', line 42 def hanging_para_style(root) root.xpath("//clause | //annex | //foreword | //introduction | "\ "//acknowledgements").each do |c| next unless c.at("./clause") next if c.elements.reject do |n| %w(clause title).include? n.name end.empty? style_warning(c, "Hanging paragraph in clause") end end |
#iev_validate(xmldoc) ⇒ Object
21 22 23 24 25 26 27 28 29 30 |
# File 'lib/asciidoctor/standoc/validate.rb', line 21 def iev_validate(xmldoc) @iev = init_iev or return xmldoc.xpath("//term").each do |t| t.xpath(".//termsource").each do |src| (/^IEC 60050-/.match(src&.at("./origin/@citeas")&.text) && loc = src.xpath(SOURCELOCALITY)&.text) or next iev_validate1(t, loc, xmldoc) end end end |
#iev_validate1(term, loc, xmldoc) ⇒ Object
32 33 34 35 36 37 38 39 40 41 |
# File 'lib/asciidoctor/standoc/validate.rb', line 32 def iev_validate1(term, loc, xmldoc) iev = @iev.fetch(loc, xmldoc&.at("//language")&.text || "en") or return pref = term.xpath("./preferred//name").inject([]) do |m, x| m << x&.text&.downcase end pref.include?(iev.downcase) or @log.add("Bibliography", term, %(Term "#{pref[0]}" does not match ) + %(IEV #{loc} "#{iev}")) end |
#init_iev ⇒ Object
13 14 15 16 17 18 19 |
# File 'lib/asciidoctor/standoc/validate.rb', line 13 def init_iev return nil if @no_isobib return @iev if @iev @iev = Iev::Db.new(@iev_globalname, @iev_localname) unless @no_isobib @iev end |
#norm_ref_validate(doc) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/asciidoctor/standoc/validate.rb', line 55 def norm_ref_validate(doc) found = false doc.xpath("//references[@normative = 'true']/bibitem").each do |b| next unless docid = b.at("./docidentifier[@type = 'metanorma']") next unless /^\[\d+\]$/.match?(docid.text) @log.add("Bibliography", b, "Numeric reference in normative references") found = true end found and @fatalerror << "Numeric reference in normative references" end |
#repeat_id_validate(doc) ⇒ Object
95 96 97 98 99 100 |
# File 'lib/asciidoctor/standoc/validate.rb', line 95 def repeat_id_validate(doc) ids = {} doc.xpath("//*[@id]").each do |x| ids = repeat_id_validate1(ids, x) end end |
#repeat_id_validate1(ids, elem) ⇒ Object
84 85 86 87 88 89 90 91 92 93 |
# File 'lib/asciidoctor/standoc/validate.rb', line 84 def repeat_id_validate1(ids, elem) if ids[elem["id"]] @log.add("Anchors", elem, "Anchor #{elem['id']} has already been "\ "used at line #{ids[elem['id']]}") @fatalerror << "Multiple instances of same ID: #{elem['id']}" else ids[elem["id"]] = elem.line end ids end |
#schema_validate(doc, schema) ⇒ Object
102 103 104 105 106 107 108 109 110 |
# File 'lib/asciidoctor/standoc/validate.rb', line 102 def schema_validate(doc, schema) Tempfile.open(["tmp", ".xml"], encoding: "UTF-8") do |f| schema_validate1(f, doc, schema) rescue Jing::Error => e clean_abort("Jing failed with error: #{e}", doc.to_xml) ensure f.close! end end |
#schema_validate1(file, doc, schema) ⇒ Object
112 113 114 115 116 117 118 119 120 121 |
# File 'lib/asciidoctor/standoc/validate.rb', line 112 def schema_validate1(file, doc, schema) file.write(doc.to_xml) file.close errors = Jing.new(schema).validate(file.path) warn "Syntax Valid!" if errors.none? errors.each do |e| @log.add("Metanorma XML Syntax", "XML Line #{'%06d' % e[:line]}:#{e[:column]}", e[:message]) end end |
#section_validate(doc) ⇒ Object
6 7 8 9 10 |
# File 'lib/asciidoctor/standoc/validate_section.rb', line 6 def section_validate(doc) sourcecode_style(doc.root) hanging_para_style(doc.root) asset_style(doc.root) end |
#sourcecode_style(root) ⇒ Object
12 13 14 15 16 17 18 19 20 21 |
# File 'lib/asciidoctor/standoc/validate_section.rb', line 12 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 @log.add("AsciiDoc Input", x, "mismatch of callouts and annotations") end end end |
#style_warning(node, msg, text = nil) ⇒ Object
23 24 25 26 27 |
# File 'lib/asciidoctor/standoc/validate_section.rb', line 23 def style_warning(node, msg, text = nil) w = msg w += ": #{text}" if text @log.add("Metanorma XML Style Warning", node, w) end |
#validate(doc) ⇒ Object
151 152 153 154 155 |
# File 'lib/asciidoctor/standoc/validate.rb', line 151 def validate(doc) content_validate(doc) schema_validate(formattedstr_strip(doc.dup), File.join(File.dirname(__FILE__), "isodoc.rng")) end |
#xref_validate(doc) ⇒ Object
manually check for xref/@target, xref/@to integrity
141 142 143 144 145 146 147 148 149 |
# File 'lib/asciidoctor/standoc/validate.rb', line 141 def xref_validate(doc) ids = doc.xpath("//*/@id").each_with_object({}) { |x, m| m[x.text] = 1 } doc.xpath("//xref/@target | //xref/@to").each do |x| next if ids[x.text] @log.add("Anchors", x.parent, "Crossreference target #{x.text} is undefined") end end |