metanorma-iso 1.10.5 → 2.0.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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +3 -33
  3. data/.gitignore +26 -0
  4. data/Makefile +1 -1
  5. data/lib/asciidoctor/iso/base.rb +2 -69
  6. data/lib/asciidoctor/iso/cleanup.rb +2 -175
  7. data/lib/asciidoctor/iso/converter.rb +2 -17
  8. data/lib/asciidoctor/iso/deprecated.rb +5 -0
  9. data/lib/asciidoctor/iso/front.rb +2 -169
  10. data/lib/asciidoctor/iso/front_id.rb +2 -224
  11. data/lib/asciidoctor/iso/section.rb +2 -48
  12. data/lib/asciidoctor/iso/validate.rb +2 -171
  13. data/lib/asciidoctor/iso/validate_image.rb +2 -96
  14. data/lib/asciidoctor/iso/validate_requirements.rb +2 -110
  15. data/lib/asciidoctor/iso/validate_section.rb +2 -246
  16. data/lib/asciidoctor/iso/validate_style.rb +2 -169
  17. data/lib/asciidoctor/iso/validate_title.rb +2 -104
  18. data/lib/isodoc/iso/html/style-human.css +19 -14
  19. data/lib/isodoc/iso/html/style-human.scss +8 -2
  20. data/lib/isodoc/iso/html/style-iso.css +21 -15
  21. data/lib/isodoc/iso/html/style-iso.scss +9 -2
  22. data/lib/isodoc/iso/html_convert.rb +6 -4
  23. data/lib/isodoc/iso/iso.amendment.xsl +1449 -1222
  24. data/lib/isodoc/iso/iso.international-standard.xsl +1449 -1222
  25. data/lib/isodoc/iso/word_convert.rb +2 -0
  26. data/lib/metanorma/iso/base.rb +70 -0
  27. data/lib/{asciidoctor → metanorma}/iso/basicdoc.rng +0 -0
  28. data/lib/{asciidoctor → metanorma}/iso/biblio.rng +2 -2
  29. data/lib/{asciidoctor → metanorma}/iso/boilerplate-fr.xml +0 -0
  30. data/lib/{asciidoctor → metanorma}/iso/boilerplate.xml +0 -0
  31. data/lib/metanorma/iso/cleanup.rb +176 -0
  32. data/lib/metanorma/iso/converter.rb +18 -0
  33. data/lib/metanorma/iso/front.rb +170 -0
  34. data/lib/metanorma/iso/front_id.rb +225 -0
  35. data/lib/{asciidoctor → metanorma}/iso/isodoc.rng +98 -1
  36. data/lib/{asciidoctor → metanorma}/iso/isostandard-amd.rng +0 -0
  37. data/lib/{asciidoctor → metanorma}/iso/isostandard.rnc +0 -0
  38. data/lib/{asciidoctor → metanorma}/iso/isostandard.rng +0 -0
  39. data/lib/{asciidoctor → metanorma}/iso/reqt.rng +0 -0
  40. data/lib/metanorma/iso/section.rb +49 -0
  41. data/lib/metanorma/iso/validate.rb +172 -0
  42. data/lib/metanorma/iso/validate_image.rb +97 -0
  43. data/lib/metanorma/iso/validate_requirements.rb +111 -0
  44. data/lib/metanorma/iso/validate_section.rb +247 -0
  45. data/lib/metanorma/iso/validate_style.rb +170 -0
  46. data/lib/metanorma/iso/validate_title.rb +105 -0
  47. data/lib/metanorma/iso/version.rb +1 -1
  48. data/lib/metanorma-iso.rb +1 -1
  49. data/metanorma-iso.gemspec +2 -2
  50. data/spec/isodoc/ref_spec.rb +4 -2
  51. data/spec/isodoc/section_spec.rb +1 -1
  52. data/spec/{asciidoctor → metanorma}/amd_spec.rb +1 -1
  53. data/spec/{asciidoctor → metanorma}/base_spec.rb +141 -130
  54. data/spec/{asciidoctor → metanorma}/blank_spec.rb +1 -1
  55. data/spec/{asciidoctor → metanorma}/blocks_spec.rb +1 -1
  56. data/spec/{asciidoctor → metanorma}/cleanup_spec.rb +1 -1
  57. data/spec/{asciidoctor → metanorma}/inline_spec.rb +1 -1
  58. data/spec/{asciidoctor → metanorma}/lists_spec.rb +1 -1
  59. data/spec/metanorma/processor_spec.rb +1 -1
  60. data/spec/{asciidoctor → metanorma}/refs_spec.rb +1 -1
  61. data/spec/{asciidoctor → metanorma}/section_spec.rb +1 -1
  62. data/spec/{asciidoctor → metanorma}/table_spec.rb +1 -1
  63. data/spec/{asciidoctor → metanorma}/validate_spec.rb +1 -1
  64. data/spec/spec_helper.rb +1 -1
  65. data/spec/vcr_cassettes/docrels.yml +21 -216
  66. metadata +39 -26
@@ -1,247 +1,3 @@
1
- require "nokogiri"
1
+ require "asciidoctor/iso/deprecated"
2
+ require "metanorma/iso/validate_section"
2
3
 
3
- module Asciidoctor
4
- module ISO
5
- class Converter < Standoc::Converter
6
- def section_validate(doc)
7
- doctype = doc&.at("//bibdata/ext/doctype")&.text
8
- unless %w(amendment technical-corrigendum).include? doctype
9
- foreword_validate(doc.root)
10
- normref_validate(doc.root)
11
- symbols_validate(doc.root)
12
- sections_presence_validate(doc.root)
13
- sections_sequence_validate(doc.root)
14
- end
15
- section_style(doc.root)
16
- subclause_validate(doc.root)
17
- super
18
- end
19
-
20
- # ISO/IEC DIR 2, 12.4
21
- def foreword_validate(root)
22
- f = root.at("//foreword") || return
23
- s = f.at("./clause")
24
- @log.add("Style", f, "foreword contains subclauses") unless s.nil?
25
- end
26
-
27
- # ISO/IEC DIR 2, 15.4
28
- def normref_validate(root)
29
- f = root.at("//references[@normative = 'true']") || return
30
- f.at("./references | ./clause") &&
31
- @log.add("Style", f, "normative references contains subclauses")
32
- end
33
-
34
- ONE_SYMBOLS_WARNING = "Only one Symbols and Abbreviated "\
35
- "Terms section in the standard".freeze
36
-
37
- NON_DL_SYMBOLS_WARNING = "Symbols and Abbreviated Terms can "\
38
- "only contain a definition list".freeze
39
-
40
- def symbols_validate(root)
41
- f = root.xpath("//definitions")
42
- f.empty? && return
43
- (f.size == 1) || @log.add("Style", f.first, ONE_SYMBOLS_WARNING)
44
- f.first.elements.each do |e|
45
- unless %w(title dl).include? e.name
46
- @log.add("Style", f.first, NON_DL_SYMBOLS_WARNING)
47
- return
48
- end
49
- end
50
- end
51
-
52
- def seqcheck(names, msg, accepted)
53
- n = names.shift
54
- return [] if n.nil?
55
-
56
- test = accepted.map { |a| n.at(a) }
57
- if test.all?(&:nil?)
58
- @log.add("Style", nil, msg)
59
- end
60
- names
61
- end
62
-
63
- def sections_presence_validate(root)
64
- root.at("//sections/clause[@type = 'scope']") or
65
- @log.add("Style", nil, "Scope clause missing")
66
- root.at("//references[@normative = 'true']") or
67
- @log.add("Style", nil, "Normative references missing")
68
- root.at("//terms") or
69
- @log.add("Style", nil, "Terms & definitions missing")
70
- end
71
-
72
- # spec of permissible section sequence
73
- # we skip normative references, it goes to end of list
74
- SEQ =
75
- [
76
- {
77
- msg: "Initial section must be (content) Foreword",
78
- val: ["./self::foreword"],
79
- },
80
- {
81
- msg: "Prefatory material must be followed by (clause) Scope",
82
- val: ["./self::introduction", "./self::clause[@type = 'scope']"],
83
- },
84
- {
85
- msg: "Prefatory material must be followed by (clause) Scope",
86
- val: ["./self::clause[@type = 'scope']"],
87
- },
88
- {
89
- msg: "Normative References must be followed by "\
90
- "Terms and Definitions",
91
- val: ["./self::terms | .//terms"],
92
- },
93
- ].freeze
94
-
95
- SECTIONS_XPATH =
96
- "//foreword | //introduction | //sections/terms | .//annex | "\
97
- "//sections/definitions | //sections/clause | "\
98
- "//references[not(parent::clause)] | "\
99
- "//clause[descendant::references][not(parent::clause)]".freeze
100
-
101
- def sections_sequence_validate(root)
102
- names, n = sections_sequence_validate_start(root)
103
- if root&.at("//bibdata/ext/subdoctype")&.text == "vocabulary"
104
- names, n = sections_sequence_validate_body_vocab(names, n)
105
- else
106
- names, n = sections_sequence_validate_body(names, n)
107
- end
108
- sections_sequence_validate_end(names, n)
109
- end
110
-
111
- def sections_sequence_validate_start(root)
112
- names = root.xpath(SECTIONS_XPATH)
113
- names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val])
114
- n = names[0]
115
- names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val])
116
- n&.at("./self::introduction") and
117
- names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val])
118
- names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val])
119
- n = names.shift
120
- n = names.shift if n&.at("./self::definitions")
121
- [names, n]
122
- end
123
-
124
- def sections_sequence_validate_body(names, elem)
125
- if elem.nil? || elem.name != "clause"
126
- @log.add("Style", elem, "Document must contain at least one clause")
127
- end
128
- elem&.at("./self::clause") ||
129
- @log.add("Style", elem, "Document must contain clause after "\
130
- "Terms and Definitions")
131
- elem&.at("./self::clause[@type = 'scope']") &&
132
- @log.add("Style", elem,
133
- "Scope must occur before Terms and Definitions")
134
- elem = names.shift
135
- while elem&.name == "clause"
136
- elem&.at("./self::clause[@type = 'scope']")
137
- @log.add("Style", elem,
138
- "Scope must occur before Terms and Definitions")
139
- elem = names.shift
140
- end
141
- %w(annex references).include? elem&.name or
142
- @log.add("Style", elem,
143
- "Only annexes and references can follow clauses")
144
- [names, elem]
145
- end
146
-
147
- def sections_sequence_validate_body_vocab(names, elem)
148
- while elem && %w(clause terms).include?(elem.name)
149
- elem = names.shift
150
- end
151
- %w(annex references).include? elem&.name or
152
- @log.add("Style", elem,
153
- "Only annexes and references can follow terms and clauses")
154
- [names, elem]
155
- end
156
-
157
- def sections_sequence_validate_end(names, elem)
158
- while elem&.name == "annex"
159
- elem = names.shift
160
- if elem.nil?
161
- @log.add("Style", nil, "Document must include (references) "\
162
- "Normative References")
163
- end
164
- end
165
- elem&.at("./self::references[@normative = 'true']") ||
166
- @log.add("Style", nil, "Document must include (references) "\
167
- "Normative References")
168
- elem = names&.shift
169
- elem&.at("./self::references[@normative = 'false']") ||
170
- @log.add("Style", elem,
171
- "Final section must be (references) Bibliography")
172
- names.empty? ||
173
- @log.add("Style", elem,
174
- "There are sections after the final Bibliography")
175
- end
176
-
177
- NORM_ISO_WARN = "non-ISO/IEC reference not expected as normative".freeze
178
- SCOPE_WARN = "Scope contains subclauses: should be succinct".freeze
179
-
180
- def section_style(root)
181
- foreword_style(root.at("//foreword"))
182
- introduction_style(root.at("//introduction"))
183
- scope_style(root.at("//clause[@type = 'scope']"))
184
- scope = root.at("//clause[@type = 'scope']/clause")
185
- # ISO/IEC DIR 2, 14.4
186
- scope.nil? || style_warning(scope, SCOPE_WARN, nil)
187
- tech_report_style(root)
188
- end
189
-
190
- def tech_report_style(root)
191
- root.at("//bibdata/ext/doctype")&.text == "technical-report" or return
192
- root.xpath("//sections/clause[not(@type = 'scope')] | //annex")
193
- .each do |s|
194
- r = requirement_check(extract_text(s)) and
195
- style_warning(s,
196
- "Technical Report clause may contain requirement", r)
197
- end
198
- end
199
-
200
- ASSETS_TO_STYLE =
201
- "//termsource | //formula | //termnote | "\
202
- "//p[not(ancestor::boilerplate)] | //li[not(p)] | //dt | "\
203
- "//dd[not(p)] | //td[not(p)] | //th[not(p)]".freeze
204
-
205
- NORM_BIBITEMS =
206
- "//references[@normative = 'true']/bibitem".freeze
207
-
208
- # ISO/IEC DIR 2, 10.2
209
- def norm_bibitem_style(root)
210
- root.xpath(NORM_BIBITEMS).each do |b|
211
- if b.at(Standoc::Converter::ISO_PUBLISHER_XPATH).nil?
212
- @log.add("Style", b, "#{NORM_ISO_WARN}: #{b.text}")
213
- end
214
- end
215
- end
216
-
217
- def asset_style(root)
218
- root.xpath("//example | //termexample").each { |e| example_style(e) }
219
- root.xpath("//definition/verbal-definition").each { |e| definition_style(e) }
220
- root.xpath("//note").each { |e| note_style(e) }
221
- root.xpath("//fn").each { |e| footnote_style(e) }
222
- root.xpath(ASSETS_TO_STYLE).each { |e| style(e, extract_text(e)) }
223
- norm_bibitem_style(root)
224
- super
225
- end
226
-
227
- def subclause_validate(root)
228
- root.xpath("//clause/clause/clause/clause/clause/clause/clause/clause")
229
- .each do |c|
230
- style_warning(c, "Exceeds the maximum clause depth of 7", nil)
231
- end
232
- end
233
-
234
- # ISO/IEC DIR 2, 22.3.2
235
- def onlychild_clause_validate(root)
236
- root.xpath(Standoc::Utils::SUBCLAUSE_XPATH).each do |c|
237
- next unless c.xpath("../clause").size == 1
238
-
239
- title = c.at("./title")
240
- location = c["id"] || "#{c.text[0..60]}..."
241
- location += ":#{title.text}" if c["id"] && !title.nil?
242
- @log.add("Style", nil, "#{location}: subclause is only child")
243
- end
244
- end
245
- end
246
- end
247
- end
@@ -1,170 +1,3 @@
1
- require "metanorma-standoc"
2
- require "nokogiri"
3
- require "tokenizer"
1
+ require "asciidoctor/iso/deprecated"
2
+ require "metanorma/iso/validate_style"
4
3
 
5
- module Asciidoctor
6
- module ISO
7
- class Converter < Standoc::Converter
8
- def extract_text(node)
9
- return "" if node.nil?
10
-
11
- node1 = Nokogiri::XML.fragment(node.to_s)
12
- node1.xpath("//link | //locality | //localityStack").each(&:remove)
13
- ret = ""
14
- node1.traverse { |x| ret += x.text if x.text? }
15
- HTMLEntities.new.decode(ret)
16
- end
17
-
18
- # ISO/IEC DIR 2, 12.2
19
- def foreword_style(node)
20
- return if @novalid
21
-
22
- style_no_guidance(node, extract_text(node), "Foreword")
23
- end
24
-
25
- # ISO/IEC DIR 2, 14.2
26
- def scope_style(node)
27
- return if @novalid
28
-
29
- style_no_guidance(node, extract_text(node), "Scope")
30
- end
31
-
32
- # ISO/IEC DIR 2, 13.2
33
- def introduction_style(node)
34
- return if @novalid
35
-
36
- r = requirement_check(extract_text(node))
37
- style_warning(node, "Introduction may contain requirement", r) if r
38
- end
39
-
40
- # ISO/IEC DIR 2, 16.5.6
41
- def definition_style(node)
42
- return if @novalid
43
-
44
- r = requirement_check(extract_text(node))
45
- style_warning(node, "Definition may contain requirement", r) if r
46
- end
47
-
48
- # ISO/IEC DIR 2, 16.5.7
49
- # ISO/IEC DIR 2, 25.5
50
- def example_style(node)
51
- return if @novalid
52
-
53
- style_no_guidance(node, extract_text(node), "Example")
54
- style(node, extract_text(node))
55
- end
56
-
57
- # ISO/IEC DIR 2, 24.5
58
- def note_style(node)
59
- return if @novalid
60
-
61
- style_no_guidance(node, extract_text(node), "Note")
62
- style(node, extract_text(node))
63
- end
64
-
65
- # ISO/IEC DIR 2, 26.5
66
- def footnote_style(node)
67
- return if @novalid
68
-
69
- style_no_guidance(node, extract_text(node), "Footnote")
70
- style(node, extract_text(node))
71
- end
72
-
73
- def style_regex(regex, warning, n, text)
74
- (m = regex.match(text)) && style_warning(n, warning, m[:num])
75
- end
76
-
77
- # style check with a regex on a token
78
- # and a negative match on its preceding token
79
- def style_two_regex_not_prev(n, text, regex, re_prev, warning)
80
- return if text.nil?
81
-
82
- arr = Tokenizer::WhitespaceTokenizer.new.tokenize(text)
83
- arr.each_index do |i|
84
- m = regex.match arr[i]
85
- m_prev = i.zero? ? nil : re_prev.match(arr[i - 1])
86
- if !m.nil? && m_prev.nil?
87
- style_warning(n, warning, m[:num])
88
- end
89
- end
90
- end
91
-
92
- def style(node, text)
93
- return if @novalid
94
-
95
- style_number(node, text)
96
- style_percent(node, text)
97
- style_abbrev(node, text)
98
- style_units(node, text)
99
- end
100
-
101
- # ISO/IEC DIR 2, 9.1
102
- # ISO/IEC DIR 2, Table B.1
103
- def style_number(node, text)
104
- style_two_regex_not_prev(
105
- node, text, /^(?<num>-?[0-9]{4,}[,0-9]*)\Z/,
106
- %r{\b(ISO|IEC|IEEE/|(in|January|February|March|April|May|June|August|September|October|November|December)\b)\Z},
107
- "number not broken up in threes"
108
- )
109
- style_regex(/\b(?<num>[0-9]+\.[0-9]+)/i,
110
- "possible decimal point", node, text)
111
- style_regex(/\b(?<num>billions?)\b/i,
112
- "ambiguous number", node, text)
113
- end
114
-
115
- # ISO/IEC DIR 2, 9.2.1
116
- def style_percent(node, text)
117
- style_regex(/\b(?<num>[0-9.,]+%)/,
118
- "no space before percent sign", node, text)
119
- style_regex(/\b(?<num>[0-9.,]+ \u00b1 [0-9,.]+ %)/,
120
- "unbracketed tolerance before percent sign", node, text)
121
- end
122
-
123
- # ISO/IEC DIR 2, 8.4
124
- # ISO/IEC DIR 2, 9.3
125
- def style_abbrev(node, text)
126
- style_regex(/(\A|\s)(?!e\.g\.|i\.e\.)
127
- (?<num>[a-z]{1,2}\.([a-z]{1,2}|\.))\b/ix,
128
- "no dots in abbreviations", node, text)
129
- style_regex(/\b(?<num>ppm)\b/i,
130
- "language-specific abbreviation", node, text)
131
- end
132
-
133
- # leaving out as problematic: N J K C S T H h d B o E
134
- SI_UNIT = "(m|cm|mm|km|μm|nm|g|kg|mgmol|cd|rad|sr|Hz|Hz|MHz|Pa|hPa|kJ|"\
135
- "V|kV|W|MW|kW|F|μF|Ω|Wb|°C|lm|lx|Bq|Gy|Sv|kat|l|t|eV|u|Np|Bd|"\
136
- "bit|kB|MB|Hart|nat|Sh|var)".freeze
137
-
138
- # ISO/IEC DIR 2, 9.3
139
- def style_units(node, text)
140
- style_regex(/\b(?<num>[0-9][0-9,]*\s+[\u00b0\u2032\u2033])/,
141
- "space between number and degrees/minutes/seconds",
142
- node, text)
143
- style_regex(/\b(?<num>[0-9][0-9,]*#{SI_UNIT})\b/o,
144
- "no space between number and SI unit", node, text)
145
- style_non_std_units(node, text)
146
- end
147
-
148
- NONSTD_UNITS = {
149
- sec: "s", mins: "min", hrs: "h", hr: "h", cc: "cm^3",
150
- lit: "l", amp: "A", amps: "A", rpm: "r/min"
151
- }.freeze
152
-
153
- # ISO/IEC DIR 2, 9.3
154
- def style_non_std_units(node, text)
155
- NONSTD_UNITS.each do |k, v|
156
- style_regex(/\b(?<num>[0-9][0-9,]*\s+#{k})\b/,
157
- "non-standard unit (should be #{v})", node, text)
158
- end
159
- end
160
-
161
- def style_warning(node, msg, text = nil)
162
- return if @novalid
163
-
164
- w = msg
165
- w += ": #{text}" if text
166
- @log.add("Style", node, w)
167
- end
168
- end
169
- end
170
- end
@@ -1,105 +1,3 @@
1
- require "metanorma-standoc"
1
+ require "asciidoctor/iso/deprecated"
2
+ require "metanorma/iso/validate_title"
2
3
 
3
- module Asciidoctor
4
- module ISO
5
- class Converter < Standoc::Converter
6
- def title_lang_part(doc, part, lang)
7
- doc.at("//bibdata/title[@type='title-#{part}' and @language='#{lang}']")
8
- end
9
-
10
- def title_intro_validate(root)
11
- title_intro_en = title_lang_part(root, "intro", "en")
12
- title_intro_fr = title_lang_part(root, "intro", "fr")
13
- if title_intro_en.nil? && !title_intro_fr.nil?
14
- @log.add("Style", title_intro_fr, "No English Title Intro!")
15
- end
16
- if !title_intro_en.nil? && title_intro_fr.nil?
17
- @log.add("Style", title_intro_en, "No French Title Intro!")
18
- end
19
- end
20
-
21
- def title_main_validate(root)
22
- title_main_en = title_lang_part(root, "main", "en")
23
- title_main_fr = title_lang_part(root, "main", "fr")
24
- if title_main_en.nil? && !title_main_fr.nil?
25
- @log.add("Style", title_main_fr, "No English Title!")
26
- end
27
- if !title_main_en.nil? && title_main_fr.nil?
28
- @log.add("Style", title_main_en, "No French Title!")
29
- end
30
- end
31
-
32
- def title_part_validate(root)
33
- title_part_en = title_lang_part(root, "part", "en")
34
- title_part_fr = title_lang_part(root, "part", "fr")
35
- (title_part_en.nil? && !title_part_fr.nil?) &&
36
- @log.add("Style", title_part_fr, "No English Title Part!")
37
- (!title_part_en.nil? && title_part_fr.nil?) &&
38
- @log.add("Style", title_part_en, "No French Title Part!")
39
- end
40
-
41
- # ISO/IEC DIR 2, 11.4
42
- def title_subpart_validate(root)
43
- docid = root.at("//bibdata/docidentifier[@type = 'ISO']")
44
- subpart = /-\d+-\d+/.match docid
45
- iec = root.at("//bibdata/contributor[role/@type = 'publisher']/"\
46
- "organization[abbreviation = 'IEC' or "\
47
- "name = 'International Electrotechnical Commission']")
48
- subpart && !iec and
49
- @log.add("Style", docid, "Subpart defined on non-IEC document!")
50
- end
51
-
52
- # ISO/IEC DIR 2, 11.5.2
53
- def title_names_type_validate(root)
54
- doctypes = /International\sStandard | Technical\sSpecification |
55
- Publicly\sAvailable\sSpecification | Technical\sReport | Guide /xi
56
- title_main_en = title_lang_part(root, "main", "en")
57
- !title_main_en.nil? && doctypes.match(title_main_en.text) and
58
- @log.add("Style", title_main_en, "Main Title may name document type")
59
- title_intro_en = title_lang_part(root, "intro", "en")
60
- !title_intro_en.nil? && doctypes.match(title_intro_en.text) and
61
- @log.add("Style", title_intro_en,
62
- "Title Intro may name document type")
63
- end
64
-
65
- # ISO/IEC DIR 2, 22.2
66
- def title_first_level_validate(root)
67
- root.xpath(SECTIONS_XPATH).each do |s|
68
- title = s&.at("./title")&.text || s.name
69
- s.xpath("./clause | ./terms | ./references").each do |ss|
70
- subtitle = ss.at("./title")
71
- !subtitle.nil? && !subtitle&.text&.empty? or
72
- @log.add("Style", ss,
73
- "#{title}: each first-level subclause must have a title")
74
- end
75
- end
76
- end
77
-
78
- # ISO/IEC DIR 2, 22.2
79
- def title_all_siblings(xpath, label)
80
- notitle = false
81
- withtitle = false
82
- xpath.each do |s|
83
- title_all_siblings(s.xpath("./clause | ./terms | ./references"),
84
- s&.at("./title")&.text || s["id"])
85
- subtitle = s.at("./title")
86
- notitle = notitle || (!subtitle || subtitle.text.empty?)
87
- withtitle = withtitle || (subtitle && !subtitle.text.empty?)
88
- end
89
- notitle && withtitle &&
90
- @log.add("Style", nil,
91
- "#{label}: all subclauses must have a title, or none")
92
- end
93
-
94
- def title_validate(root)
95
- title_intro_validate(root)
96
- title_main_validate(root)
97
- title_part_validate(root)
98
- title_subpart_validate(root)
99
- title_names_type_validate(root)
100
- title_first_level_validate(root)
101
- title_all_siblings(root.xpath(SECTIONS_XPATH), "(top level)")
102
- end
103
- end
104
- end
105
- end
@@ -443,44 +443,49 @@ p.Terms {
443
443
  margin-top: 0em; }
444
444
 
445
445
  /* Navigation*/
446
- #toc {
446
+ #toc, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) {
447
447
  font-family: {{bodyfont}};
448
448
  font-weight: 400; }
449
- #toc ul {
449
+ #toc ul, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) ul {
450
450
  margin: 0;
451
451
  padding: 0;
452
452
  list-style: none; }
453
- #toc ul li a {
453
+ #toc ul li a, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) ul li a {
454
454
  padding: 5px 10px; }
455
- #toc ul a {
455
+ #toc ul a, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) ul a {
456
456
  text-decoration: none;
457
457
  display: block; }
458
- #toc ul a:hover {
458
+ #toc ul a:hover, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) ul a:hover {
459
459
  box-shadow: none;
460
460
  color: white; }
461
- #toc .h2 {
461
+ #toc .h2, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) .h2 {
462
462
  padding-left: 30px; }
463
- #toc .h3 {
463
+ #toc .h3, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) .h3 {
464
464
  padding-left: 50px; }
465
- #toc .toc-active, #toc li:hover {
465
+ #toc .toc-active, #toc li:hover, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) .toc-active, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) li:hover {
466
466
  background: #1d1d1d;
467
467
  box-shadow: inset -5px 0px 10px -5px #1d1d1d !important; }
468
- #toc .toc-active a, #toc li:hover a {
468
+ #toc .toc-active a, #toc li:hover a, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) .toc-active a, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) li:hover a {
469
469
  color: white; }
470
470
  @media print {
471
- #toc .toc-active, #toc li:hover {
471
+ #toc .toc-active, #toc li:hover, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) .toc-active, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) li:hover {
472
472
  background: white;
473
473
  box-shadow: none !important; }
474
- #toc li:hover a {
474
+ #toc li:hover a, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) li:hover a {
475
475
  color: black; } }
476
476
  @media screen and (max-width: 768px) {
477
- #toc {
477
+ #toc, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) {
478
478
  padding: 0 1.5em;
479
479
  overflow: visible; } }
480
- #toc li:before {
480
+ #toc li:before, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) li:before {
481
481
  content: " ";
482
482
  display: none; }
483
483
 
484
+ #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) {
485
+ margin-top: 0;
486
+ margin-bottom: 0;
487
+ font-size: 100%; }
488
+
484
489
  nav {
485
490
  line-height: 1.2em; }
486
491
  @media screen and (min-width: 768px) {
@@ -534,7 +539,7 @@ nav {
534
539
  display: none; }
535
540
  h1.toc-contents {
536
541
  margin-top: 1em; }
537
- ul#toc-list {
542
+ ul#toc-list, ul#toc-list > :is(.h1, .h2, .h3, .h4, .h5, .h6) {
538
543
  padding: 0;
539
544
  margin: 0; } }
540
545
 
@@ -259,7 +259,7 @@ p.Terms {
259
259
 
260
260
  /* Navigation*/
261
261
 
262
- #toc {
262
+ #toc, #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) {
263
263
  @include toc(null, #1d1d1d, white);
264
264
  @include sidebarToc();
265
265
 
@@ -275,6 +275,12 @@ p.Terms {
275
275
  }
276
276
  }
277
277
 
278
+ #toc > ul :is(.h1, .h2, .h3, .h4, .h5, .h6) {
279
+ margin-top: 0;
280
+ margin-bottom: 0;
281
+ font-size: 100%;
282
+ }
283
+
278
284
  nav {
279
285
  @include sidebarNav(#f7f7f7, 278px, 20px);
280
286
  line-height: 1.2em;
@@ -299,7 +305,7 @@ nav {
299
305
  margin-top: 1em;
300
306
  }
301
307
 
302
- ul#toc-list {
308
+ ul#toc-list, ul#toc-list > :is(.h1, .h2, .h3, .h4, .h5, .h6) {
303
309
  padding: 0;
304
310
  margin: 0;
305
311
  }