asciidoctor-iso 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|