metanorma-iso 1.7.2 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +11 -41
- data/.gitignore +2 -0
- data/.rubocop.yml +7 -1
- data/lib/asciidoctor/iso/base.rb +14 -11
- data/lib/asciidoctor/iso/biblio.rng +4 -6
- data/lib/asciidoctor/iso/cleanup.rb +40 -24
- data/lib/asciidoctor/iso/front.rb +29 -17
- data/lib/asciidoctor/iso/front_id.rb +81 -60
- data/lib/asciidoctor/iso/isodoc.rng +327 -2
- data/lib/asciidoctor/iso/isostandard.rng +12 -97
- data/lib/asciidoctor/iso/section.rb +2 -1
- data/lib/asciidoctor/iso/validate.rb +22 -109
- data/lib/asciidoctor/iso/validate_image.rb +97 -0
- data/lib/asciidoctor/iso/validate_requirements.rb +26 -20
- data/lib/asciidoctor/iso/validate_section.rb +39 -20
- data/lib/asciidoctor/iso/validate_style.rb +36 -24
- data/lib/asciidoctor/iso/validate_title.rb +23 -17
- data/lib/isodoc/iso/base_convert.rb +19 -2
- data/lib/isodoc/iso/html/style-human.css +7 -0
- data/lib/isodoc/iso/html/style-iso.css +7 -0
- data/lib/isodoc/iso/html_convert.rb +0 -1
- data/lib/isodoc/iso/i18n-en.yaml +4 -0
- data/lib/isodoc/iso/i18n-fr.yaml +4 -0
- data/lib/isodoc/iso/i18n-zh-Hans.yaml +4 -0
- data/lib/isodoc/iso/index.rb +140 -0
- data/lib/isodoc/iso/iso.amendment.xsl +1157 -208
- data/lib/isodoc/iso/iso.international-standard.xsl +1157 -208
- data/lib/isodoc/iso/metadata.rb +1 -0
- data/lib/isodoc/iso/presentation_xml_convert.rb +45 -37
- data/lib/isodoc/iso/sts_convert.rb +10 -13
- data/lib/isodoc/iso/word_convert.rb +0 -1
- data/lib/isodoc/iso/xref.rb +46 -25
- data/lib/metanorma/iso/processor.rb +1 -0
- data/lib/metanorma/iso/version.rb +1 -1
- data/metanorma-iso.gemspec +8 -8
- data/spec/{asciidoctor-iso → asciidoctor}/amd_spec.rb +5 -5
- data/spec/asciidoctor/base_spec.rb +825 -0
- data/spec/{asciidoctor-iso → asciidoctor}/blocks_spec.rb +0 -0
- data/spec/{asciidoctor-iso → asciidoctor}/cleanup_spec.rb +383 -25
- data/spec/{asciidoctor-iso → asciidoctor}/inline_spec.rb +0 -0
- data/spec/{asciidoctor-iso → asciidoctor}/lists_spec.rb +0 -0
- data/spec/{asciidoctor-iso → asciidoctor}/refs_spec.rb +0 -0
- data/spec/{asciidoctor-iso → asciidoctor}/section_spec.rb +0 -14
- data/spec/{asciidoctor-iso → asciidoctor}/table_spec.rb +0 -0
- data/spec/{asciidoctor-iso → asciidoctor}/validate_spec.rb +188 -83
- data/spec/isodoc/postproc_spec.rb +481 -438
- data/spec/isodoc/section_spec.rb +219 -0
- data/spec/spec_helper.rb +2 -0
- metadata +65 -64
- data/lib/isodoc/iso/html/scripts.html +0 -178
- data/spec/asciidoctor-iso/base_spec.rb +0 -704
@@ -10,7 +10,7 @@ module Asciidoctor
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def scope_parse(attrs, xml, node)
|
13
|
-
attrs = attrs.merge(type: "scope") unless @amd
|
13
|
+
attrs = attrs.merge(type: "scope") unless @amd
|
14
14
|
clause_parse(attrs, xml, node)
|
15
15
|
end
|
16
16
|
|
@@ -32,6 +32,7 @@ module Asciidoctor
|
|
32
32
|
|
33
33
|
def sectiontype(node, level = true)
|
34
34
|
return nil if @amd
|
35
|
+
|
35
36
|
super
|
36
37
|
end
|
37
38
|
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
require "metanorma-standoc"
|
2
|
-
require_relative "./validate_style
|
3
|
-
require_relative "./validate_requirements
|
4
|
-
require_relative "./validate_section
|
5
|
-
require_relative "./validate_title
|
2
|
+
require_relative "./validate_style"
|
3
|
+
require_relative "./validate_requirements"
|
4
|
+
require_relative "./validate_section"
|
5
|
+
require_relative "./validate_title"
|
6
|
+
require_relative "./validate_image"
|
6
7
|
require "nokogiri"
|
7
8
|
require "jing"
|
8
9
|
require "iev"
|
@@ -10,17 +11,6 @@ require "iev"
|
|
10
11
|
module Asciidoctor
|
11
12
|
module ISO
|
12
13
|
class Converter < Standoc::Converter
|
13
|
-
# ISO/IEC DIR 2, 22.3.2
|
14
|
-
def onlychild_clause_validate(root)
|
15
|
-
root.xpath(Standoc::Utils::SUBCLAUSE_XPATH).each do |c|
|
16
|
-
next unless c.xpath("../clause").size == 1
|
17
|
-
title = c.at("./title")
|
18
|
-
location = c["id"] || c.text[0..60] + "..."
|
19
|
-
location += ":#{title.text}" if c["id"] && !title.nil?
|
20
|
-
@log.add("Style", nil, "#{location}: subclause is only child")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
14
|
def isosubgroup_validate(root)
|
25
15
|
root.xpath("//technical-committee/@type").each do |t|
|
26
16
|
unless %w{TC PC JTC JPC}.include? t.text
|
@@ -37,12 +27,13 @@ module Asciidoctor
|
|
37
27
|
end
|
38
28
|
|
39
29
|
# ISO/IEC DIR 2, 15.5.3
|
30
|
+
# does not deal with preceding text marked up
|
40
31
|
def see_xrefs_validate(root)
|
41
32
|
root.xpath("//xref").each do |t|
|
42
|
-
# does not deal with preceding text marked up
|
43
33
|
preceding = t.at("./preceding-sibling::text()[last()]")
|
44
34
|
next unless !preceding.nil? &&
|
45
35
|
/\b(see| refer to)\s*$/mi.match(preceding)
|
36
|
+
|
46
37
|
(target = root.at("//*[@id = '#{t['target']}']")) || next
|
47
38
|
if target&.at("./ancestor-or-self::*[@obligation = 'normative']")
|
48
39
|
@log.add("Style", t,
|
@@ -54,36 +45,34 @@ module Asciidoctor
|
|
54
45
|
# ISO/IEC DIR 2, 15.5.3
|
55
46
|
def see_erefs_validate(root)
|
56
47
|
root.xpath("//eref").each do |t|
|
57
|
-
|
58
|
-
next unless !
|
59
|
-
|
48
|
+
prec = t.at("./preceding-sibling::text()[last()]")
|
49
|
+
next unless !prec.nil? && /\b(see|refer to)\s*$/mi.match(prec)
|
50
|
+
|
60
51
|
unless target = root.at("//*[@id = '#{t['bibitemid']}']")
|
61
52
|
@log.add("Bibliography", t,
|
62
53
|
"'#{t} is not pointing to a real reference")
|
63
54
|
next
|
64
55
|
end
|
65
|
-
|
56
|
+
target.at("./ancestor::references[@normative = 'true']") and
|
66
57
|
@log.add("Style", t,
|
67
58
|
"'see #{t}' is pointing to a normative reference")
|
68
|
-
end
|
69
59
|
end
|
70
60
|
end
|
71
61
|
|
72
62
|
# ISO/IEC DIR 2, 10.4
|
73
63
|
def locality_erefs_validate(root)
|
74
64
|
root.xpath("//eref[descendant::locality]").each do |t|
|
75
|
-
if /^(ISO|IEC)/.match
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
end
|
65
|
+
if /^(ISO|IEC)/.match?(t["citeas"]) &&
|
66
|
+
!(/: ?(\d+{4}|–)$/.match?(t["citeas"]))
|
67
|
+
@log.add("Style", t,
|
68
|
+
"undated reference #{t['citeas']} should not contain "\
|
69
|
+
"specific elements")
|
81
70
|
end
|
82
71
|
end
|
83
72
|
end
|
84
73
|
|
85
|
-
def termdef_warn(text,
|
86
|
-
|
74
|
+
def termdef_warn(text, regex, elem, term, msg)
|
75
|
+
regex.match(text) && @log.add("Style", elem, "#{term}: #{msg}")
|
87
76
|
end
|
88
77
|
|
89
78
|
# ISO/IEC DIR 2, 16.5.6
|
@@ -103,6 +92,7 @@ module Asciidoctor
|
|
103
92
|
def cited_term_style(xmldoc)
|
104
93
|
xmldoc.xpath("//term//xref").each do |x|
|
105
94
|
next unless xmldoc.at("//term[@id = '#{x['target']}']")
|
95
|
+
|
106
96
|
x&.previous&.text == " (" and x&.previous&.previous&.name == "em" or
|
107
97
|
style_warning(x, "term citation not preceded with italicised term",
|
108
98
|
x.parent.text)
|
@@ -111,8 +101,8 @@ module Asciidoctor
|
|
111
101
|
|
112
102
|
def doctype_validate(xmldoc)
|
113
103
|
doctype = xmldoc&.at("//bibdata/ext/doctype")&.text
|
114
|
-
%w(international-standard technical-specification technical-report
|
115
|
-
publicly-available-specification international-workshop-agreement
|
104
|
+
%w(international-standard technical-specification technical-report
|
105
|
+
publicly-available-specification international-workshop-agreement
|
116
106
|
guide amendment technical-corrigendum).include? doctype or
|
117
107
|
@log.add("Document Attributes", nil,
|
118
108
|
"#{doctype} is not a recognised document type")
|
@@ -146,83 +136,6 @@ module Asciidoctor
|
|
146
136
|
"#{iteration} is not a recognised iteration")
|
147
137
|
end
|
148
138
|
|
149
|
-
# DRG directives 3.7; but anticipated by standoc
|
150
|
-
def subfigure_validate(xmldoc)
|
151
|
-
xmldoc.xpath("//figure//figure").each do |f|
|
152
|
-
{ footnote: "fn", note: "note", key: "dl" }.each do |k, v|
|
153
|
-
f.xpath(".//#{v}").each do |n|
|
154
|
-
@log.add("Style", n, "#{k} is not permitted in a subfigure")
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
def image_name_prefix(xmldoc)
|
161
|
-
std = xmldoc&.at("//bibdata/ext/structuredidentifier/project-number") or return
|
162
|
-
num = xmldoc&.at("//bibdata/docnumber")&.text or return
|
163
|
-
ed = xmldoc&.at("//bibdata/edition")&.text || "1"
|
164
|
-
prefix = num
|
165
|
-
part = std["part"] and prefix += "-#{std['part']}"
|
166
|
-
prefix += "_ed#{ed}"
|
167
|
-
amd = std["amendment"] and prefix += "amd#{amd}"
|
168
|
-
prefix
|
169
|
-
end
|
170
|
-
|
171
|
-
def image_name_suffix(xmldoc)
|
172
|
-
case xmldoc&.at("//bibdata/language")&.text
|
173
|
-
when "fr" then "_f"
|
174
|
-
when "de" then "_d"
|
175
|
-
when "ru" then "_r"
|
176
|
-
when "es" then "_s"
|
177
|
-
when "ar" then "_a"
|
178
|
-
when "en" then "_e"
|
179
|
-
else
|
180
|
-
"_e"
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
def disjunct_error(i, cond1, cond2, msg1, msg2)
|
185
|
-
cond1 && !cond2 and @log.add("Style", i, "image name #{i['src']} #{msg1}")
|
186
|
-
!cond1 && cond2 and @log.add("Style", i, "image name #{i['src']} #{msg2}")
|
187
|
-
end
|
188
|
-
|
189
|
-
def image_name_validate1(i, prefix)
|
190
|
-
m = %r[(SL)?#{prefix}fig(?<tab>Tab)?(?<annex>[A-Z])?(Text)?(?<num>\d+)
|
191
|
-
(?<subfig>[a-z])?(?<key>_key\d+)?(?<lang>_[a-z])?$]x.match(File.basename(i["src"], ".*"))
|
192
|
-
if m.nil?
|
193
|
-
@log.add("Style", i, "image name #{i['src']} does not match DRG requirements")
|
194
|
-
return
|
195
|
-
end
|
196
|
-
warn i['src']
|
197
|
-
disjunct_error(i, i.at("./ancestor::table"), !m[:tab].nil?,
|
198
|
-
"is under a table but is not so labelled", "is labelled as under a table but is not")
|
199
|
-
disjunct_error(i, i.at("./ancestor::annex"), !m[:annex].nil?,
|
200
|
-
"is under an annex but is not so labelled", "is labelled as under an annex but is not")
|
201
|
-
disjunct_error(i, i.xpath("./ancestor::figure").size > 1, !m[:subfig].nil?,
|
202
|
-
"does not have a subfigure letter but is a subfigure",
|
203
|
-
"has a subfigure letter but is not a subfigure")
|
204
|
-
lang = image_name_suffix(i.document.root)
|
205
|
-
(m[:lang] || "_e") == lang or @log.add("Style", i, "image name #{i['src']} expected to have suffix #{lang}")
|
206
|
-
end
|
207
|
-
|
208
|
-
# DRG directives 3.2
|
209
|
-
def image_name_validate(xmldoc)
|
210
|
-
prefix = image_name_prefix(xmldoc) or return
|
211
|
-
xmldoc.xpath("//image").each do |i|
|
212
|
-
if /^ISO_\d+_/.match(File.basename(i["src"]))
|
213
|
-
elsif /^(SL)?#{prefix}fig/.match(File.basename(i["src"]))
|
214
|
-
image_name_validate1(i, prefix)
|
215
|
-
else
|
216
|
-
@log.add("Style", i, "image name #{i['src']} does not match DRG requirements: expect #{prefix}fig")
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
220
|
-
|
221
|
-
def figure_validate(xmldoc)
|
222
|
-
image_name_validate(xmldoc)
|
223
|
-
subfigure_validate(xmldoc)
|
224
|
-
end
|
225
|
-
|
226
139
|
def bibdata_validate(doc)
|
227
140
|
doctype_validate(doc)
|
228
141
|
script_validate(doc)
|
@@ -250,7 +163,7 @@ module Asciidoctor
|
|
250
163
|
xmldoc.xpath("//bibitem[date/on = '–']").each do |b|
|
251
164
|
b.at("./note[@type = 'Unpublished-Status']") or
|
252
165
|
@log.add("Style", b,
|
253
|
-
"Reference #{b&.at(
|
166
|
+
"Reference #{b&.at('./@id')&.text} does not have an "\
|
254
167
|
"associated footnote indicating unpublished status")
|
255
168
|
end
|
256
169
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Asciidoctor
|
2
|
+
module ISO
|
3
|
+
class Converter < Standoc::Converter
|
4
|
+
# DRG directives 3.7; but anticipated by standoc
|
5
|
+
def subfigure_validate(xmldoc)
|
6
|
+
xmldoc.xpath("//figure//figure").each do |f|
|
7
|
+
{ footnote: "fn", note: "note", key: "dl" }.each do |k, v|
|
8
|
+
f.xpath(".//#{v}").each do |n|
|
9
|
+
@log.add("Style", n, "#{k} is not permitted in a subfigure")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def image_name_prefix(xmldoc)
|
16
|
+
std = xmldoc&.at("//bibdata/ext/structuredidentifier/project-number") or
|
17
|
+
return
|
18
|
+
num = xmldoc&.at("//bibdata/docnumber")&.text or return
|
19
|
+
ed = xmldoc&.at("//bibdata/edition")&.text || "1"
|
20
|
+
prefix = num
|
21
|
+
std["part"] and prefix += "-#{std['part']}"
|
22
|
+
prefix += "_ed#{ed}"
|
23
|
+
amd = std["amendment"] and prefix += "amd#{amd}"
|
24
|
+
prefix
|
25
|
+
end
|
26
|
+
|
27
|
+
def image_name_suffix(xmldoc)
|
28
|
+
case xmldoc&.at("//bibdata/language")&.text
|
29
|
+
when "fr" then "_f"
|
30
|
+
when "de" then "_d"
|
31
|
+
when "ru" then "_r"
|
32
|
+
when "es" then "_s"
|
33
|
+
when "ar" then "_a"
|
34
|
+
when "en" then "_e"
|
35
|
+
else
|
36
|
+
"_e"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def disjunct_error(img, cond1, cond2, msg1, msg2)
|
41
|
+
cond1 && !cond2 and
|
42
|
+
@log.add("Style", img, "image name #{img['src']} #{msg1}")
|
43
|
+
!cond1 && cond2 and
|
44
|
+
@log.add("Style", img, "image name #{img['src']} #{msg2}")
|
45
|
+
end
|
46
|
+
|
47
|
+
def image_name_parse(img, prefix)
|
48
|
+
m = %r[(SL)?#{prefix}fig(?<tab>Tab)?(?<annex>[A-Z])?(Text)?(?<num>\d+)
|
49
|
+
(?<subfig>[a-z])?(?<key>_key\d+)?(?<lang>_[a-z])?$]x
|
50
|
+
.match(File.basename(img["src"], ".*"))
|
51
|
+
m.nil? and
|
52
|
+
@log.add("Style", img,
|
53
|
+
"image name #{img['src']} does not match DRG requirements")
|
54
|
+
m
|
55
|
+
end
|
56
|
+
|
57
|
+
def image_name_validate1(i, prefix)
|
58
|
+
m = image_name_parse(i, prefix) or return
|
59
|
+
warn i["src"]
|
60
|
+
disjunct_error(i, i.at("./ancestor::table"), !m[:tab].nil?,
|
61
|
+
"is under a table but is not so labelled",
|
62
|
+
"is labelled as under a table but is not")
|
63
|
+
disjunct_error(i, i.at("./ancestor::annex"), !m[:annex].nil?,
|
64
|
+
"is under an annex but is not so labelled",
|
65
|
+
"is labelled as under an annex but is not")
|
66
|
+
disjunct_error(i, i.xpath("./ancestor::figure").size > 1, !m[:subfig].nil?,
|
67
|
+
"does not have a subfigure letter but is a subfigure",
|
68
|
+
"has a subfigure letter but is not a subfigure")
|
69
|
+
lang = image_name_suffix(i.document.root)
|
70
|
+
(m[:lang] || "_e") == lang or
|
71
|
+
@log.add("Style", i,
|
72
|
+
"image name #{i['src']} expected to have suffix #{lang}")
|
73
|
+
end
|
74
|
+
|
75
|
+
# DRG directives 3.2
|
76
|
+
def image_name_validate(xmldoc)
|
77
|
+
prefix = image_name_prefix(xmldoc) or return
|
78
|
+
xmldoc.xpath("//image").each do |i|
|
79
|
+
next if i["src"].start_with?("data:")
|
80
|
+
|
81
|
+
if /^ISO_\d+_/.match?(File.basename(i["src"]))
|
82
|
+
elsif /^(SL)?#{prefix}fig/.match?(File.basename(i["src"]))
|
83
|
+
image_name_validate1(i, prefix)
|
84
|
+
else
|
85
|
+
@log.add("Style", i,
|
86
|
+
"image name #{i['src']} does not match DRG requirements: expect #{prefix}fig")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def figure_validate(xmldoc)
|
92
|
+
image_name_validate(xmldoc)
|
93
|
+
subfigure_validate(xmldoc)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -1,6 +1,4 @@
|
|
1
1
|
require "metanorma-standoc"
|
2
|
-
require "nokogiri"
|
3
|
-
require "pp"
|
4
2
|
|
5
3
|
module Asciidoctor
|
6
4
|
module ISO
|
@@ -19,13 +17,15 @@ module Asciidoctor
|
|
19
17
|
[.,:;]_do_not )
|
20
18
|
\\b
|
21
19
|
REGEXP
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
|
21
|
+
def requirement_re
|
22
|
+
Regexp.new(self.class::REQUIREMENT_RE_STR.gsub(/\s/, "")
|
23
|
+
.gsub(/_/, "\\s"), Regexp::IGNORECASE)
|
24
|
+
end
|
25
25
|
|
26
26
|
def requirement_check(text)
|
27
27
|
text.split(/\.\s+/).each do |t|
|
28
|
-
return t if
|
28
|
+
return t if requirement_re.match t
|
29
29
|
end
|
30
30
|
nil
|
31
31
|
end
|
@@ -37,13 +37,15 @@ module Asciidoctor
|
|
37
37
|
it_is_(not_)?recommended_that
|
38
38
|
\\b
|
39
39
|
REGEXP
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
|
41
|
+
def recommendation_re
|
42
|
+
Regexp.new(self.class::RECOMMENDATION_RE_STR.gsub(/\s/, "")
|
43
|
+
.gsub(/_/, "\\s"), Regexp::IGNORECASE)
|
44
|
+
end
|
43
45
|
|
44
46
|
def recommendation_check(text)
|
45
47
|
text.split(/\.\s+/).each do |t|
|
46
|
-
return t if
|
48
|
+
return t if recommendation_re.match t
|
47
49
|
end
|
48
50
|
nil
|
49
51
|
end
|
@@ -56,13 +58,15 @@ module Asciidoctor
|
|
56
58
|
no\\b[^.,]+\\b(is|are)_required
|
57
59
|
\\b
|
58
60
|
REGEXP
|
59
|
-
|
60
|
-
|
61
|
-
|
61
|
+
|
62
|
+
def permission_re
|
63
|
+
Regexp.new(self.class::PERMISSION_RE_STR.gsub(/\s/, "")
|
64
|
+
.gsub(/_/, "\\s"), Regexp::IGNORECASE)
|
65
|
+
end
|
62
66
|
|
63
67
|
def permission_check(text)
|
64
68
|
text.split(/\.\s+/).each do |t|
|
65
|
-
return t if
|
69
|
+
return t if permission_re.match t
|
66
70
|
end
|
67
71
|
nil
|
68
72
|
end
|
@@ -76,18 +80,20 @@ module Asciidoctor
|
|
76
80
|
it_is_not_possible_to
|
77
81
|
\\b
|
78
82
|
REGEXP
|
79
|
-
POSSIBILITY_RE =
|
80
|
-
Regexp.new(POSSIBILITY_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"),
|
81
|
-
Regexp::IGNORECASE)
|
82
83
|
|
83
|
-
def
|
84
|
-
|
84
|
+
def possibility_re
|
85
|
+
Regexp.new(self.class::POSSIBILITY_RE_STR.gsub(/\s/, "")
|
86
|
+
.gsub(/_/, "\\s"), Regexp::IGNORECASE)
|
87
|
+
end
|
88
|
+
|
89
|
+
def possibility_check(text)
|
90
|
+
text.split(/\.\s+/).each { |t| return t if possibility_re.match t }
|
85
91
|
nil
|
86
92
|
end
|
87
93
|
|
88
94
|
def external_constraint(text)
|
89
95
|
text.split(/\.\s+/).each do |t|
|
90
|
-
return t if /\b(must)\b/xi.match t
|
96
|
+
return t if /\b(must)\b/xi.match? t
|
91
97
|
end
|
92
98
|
nil
|
93
99
|
end
|
@@ -50,10 +50,11 @@ module Asciidoctor
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def seqcheck(names, msg, accepted)
|
53
|
-
n = names.shift
|
53
|
+
n = names.shift
|
54
54
|
return [] if n.nil?
|
55
|
+
|
55
56
|
test = accepted.map { |a| n.at(a) }
|
56
|
-
if test.all?
|
57
|
+
if test.all?(&:nil?)
|
57
58
|
@log.add("Style", nil, msg)
|
58
59
|
end
|
59
60
|
names
|
@@ -74,37 +75,38 @@ module Asciidoctor
|
|
74
75
|
[
|
75
76
|
{
|
76
77
|
msg: "Initial section must be (content) Foreword",
|
77
|
-
val:
|
78
|
+
val: ["./self::foreword"],
|
78
79
|
},
|
79
80
|
{
|
80
81
|
msg: "Prefatory material must be followed by (clause) Scope",
|
81
|
-
val: ["./self::introduction", "./self::clause[@type = 'scope']"
|
82
|
+
val: ["./self::introduction", "./self::clause[@type = 'scope']"],
|
82
83
|
},
|
83
84
|
{
|
84
85
|
msg: "Prefatory material must be followed by (clause) Scope",
|
85
|
-
val: ["./self::clause[@type = 'scope']"
|
86
|
+
val: ["./self::clause[@type = 'scope']"],
|
86
87
|
},
|
87
88
|
{
|
88
89
|
msg: "Normative References must be followed by "\
|
89
90
|
"Terms and Definitions",
|
90
|
-
val: ["./self::terms | .//terms"]
|
91
|
+
val: ["./self::terms | .//terms"],
|
91
92
|
},
|
92
|
-
|
93
|
+
].freeze
|
93
94
|
|
94
95
|
SECTIONS_XPATH =
|
95
96
|
"//foreword | //introduction | //sections/terms | .//annex | "\
|
96
|
-
"//sections/definitions | //sections/clause |
|
97
|
+
"//sections/definitions | //sections/clause | "\
|
98
|
+
"//references[not(parent::clause)] | "\
|
97
99
|
"//clause[descendant::references][not(parent::clause)]".freeze
|
98
100
|
|
99
101
|
def sections_sequence_validate(root)
|
100
102
|
names = root.xpath(SECTIONS_XPATH)
|
101
|
-
names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val])
|
103
|
+
names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val])
|
102
104
|
n = names[0]
|
103
|
-
names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val])
|
105
|
+
names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val])
|
104
106
|
if n&.at("./self::introduction")
|
105
|
-
names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val])
|
107
|
+
names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val])
|
106
108
|
end
|
107
|
-
names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val])
|
109
|
+
names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val])
|
108
110
|
n = names.shift
|
109
111
|
if n&.at("./self::definitions")
|
110
112
|
n = names.shift
|
@@ -117,11 +119,11 @@ module Asciidoctor
|
|
117
119
|
"Terms and Definitions")
|
118
120
|
n&.at("./self::clause[@type = 'scope']") &&
|
119
121
|
@log.add("Style", nil, "Scope must occur before Terms and Definitions")
|
120
|
-
n = names.shift
|
122
|
+
n = names.shift
|
121
123
|
while n&.name == "clause"
|
122
124
|
n&.at("./self::clause[@type = 'scope']")
|
123
125
|
@log.add("Style", nil, "Scope must occur before Terms and Definitions")
|
124
|
-
n = names.shift
|
126
|
+
n = names.shift
|
125
127
|
end
|
126
128
|
unless %w(annex references).include? n&.name
|
127
129
|
@log.add("Style", nil, "Only annexes and references can follow clauses")
|
@@ -145,6 +147,7 @@ module Asciidoctor
|
|
145
147
|
|
146
148
|
def style_warning(node, msg, text = nil)
|
147
149
|
return if @novalid
|
150
|
+
|
148
151
|
w = msg
|
149
152
|
w += ": #{text}" if text
|
150
153
|
@log.add("Style", node, w)
|
@@ -165,15 +168,18 @@ module Asciidoctor
|
|
165
168
|
|
166
169
|
def tech_report_style(root)
|
167
170
|
root.at("//bibdata/ext/doctype")&.text == "technical-report" or return
|
168
|
-
root.xpath("//sections/clause[not(@type = 'scope')] | //annex")
|
169
|
-
|
170
|
-
|
171
|
+
root.xpath("//sections/clause[not(@type = 'scope')] | //annex")
|
172
|
+
.each do |s|
|
173
|
+
r = requirement_check(extract_text(s)) and
|
174
|
+
style_warning(s,
|
175
|
+
"Technical Report clause may contain requirement", r)
|
171
176
|
end
|
172
177
|
end
|
173
178
|
|
174
179
|
ASSETS_TO_STYLE =
|
175
|
-
"//termsource | //formula | //termnote |
|
176
|
-
"//
|
180
|
+
"//termsource | //formula | //termnote | "\
|
181
|
+
"//p[not(ancestor::boilerplate)] | //li[not(p)] | //dt | "\
|
182
|
+
"//dd[not(p)] | //td[not(p)] | //th[not(p)]".freeze
|
177
183
|
|
178
184
|
NORM_BIBITEMS =
|
179
185
|
"//references[@normative = 'true']/bibitem".freeze
|
@@ -198,10 +204,23 @@ module Asciidoctor
|
|
198
204
|
end
|
199
205
|
|
200
206
|
def subclause_validate(root)
|
201
|
-
root.xpath("//clause/clause/clause/clause/clause/clause/clause/clause")
|
207
|
+
root.xpath("//clause/clause/clause/clause/clause/clause/clause/clause")
|
208
|
+
.each do |c|
|
202
209
|
style_warning(c, "Exceeds the maximum clause depth of 7", nil)
|
203
210
|
end
|
204
211
|
end
|
212
|
+
|
213
|
+
# ISO/IEC DIR 2, 22.3.2
|
214
|
+
def onlychild_clause_validate(root)
|
215
|
+
root.xpath(Standoc::Utils::SUBCLAUSE_XPATH).each do |c|
|
216
|
+
next unless c.xpath("../clause").size == 1
|
217
|
+
|
218
|
+
title = c.at("./title")
|
219
|
+
location = c["id"] || "#{c.text[0..60]}..."
|
220
|
+
location += ":#{title.text}" if c["id"] && !title.nil?
|
221
|
+
@log.add("Style", nil, "#{location}: subclause is only child")
|
222
|
+
end
|
223
|
+
end
|
205
224
|
end
|
206
225
|
end
|
207
226
|
end
|