metanorma-iso 1.3.19 → 1.3.20
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/asciidoctor/iso/base.rb +1 -0
- data/lib/asciidoctor/iso/cleanup.rb +3 -1
- data/lib/asciidoctor/iso/isodoc.rng +5 -0
- data/lib/asciidoctor/iso/isostandard.rng +80 -0
- data/lib/asciidoctor/iso/validate.rb +19 -19
- data/lib/asciidoctor/iso/validate_section.rb +19 -19
- data/lib/asciidoctor/iso/validate_title.rb +11 -11
- data/lib/isodoc/iso/base_convert.rb +42 -1
- data/lib/isodoc/iso/html/isodoc.scss +4 -0
- data/lib/isodoc/iso/html/style-human.scss +7 -0
- data/lib/isodoc/iso/html/style-iso.scss +6 -0
- data/lib/isodoc/iso/html_convert.rb +6 -0
- data/lib/metanorma/iso/version.rb +1 -1
- data/metanorma-iso.gemspec +0 -1
- data/spec/asciidoctor-iso/cleanup_spec.rb +57 -21
- data/spec/asciidoctor-iso/validate_spec.rb +225 -75
- data/spec/isodoc/postproc_spec.rb +123 -3
- data/spec/isodoc/section_spec.rb +45 -0
- data/spec/isodoc/table_spec.rb +289 -0
- data/spec/isodoc/xref_spec.rb +92 -25
- metadata +3 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0620b97c9f91f8019da7ec0cb25086303d5a98c9eda18740e14c581acd8bcea
|
4
|
+
data.tar.gz: 35ca2d87cf4d58f1d8e8d174f8fe802c1e986ad5a6a6d13dc45125e2f4b9dfd6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c99794ef6ca381337f1be16465e1e97ac0656712608d69a7edbb5996213cca0cbe8c2558105e1543e0ef8760b7790dad9bed31b252b34cddd97d54b263be4d3
|
7
|
+
data.tar.gz: 51ca61be6991b07fd9f3b044bbd268893297bba14b59af561a2082983998e183548108e945cf113a9d0046055ced4f56600b0decc4fde38acb6730dd8295f951
|
data/lib/asciidoctor/iso/base.rb
CHANGED
@@ -91,6 +91,7 @@ module Asciidoctor
|
|
91
91
|
# then standard class (docid class other than DOI &c)
|
92
92
|
# then docnumber if present, numeric sort
|
93
93
|
# else alphanumeric metanorma id (abbreviation)
|
94
|
+
# then doc part number if present, numeric sort
|
94
95
|
# then doc id (not DOI &c)
|
95
96
|
# then title
|
96
97
|
def sort_biblio_key(bib)
|
@@ -99,12 +100,13 @@ module Asciidoctor
|
|
99
100
|
id = bib&.at("./docidentifier[not(#{OTHERIDS})]")
|
100
101
|
metaid = bib&.at("./docidentifier[@type = 'metanorma']")&.text
|
101
102
|
abbrid = metaid unless /^\[\d+\]$/.match(metaid)
|
103
|
+
/\d-(?<partid>\d+)/ =~ id&.text
|
102
104
|
type = id['type'] if id
|
103
105
|
title = bib&.at("./title[@type = 'main']")&.text ||
|
104
106
|
bib&.at("./title")&.text || bib&.at("./formattedref")&.text
|
105
107
|
"#{pubclass} :: #{type} :: "\
|
106
108
|
"#{num.nil? ? abbrid : sprintf("%09d", num.to_i)} :: "\
|
107
|
-
"#{id&.text} :: #{title}"
|
109
|
+
"#{partid} :: #{id&.text} :: #{title}"
|
108
110
|
end
|
109
111
|
end
|
110
112
|
end
|
@@ -73,6 +73,19 @@
|
|
73
73
|
</choice>
|
74
74
|
</element>
|
75
75
|
</define>
|
76
|
+
<define name="ul">
|
77
|
+
<element name="ul">
|
78
|
+
<attribute name="id">
|
79
|
+
<data type="ID"/>
|
80
|
+
</attribute>
|
81
|
+
<oneOrMore>
|
82
|
+
<ref name="ul_li"/>
|
83
|
+
</oneOrMore>
|
84
|
+
<zeroOrMore>
|
85
|
+
<ref name="note"/>
|
86
|
+
</zeroOrMore>
|
87
|
+
</element>
|
88
|
+
</define>
|
76
89
|
<define name="sections">
|
77
90
|
<element name="sections">
|
78
91
|
<ref name="clause"/>
|
@@ -325,6 +338,51 @@
|
|
325
338
|
</oneOrMore>
|
326
339
|
</choice>
|
327
340
|
</define>
|
341
|
+
<define name="table">
|
342
|
+
<element name="table">
|
343
|
+
<attribute name="id">
|
344
|
+
<data type="ID"/>
|
345
|
+
</attribute>
|
346
|
+
<optional>
|
347
|
+
<attribute name="width"/>
|
348
|
+
</optional>
|
349
|
+
<optional>
|
350
|
+
<attribute name="unnumbered">
|
351
|
+
<data type="boolean"/>
|
352
|
+
</attribute>
|
353
|
+
</optional>
|
354
|
+
<optional>
|
355
|
+
<attribute name="subsequence"/>
|
356
|
+
</optional>
|
357
|
+
<optional>
|
358
|
+
<attribute name="alt"/>
|
359
|
+
</optional>
|
360
|
+
<optional>
|
361
|
+
<attribute name="summary"/>
|
362
|
+
</optional>
|
363
|
+
<optional>
|
364
|
+
<attribute name="uri">
|
365
|
+
<data type="anyURI"/>
|
366
|
+
</attribute>
|
367
|
+
</optional>
|
368
|
+
<optional>
|
369
|
+
<ref name="tname"/>
|
370
|
+
</optional>
|
371
|
+
<optional>
|
372
|
+
<ref name="thead"/>
|
373
|
+
</optional>
|
374
|
+
<ref name="tbody"/>
|
375
|
+
<optional>
|
376
|
+
<ref name="tfoot"/>
|
377
|
+
</optional>
|
378
|
+
<zeroOrMore>
|
379
|
+
<ref name="table-note"/>
|
380
|
+
</zeroOrMore>
|
381
|
+
<optional>
|
382
|
+
<ref name="dl"/>
|
383
|
+
</optional>
|
384
|
+
</element>
|
385
|
+
</define>
|
328
386
|
</include>
|
329
387
|
<!-- end overrides -->
|
330
388
|
<!--
|
@@ -431,4 +489,26 @@
|
|
431
489
|
<ref name="Clause-Section"/>
|
432
490
|
</element>
|
433
491
|
</define>
|
492
|
+
<define name="ul_li">
|
493
|
+
<element name="li">
|
494
|
+
<optional>
|
495
|
+
<attribute name="id">
|
496
|
+
<data type="ID"/>
|
497
|
+
</attribute>
|
498
|
+
</optional>
|
499
|
+
<optional>
|
500
|
+
<attribute name="uncheckedcheckbox">
|
501
|
+
<data type="boolean"/>
|
502
|
+
</attribute>
|
503
|
+
</optional>
|
504
|
+
<optional>
|
505
|
+
<attribute name="checkedcheckbox">
|
506
|
+
<data type="boolean"/>
|
507
|
+
</attribute>
|
508
|
+
</optional>
|
509
|
+
<oneOrMore>
|
510
|
+
<ref name="paragraph-with-footnote"/>
|
511
|
+
</oneOrMore>
|
512
|
+
</element>
|
513
|
+
</define>
|
434
514
|
</grammar>
|
@@ -17,19 +17,19 @@ module Asciidoctor
|
|
17
17
|
title = c.at("./title")
|
18
18
|
location = c["id"] || c.text[0..60] + "..."
|
19
19
|
location += ":#{title.text}" if c["id"] && !title.nil?
|
20
|
-
|
20
|
+
@log.add("Style", nil, "#{location}: subclause is only child")
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
def isosubgroup_validate(root)
|
25
25
|
root.xpath("//technical-committee/@type").each do |t|
|
26
26
|
unless %w{TC PC JTC JPC}.include? t.text
|
27
|
-
|
27
|
+
@log.add("Document Attributes", nil, "invalid technical committee type #{t}")
|
28
28
|
end
|
29
29
|
end
|
30
30
|
root.xpath("//subcommittee/@type").each do |t|
|
31
31
|
unless %w{SC JSC}.include? t.text
|
32
|
-
|
32
|
+
@log.add("Document Attributes", nil, "invalid subcommittee type #{t}")
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -42,7 +42,7 @@ module Asciidoctor
|
|
42
42
|
next unless !preceding.nil? && /\b(see| refer to)\s*$/mi.match(preceding)
|
43
43
|
(target = root.at("//*[@id = '#{t['target']}']")) || next
|
44
44
|
if target&.at("./ancestor-or-self::*[@obligation = 'normative']")
|
45
|
-
|
45
|
+
@log.add("Style", t, "'see #{t['target']}' is pointing to a normative section")
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -53,12 +53,12 @@ module Asciidoctor
|
|
53
53
|
preceding = t.at("./preceding-sibling::text()[last()]")
|
54
54
|
next unless !preceding.nil? && /\b(see|refer to)\s*$/mi.match(preceding)
|
55
55
|
unless target = root.at("//*[@id = '#{t['bibitemid']}']")
|
56
|
-
|
56
|
+
@log.add("Bibliography", t, "'#{t} is not pointing to a real reference")
|
57
57
|
next
|
58
58
|
end
|
59
59
|
if target.at("./ancestor::references"\
|
60
60
|
"[title = 'Normative References']")
|
61
|
-
|
61
|
+
@log.add("Style", t, "'see #{t}' is pointing to a normative reference")
|
62
62
|
end
|
63
63
|
end
|
64
64
|
end
|
@@ -68,15 +68,15 @@ module Asciidoctor
|
|
68
68
|
root.xpath("//eref[locality]").each do |t|
|
69
69
|
if /^(ISO|IEC)/.match t["citeas"]
|
70
70
|
unless /:[ ]?(\d+{4}|–)$/.match t["citeas"]
|
71
|
-
|
72
|
-
"specific elements"
|
71
|
+
@log.add("Style", t, "undated reference #{t['citeas']} should not contain "\
|
72
|
+
"specific elements")
|
73
73
|
end
|
74
74
|
end
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def termdef_warn(text, re, term, msg)
|
79
|
-
re.match(text) &&
|
78
|
+
def termdef_warn(text, re, t, term, msg)
|
79
|
+
re.match(text) && @log.add("Style", t, "#{term}: #{msg}")
|
80
80
|
end
|
81
81
|
|
82
82
|
# ISO/IEC DIR 2, 16.5.6
|
@@ -84,9 +84,9 @@ module Asciidoctor
|
|
84
84
|
xmldoc.xpath("//term").each do |t|
|
85
85
|
para = t.at("./definition") || return
|
86
86
|
term = t.at("./preferred").text
|
87
|
-
termdef_warn(para.text, /^(the|a)\b/i, term,
|
87
|
+
termdef_warn(para.text, /^(the|a)\b/i, t, term,
|
88
88
|
"term definition starts with article")
|
89
|
-
termdef_warn(para.text, /\.$/i, term,
|
89
|
+
termdef_warn(para.text, /\.$/i, t, term,
|
90
90
|
"term definition ends with period")
|
91
91
|
end
|
92
92
|
cited_term_style(xmldoc)
|
@@ -107,31 +107,31 @@ module Asciidoctor
|
|
107
107
|
%w(international-standard technical-specification technical-report
|
108
108
|
publicly-available-specification international-workshop-agreement
|
109
109
|
guide).include? doctype or
|
110
|
-
|
110
|
+
@log.add("Document Attributes", nil, "#{doctype} is not a recognised document type")
|
111
111
|
end
|
112
112
|
|
113
113
|
def script_validate(xmldoc)
|
114
114
|
script = xmldoc&.at("//bibdata/script")&.text
|
115
115
|
script == "Latn" or
|
116
|
-
|
116
|
+
@log.add("Document Attributes", nil, "#{script} is not a recognised script")
|
117
117
|
end
|
118
118
|
|
119
119
|
def stage_validate(xmldoc)
|
120
120
|
stage = xmldoc&.at("//bibdata/status/stage")&.text
|
121
121
|
%w(00 10 20 30 40 50 60 90 95).include? stage or
|
122
|
-
|
122
|
+
@log.add("Document Attributes", nil, "#{stage} is not a recognised stage")
|
123
123
|
end
|
124
124
|
|
125
125
|
def substage_validate(xmldoc)
|
126
126
|
substage = xmldoc&.at("//bibdata/status/substage")&.text or return
|
127
127
|
%w(00 20 60 90 92 93 98 99).include? substage or
|
128
|
-
|
128
|
+
@log.add("Document Attributes", nil, "#{substage} is not a recognised substage")
|
129
129
|
end
|
130
130
|
|
131
131
|
def iteration_validate(xmldoc)
|
132
132
|
iteration = xmldoc&.at("//bibdata/status/iteration")&.text or return
|
133
133
|
/^\d+/.match(iteration) or
|
134
|
-
|
134
|
+
@log.add("Document Attributes", nil, "#{iteration} is not a recognised iteration")
|
135
135
|
end
|
136
136
|
|
137
137
|
def bibdata_validate(doc)
|
@@ -163,8 +163,8 @@ module Asciidoctor
|
|
163
163
|
found = true if /^ISO DATE:/.match n.text
|
164
164
|
end
|
165
165
|
found or
|
166
|
-
|
167
|
-
"associated footnote indicating unpublished status"
|
166
|
+
@log.add("Style", b, "Reference #{b&.at("./@id")&.text} does not have an "\
|
167
|
+
"associated footnote indicating unpublished status")
|
168
168
|
end
|
169
169
|
end
|
170
170
|
|
@@ -17,29 +17,29 @@ module Asciidoctor
|
|
17
17
|
def foreword_validate(root)
|
18
18
|
f = root.at("//foreword") || return
|
19
19
|
s = f.at("./clause")
|
20
|
-
|
20
|
+
@log.add("Style", f, "foreword contains subclauses") unless s.nil?
|
21
21
|
end
|
22
22
|
|
23
23
|
# ISO/IEC DIR 2, 15.4
|
24
24
|
def normref_validate(root)
|
25
25
|
f = root.at("//references[title = 'Normative References']") || return
|
26
26
|
f.at("./references | ./clause") &&
|
27
|
-
|
27
|
+
@log.add("Style", f, "normative references contains subclauses")
|
28
28
|
end
|
29
29
|
|
30
|
-
ONE_SYMBOLS_WARNING = "
|
30
|
+
ONE_SYMBOLS_WARNING = "Only one Symbols and Abbreviated "\
|
31
31
|
"Terms section in the standard".freeze
|
32
32
|
|
33
|
-
NON_DL_SYMBOLS_WARNING = "
|
33
|
+
NON_DL_SYMBOLS_WARNING = "Symbols and Abbreviated Terms can "\
|
34
34
|
"only contain a definition list".freeze
|
35
35
|
|
36
36
|
def symbols_validate(root)
|
37
37
|
f = root.xpath("//definitions")
|
38
38
|
f.empty? && return
|
39
|
-
(f.size == 1) ||
|
39
|
+
(f.size == 1) || @log.add("Style", f.first, ONE_SYMBOLS_WARNING)
|
40
40
|
f.first.elements.each do |e|
|
41
41
|
unless e.name == "dl"
|
42
|
-
|
42
|
+
@log.add("Style", f.first, NON_DL_SYMBOLS_WARNING)
|
43
43
|
return
|
44
44
|
end
|
45
45
|
end
|
@@ -48,7 +48,7 @@ module Asciidoctor
|
|
48
48
|
def seqcheck(names, msg, accepted)
|
49
49
|
n = names.shift
|
50
50
|
unless accepted.include? n
|
51
|
-
|
51
|
+
@log.add("Style", nil, msg)
|
52
52
|
names = []
|
53
53
|
end
|
54
54
|
names
|
@@ -109,46 +109,46 @@ module Asciidoctor
|
|
109
109
|
n = names.shift || return
|
110
110
|
end
|
111
111
|
unless n
|
112
|
-
|
112
|
+
@log.add("Style", nil, "Document must contain at least one clause")
|
113
113
|
return
|
114
114
|
end
|
115
115
|
n[:tag] == "clause" ||
|
116
|
-
|
116
|
+
@log.add("Style", nil, "Document must contain clause after "\
|
117
117
|
"Terms and Definitions")
|
118
118
|
n == { tag: "clause", title: "Scope" } &&
|
119
|
-
|
119
|
+
@log.add("Style", nil, "Scope must occur before Terms and Definitions")
|
120
120
|
n = names.shift || return
|
121
121
|
while n[:tag] == "clause"
|
122
122
|
n[:title] == "Scope" &&
|
123
|
-
|
123
|
+
@log.add("Style", nil, "Scope must occur before Terms and Definitions")
|
124
124
|
n = names.shift || return
|
125
125
|
end
|
126
126
|
unless n[:tag] == "annex" || n[:tag] == "references"
|
127
|
-
|
127
|
+
@log.add("Style", nil, "Only annexes and references can follow clauses")
|
128
128
|
end
|
129
129
|
while n[:tag] == "annex"
|
130
130
|
n = names.shift
|
131
131
|
if n.nil?
|
132
|
-
|
132
|
+
@log.add("Style", nil, "Document must include (references) "\
|
133
133
|
"Normative References")
|
134
134
|
return
|
135
135
|
end
|
136
136
|
end
|
137
137
|
n == { tag: "references", title: "Normative References" } ||
|
138
|
-
|
138
|
+
@log.add("Style", nil, "Document must include (references) "\
|
139
139
|
"Normative References")
|
140
140
|
n = names.shift
|
141
141
|
n == { tag: "references", title: "Bibliography" } ||
|
142
|
-
|
142
|
+
@log.add("Style", nil, "Final section must be (references) Bibliography")
|
143
143
|
names.empty? ||
|
144
|
-
|
144
|
+
@log.add("Style", nil, "There are sections after the final Bibliography")
|
145
145
|
end
|
146
146
|
|
147
147
|
def style_warning(node, msg, text = nil)
|
148
148
|
return if @novalid
|
149
|
-
w =
|
149
|
+
w = msg
|
150
150
|
w += ": #{text}" if text
|
151
|
-
|
151
|
+
@log.add("Style", node, w)
|
152
152
|
end
|
153
153
|
|
154
154
|
NORM_ISO_WARN = "non-ISO/IEC reference not expected as normative".freeze
|
@@ -174,7 +174,7 @@ module Asciidoctor
|
|
174
174
|
def norm_bibitem_style(root)
|
175
175
|
root.xpath(NORM_BIBITEMS).each do |b|
|
176
176
|
if b.at(Standoc::Converter::ISO_PUBLISHER_XPATH).nil?
|
177
|
-
|
177
|
+
@log.add("Style", b, "#{NORM_ISO_WARN}: #{b.text}")
|
178
178
|
end
|
179
179
|
end
|
180
180
|
end
|
@@ -7,10 +7,10 @@ module Asciidoctor
|
|
7
7
|
title_intro_en = root.at("//title[@type='title-intro' and @language='en']")
|
8
8
|
title_intro_fr = root.at("//title[@type='title-intro' and @language='fr']")
|
9
9
|
if title_intro_en.nil? && !title_intro_fr.nil?
|
10
|
-
|
10
|
+
@log.add("Style", title_intro_fr, "No English Title Intro!")
|
11
11
|
end
|
12
12
|
if !title_intro_en.nil? && title_intro_fr.nil?
|
13
|
-
|
13
|
+
@log.add("Style", title_intro_en, "No French Title Intro!")
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -18,10 +18,10 @@ module Asciidoctor
|
|
18
18
|
title_main_en = root.at("//title[@type='title-main' and @language='en']")
|
19
19
|
title_main_fr = root.at("//title[@type='title-main' and @language='fr']")
|
20
20
|
if title_main_en.nil? && !title_main_fr.nil?
|
21
|
-
|
21
|
+
@log.add("Style", title_main_fr, "No English Title!")
|
22
22
|
end
|
23
23
|
if !title_main_en.nil? && title_main_fr.nil?
|
24
|
-
|
24
|
+
@log.add("Style", title_main_en, "No French Title!")
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -29,9 +29,9 @@ module Asciidoctor
|
|
29
29
|
title_part_en = root.at("//title[@type='title-part' and @language='en']")
|
30
30
|
title_part_fr = root.at("//title[@type='title-part' and @language='fr']")
|
31
31
|
(title_part_en.nil? && !title_part_fr.nil?) &&
|
32
|
-
|
32
|
+
@log.add("Style", title_part_fr, "No English Title Part!")
|
33
33
|
(!title_part_en.nil? && title_part_fr.nil?) &&
|
34
|
-
|
34
|
+
@log.add("Style", title_part_en, "No French Title Part!")
|
35
35
|
end
|
36
36
|
|
37
37
|
# ISO/IEC DIR 2, 11.4
|
@@ -41,7 +41,7 @@ module Asciidoctor
|
|
41
41
|
iec = root.at("//bibdata/contributor[role/@type = 'publisher']/"\
|
42
42
|
"organization[abbreviation = 'IEC' or "\
|
43
43
|
"name = 'International Electrotechnical Commission']")
|
44
|
-
|
44
|
+
@log.add("Style", docid, "Subpart defined on non-IEC document!") if subpart && !iec
|
45
45
|
end
|
46
46
|
|
47
47
|
# ISO/IEC DIR 2, 11.5.2
|
@@ -50,11 +50,11 @@ module Asciidoctor
|
|
50
50
|
Publicly\sAvailable\sSpecification | Technical\sReport | Guide /xi
|
51
51
|
title_main_en = root.at("//title[@type='title-main' and @language='en']")
|
52
52
|
if !title_main_en.nil? && doctypes.match(title_main_en.text)
|
53
|
-
|
53
|
+
@log.add("Style", title_main_en, "Main Title may name document type")
|
54
54
|
end
|
55
55
|
title_intro_en = root.at("//title[@type='title-intro' and @language='en']")
|
56
56
|
if !title_intro_en.nil? && doctypes.match(title_intro_en.text)
|
57
|
-
|
57
|
+
@log.add("Style", title_intro_en, "Title Intro may name document type")
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -65,7 +65,7 @@ module Asciidoctor
|
|
65
65
|
s.xpath("./clause | ./terms | ./references").each do |ss|
|
66
66
|
subtitle = ss.at("./title")
|
67
67
|
!subtitle.nil? && !subtitle&.text&.empty? ||
|
68
|
-
|
68
|
+
@log.add("Style", ss, "#{title}: each first-level subclause must have a title")
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -82,7 +82,7 @@ module Asciidoctor
|
|
82
82
|
withtitle = withtitle || (subtitle && !subtitle.text.empty?)
|
83
83
|
end
|
84
84
|
notitle && withtitle &&
|
85
|
-
|
85
|
+
@log.add("Style", nil, "#{label}: all subclauses must have a title, or none")
|
86
86
|
end
|
87
87
|
|
88
88
|
def title_validate(root)
|