Module: Metanorma::Standoc::Validate
- Includes:
- Utils
- Included in:
- Converter
- Defined in:
- lib/metanorma/standoc/validate.rb,
lib/metanorma/standoc/validate_term.rb,
lib/metanorma/standoc/validate_image.rb,
lib/metanorma/standoc/validate_table.rb,
lib/metanorma/standoc/validate_schema.rb,
lib/metanorma/standoc/validate_section.rb
Constant Summary
collapse
- MATHML_NS =
"http://www.w3.org/1998/Math/MathML".freeze
- SOURCELOCALITY =
"./origin//locality[@type = 'clause']/" \
"referenceFrom".freeze
- TOO_BIG_IMG_ERR =
"Image too large for Data URI encoding: disable Data URI encoding (`:data-uri-image: false`), or set `:data-uri-maxsize: 0`\n".freeze
- SVG_NS =
"http://www.w3.org/2000/svg".freeze
- WILDCARD_ATTRS =
"//stem | //metanorma-extension".freeze
Constants included
from Utils
Utils::SECTION_CONTAINERS, Utils::SUBCLAUSE_XPATH
Instance Method Summary
collapse
-
#add_ns_to_fragment(xml_fragment) ⇒ Object
-
#all_empty_block_validate(doc) ⇒ Object
-
#asset_style(root) ⇒ Object
-
#asset_title_style(root) ⇒ Object
-
#block_validate(doc) ⇒ Object
-
#callouts_error(elem, callouts, annotations) ⇒ Object
-
#concept_validate(doc, tag, refterm) ⇒ Object
-
#concept_validate_ids(doc) ⇒ Object
-
#concept_validate_msg(_doc, tag, refterm, xref) ⇒ Object
-
#content_validate(doc) ⇒ Object
-
#empty_block?(block) ⇒ Boolean
-
#empty_block_validate(doc, tag, body) ⇒ Object
-
#empty_table_validate(doc) ⇒ Object
-
#expand_path(loc) ⇒ Object
-
#find_illegal_designations(xmldoc) ⇒ Object
-
#formattedstr_strip(doc) ⇒ Object
RelaxNG cannot cope well with wildcard attributes.
-
#fragment_schema(root_element) ⇒ Object
-
#get_anchors_between(start_id, end_id) ⇒ Object
Retrieve anchors between two nominated values (exclusive of start_id AND exclusive of end_id).
-
#hanging_para_style(root) ⇒ Object
-
#iev_validate(xmldoc) ⇒ Object
-
#iev_validate1(term, loc, xmldoc) ⇒ Object
-
#image_exists(doc) ⇒ Object
-
#image_toobig(doc) ⇒ Object
-
#image_validate(doc) ⇒ Object
-
#init_iev ⇒ Object
-
#math_validate(doc) ⇒ Object
-
#math_validate_error(math, elem, error) ⇒ Object
-
#mathml_sanitise(math) ⇒ Object
-
#max_td_count(table) ⇒ Object
-
#maxcols_check(col, maxcols, tcell) ⇒ Object
if maxcols or maxrows negative, do not check them.
-
#maxcols_validate1(tcell, row, curr, cells2d, maxcols, mode) ⇒ Object
code doesn’t actually do anything, since Asciidoctor refuses to generate table with inconsistent column count.
-
#maxrowcols_validate(table, maxcols, mode: "row_cols") ⇒ Object
-
#maxrowcols_validate0(table, maxcols, tablechild, mode) ⇒ Object
-
#maxrows_validate(table, cells2d, tablechild, mode) ⇒ Object
-
#nested_asset_report(outer, inner, doc) ⇒ Object
-
#nested_asset_validate(doc) ⇒ Object
-
#nested_asset_validate_basic(doc) ⇒ Object
-
#nested_asset_xref_report(outer, inner, _doc) ⇒ Object
-
#nested_note_validate(doc) ⇒ Object
-
#norm_ref_validate(doc) ⇒ Object
-
#png_validate(doc) ⇒ Object
-
#png_validate1(img, buffer) ⇒ Object
-
#preferred_validate(doc) ⇒ Object
-
#preferred_validate_report(terms) ⇒ Object
-
#process_range_location(to_location) ⇒ Object
-
#repeat_anchor_validate1(elem) ⇒ Object
-
#repeat_id_validate(doc) ⇒ Object
Check should never happen with content ids, but will check it anyway.
-
#repeat_id_validate1(elem) ⇒ Object
Check should never happen with content ids, but will check it anyway since consequences are so catastrophic.
-
#repeat_id_validate_prep ⇒ Object
-
#schema_file ⇒ Object
-
#schema_location ⇒ 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
-
#table_tracker_update(cells2d, row, curr, rowspan, colspan) ⇒ Object
-
#table_validate(doc) ⇒ Object
-
#termsect_validate(xmldoc) ⇒ Object
-
#validate(doc) ⇒ Object
-
#validate_document_fragment(xml_fragment) ⇒ Object
-
#xref_range_record(doc) ⇒ Object
If there is an xref range, record the IDs between the two targets.
-
#xref_validate(doc) ⇒ Object
manually check for xref/@target et sim.
-
#xref_validate_exists(doc) ⇒ Object
Methods included from Utils
#add_id, #add_id_text, adoc2xml, #asciimath_key, #attr_code, #convert, #csv_split, #dl_to_attrs, #dl_to_elems, #document_ns_attributes, #grkletters, #insert_before, #isodoc, #kv_parse, #link_unwrap, #noko, #processor, #quoted_csv_split, #refid?, #section_containers, #term_expr, #to_xml, #wrap_in_para, #xml_encode
Instance Method Details
#add_ns_to_fragment(xml_fragment) ⇒ Object
54
55
56
57
58
59
60
61
62
63
64
65
|
# File 'lib/metanorma/standoc/validate_schema.rb', line 54
def add_ns_to_fragment(xml_fragment)
f = Nokogiri::XML(xml_fragment, &:strict)
f.errors.any? || f.root.nil? and return nil
root_tag = f.root.name
f.root.namespace or
f = Nokogiri::XML(xml_fragment
.sub(/<#{root_tag}([^>]*)>/,
"<#{root_tag}\\1 xmlns='#{xml_namespace}'>"))
f
rescue StandardError
nil
end
|
#all_empty_block_validate(doc) ⇒ Object
204
205
206
207
208
209
210
211
212
213
|
# File 'lib/metanorma/standoc/validate.rb', line 204
def all_empty_block_validate(doc)
%w(note example admonition figure quote pre).each do |tag|
empty_block_validate(doc, "//#{tag}", nil)
end
empty_block_validate(doc, "//sourcecode", "body")
empty_block_validate(doc, "//formula", "stem")
empty_block_validate(doc, "//ol", "li")
empty_block_validate(doc, "//ul", "li")
empty_block_validate(doc, "//dl", "dt")
end
|
#asset_style(root) ⇒ Object
43
44
45
|
# File 'lib/metanorma/standoc/validate_section.rb', line 43
def asset_style(root)
asset_title_style(root)
end
|
#asset_title_style(root) ⇒ Object
34
35
36
37
38
39
40
41
|
# File 'lib/metanorma/standoc/validate_section.rb', line 34
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
|
#block_validate(doc) ⇒ Object
199
200
201
202
|
# File 'lib/metanorma/standoc/validate.rb', line 199
def block_validate(doc)
nested_asset_validate(doc)
all_empty_block_validate(doc)
end
|
#callouts_error(elem, callouts, annotations) ⇒ Object
20
21
22
23
24
25
26
|
# File 'lib/metanorma/standoc/validate_section.rb', line 20
def callouts_error(elem, callouts, annotations)
if callouts.size != annotations.size && !annotations.empty?
err = "mismatch of callouts (#{callouts.size}) and annotations " \
"(#{annotations.size})"
@log.add("Crossreferences", elem, err, severity: 0)
end
end
|
#concept_validate(doc, tag, refterm) ⇒ Object
38
39
40
41
42
43
44
45
|
# File 'lib/metanorma/standoc/validate_term.rb', line 38
def concept_validate(doc, tag, refterm)
concept_validate_ids(doc)
doc.xpath("//#{tag}/xref").each do |x|
@concept_ids[x["target"]] and next
@log.add("Anchors", x, concept_validate_msg(doc, tag, refterm, x),
severity: 0)
end
end
|
#concept_validate_ids(doc) ⇒ Object
47
48
49
50
51
52
53
|
# File 'lib/metanorma/standoc/validate_term.rb', line 47
def concept_validate_ids(doc)
@concept_ids ||= doc.xpath("//term | //definitions//dt")
.each_with_object({}) { |x, m| m[x["anchor"]] = true }
@concept_terms_tags ||= doc.xpath("//terms")
.each_with_object({}) { |t, m| m[t["anchor"]] = true }
nil
end
|
#concept_validate_msg(_doc, tag, refterm, xref) ⇒ Object
55
56
57
58
59
60
61
62
63
64
65
|
# File 'lib/metanorma/standoc/validate_term.rb', line 55
def concept_validate_msg(_doc, tag, refterm, xref)
t = @doc_ids.dig(xref["target"], :anchor) || xref["target"]
ret = " \#{tag.capitalize} \#{xref.at(\"../\#{refterm}\")&.text} is pointing to \#{t}, which is not a term or symbol\n LOG\n if @concept_terms_tags[xref[\"target\"]]\n ret = ret.strip\n ret += \". Did you mean to point to a subterm?\"\n end\n ret\nend\n"
|
#content_validate(doc) ⇒ Object
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
# File 'lib/metanorma/standoc/validate.rb', line 13
def content_validate(doc)
@doctype = doc.at("//bibdata/ext/doctype")&.text
repeat_id_validate(doc.root)
xref_validate(doc)
section_validate(doc)
norm_ref_validate(doc)
iev_validate(doc.root)
concept_validate(doc, "concept", "refterm")
concept_validate(doc, "related", "preferred//name")
preferred_validate(doc)
termsect_validate(doc)
table_validate(doc)
requirement_validate(doc)
image_validate(doc)
block_validate(doc)
math_validate(doc)
fatalerrors = @log.abort_messages
fatalerrors.empty? or
clean_abort("\n\nFATAL ERRROS:\n\n#{fatalerrors.join("\n\n")}", doc)
end
|
#empty_block?(block) ⇒ Boolean
224
225
226
227
228
229
230
|
# File 'lib/metanorma/standoc/validate.rb', line 224
def empty_block?(block)
content = block.children.reject { |n| n.name == "name" }
content.map do |n|
%w(image xref eref).include?(n.name) ? n.name : n
end
content.map(&:to_s).join.strip.empty?
end
|
#empty_block_validate(doc, tag, body) ⇒ Object
215
216
217
218
219
220
221
222
|
# File 'lib/metanorma/standoc/validate.rb', line 215
def empty_block_validate(doc, tag, body)
doc.xpath(tag).each do |t|
body and t = t.at("./#{body}")
empty_block?(t) or next
@log.add("Blocks", t, "#{tag.sub(/^\/\//, '')} is empty", severity: 1)
end
end
|
#empty_table_validate(doc) ⇒ Object
17
18
19
20
21
|
# File 'lib/metanorma/standoc/validate_table.rb', line 17
def empty_table_validate(doc)
doc.xpath("//table[not(.//tr)]").each do |t|
@log.add("Table", t, "Empty table", severity: 0)
end
end
|
#expand_path(loc) ⇒ Object
22
23
24
25
26
27
|
# File 'lib/metanorma/standoc/validate_image.rb', line 22
def expand_path(loc)
relative_path = File.join(@localdir, loc)
[loc, relative_path].detect do |p|
File.exist?(p) ? p : nil
end
end
|
#find_illegal_designations(xmldoc) ⇒ Object
89
90
91
92
93
94
95
96
97
98
99
100
|
# File 'lib/metanorma/standoc/validate_term.rb', line 89
def find_illegal_designations(xmldoc)
xmldoc.xpath("//preferred | //admitted | //deprecates")
.each_with_object({}) do |d, m|
d.ancestors.detect { |x| x.name == "terms" } and next
c = d.ancestors.detect do |x|
section_containers.include?(x.name)
end
c["id"] or add_id(c["id"])
m[c["id"]] ||= { clause: c, designations: [] }
m[c["id"]][:designations] << d
end
end
|
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.
91
92
93
94
95
96
97
98
99
100
101
|
# File 'lib/metanorma/standoc/validate_schema.rb', line 91
def formattedstr_strip(doc)
doc.xpath(WILDCARD_ATTRS, "m" => SVG_NS).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.xpath("//m:svg", "m" => SVG_NS).each { |n| n.replace("<svg/>") }
doc
end
|
#fragment_schema(root_element) ⇒ Object
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
# File 'lib/metanorma/standoc/validate_schema.rb', line 67
def fragment_schema(root_element)
temp_schema = Tempfile.new(["dynamic_schema", ".rng"])
temp_schema.write(" <grammar xmlns=\"http://relaxng.org/ns/structure/1.0\">\n <include href=\"\#{schema_location}\">\n <start combine=\"choice\">\n <ref name=\"\#{root_element}\"/>\n </start>\n </include>\n </grammar>\n SCHEMA\n temp_schema.close\n [temp_schema, Nokogiri::XML::RelaxNG(File.open(temp_schema.path))]\nrescue StandardError # error because root_element is not in schema\n [temp_schema, nil]\nend\n")
|
#get_anchors_between(start_id, end_id) ⇒ Object
Retrieve anchors between two nominated values (exclusive of start_id AND exclusive of end_id)
157
158
159
160
161
162
163
|
# File 'lib/metanorma/standoc/validate.rb', line 157
def get_anchors_between(start_id, end_id)
start_index = @doc_anchor_seq_hash[start_id]
end_index = @doc_anchor_seq_hash[end_id]
start_index.nil? || end_index.nil? and return []
start_index >= end_index and return []
@doc_anchor_seq[start_index...end_index]
end
|
#hanging_para_style(root) ⇒ Object
47
48
49
50
51
52
53
54
55
56
|
# File 'lib/metanorma/standoc/validate_section.rb', line 47
def hanging_para_style(root)
root.xpath("//clause | //annex | //foreword | //introduction | " \
"//acknowledgements | //executivesummary").each do |c|
c.at("./clause") or next
c.elements.reject do |n|
%w(clause title).include? n.name
end.empty? and next
style_warning(c, "Hanging paragraph in clause")
end
end
|
#iev_validate(xmldoc) ⇒ Object
16
17
18
19
20
21
22
23
24
25
|
# File 'lib/metanorma/standoc/validate_term.rb', line 16
def iev_validate(xmldoc)
@iev = init_iev or return
xmldoc.xpath("//term").each do |t|
t.xpath("./source | ./preferred/source | ./admitted/source | ./deprecates/source | ./related/source").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
27
28
29
30
31
32
33
34
35
36
|
# File 'lib/metanorma/standoc/validate_term.rb', line 27
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}"), severity: 1)
end
|
#image_exists(doc) ⇒ Object
12
13
14
15
16
17
18
19
20
|
# File 'lib/metanorma/standoc/validate_image.rb', line 12
def image_exists(doc)
doc.xpath("//image").each do |i|
Vectory::Utils::url?(i["src"]) and next
Vectory::Utils::datauri?(i["src"]) and next
expand_path(i["src"]) and next
@log.add("Images", i.parent,
"Image not found: #{i['src']}", severity: 0)
end
end
|
#image_toobig(doc) ⇒ Object
53
54
55
56
57
58
59
|
# File 'lib/metanorma/standoc/validate_image.rb', line 53
def image_toobig(doc)
@dataurimaxsize.zero? and return
doc.xpath("//image").each do |i|
i["src"].size > @dataurimaxsize and
@log.add("Images", i.parent, TOO_BIG_IMG_ERR, severity: 0)
end
end
|
#image_validate(doc) ⇒ Object
6
7
8
9
10
|
# File 'lib/metanorma/standoc/validate_image.rb', line 6
def image_validate(doc)
image_exists(doc)
image_toobig(doc)
png_validate(doc)
end
|
#init_iev ⇒ Object
9
10
11
12
13
14
|
# File 'lib/metanorma/standoc/validate_term.rb', line 9
def init_iev
@no_isobib and return nil
@iev and return @iev
@iev = ::Iev::Db.new(@iev_globalname, @iev_localname) unless @no_isobib
@iev
end
|
#math_validate(doc) ⇒ Object
36
37
38
39
40
41
42
43
44
45
46
47
|
# File 'lib/metanorma/standoc/validate.rb', line 36
def math_validate(doc)
doc.xpath("//m:math", "m" => MATHML_NS).each do |m|
if m.parent["validate"] == "false"
m.parent.delete("validate")
else
math = mathml_sanitise(m.dup)
Plurimath::Math.parse(math, "mathml").to_mathml
end
rescue StandardError => e
math_validate_error(math, m, e)
end
end
|
#math_validate_error(math, elem, error) ⇒ Object
54
55
56
57
58
59
60
61
62
|
# File 'lib/metanorma/standoc/validate.rb', line 54
def math_validate_error(math, elem, error)
a = elem.parent.at("./asciimath")
l = elem.parent.at("./latexmath")
orig = ""
a and orig += "\n\tAsciimath original: #{@c.decode(a.children.to_xml)}"
l and orig += "\n\tLatexmath original: #{@c.decode(l.children.to_xml)}"
@log.add("Maths", elem,
"Invalid MathML: #{math}\n #{error}#{orig}", severity: 0)
end
|
#mathml_sanitise(math) ⇒ Object
49
50
51
52
|
# File 'lib/metanorma/standoc/validate.rb', line 49
def mathml_sanitise(math)
math.to_xml(encoding: "US-ASCII").gsub(/ xmlns=["'][^"']+["']/, "")
.gsub(%r{<[^:/>]+:}, "<").gsub(%r{</[^:/>]+:}, "</")
end
|
#max_td_count(table) ⇒ Object
23
24
25
26
27
28
29
30
|
# File 'lib/metanorma/standoc/validate_table.rb', line 23
def max_td_count(table)
max = 0
table.xpath("./tr").each do |tr|
n = tr.xpath("./td | ./th").size
max < n and max = n
end
max
end
|
#maxcols_check(col, maxcols, tcell) ⇒ Object
if maxcols or maxrows negative, do not check them
87
88
89
90
91
92
|
# File 'lib/metanorma/standoc/validate_table.rb', line 87
def maxcols_check(col, maxcols, tcell)
if maxcols.positive? && col > maxcols
@log.add("Table", tcell, "Table exceeds maximum number of columns "\
"defined (#{maxcols})", severity: 0)
end
end
|
#maxcols_validate1(tcell, row, curr, cells2d, maxcols, mode) ⇒ Object
code doesn’t actually do anything, since Asciidoctor refuses to generate table with inconsistent column count
57
58
59
60
61
62
63
|
# File 'lib/metanorma/standoc/validate_table.rb', line 57
def maxcols_validate1(tcell, row, curr, cells2d, maxcols, mode)
rs = tcell&.attr("rowspan")&.to_i || 1
cs = tcell&.attr("colspan")&.to_i || 1
curr = table_tracker_update(cells2d, row, curr, rs, cs)
maxcols_check(curr + cs - 1, maxcols, tcell) if mode == "row_cols"
curr + cs
end
|
#maxrowcols_validate(table, maxcols, mode: "row_cols") ⇒ Object
32
33
34
35
36
37
38
39
40
41
|
# File 'lib/metanorma/standoc/validate_table.rb', line 32
def maxrowcols_validate(table, maxcols, mode: "row_cols")
case mode
when "row_cols"
maxrowcols_validate0(table, maxcols, "*", mode)
when "thead_row"
%w{thead tbody tfoot}.each do |w|
maxrowcols_validate0(table, maxcols, w, mode)
end
end
end
|
#maxrowcols_validate0(table, maxcols, tablechild, mode) ⇒ Object
43
44
45
46
47
48
49
50
51
52
53
|
# File 'lib/metanorma/standoc/validate_table.rb', line 43
def maxrowcols_validate0(table, maxcols, tablechild, mode)
cells2d = table.xpath("./#{tablechild}/tr")
.each_with_object([]) { |_r, m| m << {} }
table.xpath("./#{tablechild}/tr").each_with_index do |tr, r|
curr = 0
tr.xpath("./td | ./th").each do |td|
curr = maxcols_validate1(td, r, curr, cells2d, maxcols, mode)
end
end
maxrows_validate(table, cells2d, tablechild, mode)
end
|
#maxrows_validate(table, cells2d, tablechild, mode) ⇒ Object
77
78
79
80
81
82
83
84
|
# File 'lib/metanorma/standoc/validate_table.rb', line 77
def maxrows_validate(table, cells2d, tablechild, mode)
err = "are inconsistent"
mode == "thead_row" and err = "cannot go outside #{tablechild}"
err = "Table rows in table #{err}: check rowspan"
if cells2d.any? { |x| x.size != cells2d.first.size }
@log.add("Table", table, err, severity: 0)
end
end
|
#nested_asset_report(outer, inner, doc) ⇒ Object
86
87
88
89
90
91
92
|
# File 'lib/metanorma/standoc/validate.rb', line 86
def nested_asset_report(outer, inner, doc)
outer.name == "figure" && inner.name == "figure" and return
err =
"There is an instance of #{inner.name} nested within #{outer.name}"
@log.add("Style", inner, err)
nested_asset_xref_report(outer, inner, doc)
end
|
#nested_asset_validate(doc) ⇒ Object
64
65
66
67
|
# File 'lib/metanorma/standoc/validate.rb', line 64
def nested_asset_validate(doc)
nested_asset_validate_basic(doc)
nested_note_validate(doc)
end
|
#nested_asset_validate_basic(doc) ⇒ Object
69
70
71
72
73
74
75
76
|
# File 'lib/metanorma/standoc/validate.rb', line 69
def nested_asset_validate_basic(doc)
a = "//example | //figure | //termnote | //termexample | //table"
doc.xpath("#{a} | //note").each do |m|
m.xpath(a.gsub(%r{//}, ".//")).each do |n|
nested_asset_report(m, n, doc)
end
end
end
|
#nested_asset_xref_report(outer, inner, _doc) ⇒ Object
94
95
96
97
98
99
|
# File 'lib/metanorma/standoc/validate.rb', line 94
def nested_asset_xref_report(outer, inner, _doc)
i = @doc_xrefs[inner["anchor"]] or return
err2 = "There is a crossreference to an instance of #{inner.name} " \
"nested within #{outer.name}: #{i.to_xml}"
@log.add("Style", i, err2)
end
|
#nested_note_validate(doc) ⇒ Object
78
79
80
81
82
83
84
|
# File 'lib/metanorma/standoc/validate.rb', line 78
def nested_note_validate(doc)
doc.xpath("//termnote | //note").each do |m|
m.xpath(".//note").each do |n|
nested_asset_report(m, n, doc)
end
end
end
|
#norm_ref_validate(doc) ⇒ Object
58
59
60
61
62
63
64
65
|
# File 'lib/metanorma/standoc/validate_section.rb', line 58
def norm_ref_validate(doc)
doc.xpath("//references[@normative = 'true']/bibitem").each do |b|
docid = b.at("./docidentifier[@type = 'metanorma']") or next
/^\[\d+\]$/.match?(docid.text) or next
@log.add("Bibliography", b,
"Numeric reference in normative references", severity: 1)
end
end
|
#png_validate(doc) ⇒ Object
29
30
31
32
33
34
35
36
37
38
39
40
|
# File 'lib/metanorma/standoc/validate_image.rb', line 29
def png_validate(doc)
doc.xpath("//image[@mimetype = 'image/png']").each do |i|
Vectory::Utils::url?(i["src"]) and next
decoded = if Vectory::Utils::datauri?(i["src"])
Vectory::Utils::decode_datauri(i["src"])[:data]
else
path = expand_path(i["src"]) or next
File.binread(path)
end
png_validate1(i, decoded)
end
end
|
#png_validate1(img, buffer) ⇒ Object
42
43
44
45
46
47
|
# File 'lib/metanorma/standoc/validate_image.rb', line 42
def png_validate1(img, buffer)
PngCheck.check_buffer(buffer)
rescue PngCheck::CorruptPngError => e
@log.add("Images", img.parent,
"Corrupt PNG image detected: #{e.message}")
end
|
#preferred_validate(doc) ⇒ Object
67
68
69
70
71
72
73
74
75
76
77
78
|
# File 'lib/metanorma/standoc/validate_term.rb', line 67
def preferred_validate(doc)
ret = doc.xpath("//term").each_with_object({}) do |t, m|
prefix = t.at("./domain")&.text
t.xpath("./preferred//name").each do |n|
ret = n.text
prefix and ret = "<#{prefix}> #{ret}"
m[ret] ||= []
m[ret] << t
end
end
preferred_validate_report(ret)
end
|
#preferred_validate_report(terms) ⇒ Object
80
81
82
83
84
85
86
87
|
# File 'lib/metanorma/standoc/validate_term.rb', line 80
def preferred_validate_report(terms)
terms.each do |k, v|
v.size > 1 or next
loc = v.map { |x| x["anchor"] }.join(", ")
err = "Term #{k} occurs twice as preferred designation: #{loc}"
@log.add("Terms", v.first, err, severity: 1)
end
end
|
#process_range_location(to_location) ⇒ Object
190
191
192
193
194
195
196
197
|
# File 'lib/metanorma/standoc/validate.rb', line 190
def process_range_location(to_location)
from = to_location.previous_element
from && from.name == "location" or return
from["target"] && to_location["target"] or return
get_anchors_between(from["target"], to_location["target"])
.each { |id| @doc_xrefs[id] = from }
end
|
#repeat_anchor_validate1(elem) ⇒ Object
119
120
121
122
123
124
125
126
127
128
|
# File 'lib/metanorma/standoc/validate.rb', line 119
def repeat_anchor_validate1(elem)
if @doc_anchors[elem["anchor"]]
@log.add("Anchors", elem,
"Anchor #{elem['anchor']} has already been used at line " \
"#{@doc_anchors[elem['anchor']][:line]}", severity: 0)
else
@doc_anchors[elem["anchor"]] = { line: elem.line, id: elem["id"] }
@doc_anchor_seq << elem["anchor"]
end
end
|
#repeat_id_validate(doc) ⇒ Object
Check should never happen with content ids, but will check it anyway
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
# File 'lib/metanorma/standoc/validate.rb', line 131
def repeat_id_validate(doc)
repeat_id_validate_prep
doc.xpath("//*[@id]").each do |x|
@doc_id_seq << x["id"]
repeat_id_validate1(x)
x["anchor"] and repeat_anchor_validate1(x)
end
@doc_id_seq_hash = @doc_id_seq.each_with_index
.with_object({}) do |(x, i), m|
m[x] = i
end
@doc_anchor_seq_hash = @doc_anchor_seq.each_with_index
.with_object({}) do |(x, i), m|
m[x] = i
end
end
|
#repeat_id_validate1(elem) ⇒ Object
Check should never happen with content ids, but will check it anyway since consequences are so catastrophic
108
109
110
111
112
113
114
115
116
117
|
# File 'lib/metanorma/standoc/validate.rb', line 108
def repeat_id_validate1(elem)
if @doc_ids[elem["id"]]
@log.add("Anchors", elem,
"ID #{elem['id']} has already been " \
"used at line #{@doc_ids[elem['id']][:line]}", severity: 0)
else
@doc_ids[elem["id"]] =
{ line: elem.line, anchor: elem["anchor"] }.compact
end
end
|
#repeat_id_validate_prep ⇒ Object
148
149
150
151
152
153
|
# File 'lib/metanorma/standoc/validate.rb', line 148
def repeat_id_validate_prep
@doc_ids = {}
@doc_anchors = {}
@doc_id_seq = []
@doc_anchor_seq = []
end
|
#schema_file ⇒ Object
13
14
15
|
# File 'lib/metanorma/standoc/validate_schema.rb', line 13
def schema_file
"isodoc-compile.rng"
end
|
#schema_location ⇒ Object
6
7
8
9
10
11
|
# File 'lib/metanorma/standoc/validate_schema.rb', line 6
def schema_location
self.class.respond_to?(:_file) and ret = self.class::_file
ret ||= caller_locations(1..1).first.absolute_path
ret ||= __FILE__
File.join(File.dirname(ret), schema_file)
end
|
#schema_validate(doc, schema) ⇒ Object
17
18
19
20
21
22
23
24
25
|
# File 'lib/metanorma/standoc/validate_schema.rb', line 17
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)
ensure
f.close!
end
end
|
#schema_validate1(file, doc, schema) ⇒ Object
27
28
29
30
31
32
33
34
35
36
|
# File 'lib/metanorma/standoc/validate_schema.rb', line 27
def schema_validate1(file, doc, schema)
file.write(to_xml(doc))
file.close
errors = Jing.new(schema, encoding: "UTF-8").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/metanorma/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
|
# File 'lib/metanorma/standoc/validate_section.rb', line 12
def sourcecode_style(root)
root.xpath("//sourcecode").each do |x|
callouts = x.xpath("./body/callout")
annotations = x.xpath("./callout-annotation")
callouts_error(x, callouts, annotations)
end
end
|
#style_warning(node, msg, text = nil) ⇒ Object
28
29
30
31
32
|
# File 'lib/metanorma/standoc/validate_section.rb', line 28
def style_warning(node, msg, text = nil)
w = msg
w += ": #{text}" if text
@log.add("Style", node, w)
end
|
#table_tracker_update(cells2d, row, curr, rowspan, colspan) ⇒ Object
65
66
67
68
69
70
71
72
73
74
75
|
# File 'lib/metanorma/standoc/validate_table.rb', line 65
def table_tracker_update(cells2d, row, curr, rowspan, colspan)
cells2d[row] ||= {}
while cells2d[row][curr]
curr += 1
end
(row..(row + rowspan - 1)).each do |y2|
cells2d[y2] ||= {}
(curr..(curr + colspan - 1)).each { |x2| cells2d[y2][x2] = 1 }
end
curr
end
|
#table_validate(doc) ⇒ Object
4
5
6
7
8
9
10
11
12
13
14
15
|
# File 'lib/metanorma/standoc/validate_table.rb', line 4
def table_validate(doc)
empty_table_validate(doc)
doc.xpath("//table[colgroup]").each do |t|
maxrowcols_validate(t, t.xpath("./colgroup/col").size)
end
doc.xpath("//table[.//*[@colspan] | .//*[@rowspan]]").each do |t|
maxrowcols_validate(t, max_td_count(t), mode: "row_cols")
end
doc.xpath("//table[.//*[@rowspan]]").each do |t|
maxrowcols_validate(t, max_td_count(t), mode: "thead_row")
end
end
|
#termsect_validate(xmldoc) ⇒ Object
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
# File 'lib/metanorma/standoc/validate_term.rb', line 102
def termsect_validate(xmldoc)
errors = find_illegal_designations(xmldoc)
errors.each_value do |v|
desgns = v[:designations].map do |x|
@c.encode(x.text.strip, :basic, :hexadecimal)
end.join(", ")
err = " Clause not recognised as a term clause, but contains designation markup\n (<code>preferred:[], admitted:[], alt:[], deprecated:[]</code>):<br/>\n \#{desgns}</br>\n Ensure the parent clause is recognised as a terms clause by inserting <code>[heading=terms and definitions]</code> above the title,\n in case the heading is not automatically recognised. See also <a href=\"https://www.metanorma.org/author/topics/sections/concepts/#clause-title\">Metanorma documentation</a>.\n ERROR\n @log.add(\"Terms\", v[:clause], err, severity: 0)\n end\nend\n"
|
#validate(doc) ⇒ Object
101
102
103
104
|
# File 'lib/metanorma/standoc/validate.rb', line 101
def validate(doc)
content_validate(doc)
schema_validate(formattedstr_strip(doc.dup), schema_location)
end
|
#validate_document_fragment(xml_fragment) ⇒ Object
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
# File 'lib/metanorma/standoc/validate_schema.rb', line 38
def validate_document_fragment(xml_fragment)
f = add_ns_to_fragment(xml_fragment) or
return [true,
"Fragment is not well-formed XML, not validating"]
begin
temp_schema, schema = fragment_schema(f.root.name)
schema or return [false, "Did not expect element #{f.root.name}"]
validation_errors = schema.validate(f)
[validation_errors.none? do |x|
x.to_s.include?("Did not expect element")
end, validation_errors]
ensure
temp_schema.unlink
end
end
|
#xref_range_record(doc) ⇒ Object
If there is an xref range, record the IDs between the two targets
184
185
186
187
188
|
# File 'lib/metanorma/standoc/validate.rb', line 184
def xref_range_record(doc)
doc.xpath("//xref//location[@connective = 'to']").each do |to|
process_range_location(to)
end
end
|
#xref_validate(doc) ⇒ Object
manually check for xref/@target et sim. integrity
166
167
168
169
|
# File 'lib/metanorma/standoc/validate.rb', line 166
def xref_validate(doc)
xref_validate_exists(doc)
xref_range_record(doc)
end
|
#xref_validate_exists(doc) ⇒ Object
171
172
173
174
175
176
177
178
179
180
181
|
# File 'lib/metanorma/standoc/validate.rb', line 171
def xref_validate_exists(doc)
@doc_xrefs = {}
Metanorma::Utils::anchor_attributes.each do |a|
doc.xpath("//#{a[0]}/@#{a[1]}").each do |x|
@doc_xrefs[x.text] = x.parent
@doc_anchors[x.text] and next
@log.add("Anchors", x.parent,
"Crossreference target #{x} is undefined", severity: 1)
end
end
end
|