asciidoctor-iso 0.6.0 → 0.6.1
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/Gemfile.lock +7 -10
- data/README.adoc +118 -6
- data/asciidoctor-iso.gemspec +1 -4
- data/lib/asciidoctor-iso.rb +2 -0
- data/lib/asciidoctor/iso/base.rb +20 -95
- data/lib/asciidoctor/iso/blocks.rb +47 -39
- data/lib/asciidoctor/iso/cleanup.rb +25 -97
- data/lib/asciidoctor/iso/cleanup_block.rb +10 -1
- data/lib/asciidoctor/iso/cleanup_ref.rb +100 -0
- data/lib/asciidoctor/iso/converter.rb +5 -2
- data/lib/asciidoctor/iso/front.rb +52 -24
- data/lib/asciidoctor/iso/html/header.html +10 -10
- data/lib/asciidoctor/iso/html/html_iso_intro.html +1 -1
- data/lib/asciidoctor/iso/html/html_iso_titlepage.html +5 -5
- data/lib/asciidoctor/iso/html/htmlstyle.css +0 -21
- data/lib/asciidoctor/iso/html/isodoc.css +13 -28
- data/lib/asciidoctor/iso/html/word_iso_intro.html +2 -2
- data/lib/asciidoctor/iso/html/word_iso_titlepage.html +7 -7
- data/lib/asciidoctor/iso/html/wordstyle.css +998 -0
- data/lib/asciidoctor/iso/inline.rb +128 -0
- data/lib/asciidoctor/iso/isodoc.rng +1516 -0
- data/lib/asciidoctor/iso/isostandard.rnc +38 -39
- data/lib/asciidoctor/iso/isostandard.rng +529 -1276
- data/lib/asciidoctor/iso/isostandard_diff.rnc +40 -56
- data/lib/asciidoctor/iso/lists.rb +30 -28
- data/lib/asciidoctor/iso/macros.rb +37 -0
- data/lib/asciidoctor/iso/section.rb +1 -1
- data/lib/asciidoctor/iso/utils.rb +9 -0
- data/lib/asciidoctor/iso/validate.rb +41 -120
- data/lib/asciidoctor/iso/validate_section.rb +117 -0
- data/lib/asciidoctor/iso/validate_style.rb +5 -7
- data/lib/asciidoctor/iso/version.rb +1 -1
- data/spec/examples/rice.adoc +41 -8
- data/spec/examples/rice.doc +2885 -2859
- data/spec/examples/rice.html +316 -649
- data/spec/examples/rice.preview.html +51 -10
- data/spec/examples/rice.xml +418 -343
- metadata +12 -50
- data/lib/asciidoctor/iso/inline_anchor.rb +0 -59
- data/lib/asciidoctor/iso/validate.make.sh +0 -8
@@ -6,23 +6,15 @@ start = iso-standard
|
|
6
6
|
|
7
7
|
iso-standard =
|
8
8
|
element iso-standard {
|
9
|
-
title+,
|
10
|
-
|
11
|
-
creator,
|
12
|
-
language,
|
13
|
-
script,
|
14
|
-
type,
|
15
|
-
id,
|
16
|
-
version?,
|
17
|
-
copyright,
|
18
|
-
sections
|
9
|
+
#title+, status, creator, language, script, type, id, version?, copyright, sections
|
10
|
+
bibdata, version?, sections+
|
19
11
|
}
|
20
12
|
|
21
13
|
language =
|
22
14
|
element language { ( "en" | "fr" ) }
|
23
15
|
|
24
16
|
script =
|
25
|
-
element script { "
|
17
|
+
element script { "Latn" }
|
26
18
|
|
27
19
|
# draft into isodoc? To replace version/version?
|
28
20
|
version =
|
@@ -34,44 +26,47 @@ version =
|
|
34
26
|
|
35
27
|
draft = element draft {text}
|
36
28
|
|
37
|
-
|
38
|
-
|
39
|
-
|
29
|
+
# TODO to docidentifier
|
30
|
+
#id =
|
31
|
+
#element id {
|
32
|
+
#documentnumber,
|
33
|
+
#tc-documentnumber?
|
34
|
+
#}
|
35
|
+
|
36
|
+
# add type to docidentifier in isodoc?
|
37
|
+
docidentifier =
|
38
|
+
element docidentifier {
|
39
|
+
( text | documentnumber | tc-documentnumber )
|
40
40
|
}
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
# TODO to orgname
|
43
|
+
#creator =
|
44
|
+
#element creator {
|
45
|
+
#attribute role { text },
|
46
|
+
#technical-committee,
|
47
|
+
#subcommittee?,
|
48
|
+
#workgroup?,
|
49
|
+
#secretariat?
|
50
|
+
#}
|
51
|
+
|
52
|
+
organization =
|
53
|
+
element organization {
|
54
|
+
orgname, uri?, org-identifier*, contact*,
|
55
|
+
technical-committee?, subcommittee?, workgroup?, secretariat?
|
45
56
|
}
|
46
57
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
}
|
54
|
-
|
55
|
-
creator =
|
56
|
-
element creator {
|
57
|
-
attribute role { text },
|
58
|
-
technical-committee,
|
59
|
-
subcommittee?,
|
60
|
-
workgroup?,
|
61
|
-
secretariat?
|
62
|
-
}
|
63
|
-
|
64
|
-
type =
|
65
|
-
element type {
|
66
|
-
( "international-standard" | "technical-specification" |
|
67
|
-
"technical-report" | "publicly-available-specification" |
|
68
|
-
"international-workshop-agreement" | "guide" )
|
69
|
-
}
|
58
|
+
# Do not constrain in XML: add to validation
|
59
|
+
# type =
|
60
|
+
# element type {
|
61
|
+
# ( "international-standard" | "technical-specification" |
|
62
|
+
# "technical-report" | "publicly-available-specification" |
|
63
|
+
# "international-workshop-agreement" | "guide" )
|
64
|
+
# }
|
70
65
|
|
71
66
|
status =
|
72
67
|
element status {
|
73
|
-
|
74
|
-
substage?
|
68
|
+
FormattedString |
|
69
|
+
( stage, substage? )
|
75
70
|
}
|
76
71
|
|
77
72
|
stage =
|
@@ -116,10 +111,10 @@ workgroup =
|
|
116
111
|
secretariat =
|
117
112
|
element secretariat { text }
|
118
113
|
|
119
|
-
|
114
|
+
btitle =
|
120
115
|
element title {
|
121
|
-
|
122
|
-
title-intro?, title-main, title-part?
|
116
|
+
text |
|
117
|
+
( title-intro?, title-main, title-part? )
|
123
118
|
}
|
124
119
|
|
125
120
|
title-intro =
|
@@ -279,17 +274,6 @@ Clause-Section =
|
|
279
274
|
clause-subsection+
|
280
275
|
)
|
281
276
|
|
282
|
-
|
283
|
-
BibliographicItem =
|
284
|
-
attribute id { xsd:ID },
|
285
|
-
attribute type { "article" | "book" | "booklet" | "conference" | "manual" |
|
286
|
-
"proceedings" | "presentation" | "thesis" | "techreport" |
|
287
|
-
"standard" | "unpublished" }?,
|
288
|
-
(bname | formatted), source?, publishdate?, docidentifier*, accesseddate?, creator*,
|
289
|
-
publisher*, edition?,
|
290
|
-
biblionote*, partof*, creationdate?, language*, script*, abstract?
|
291
|
-
|
292
|
-
|
293
277
|
# }
|
294
278
|
|
295
279
|
|
@@ -7,12 +7,12 @@ module Asciidoctor
|
|
7
7
|
style(item, item.text)
|
8
8
|
if item.blocks?
|
9
9
|
xml_li.p **id_attr(item) do |t|
|
10
|
-
t << item.text
|
10
|
+
t << item.text
|
11
11
|
end
|
12
12
|
xml_li << item.content
|
13
13
|
else
|
14
14
|
xml_li.p **id_attr(item) do |p|
|
15
|
-
p << item.text
|
15
|
+
p << item.text
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -31,40 +31,41 @@ module Asciidoctor
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def iso_publisher(t)
|
34
|
-
t.
|
35
|
-
|
34
|
+
t.contributor do |c|
|
35
|
+
c.role **{ type: "publisher" }
|
36
|
+
c.organization do |aff|
|
36
37
|
aff.name "ISO"
|
37
38
|
end
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
41
|
-
def isorefmatches(xml,
|
42
|
-
ref_attributes = { id:
|
42
|
+
def isorefmatches(xml, m)
|
43
|
+
ref_attributes = { id: m[:anchor], type: "standard" }
|
43
44
|
xml.bibitem **attr_code(ref_attributes) do |t|
|
44
|
-
t.
|
45
|
-
t.
|
46
|
-
t.
|
45
|
+
t.title **{ format: "text/plain" } { |i| i << ref_normalise(m[:text]) }
|
46
|
+
t.docidentifier m[:code]
|
47
|
+
t.date m[:year], { type: "published" } if m[:year]
|
47
48
|
iso_publisher(t)
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
51
|
-
def isorefmatches2(xml,
|
52
|
-
ref_attributes = { id:
|
52
|
+
def isorefmatches2(xml, m)
|
53
|
+
ref_attributes = { id: m[:anchor], type: "standard" }
|
53
54
|
xml.bibitem **attr_code(ref_attributes) do |t|
|
54
|
-
t.
|
55
|
-
t.
|
56
|
-
t.
|
55
|
+
t.title **{ format: "text/plain" } { |i| i << ref_normalise(m[:text]) }
|
56
|
+
t.docidentifier m[:code]
|
57
|
+
t.date "--", { type: "published" }
|
57
58
|
iso_publisher(t)
|
58
|
-
t.note { |p| p << "ISO DATE: #{
|
59
|
+
t.note **{ format: "text/plain" } { |p| p << "ISO DATE: #{m[:fn]}" }
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
62
|
-
def isorefmatches3(xml,
|
63
|
-
ref_attributes = { id:
|
63
|
+
def isorefmatches3(xml, m)
|
64
|
+
ref_attributes = { id: m[:anchor], type: "standard" }
|
64
65
|
xml.bibitem **attr_code(ref_attributes) do |t|
|
65
|
-
t.
|
66
|
-
t.
|
67
|
-
t.
|
66
|
+
t.title **{ format: "text/plain" } { |i| i << ref_normalise(m[:text]) }
|
67
|
+
t.docidentifier "#{m[:code]}:All Parts"
|
68
|
+
t.date m[:year], { type: "published" } if m[:year]
|
68
69
|
iso_publisher(t)
|
69
70
|
end
|
70
71
|
end
|
@@ -74,7 +75,9 @@ module Asciidoctor
|
|
74
75
|
if m.nil? then Utils::warning(node, "no anchor on reference", item)
|
75
76
|
else
|
76
77
|
xml.bibitem **attr_code(id: m[:anchor]) do |t|
|
77
|
-
t.
|
78
|
+
t.formattedref **{ format: "application/x-isodoc+xml" } do |i|
|
79
|
+
i << ref_normalise_no_format(m[:text])
|
80
|
+
end
|
78
81
|
code = m[:code]
|
79
82
|
code = "[#{code}]" if /^\d+$?/.match? code
|
80
83
|
t.docidentifier code
|
@@ -96,15 +99,15 @@ module Asciidoctor
|
|
96
99
|
end
|
97
100
|
|
98
101
|
ISO_REF = %r{^<ref\sid="(?<anchor>[^"]+)">
|
99
|
-
\[
|
102
|
+
\[(?<code>(ISO|IEC)[^0-9]*\s[0-9-]+)(:(?<year>[0-9]+))?\]</ref>,?\s
|
100
103
|
(?<text>.*)$}xm
|
101
104
|
|
102
105
|
ISO_REF_NO_YEAR = %r{^<ref\sid="(?<anchor>[^"]+)">
|
103
|
-
\[
|
106
|
+
\[(?<code>(ISO|IEC)[^0-9]*\s[0-9-]+):--\]</ref>,?\s?
|
104
107
|
<fn[^>]*>\s*<p>(?<fn>[^\]]+)</p>\s*</fn>,?\s?(?<text>.*)$}xm
|
105
108
|
|
106
109
|
ISO_REF_ALL_PARTS = %r{^<ref\sid="(?<anchor>[^"]+)">
|
107
|
-
\[
|
110
|
+
\[(?<code>(ISO|IEC)[^0-9]*\s[0-9]+)\s\(all\sparts\)\]</ref>(<p>)?,?\s?
|
108
111
|
(?<text>.*)(</p>)?$}xm
|
109
112
|
|
110
113
|
NON_ISO_REF = %r{^<ref\sid="(?<anchor>[^"]+)">
|
@@ -122,9 +125,8 @@ module Asciidoctor
|
|
122
125
|
elsif !matched3.nil? then isorefmatches3(xml, matched3)
|
123
126
|
end
|
124
127
|
if matched3.nil? && matched2.nil? && matched.nil? && normative
|
125
|
-
|
126
|
-
|
127
|
-
item)
|
128
|
+
w = "non-ISO/IEC reference not expected as normative"
|
129
|
+
Utils::warning(node, w, item)
|
128
130
|
end
|
129
131
|
end
|
130
132
|
|
@@ -169,7 +171,7 @@ module Asciidoctor
|
|
169
171
|
return
|
170
172
|
end
|
171
173
|
xml_dl.dd do |xml_dd|
|
172
|
-
style(dd, dd.text)
|
174
|
+
style(dd, dd.text) if dd.text?
|
173
175
|
xml_dd.p { |t| t << dd.text } if dd.text?
|
174
176
|
xml_dd << dd.content if dd.blocks?
|
175
177
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'asciidoctor/extensions'
|
2
|
+
module Asciidoctor
|
3
|
+
module ISO
|
4
|
+
class AltTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
5
|
+
use_dsl
|
6
|
+
named :alt
|
7
|
+
parse_content_as :text
|
8
|
+
using_format :short
|
9
|
+
|
10
|
+
def process parent, target, attrs
|
11
|
+
%{<admitted>#{Asciidoctor::Inline.new(parent, :quoted, attrs['text']).convert}</admitted>}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class DeprecatedTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
16
|
+
use_dsl
|
17
|
+
named :deprecated
|
18
|
+
parse_content_as :text
|
19
|
+
using_format :short
|
20
|
+
|
21
|
+
def process parent, target, attrs
|
22
|
+
%{<deprecates>#{attrs["text"]}</deprecates>}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class DomainTermInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
27
|
+
use_dsl
|
28
|
+
named :domain
|
29
|
+
parse_content_as :text
|
30
|
+
using_format :short
|
31
|
+
|
32
|
+
def process parent, target, attrs
|
33
|
+
%{<domain>#{attrs["text"]}</domain>}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -131,7 +131,7 @@ module Asciidoctor
|
|
131
131
|
end
|
132
132
|
|
133
133
|
def introduction_parse(attrs, xml, node)
|
134
|
-
xml.
|
134
|
+
xml.introduction **attr_code(attrs) do |xml_section|
|
135
135
|
xml_section.title = "Introduction"
|
136
136
|
content = node.content
|
137
137
|
xml_section << content
|
@@ -97,6 +97,15 @@ module Asciidoctor
|
|
97
97
|
end.to_h
|
98
98
|
end
|
99
99
|
|
100
|
+
# if the contents of node are blocks, output them to out;
|
101
|
+
# else, wrap them in <p>
|
102
|
+
def wrap_in_para(node, out)
|
103
|
+
if node.blocks? then out << node.content
|
104
|
+
else
|
105
|
+
out.p { |p| p << node.content }
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
100
109
|
end
|
101
110
|
end
|
102
111
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "asciidoctor/iso/utils"
|
2
|
-
require_relative
|
2
|
+
require_relative "./validate_style.rb"
|
3
|
+
require_relative "./validate_section.rb"
|
3
4
|
require "nokogiri"
|
4
5
|
require "jing"
|
5
6
|
require "pp"
|
@@ -7,10 +8,9 @@ require "pp"
|
|
7
8
|
module Asciidoctor
|
8
9
|
module ISO
|
9
10
|
module Validate
|
10
|
-
|
11
11
|
def title_intro_validate(root)
|
12
|
-
title_intro_en = root.at("//title[@language='en']
|
13
|
-
title_intro_fr = root.at("//title[@language='fr']
|
12
|
+
title_intro_en = root.at("//title-intro[@language='en']")
|
13
|
+
title_intro_fr = root.at("//title-intro[@language='fr']")
|
14
14
|
if title_intro_en.nil? && !title_intro_fr.nil?
|
15
15
|
warn "No English Title Intro!"
|
16
16
|
end
|
@@ -20,8 +20,8 @@ module Asciidoctor
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def title_part_validate(root)
|
23
|
-
title_part_en = root.at("//title[@language='en']
|
24
|
-
title_part_fr = root.at("//title[@language='fr']
|
23
|
+
title_part_en = root.at("//title-part[@language='en']")
|
24
|
+
title_part_fr = root.at("//title-part[@language='fr']")
|
25
25
|
if title_part_en.nil? && !title_part_fr.nil?
|
26
26
|
warn "No English Title Part!"
|
27
27
|
end
|
@@ -33,11 +33,11 @@ module Asciidoctor
|
|
33
33
|
def title_names_type_validate(root)
|
34
34
|
doctypes = /International\sStandard | Technical\sSpecification |
|
35
35
|
Publicly\sAvailable\sSpecification | Technical\sReport | Guide /xi
|
36
|
-
title_main_en = root.at("//title[@language='en']
|
36
|
+
title_main_en = root.at("//title-main[@language='en']")
|
37
37
|
if doctypes.match? title_main_en.text
|
38
38
|
warn "Main Title may name document type"
|
39
39
|
end
|
40
|
-
title_intro_en = root.at("//title[@language='en']
|
40
|
+
title_intro_en = root.at("//title-intro[@language='en']")
|
41
41
|
if !title_intro_en.nil? && doctypes.match?(title_intro_en.text)
|
42
42
|
warn "Part Title may name document type"
|
43
43
|
end
|
@@ -54,121 +54,12 @@ module Asciidoctor
|
|
54
54
|
root.xpath(q).each do |c|
|
55
55
|
next unless c.xpath("../subsection").size == 1
|
56
56
|
title = c.at("./title")
|
57
|
-
location =
|
58
|
-
|
59
|
-
else
|
60
|
-
c["id"]
|
61
|
-
end
|
62
|
-
location += ":#{title.text}" unless title.nil?
|
57
|
+
location = c["id"] || c.text[0..60] + "..."
|
58
|
+
location += ":#{title.text}" if c["id"] && !title.nil?
|
63
59
|
warn "ISO style: #{location}: subsection is only child"
|
64
60
|
end
|
65
61
|
end
|
66
62
|
|
67
|
-
def foreword_validate(root)
|
68
|
-
f = root.at("//content[title = 'Foreword']")
|
69
|
-
s = f.at("./subsection")
|
70
|
-
warn "ISO style: foreword contains subsections" unless s.nil?
|
71
|
-
end
|
72
|
-
|
73
|
-
def normref_validate(root)
|
74
|
-
f = root.at("//references[title = 'Normative References']")
|
75
|
-
f.at("./references") and
|
76
|
-
warn "ISO style: normative references contains subsections"
|
77
|
-
end
|
78
|
-
|
79
|
-
def symbols_validate(root)
|
80
|
-
f = root.at("//clause[title = 'Symbols and Abbreviations']")
|
81
|
-
return if f.nil?
|
82
|
-
f.elements do |e|
|
83
|
-
unless e.name == "dl"
|
84
|
-
warn "ISO style: Symbols and Abbreviations can only contain "\
|
85
|
-
"a definition list"
|
86
|
-
return
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def seqcheck(names, msg, accepted)
|
92
|
-
n = names.shift
|
93
|
-
unless accepted.include? n
|
94
|
-
warn "ISO style: #{msg}"
|
95
|
-
names = []
|
96
|
-
end
|
97
|
-
names
|
98
|
-
end
|
99
|
-
|
100
|
-
# spec of permissible section sequence
|
101
|
-
SEQ = [
|
102
|
-
{
|
103
|
-
msg: "Initial section must be (content) Foreword",
|
104
|
-
val: [{ tag: "content", title: "Foreword" }],
|
105
|
-
},
|
106
|
-
{
|
107
|
-
msg: "Prefatory material must be followed by (clause) Scope",
|
108
|
-
val: [{ tag: "content", title: "Introduction" },
|
109
|
-
{ tag: "clause", title: "Scope" }],
|
110
|
-
},
|
111
|
-
{
|
112
|
-
msg: "Prefatory material must be followed by (clause) Scope",
|
113
|
-
val: [{ tag: "clause", title: "Scope" }],
|
114
|
-
},
|
115
|
-
{
|
116
|
-
msg: "Scope must be followed by Normative References",
|
117
|
-
val: [{ tag: "references", title: "Normative References" }]
|
118
|
-
},
|
119
|
-
{
|
120
|
-
msg: "Normative References must be followed by "\
|
121
|
-
"Terms and Definitions",
|
122
|
-
val: [
|
123
|
-
{ tag: "terms", title: "Terms and Definitions" },
|
124
|
-
{ tag: "terms",
|
125
|
-
title: "Terms, Definitions, Symbols and Abbreviations" }
|
126
|
-
]
|
127
|
-
},
|
128
|
-
]
|
129
|
-
|
130
|
-
def sections_sequence_validate(root)
|
131
|
-
f = root.xpath(" //sections/content | //sections/terms | "\
|
132
|
-
"//sections/clause | //sections/references | "\
|
133
|
-
"//sections/annex")
|
134
|
-
names = f.map { |s| { tag: s.name, title: s.at("./title").text } }
|
135
|
-
names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val]) or return
|
136
|
-
n = names[0]
|
137
|
-
names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val]) or return
|
138
|
-
if n == { tag: "content", title: "Introduction" }
|
139
|
-
names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val]) or return
|
140
|
-
end
|
141
|
-
names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val]) or return
|
142
|
-
names = seqcheck(names, SEQ[4][:msg], SEQ[4][:val]) or return
|
143
|
-
n = names.shift
|
144
|
-
if n == { tag: "clause", title: "Symbols and Abbreviations" }
|
145
|
-
n = names.shift or return
|
146
|
-
end
|
147
|
-
n[:tag] == "clause" or
|
148
|
-
warn "ISO style: Document must contain at least one clause"
|
149
|
-
n == { tag: "clause", title: "Scope" } and
|
150
|
-
warn "ISO style: Scope must occur before Terms and Definitions"
|
151
|
-
n = names.shift or return
|
152
|
-
while n[:tag] == "clause"
|
153
|
-
n[:title] == "Scope" and
|
154
|
-
warn "ISO style: Scope must occur before Terms and Definitions"
|
155
|
-
n[:title] == "Symbols and Abbreviations" and
|
156
|
-
warn "ISO style: Symbols and Abbreviations must occur "\
|
157
|
-
"right after Terms and Definitions"
|
158
|
-
n = names.shift or return
|
159
|
-
end
|
160
|
-
unless n[:tag] == "annex" or n[:tag] == "references"
|
161
|
-
warn "ISO style: Only annexes and references can follow clauses"
|
162
|
-
end
|
163
|
-
while n[:tag] == "annex"
|
164
|
-
n = names.shift or return
|
165
|
-
end
|
166
|
-
n == { tag: "references", title: "Bibliography" } or
|
167
|
-
warn "ISO style: Final section must be (references) Bibliography"
|
168
|
-
names.empty? or
|
169
|
-
warn "ISO style: There are sections after the final Bibliography"
|
170
|
-
end
|
171
|
-
|
172
63
|
def iso8601_validate(root)
|
173
64
|
root.xpath("//review/@date | //revision-date").each do |d|
|
174
65
|
/^\d{8}(T\d{4,6})?$/.match? d.text or
|
@@ -176,8 +67,22 @@ module Asciidoctor
|
|
176
67
|
end
|
177
68
|
end
|
178
69
|
|
70
|
+
def isosubgroup_validate(root)
|
71
|
+
root.xpath("//technical-committee/@type").each do |t|
|
72
|
+
unless %w{TC PC JTC JPC}.include? t.text
|
73
|
+
warn "ISO: invalid technical committee type #{t}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
root.xpath("//subcommittee/@type").each do |t|
|
77
|
+
unless %w{SC JSC}.include? t.text
|
78
|
+
warn "ISO: invalid subcommittee type #{t}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
179
83
|
def content_validate(doc)
|
180
84
|
title_validate(doc.root)
|
85
|
+
isosubgroup_validate(doc.root)
|
181
86
|
foreword_validate(doc.root)
|
182
87
|
normref_validate(doc.root)
|
183
88
|
symbols_validate(doc.root)
|
@@ -199,9 +104,25 @@ module Asciidoctor
|
|
199
104
|
end
|
200
105
|
end
|
201
106
|
|
107
|
+
# RelaxNG cannot cope well with wildcard attributes. So we strip
|
108
|
+
# any attributes from FormattedString instances (which can contain
|
109
|
+
# xs:any markup, and are signalled with @format) before validation.
|
110
|
+
def formattedstr_strip(doc)
|
111
|
+
doc.xpath("//*[@format]").each do |n|
|
112
|
+
n.elements.each do |e|
|
113
|
+
e.traverse do |e1|
|
114
|
+
next unless e1.element?
|
115
|
+
e1.each { |k, v| e.delete(k) }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
doc
|
120
|
+
end
|
121
|
+
|
202
122
|
def validate(doc)
|
203
123
|
content_validate(doc)
|
204
|
-
schema_validate(doc
|
124
|
+
schema_validate(formattedstr_strip(doc.dup),
|
125
|
+
File.join(File.dirname(__FILE__), "isostandard.rng"))
|
205
126
|
end
|
206
127
|
end
|
207
128
|
end
|