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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/rake.yml +13 -0
  3. data/.rubocop.yml +10 -0
  4. data/CODE_OF_CONDUCT.md +74 -0
  5. data/Gemfile +11 -0
  6. data/LICENSE +25 -0
  7. data/README.adoc +30 -0
  8. data/Rakefile +8 -0
  9. data/bin/console +14 -0
  10. data/bin/rspec +17 -0
  11. data/bin/setup +8 -0
  12. data/lib/html2doc/ieee.rb +89 -0
  13. data/lib/isodoc/ieee/base_convert.rb +33 -0
  14. data/lib/isodoc/ieee/html/header.html +146 -0
  15. data/lib/isodoc/ieee/html/html_ieee_intro.html +12 -0
  16. data/lib/isodoc/ieee/html/html_ieee_titlepage.html +44 -0
  17. data/lib/isodoc/ieee/html/htmlstyle.css +1027 -0
  18. data/lib/isodoc/ieee/html/htmlstyle.scss +736 -0
  19. data/lib/isodoc/ieee/html/ieee.css +3603 -0
  20. data/lib/isodoc/ieee/html/ieee.scss +3418 -0
  21. data/lib/isodoc/ieee/html/scripts.html +70 -0
  22. data/lib/isodoc/ieee/html/word_ieee_intro.html +70 -0
  23. data/lib/isodoc/ieee/html/word_ieee_titlepage.html +28 -0
  24. data/lib/isodoc/ieee/html/wordstyle.css +5310 -0
  25. data/lib/isodoc/ieee/html/wordstyle.scss +5026 -0
  26. data/lib/isodoc/ieee/html_convert.rb +52 -0
  27. data/lib/isodoc/ieee/i18n-en.yaml +28 -0
  28. data/lib/isodoc/ieee/i18n.rb +19 -0
  29. data/lib/isodoc/ieee/ieee.amendment.xsl +11177 -0
  30. data/lib/isodoc/ieee/ieee.rb +11 -0
  31. data/lib/isodoc/ieee/ieee.standard.xsl +11177 -0
  32. data/lib/isodoc/ieee/init.rb +28 -0
  33. data/lib/isodoc/ieee/metadata.rb +136 -0
  34. data/lib/isodoc/ieee/pdf_convert.rb +24 -0
  35. data/lib/isodoc/ieee/presentation_terms.rb +181 -0
  36. data/lib/isodoc/ieee/presentation_xml_convert.rb +89 -0
  37. data/lib/isodoc/ieee/word_authority.rb +160 -0
  38. data/lib/isodoc/ieee/word_cleanup.rb +134 -0
  39. data/lib/isodoc/ieee/word_convert.rb +75 -0
  40. data/lib/isodoc/ieee/xref.rb +77 -0
  41. data/lib/isodoc/ieee.rb +11 -0
  42. data/lib/metanorma/ieee/basicdoc.rng +1150 -0
  43. data/lib/metanorma/ieee/biblio.rng +1385 -0
  44. data/lib/metanorma/ieee/boilerplate.xml +298 -0
  45. data/lib/metanorma/ieee/cleanup.rb +160 -0
  46. data/lib/metanorma/ieee/converter.rb +81 -0
  47. data/lib/metanorma/ieee/front.rb +120 -0
  48. data/lib/metanorma/ieee/ieee.rng +97 -0
  49. data/lib/metanorma/ieee/isodoc.rng +2776 -0
  50. data/lib/metanorma/ieee/processor.rb +56 -0
  51. data/lib/metanorma/ieee/reqt.rng +226 -0
  52. data/lib/metanorma/ieee/validate.rb +198 -0
  53. data/lib/metanorma/ieee/validate_section.rb +119 -0
  54. data/lib/metanorma/ieee/validate_style.rb +108 -0
  55. data/lib/metanorma/ieee/version.rb +5 -0
  56. data/lib/metanorma/ieee.rb +11 -0
  57. data/lib/metanorma-ieee.rb +8 -0
  58. data/metanorma-itu.gemspec +41 -0
  59. 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