metanorma-ietf 2.3.5 → 2.4.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/lib/asciidoctor/ietf/cleanup.rb +99 -0
- data/lib/asciidoctor/ietf/converter.rb +23 -89
- data/lib/asciidoctor/ietf/front.rb +1 -1
- data/lib/asciidoctor/ietf/ietf.rng +5 -2
- data/lib/asciidoctor/ietf/isodoc.rng +93 -18
- data/lib/asciidoctor/ietf/macros.rb +17 -0
- data/lib/asciidoctor/ietf/reqt.rng +15 -4
- data/lib/asciidoctor/ietf/validate.rb +3 -54
- data/lib/isodoc/ietf/blocks.rb +181 -174
- data/lib/isodoc/ietf/cleanup.rb +19 -1
- data/lib/isodoc/ietf/inline.rb +127 -124
- data/lib/isodoc/ietf/references.rb +152 -128
- data/lib/isodoc/ietf/section.rb +1 -1
- data/lib/isodoc/ietf/validation.rb +158 -157
- data/lib/metanorma/ietf/version.rb +1 -1
- data/metanorma-ietf.gemspec +1 -1
- metadata +12 -10
@@ -1,191 +1,192 @@
|
|
1
1
|
require "jing"
|
2
2
|
require "fileutils"
|
3
3
|
|
4
|
-
module IsoDoc
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
errors = Jing.new(File.join(File.dirname(__FILE__), "v3.rng"))
|
9
|
-
validate(filename)
|
4
|
+
module IsoDoc
|
5
|
+
module Ietf
|
6
|
+
class RfcConvert < ::IsoDoc::Convert
|
7
|
+
def schema_validate(filename)
|
8
|
+
errors = Jing.new(File.join(File.dirname(__FILE__), "v3.rng"))
|
9
|
+
.validate(filename)
|
10
10
|
errors.each do |error|
|
11
|
-
warn "RFC XML: Line #{
|
12
|
-
|
11
|
+
warn "RFC XML: Line #{'%06d' % error[:line]}:#{error[:column]} "\
|
12
|
+
"#{error[:message]}"
|
13
13
|
end
|
14
14
|
rescue Jing::Error => e
|
15
15
|
abort "Jing failed with error: #{e}"
|
16
16
|
end
|
17
|
-
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
FileUtils.mv(filename, "#{filename}.err")
|
28
|
-
err.each { |e| warn "RFC XML: #{e}" }
|
29
|
-
warn "Cannot continue processing"
|
30
|
-
end
|
18
|
+
def content_validate(xml, filename)
|
19
|
+
err = []
|
20
|
+
err += numbered_sections_check(xml)
|
21
|
+
err += toc_sections_check(xml)
|
22
|
+
err += references_check(xml)
|
23
|
+
err += xref_check(xml)
|
24
|
+
err += metadata_check(xml)
|
25
|
+
return if err.empty?
|
31
26
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
FileUtils.mv(filename, "#{filename}.err")
|
28
|
+
err.each { |e| warn "RFC XML: #{e}" }
|
29
|
+
warn "Cannot continue processing"
|
30
|
+
end
|
36
31
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
xml.xpath("//section[@numbered = 'false']").each do |s1|
|
41
|
-
s1.xpath("./section[not(@numbered) or @numbered = 'true']").
|
42
|
-
each do |s2|
|
43
|
-
ret << "Numbered section #{label(s2)} under unnumbered section "\
|
44
|
-
"#{label(s1)}"
|
45
|
-
end
|
46
|
-
s1.xpath("./following-sibling::*[name() = 'section']"\
|
47
|
-
"[not(@numbered) or @numbered = 'true']").each do |s2|
|
48
|
-
ret << "Numbered section #{label(s2)} following unnumbered section "\
|
49
|
-
"#{label(s1)}"
|
50
|
-
end
|
32
|
+
def label(sect)
|
33
|
+
sect&.at("./name")&.text ||
|
34
|
+
sect["name"] || sect["anchor"]
|
51
35
|
end
|
52
|
-
ret
|
53
|
-
end
|
54
36
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
"section #{label(
|
37
|
+
# 2.46.2. "numbered" Attribute
|
38
|
+
def numbered_sections_check(xml)
|
39
|
+
ret = []
|
40
|
+
xml.xpath("//section[@numbered = 'false']").each do |s1|
|
41
|
+
s1.xpath("./section[not(@numbered) or @numbered = 'true']")
|
42
|
+
.each do |s2|
|
43
|
+
ret << "Numbered section #{label(s2)} under unnumbered section "\
|
44
|
+
"#{label(s1)}"
|
45
|
+
end
|
46
|
+
s1.xpath("./following-sibling::*[name() = 'section']"\
|
47
|
+
"[not(@numbered) or @numbered = 'true']").each do |s2|
|
48
|
+
ret << "Numbered section #{label(s2)} following unnumbered "\
|
49
|
+
"section #{label(s1)}"
|
50
|
+
end
|
62
51
|
end
|
52
|
+
ret
|
63
53
|
end
|
64
|
-
ret
|
65
|
-
end
|
66
54
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
"
|
74
|
-
|
75
|
-
"name=#{s1['name']} has been given no value"
|
55
|
+
# 5.2.7. Section "toc" attribute
|
56
|
+
def toc_sections_check(xml)
|
57
|
+
ret = []
|
58
|
+
xml.xpath("//section[@toc = 'exclude']").each do |s1|
|
59
|
+
s1.xpath(".//section[@toc = 'include']").each do |s2|
|
60
|
+
ret << "Section #{label(s2)} with toc=include is included in "\
|
61
|
+
"section #{label(s1)} with toc=exclude"
|
62
|
+
end
|
76
63
|
end
|
64
|
+
ret
|
77
65
|
end
|
78
|
-
xml.xpath("//references | //section").each do |s|
|
79
|
-
s.at("./name") or ret << "Cannot generate table of contents entry "\
|
80
|
-
"for #{label(s)}, as it has no title"
|
81
|
-
end
|
82
|
-
ret
|
83
|
-
end
|
84
66
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
if x["format"] == "title" && t.name == "reference"
|
96
|
-
t.at("./front/title") or
|
97
|
-
ret << "reference #{t['anchor']} has been referenced by #{x.name} "\
|
98
|
-
"with format=title, but the reference has no title"
|
99
|
-
end
|
100
|
-
if x["format"] == "counter" && !%w(section table figure li
|
101
|
-
reference references t dt).include?(t.name)
|
102
|
-
ret << "#{x.to_xml} with format=counter is only allowed for "\
|
103
|
-
"clauses, tables, figures, list entries, definition terms, "\
|
104
|
-
"paragraphs, bibliographies, and bibliographic entries"
|
105
|
-
end
|
106
|
-
if x["format"] == "counter" && t.name == "reference" && !x["section"]
|
107
|
-
ret << "reference #{t['anchor']} has been referenced by xref "\
|
108
|
-
"#{x.to_xml} with format=counter, which requires a "\
|
109
|
-
"section attribute"
|
110
|
-
end
|
111
|
-
if x["format"] == "counter" && t.name == "li" && t.parent.name != "ol"
|
112
|
-
ret << "#{x.to_xml} with format=counter refers to an unnumbered "\
|
113
|
-
"list entry"
|
114
|
-
end
|
115
|
-
if x["format"] == "title" && %w(u author contact).include?(t.name)
|
116
|
-
ret << "#{x.to_xml} with format=title cannot reference a "\
|
117
|
-
"<#{t.name}> element"
|
118
|
-
end
|
119
|
-
if x["relative"] && !x["section"]
|
120
|
-
ret << "#{x.to_xml} with relative attribute requires a section "\
|
121
|
-
"attribute"
|
122
|
-
end
|
123
|
-
if (x["section"]) && t.name != "reference"
|
124
|
-
ret << "#{x.to_xml} has a section attribute, but #{x['target']} "\
|
125
|
-
"points to a #{t.name}"
|
67
|
+
# 5.4.3 <reference> "target" Insertion
|
68
|
+
# 5.4.2.4 "Table of Contents" Insertion
|
69
|
+
def references_check(xml)
|
70
|
+
ret = []
|
71
|
+
xml.xpath("//reference[not(@target)]").each do |s|
|
72
|
+
s.xpath(".//seriesInfo[@name = 'RFC' or @name = 'Internet-Draft' "\
|
73
|
+
"or @name = 'DOI'][not(@value)]").each do |s1|
|
74
|
+
ret << "for reference #{s['anchor']}, the seriesInfo with "\
|
75
|
+
"name=#{s1['name']} has been given no value"
|
76
|
+
end
|
126
77
|
end
|
127
|
-
|
128
|
-
ret << "
|
129
|
-
|
78
|
+
xml.xpath("//references | //section").each do |s|
|
79
|
+
s.at("./name") or ret << "Cannot generate table of contents entry "\
|
80
|
+
"for #{label(s)}, as it has no title"
|
130
81
|
end
|
131
|
-
|
132
|
-
|
133
|
-
|
82
|
+
ret
|
83
|
+
end
|
84
|
+
|
85
|
+
# 5.4.8.2. "derivedContent" Insertion (without Content)
|
86
|
+
def xref_check(xml)
|
87
|
+
ret = []
|
88
|
+
xml.xpath("//xref | //relref").each do |x|
|
89
|
+
t = xml.at(".//*[@anchor = '#{x['target']}']") ||
|
90
|
+
xml.at(".//*[@pn = '#{x['target']}']") or
|
91
|
+
ret << "#{x.name} target #{x['target']} does not exist in the document"
|
92
|
+
next unless t
|
93
|
+
|
94
|
+
x.delete("relative") if x["relative"] && x["relative"].empty?
|
95
|
+
x.delete("section") if x["section"] && x["section"].empty?
|
96
|
+
if x["format"] == "title" && t.name == "reference"
|
97
|
+
t.at("./front/title") or
|
98
|
+
ret << "reference #{t['anchor']} has been referenced by #{x.name} "\
|
99
|
+
"with format=title, but the reference has no title"
|
100
|
+
end
|
101
|
+
if x["format"] == "counter" && !%w(section table figure li
|
102
|
+
reference references t dt).include?(t.name)
|
103
|
+
ret << "#{x.to_xml} with format=counter is only allowed for "\
|
104
|
+
"clauses, tables, figures, list entries, definition terms, "\
|
105
|
+
"paragraphs, bibliographies, and bibliographic entries"
|
106
|
+
end
|
107
|
+
if x["format"] == "counter" && t.name == "reference" && !x["section"]
|
108
|
+
ret << "reference #{t['anchor']} has been referenced by xref "\
|
109
|
+
"#{x.to_xml} with format=counter, which requires a "\
|
110
|
+
"section attribute"
|
111
|
+
end
|
112
|
+
if x["format"] == "counter" && t.name == "li" && t.parent.name != "ol"
|
113
|
+
ret << "#{x.to_xml} with format=counter refers to an unnumbered "\
|
114
|
+
"list entry"
|
115
|
+
end
|
116
|
+
if x["format"] == "title" && %w(u author contact).include?(t.name)
|
117
|
+
ret << "#{x.to_xml} with format=title cannot reference a "\
|
118
|
+
"<#{t.name}> element"
|
119
|
+
end
|
120
|
+
if x["relative"] && !x["section"]
|
121
|
+
ret << "#{x.to_xml} with relative attribute requires a section "\
|
122
|
+
"attribute"
|
123
|
+
end
|
124
|
+
if (x["section"]) && t.name != "reference"
|
125
|
+
ret << "#{x.to_xml} has a section attribute, but #{x['target']} "\
|
126
|
+
"points to a #{t.name}"
|
127
|
+
end
|
128
|
+
if (x["relative"]) && t.name != "reference"
|
129
|
+
ret << "#{x.to_xml} has a relative attribute, but #{x['target']} "\
|
130
|
+
"points to a #{t.name}"
|
131
|
+
end
|
132
|
+
if !x["relative"] && x["section"] && !t.at(".//seriesInfo[@name = 'RFC' or @name = "\
|
133
|
+
"'Internet-Draft']")
|
134
134
|
ret << "#{x.to_xml} must use a relative attribute, "\
|
135
|
-
|
135
|
+
"since it does not point to a RFC or Internet-Draft reference"
|
136
136
|
end
|
137
|
-
|
138
|
-
|
139
|
-
unless t.at(".//seriesInfo[@name = 'RFC' or @name = "\
|
140
|
-
"'Internet-Draft']") || t["target"]
|
137
|
+
if x["relative"] && !(t.at(".//seriesInfo[@name = 'RFC' or @name = "\
|
138
|
+
"'Internet-Draft']") || t["target"])
|
141
139
|
ret << "need an explicit target= URL attribute in the reference "\
|
142
|
-
|
140
|
+
"pointed to by #{x.to_xml}"
|
143
141
|
end
|
144
142
|
end
|
143
|
+
ret
|
145
144
|
end
|
146
|
-
ret
|
147
|
-
end
|
148
145
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
146
|
+
def metadata_check(xml)
|
147
|
+
ret = []
|
148
|
+
ret += link_check(xml)
|
149
|
+
ret += seriesInfo_check(xml)
|
150
|
+
ret += ipr_check(xml)
|
151
|
+
ret
|
152
|
+
end
|
156
153
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
154
|
+
# 5.6.3. <link> Processing
|
155
|
+
def link_check(xml)
|
156
|
+
l = xml&.at("//link[@rel = 'convertedFrom']")&.text
|
157
|
+
!l || %r{^https://datatracker\.ietf\.org/doc/draft-}.match(l) or
|
158
|
+
return ["<link rel='convertedFrom'> (:derived-from: document "\
|
159
|
+
"attribute) must start with "\
|
160
|
+
"https://datatracker.ietf.org/doc/draft-"]
|
161
|
+
[]
|
162
|
+
end
|
166
163
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
164
|
+
# 5.2.2. "seriesInfo" Insertion
|
165
|
+
def seriesInfo_check(xml)
|
166
|
+
ret = []
|
167
|
+
xml.root["ipr"] == "none" and return []
|
168
|
+
rfcinfo = xml.at("//front//seriesInfo[@name = 'RFC']")
|
169
|
+
rfcnumber = xml.root["number"]
|
170
|
+
rfcinfo && rfcnumber && rfcnumber != rfcinfo["value"] and
|
171
|
+
ret << "Mismatch between <rfc number='#{rfcnumber}'> "\
|
172
|
+
"(:docnumber: NUMBER) "\
|
173
|
+
"and <seriesInfo name='RFC' value='#{rfcinfo['value']}'> "\
|
174
|
+
"(:intended-series: TYPE NUMBER)"
|
175
|
+
rfcinfo && !/^\d+$/.match(rfcnumber) and
|
176
|
+
ret << "RFC identifier <rfc number='#{rfcnumber}'> "\
|
177
|
+
"(:docnumber: NUMBER) must be a number"
|
178
|
+
ret
|
179
|
+
end
|
182
180
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
181
|
+
# 5.4.2.3. "Copyright Notice" Insertion
|
182
|
+
def ipr_check(xml)
|
183
|
+
xml.root["ipr"] or
|
184
|
+
return ["Missing ipr attribute on <rfc> element (:ipr:)"]
|
185
|
+
/trust200902$/.match(xml.root["ipr"]) or
|
186
|
+
return ["Unknown ipr attribute on <rfc> element (:ipr:): "\
|
187
|
+
"#{xml.root['ipr']}"]
|
188
|
+
[]
|
189
|
+
end
|
189
190
|
end
|
190
191
|
end
|
191
192
|
end
|
data/metanorma-ietf.gemspec
CHANGED
@@ -37,8 +37,8 @@ Gem::Specification.new do |spec|
|
|
37
37
|
|
38
38
|
spec.add_dependency "isodoc", "~> 1.7.0"
|
39
39
|
spec.add_dependency "mathml2asciimath"
|
40
|
+
spec.add_dependency "metanorma-ietf-data"
|
40
41
|
spec.add_dependency "metanorma-standoc", "~> 1.10.0"
|
41
|
-
spec.add_dependency "nokogiri", "~> 1.11.6"
|
42
42
|
spec.add_dependency "open-uri"
|
43
43
|
|
44
44
|
spec.add_development_dependency "byebug"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: metanorma-ietf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: isodoc
|
@@ -39,33 +39,33 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: metanorma-
|
42
|
+
name: metanorma-ietf-data
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: '0'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: metanorma-standoc
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.
|
61
|
+
version: 1.10.0
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 1.
|
68
|
+
version: 1.10.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: open-uri
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -275,10 +275,12 @@ files:
|
|
275
275
|
- lib/asciidoctor/ietf/basicdoc.rng
|
276
276
|
- lib/asciidoctor/ietf/biblio.rng
|
277
277
|
- lib/asciidoctor/ietf/blocks.rb
|
278
|
+
- lib/asciidoctor/ietf/cleanup.rb
|
278
279
|
- lib/asciidoctor/ietf/converter.rb
|
279
280
|
- lib/asciidoctor/ietf/front.rb
|
280
281
|
- lib/asciidoctor/ietf/ietf.rng
|
281
282
|
- lib/asciidoctor/ietf/isodoc.rng
|
283
|
+
- lib/asciidoctor/ietf/macros.rb
|
282
284
|
- lib/asciidoctor/ietf/reqt.rng
|
283
285
|
- lib/asciidoctor/ietf/validate.rb
|
284
286
|
- lib/isodoc/ietf/SVG-1.2-RFC.rng
|