metanorma-ieee 0.0.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 +7 -0
- data/.github/workflows/rake.yml +13 -0
- data/.rubocop.yml +10 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +11 -0
- data/LICENSE +25 -0
- data/README.adoc +30 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/rspec +17 -0
- data/bin/setup +8 -0
- data/lib/html2doc/ieee.rb +89 -0
- data/lib/isodoc/ieee/base_convert.rb +33 -0
- data/lib/isodoc/ieee/html/header.html +146 -0
- data/lib/isodoc/ieee/html/html_ieee_intro.html +12 -0
- data/lib/isodoc/ieee/html/html_ieee_titlepage.html +44 -0
- data/lib/isodoc/ieee/html/htmlstyle.css +1027 -0
- data/lib/isodoc/ieee/html/htmlstyle.scss +736 -0
- data/lib/isodoc/ieee/html/ieee.css +3603 -0
- data/lib/isodoc/ieee/html/ieee.scss +3418 -0
- data/lib/isodoc/ieee/html/scripts.html +70 -0
- data/lib/isodoc/ieee/html/word_ieee_intro.html +70 -0
- data/lib/isodoc/ieee/html/word_ieee_titlepage.html +28 -0
- data/lib/isodoc/ieee/html/wordstyle.css +5310 -0
- data/lib/isodoc/ieee/html/wordstyle.scss +5026 -0
- data/lib/isodoc/ieee/html_convert.rb +52 -0
- data/lib/isodoc/ieee/i18n-en.yaml +28 -0
- data/lib/isodoc/ieee/i18n.rb +19 -0
- data/lib/isodoc/ieee/ieee.amendment.xsl +11177 -0
- data/lib/isodoc/ieee/ieee.rb +11 -0
- data/lib/isodoc/ieee/ieee.standard.xsl +11177 -0
- data/lib/isodoc/ieee/init.rb +28 -0
- data/lib/isodoc/ieee/metadata.rb +136 -0
- data/lib/isodoc/ieee/pdf_convert.rb +24 -0
- data/lib/isodoc/ieee/presentation_terms.rb +181 -0
- data/lib/isodoc/ieee/presentation_xml_convert.rb +89 -0
- data/lib/isodoc/ieee/word_authority.rb +160 -0
- data/lib/isodoc/ieee/word_cleanup.rb +134 -0
- data/lib/isodoc/ieee/word_convert.rb +75 -0
- data/lib/isodoc/ieee/xref.rb +77 -0
- data/lib/isodoc/ieee.rb +11 -0
- data/lib/metanorma/ieee/basicdoc.rng +1150 -0
- data/lib/metanorma/ieee/biblio.rng +1385 -0
- data/lib/metanorma/ieee/boilerplate.xml +298 -0
- data/lib/metanorma/ieee/cleanup.rb +160 -0
- data/lib/metanorma/ieee/converter.rb +81 -0
- data/lib/metanorma/ieee/front.rb +120 -0
- data/lib/metanorma/ieee/ieee.rng +97 -0
- data/lib/metanorma/ieee/isodoc.rng +2776 -0
- data/lib/metanorma/ieee/processor.rb +56 -0
- data/lib/metanorma/ieee/reqt.rng +226 -0
- data/lib/metanorma/ieee/validate.rb +198 -0
- data/lib/metanorma/ieee/validate_section.rb +119 -0
- data/lib/metanorma/ieee/validate_style.rb +108 -0
- data/lib/metanorma/ieee/version.rb +5 -0
- data/lib/metanorma/ieee.rb +11 -0
- data/lib/metanorma-ieee.rb +8 -0
- data/metanorma-itu.gemspec +41 -0
- metadata +284 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
require "metanorma/processor"
|
2
|
+
|
3
|
+
module Metanorma
|
4
|
+
module IEEE
|
5
|
+
class Processor < Metanorma::Processor
|
6
|
+
def initialize
|
7
|
+
@short = :ieee
|
8
|
+
@input_format = :asciidoc
|
9
|
+
@asciidoctor_backend = :ieee
|
10
|
+
end
|
11
|
+
|
12
|
+
def output_formats
|
13
|
+
super.merge(
|
14
|
+
html: "html",
|
15
|
+
doc: "doc",
|
16
|
+
pdf: "pdf",
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def fonts_manifest
|
21
|
+
{
|
22
|
+
"Arial" => nil,
|
23
|
+
"Courier New" => nil,
|
24
|
+
"Times New Roman" => nil,
|
25
|
+
"Source Han Sans" => nil,
|
26
|
+
"Source Han Sans Normal" => nil,
|
27
|
+
"STIX Two Math" => nil,
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def version
|
32
|
+
"Metanorma::IEEE #{Metanorma::IEEE::VERSION}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def output(isodoc_node, inname, outname, format, options = {})
|
36
|
+
case format
|
37
|
+
when :html
|
38
|
+
IsoDoc::IEEE::HtmlConvert.new(options).convert(inname, isodoc_node,
|
39
|
+
nil, outname)
|
40
|
+
when :doc
|
41
|
+
IsoDoc::IEEE::WordConvert.new(options).convert(inname, isodoc_node,
|
42
|
+
nil, outname)
|
43
|
+
when :pdf
|
44
|
+
IsoDoc::IEEE::PdfConvert.new(options).convert(inname, isodoc_node,
|
45
|
+
nil, outname)
|
46
|
+
when :presentation
|
47
|
+
IsoDoc::IEEE::PresentationXMLConvert.new(options).convert(
|
48
|
+
inname, isodoc_node, nil, outname
|
49
|
+
)
|
50
|
+
else
|
51
|
+
super
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<grammar xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
|
3
|
+
<!--
|
4
|
+
Presupposes isodoc.rnc, is included in it
|
5
|
+
include "isodoc.rnc" { }
|
6
|
+
-->
|
7
|
+
<define name="requirement">
|
8
|
+
<element name="requirement">
|
9
|
+
<ref name="RequirementType"/>
|
10
|
+
</element>
|
11
|
+
</define>
|
12
|
+
<define name="recommendation">
|
13
|
+
<element name="recommendation">
|
14
|
+
<ref name="RequirementType"/>
|
15
|
+
</element>
|
16
|
+
</define>
|
17
|
+
<define name="permission">
|
18
|
+
<element name="permission">
|
19
|
+
<ref name="RequirementType"/>
|
20
|
+
</element>
|
21
|
+
</define>
|
22
|
+
<define name="RequirementType">
|
23
|
+
<optional>
|
24
|
+
<attribute name="obligation">
|
25
|
+
<ref name="ObligationType"/>
|
26
|
+
</attribute>
|
27
|
+
</optional>
|
28
|
+
<optional>
|
29
|
+
<attribute name="unnumbered">
|
30
|
+
<data type="boolean"/>
|
31
|
+
</attribute>
|
32
|
+
</optional>
|
33
|
+
<optional>
|
34
|
+
<attribute name="number"/>
|
35
|
+
</optional>
|
36
|
+
<optional>
|
37
|
+
<attribute name="subsequence"/>
|
38
|
+
</optional>
|
39
|
+
<optional>
|
40
|
+
<attribute name="keep-with-next">
|
41
|
+
<data type="boolean"/>
|
42
|
+
</attribute>
|
43
|
+
</optional>
|
44
|
+
<optional>
|
45
|
+
<attribute name="keep-lines-together">
|
46
|
+
<data type="boolean"/>
|
47
|
+
</attribute>
|
48
|
+
</optional>
|
49
|
+
<attribute name="id">
|
50
|
+
<data type="ID"/>
|
51
|
+
</attribute>
|
52
|
+
<optional>
|
53
|
+
<attribute name="filename"/>
|
54
|
+
</optional>
|
55
|
+
<optional>
|
56
|
+
<attribute name="model"/>
|
57
|
+
</optional>
|
58
|
+
<optional>
|
59
|
+
<attribute name="type"/>
|
60
|
+
</optional>
|
61
|
+
<optional>
|
62
|
+
<attribute name="tag"/>
|
63
|
+
</optional>
|
64
|
+
<optional>
|
65
|
+
<attribute name="multilingual-rendering">
|
66
|
+
<ref name="MultilingualRenderingType"/>
|
67
|
+
</attribute>
|
68
|
+
</optional>
|
69
|
+
<optional>
|
70
|
+
<ref name="reqtitle"/>
|
71
|
+
</optional>
|
72
|
+
<optional>
|
73
|
+
<ref name="label"/>
|
74
|
+
</optional>
|
75
|
+
<zeroOrMore>
|
76
|
+
<ref name="subject"/>
|
77
|
+
</zeroOrMore>
|
78
|
+
<zeroOrMore>
|
79
|
+
<ref name="reqinherit"/>
|
80
|
+
</zeroOrMore>
|
81
|
+
<zeroOrMore>
|
82
|
+
<ref name="classification"/>
|
83
|
+
</zeroOrMore>
|
84
|
+
<zeroOrMore>
|
85
|
+
<choice>
|
86
|
+
<ref name="measurementtarget"/>
|
87
|
+
<ref name="specification"/>
|
88
|
+
<ref name="verification"/>
|
89
|
+
<ref name="import"/>
|
90
|
+
<ref name="description"/>
|
91
|
+
<ref name="component"/>
|
92
|
+
</choice>
|
93
|
+
</zeroOrMore>
|
94
|
+
<optional>
|
95
|
+
<ref name="reqt_references"/>
|
96
|
+
</optional>
|
97
|
+
<zeroOrMore>
|
98
|
+
<choice>
|
99
|
+
<ref name="requirement"/>
|
100
|
+
<ref name="recommendation"/>
|
101
|
+
<ref name="permission"/>
|
102
|
+
</choice>
|
103
|
+
</zeroOrMore>
|
104
|
+
</define>
|
105
|
+
<define name="reqtitle">
|
106
|
+
<element name="title">
|
107
|
+
<ref name="FormattedString"/>
|
108
|
+
</element>
|
109
|
+
</define>
|
110
|
+
<define name="label">
|
111
|
+
<element name="label">
|
112
|
+
<oneOrMore>
|
113
|
+
<ref name="TextElement"/>
|
114
|
+
</oneOrMore>
|
115
|
+
</element>
|
116
|
+
</define>
|
117
|
+
<define name="subject">
|
118
|
+
<element name="subject">
|
119
|
+
<oneOrMore>
|
120
|
+
<ref name="TextElement"/>
|
121
|
+
</oneOrMore>
|
122
|
+
</element>
|
123
|
+
</define>
|
124
|
+
<define name="reqinherit">
|
125
|
+
<element name="inherit">
|
126
|
+
<oneOrMore>
|
127
|
+
<ref name="TextElement"/>
|
128
|
+
</oneOrMore>
|
129
|
+
</element>
|
130
|
+
</define>
|
131
|
+
<define name="measurementtarget">
|
132
|
+
<element name="measurement-target">
|
133
|
+
<ref name="RequirementSubpart"/>
|
134
|
+
</element>
|
135
|
+
</define>
|
136
|
+
<define name="specification">
|
137
|
+
<element name="specification">
|
138
|
+
<ref name="RequirementSubpart"/>
|
139
|
+
</element>
|
140
|
+
</define>
|
141
|
+
<define name="verification">
|
142
|
+
<element name="verification">
|
143
|
+
<ref name="RequirementSubpart"/>
|
144
|
+
</element>
|
145
|
+
</define>
|
146
|
+
<define name="import">
|
147
|
+
<element name="import">
|
148
|
+
<ref name="RequirementSubpart"/>
|
149
|
+
</element>
|
150
|
+
</define>
|
151
|
+
<define name="description">
|
152
|
+
<element name="description">
|
153
|
+
<ref name="RequirementSubpart"/>
|
154
|
+
</element>
|
155
|
+
</define>
|
156
|
+
<define name="component">
|
157
|
+
<element name="component">
|
158
|
+
<attribute name="class"/>
|
159
|
+
<ref name="RequirementSubpart"/>
|
160
|
+
</element>
|
161
|
+
</define>
|
162
|
+
<define name="reqt_references">
|
163
|
+
<element name="references">
|
164
|
+
<oneOrMore>
|
165
|
+
<ref name="bibitem"/>
|
166
|
+
</oneOrMore>
|
167
|
+
</element>
|
168
|
+
</define>
|
169
|
+
<define name="RequirementSubpart">
|
170
|
+
<optional>
|
171
|
+
<attribute name="type"/>
|
172
|
+
</optional>
|
173
|
+
<optional>
|
174
|
+
<attribute name="exclude">
|
175
|
+
<data type="boolean"/>
|
176
|
+
</attribute>
|
177
|
+
</optional>
|
178
|
+
<optional>
|
179
|
+
<attribute name="keep-with-next">
|
180
|
+
<data type="boolean"/>
|
181
|
+
</attribute>
|
182
|
+
</optional>
|
183
|
+
<optional>
|
184
|
+
<attribute name="keep-lines-together">
|
185
|
+
<data type="boolean"/>
|
186
|
+
</attribute>
|
187
|
+
</optional>
|
188
|
+
<optional>
|
189
|
+
<attribute name="tag"/>
|
190
|
+
</optional>
|
191
|
+
<optional>
|
192
|
+
<attribute name="multilingual-rendering">
|
193
|
+
<ref name="MultilingualRenderingType"/>
|
194
|
+
</attribute>
|
195
|
+
</optional>
|
196
|
+
<oneOrMore>
|
197
|
+
<choice>
|
198
|
+
<ref name="BasicBlock"/>
|
199
|
+
<ref name="component"/>
|
200
|
+
</choice>
|
201
|
+
</oneOrMore>
|
202
|
+
</define>
|
203
|
+
<define name="ObligationType">
|
204
|
+
<choice>
|
205
|
+
<value>requirement</value>
|
206
|
+
<value>recommendation</value>
|
207
|
+
<value>permission</value>
|
208
|
+
</choice>
|
209
|
+
</define>
|
210
|
+
<define name="classification">
|
211
|
+
<element name="classification">
|
212
|
+
<ref name="classification_tag"/>
|
213
|
+
<ref name="classification_value"/>
|
214
|
+
</element>
|
215
|
+
</define>
|
216
|
+
<define name="classification_tag">
|
217
|
+
<element name="tag">
|
218
|
+
<text/>
|
219
|
+
</element>
|
220
|
+
</define>
|
221
|
+
<define name="classification_value">
|
222
|
+
<element name="value">
|
223
|
+
<text/>
|
224
|
+
</element>
|
225
|
+
</define>
|
226
|
+
</grammar>
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require_relative "validate_section"
|
2
|
+
require_relative "validate_style"
|
3
|
+
|
4
|
+
module Metanorma
|
5
|
+
module IEEE
|
6
|
+
class Converter < Standoc::Converter
|
7
|
+
def validate(doc)
|
8
|
+
content_validate(doc)
|
9
|
+
schema_validate(formattedstr_strip(doc.dup),
|
10
|
+
File.join(File.dirname(__FILE__), "ieee.rng"))
|
11
|
+
end
|
12
|
+
|
13
|
+
def content_validate(doc)
|
14
|
+
super
|
15
|
+
bibdata_validate(doc.root)
|
16
|
+
title_validate(doc.root)
|
17
|
+
locality_erefs_validate(doc.root)
|
18
|
+
bibitem_validate(doc.root)
|
19
|
+
listcount_validate(doc)
|
20
|
+
table_style(doc)
|
21
|
+
figure_validate(doc)
|
22
|
+
end
|
23
|
+
|
24
|
+
def bibdata_validate(doc)
|
25
|
+
doctype_validate(doc)
|
26
|
+
# stage_validate(doc)
|
27
|
+
# substage_validate(doc)
|
28
|
+
end
|
29
|
+
|
30
|
+
def doctype_validate(xmldoc)
|
31
|
+
doctype = xmldoc&.at("//bibdata/ext/doctype")&.text
|
32
|
+
%w(standard recommended-practice guide
|
33
|
+
amendment technical-corrigendum).include? doctype or
|
34
|
+
@log.add("Document Attributes", nil,
|
35
|
+
"#{doctype} is not a recognised document type")
|
36
|
+
end
|
37
|
+
|
38
|
+
def title_validate(xml)
|
39
|
+
title_validate_type(xml)
|
40
|
+
title_validate_capitalisation(xml)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Style Manual 11.3
|
44
|
+
def title_validate_type(xml)
|
45
|
+
title = xml.at("//bibdata/title") or return
|
46
|
+
draft = xml.at("//bibdata//draft")
|
47
|
+
type = xml.at("//bibdata/ext/doctype")
|
48
|
+
subtype = xml.at("//bibdata/ext/subdoctype")
|
49
|
+
target = draft ? "Draft " : ""
|
50
|
+
target += subtype ? "#{strict_capitalize_phrase(subtype.text)} " : ""
|
51
|
+
target += type ? "#{strict_capitalize_phrase(type.text)} " : ""
|
52
|
+
/^#{target}/.match?(title.text) or
|
53
|
+
@log.add("Style", title,
|
54
|
+
"Expected title to start as: #{target}")
|
55
|
+
end
|
56
|
+
|
57
|
+
def strict_capitalize_phrase(str)
|
58
|
+
ret = str.split(/[ -]/).map do |w|
|
59
|
+
letters = w.chars
|
60
|
+
letters.first.upcase! unless /^[ -]/.match?(w)
|
61
|
+
letters.join
|
62
|
+
end.join(" ")
|
63
|
+
ret = "Trial-Use" if ret == "Trial Use"
|
64
|
+
ret
|
65
|
+
end
|
66
|
+
|
67
|
+
# Style Manual 11.3
|
68
|
+
def title_validate_capitalisation(xml)
|
69
|
+
title = xml.at("//bibdata/title") or return
|
70
|
+
found = false
|
71
|
+
title.text.split(/[ -]/).each do |w|
|
72
|
+
/^[[:upper:]]/.match?(w) or preposition?(w) or
|
73
|
+
found = true
|
74
|
+
end
|
75
|
+
found and @log.add("Style", title,
|
76
|
+
"Title contains uncapitalised word other than preposition")
|
77
|
+
end
|
78
|
+
|
79
|
+
def preposition?(word)
|
80
|
+
%w(aboard about above across after against along amid among anti around
|
81
|
+
as at before behind below beneath beside besides between beyond but
|
82
|
+
by concerning considering despite down during except excepting
|
83
|
+
excluding following for from in inside into like minus near of off
|
84
|
+
on onto opposite outside over past per plus regarding round save
|
85
|
+
since than through to toward towards under underneath unlike until
|
86
|
+
up upon versus via with within without a an the).include?(word)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Style manual 12.3.2
|
90
|
+
def locality_erefs_validate(root)
|
91
|
+
root.xpath("//eref[descendant::locality]").each do |t|
|
92
|
+
if !/[:-](\d+{4})$/.match?(t["citeas"])
|
93
|
+
@log.add("Style", t,
|
94
|
+
"undated reference #{t['citeas']} should not contain "\
|
95
|
+
"specific elements")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def bibitem_validate(root)
|
101
|
+
normative_dated_refs(root)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Style manual 12.3.1
|
105
|
+
def normative_dated_refs(root)
|
106
|
+
root.xpath("//references[@normative = 'true']/bibitem").each do |b|
|
107
|
+
b.at(".//date") or
|
108
|
+
@log.add("Style", b,
|
109
|
+
"Normative reference #{b&.at('./@id')&.text} is not dated.")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Style manual 13.3
|
114
|
+
def listcount_validate(doc)
|
115
|
+
doc.xpath("//clause | //annex").each do |c|
|
116
|
+
next if c.xpath(".//ol").empty?
|
117
|
+
|
118
|
+
ols = c.xpath(".//ol") -
|
119
|
+
c.xpath(".//ul//ol | .//ol//ol | .//clause//ol")
|
120
|
+
ols.size > 1 and
|
121
|
+
style_warning(c, "More than 1 ordered list in a numbered clause",
|
122
|
+
nil)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Style manual 17.1
|
127
|
+
def figure_validate(xmldoc)
|
128
|
+
xrefs = xrefs(xmldoc)
|
129
|
+
figure_name_validate(xmldoc, xrefs)
|
130
|
+
table_figure_name_validate(xmldoc, xrefs)
|
131
|
+
table_figure_quantity_validate(xmldoc)
|
132
|
+
end
|
133
|
+
|
134
|
+
def xrefs(xmldoc)
|
135
|
+
klass = IsoDoc::IEEE::HtmlConvert.new(language: @lang, script: @script)
|
136
|
+
xrefs = IsoDoc::IEEE::Xref
|
137
|
+
.new(@lang, @script, klass, IsoDoc::IEEE::I18n.new(@lang, @script),
|
138
|
+
{ hierarchical_assets: @hierarchical_assets })
|
139
|
+
xrefs.parse(Nokogiri::XML(xmldoc.to_xml))
|
140
|
+
xrefs
|
141
|
+
end
|
142
|
+
|
143
|
+
def image_name_prefix(xmldoc)
|
144
|
+
num = xmldoc.at("//bibdata/docnumber") or return
|
145
|
+
yr = xmldoc.at("//bibdata/date[@type = 'published']") ||
|
146
|
+
xmldoc.at("//bibdata/date[@type = 'issued']") ||
|
147
|
+
xmldoc.at("//bibdata/copyright/from")
|
148
|
+
yr = yr&.text || Date.now.year
|
149
|
+
"#{num.text}-#{yr.sub(/-*$/, '')}"
|
150
|
+
end
|
151
|
+
|
152
|
+
def figure_name_validate(xmldoc, xrefs)
|
153
|
+
pref = image_name_prefix(xmldoc)
|
154
|
+
(xmldoc.xpath("//figure") - xmldoc.xpath("//table//figure"))
|
155
|
+
.each do |f|
|
156
|
+
i = f.at("./image") or next
|
157
|
+
next if i["src"].start_with?("data:")
|
158
|
+
|
159
|
+
num = xrefs.anchor(f["id"], :label)
|
160
|
+
File.basename(i["src"], ".*") == "#{pref}_fig#{num}" or
|
161
|
+
@log.add("Style", i,
|
162
|
+
"image name #{i['src']} is expected to be #{pref}_fig#{num}")
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def table_figure_name_validate(xmldoc, xrefs)
|
167
|
+
xmldoc.xpath("//table[.//figure]").each do |t|
|
168
|
+
xmldoc.xpath(".//figure").each do |f|
|
169
|
+
i = f.at("./image") or next
|
170
|
+
next if i["src"].start_with?("data:")
|
171
|
+
|
172
|
+
num = tablefigurenumber(t, f, xrefs)
|
173
|
+
File.basename(i["src"]) == num or
|
174
|
+
@log.add("Style", i,
|
175
|
+
"image name #{i['src']} is expected to be #{num}")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def tablefigurenumber(table, figure, xrefs)
|
181
|
+
tab = xrefs.anchor(table["id"], :label)
|
182
|
+
td = figure.at("./ancestor::td | ./ancestor::th")
|
183
|
+
cols = td.xpath("./preceding-sibling::td | ./preceding-sibling::td")
|
184
|
+
rows = td.parent.xpath("./preceding::tr") &
|
185
|
+
td.at("./ancestor::table").xpath(".//tr")
|
186
|
+
"Tab#{tab}Row#{rows.size + 1}Col#{cols.size + 1}"
|
187
|
+
end
|
188
|
+
|
189
|
+
def table_figure_quantity_validate(xmldoc)
|
190
|
+
xmldoc.xpath("//td[.//image] | //th[.//image]").each do |d|
|
191
|
+
d.xpath(".//image").size > 1 and
|
192
|
+
@log.add("Style", d,
|
193
|
+
"More than one image in the table cell")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Metanorma
|
2
|
+
module IEEE
|
3
|
+
class Converter < Standoc::Converter
|
4
|
+
def section_validate(doc)
|
5
|
+
doctype = doc&.at("//bibdata/ext/doctype")&.text
|
6
|
+
unless %w(amendment technical-corrigendum).include? doctype
|
7
|
+
sections_presence_validate(doc.root)
|
8
|
+
sections_sequence_validate(doc.root)
|
9
|
+
end
|
10
|
+
subclause_validate(doc.root)
|
11
|
+
onlychild_clause_validate(doc.root)
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def sections_presence_validate(root)
|
16
|
+
root.at("//sections/clause[@type = 'overview']") or
|
17
|
+
@log.add("Style", nil, "Overview clause missing")
|
18
|
+
root.at("//sections/clause[@type = 'overview']/clause[@type = 'scope']") or
|
19
|
+
@log.add("Style", nil, "Scope subclause missing")
|
20
|
+
root.at("//sections/clause[@type = 'overview']/clause[@type = 'word-usage']") or
|
21
|
+
@log.add("Style", nil, "Word Usage subclause missing")
|
22
|
+
root.at("//references[@normative = 'true']") or
|
23
|
+
@log.add("Style", nil, "Normative references missing")
|
24
|
+
root.at("//terms") or
|
25
|
+
@log.add("Style", nil, "Definitions missing")
|
26
|
+
end
|
27
|
+
|
28
|
+
def seqcheck(names, msg, accepted)
|
29
|
+
n = names.shift
|
30
|
+
return [] if n.nil?
|
31
|
+
|
32
|
+
test = accepted.map { |a| n.at(a) }
|
33
|
+
if test.all?(&:nil?)
|
34
|
+
@log.add("Style", nil, msg)
|
35
|
+
end
|
36
|
+
names
|
37
|
+
end
|
38
|
+
|
39
|
+
# spec of permissible section sequence
|
40
|
+
# we skip normative references, it goes to end of list
|
41
|
+
SEQ = [
|
42
|
+
{ msg: "Initial section must be (content) Abstract",
|
43
|
+
val: ["./self::abstract"] },
|
44
|
+
{ msg: "Prefatory material must be followed by (clause) Overview",
|
45
|
+
val: ["./self::clause[@type = 'overview']"] },
|
46
|
+
{ msg: "Normative References must be followed by "\
|
47
|
+
"Definitions",
|
48
|
+
val: ["./self::terms | .//terms"] },
|
49
|
+
].freeze
|
50
|
+
|
51
|
+
SECTIONS_XPATH =
|
52
|
+
"//preface/abstract | //sections/terms | .//annex | "\
|
53
|
+
"//sections/definitions | //sections/clause | "\
|
54
|
+
"//references[not(parent::clause)] | "\
|
55
|
+
"//clause[descendant::references][not(parent::clause)]".freeze
|
56
|
+
|
57
|
+
def sections_sequence_validate(root)
|
58
|
+
names, n = sections_sequence_validate_start(root)
|
59
|
+
names, n = sections_sequence_validate_body(names, n)
|
60
|
+
sections_sequence_validate_end(names, n)
|
61
|
+
end
|
62
|
+
|
63
|
+
def sections_sequence_validate_start(root)
|
64
|
+
names = root.xpath(SECTIONS_XPATH)
|
65
|
+
names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val])
|
66
|
+
n = names[0]
|
67
|
+
names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val])
|
68
|
+
names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val])
|
69
|
+
n = names.shift
|
70
|
+
n = names.shift if n&.at("./self::definitions")
|
71
|
+
[names, n]
|
72
|
+
end
|
73
|
+
|
74
|
+
def sections_sequence_validate_body(names, elem)
|
75
|
+
[names, elem]
|
76
|
+
end
|
77
|
+
|
78
|
+
def sections_sequence_validate_end(names, elem)
|
79
|
+
while elem&.name == "annex"
|
80
|
+
elem = names.shift
|
81
|
+
if elem.nil?
|
82
|
+
@log.add("Style", nil, "Document must include (references) "\
|
83
|
+
"Normative References")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
elem&.at("./self::references[@normative = 'true']") ||
|
87
|
+
@log.add("Style", nil, "Document must include (references) "\
|
88
|
+
"Normative References")
|
89
|
+
elem = names&.shift
|
90
|
+
elem&.at("./self::references[@normative = 'false']") ||
|
91
|
+
@log.add("Style", elem,
|
92
|
+
"Final section must be (references) Bibliography")
|
93
|
+
names.empty? ||
|
94
|
+
@log.add("Style", elem,
|
95
|
+
"There are sections after the final Bibliography")
|
96
|
+
end
|
97
|
+
|
98
|
+
# Style manual 13.1
|
99
|
+
def subclause_validate(root)
|
100
|
+
root.xpath("//clause/clause/clause/clause/clause/clause")
|
101
|
+
.each do |c|
|
102
|
+
style_warning(c, "Exceeds the maximum clause depth of 5", nil)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Style manual 13.1
|
107
|
+
def onlychild_clause_validate(root)
|
108
|
+
root.xpath(Standoc::Utils::SUBCLAUSE_XPATH).each do |c|
|
109
|
+
next unless c.xpath("../clause").size == 1
|
110
|
+
|
111
|
+
title = c.at("./title")
|
112
|
+
location = c["id"] || "#{c.text[0..60]}..."
|
113
|
+
location += ":#{title.text}" if c["id"] && !title.nil?
|
114
|
+
@log.add("Style", nil, "#{location}: subclause is only child")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|