metanorma-iso 1.8.4 → 1.9.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +1 -1
  3. data/.rubocop.yml +1 -1
  4. data/lib/asciidoctor/iso/cleanup.rb +0 -1
  5. data/lib/asciidoctor/iso/isodoc.rng +50 -8
  6. data/lib/asciidoctor/iso/isostandard.rng +7 -3
  7. data/lib/asciidoctor/iso/section.rb +3 -0
  8. data/lib/asciidoctor/iso/validate.rb +4 -17
  9. data/lib/asciidoctor/iso/validate_section.rb +50 -34
  10. data/lib/asciidoctor/iso/validate_style.rb +3 -3
  11. data/lib/isodoc/iso/base_convert.rb +41 -16
  12. data/lib/isodoc/iso/html/isodoc.css +475 -20
  13. data/lib/isodoc/iso/html/isodoc.scss +456 -23
  14. data/lib/isodoc/iso/html/wordstyle.css +202 -31
  15. data/lib/isodoc/iso/html/wordstyle.scss +194 -32
  16. data/lib/isodoc/iso/iso.amendment.xsl +480 -388
  17. data/lib/isodoc/iso/iso.international-standard.xsl +480 -388
  18. data/lib/isodoc/iso/isosts_convert.rb +12 -13
  19. data/lib/isodoc/iso/metadata.rb +2 -2
  20. data/lib/isodoc/iso/presentation_xml_convert.rb +62 -9
  21. data/lib/isodoc/iso/sts_convert.rb +4 -5
  22. data/lib/isodoc/iso/word_convert.rb +153 -39
  23. data/lib/isodoc/iso/xref.rb +17 -1
  24. data/lib/metanorma/iso/version.rb +1 -1
  25. data/metanorma-iso.gemspec +4 -4
  26. data/spec/asciidoctor/section_spec.rb +128 -7
  27. data/spec/asciidoctor/validate_spec.rb +15 -15
  28. data/spec/isodoc/amd_spec.rb +193 -201
  29. data/spec/isodoc/blocks_spec.rb +100 -88
  30. data/spec/isodoc/i18n_spec.rb +36 -36
  31. data/spec/isodoc/inline_spec.rb +472 -2
  32. data/spec/isodoc/iso_spec.rb +86 -138
  33. data/spec/isodoc/postproc_spec.rb +19 -10
  34. data/spec/isodoc/ref_spec.rb +6 -6
  35. data/spec/isodoc/section_spec.rb +394 -276
  36. data/spec/isodoc/table_spec.rb +166 -231
  37. data/spec/isodoc/terms_spec.rb +11 -8
  38. data/spec/isodoc/xref_spec.rb +147 -118
  39. metadata +8 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40c9fc0bf08ed5cca2885426c54c0b1970511fbdd14a7e982197bb57f95fc55b
4
- data.tar.gz: 4695506d2644d2b01090cd4bfa7cd123672dd99de111a6c09f50fea1c84ed3c3
3
+ metadata.gz: 4ad1b23ba99cb087c9e257a7bb0bd4d0245bfdc2a2d00c881cc700db7e5c8c42
4
+ data.tar.gz: bc6b4e4d61c32fe3b01cb64a8d0cefc33410814dfa740e140e74a1b2ad4f686f
5
5
  SHA512:
6
- metadata.gz: 5b8317d64f94cee315afeb98045ff026c0b5df38ea7c141c4fa1d839d758dce919382ff5ae72c76893d296b74d69bae965a50096b7fdfb159b0085c122783a19
7
- data.tar.gz: 2f6a2bdb6e5b33adbe3970838f4d4c2ca0f97fe8b40cbe66b828e5fec18fc5cd7932cc42a2880c0765d5b6621a26502d3ae0fa38533488e0cfebb2a1e96917ea
6
+ metadata.gz: 84dc22c62dc17b3d93b1ec601de1b6662762be8963b830ebe305171d1955e3c0cab44e459ad65600752d8de2d97d6caa003e88daed3e6175527fd8feb4f5ea6a
7
+ data.tar.gz: 7ee4889948da20e6db0a534396dd4946cf890b87c67e1cec8a7c2a0eaa4cf85d0d72443fe2535e8b93223c2a66dcadaf42402a8ad786f90bcded7cc9d2a7a1dc
@@ -16,7 +16,7 @@ jobs:
16
16
  strategy:
17
17
  fail-fast: false
18
18
  matrix:
19
- ruby: [ '3.0', '2.7', '2.6', '2.5', '2.4' ]
19
+ ruby: [ '3.0', '2.7', '2.6', '2.5' ]
20
20
  os: [ ubuntu-latest, windows-latest, macos-latest ]
21
21
  experimental: [ false ]
22
22
  steps:
data/.rubocop.yml CHANGED
@@ -7,4 +7,4 @@ inherit_from:
7
7
  # ...
8
8
 
9
9
  AllCops:
10
- TargetRubyVersion: 2.4
10
+ TargetRubyVersion: 2.5
@@ -3,7 +3,6 @@ require "nokogiri"
3
3
  require "htmlentities"
4
4
  require "json"
5
5
  require "pathname"
6
- require "open-uri"
7
6
 
8
7
  module Asciidoctor
9
8
  module ISO
@@ -204,6 +204,18 @@
204
204
  </zeroOrMore>
205
205
  </element>
206
206
  </define>
207
+ <define name="dt">
208
+ <element name="dt">
209
+ <optional>
210
+ <attribute name="id">
211
+ <data type="ID"/>
212
+ </attribute>
213
+ </optional>
214
+ <zeroOrMore>
215
+ <ref name="TextElement"/>
216
+ </zeroOrMore>
217
+ </element>
218
+ </define>
207
219
  <define name="example">
208
220
  <element name="example">
209
221
  <attribute name="id">
@@ -899,7 +911,7 @@
899
911
  </include>
900
912
  <!-- end overrides -->
901
913
  <define name="docsubtype">
902
- <element name="docsubtype">
914
+ <element name="subdoctype">
903
915
  <ref name="DocumentSubtype"/>
904
916
  </element>
905
917
  </define>
@@ -955,7 +967,34 @@
955
967
  <define name="concept">
956
968
  <element name="concept">
957
969
  <optional>
958
- <attribute name="term"/>
970
+ <attribute name="ital">
971
+ <data type="boolean"/>
972
+ </attribute>
973
+ </optional>
974
+ <optional>
975
+ <attribute name="ref">
976
+ <data type="boolean"/>
977
+ </attribute>
978
+ </optional>
979
+ <optional>
980
+ <element name="refterm">
981
+ <zeroOrMore>
982
+ <choice>
983
+ <ref name="PureTextElement"/>
984
+ <ref name="stem"/>
985
+ </choice>
986
+ </zeroOrMore>
987
+ </element>
988
+ </optional>
989
+ <optional>
990
+ <element name="renderterm">
991
+ <zeroOrMore>
992
+ <choice>
993
+ <ref name="PureTextElement"/>
994
+ <ref name="stem"/>
995
+ </choice>
996
+ </zeroOrMore>
997
+ </element>
959
998
  </optional>
960
999
  <choice>
961
1000
  <ref name="eref"/>
@@ -981,6 +1020,9 @@
981
1020
  </attribute>
982
1021
  <attribute name="name"/>
983
1022
  <attribute name="action"/>
1023
+ <optional>
1024
+ <attribute name="class"/>
1025
+ </optional>
984
1026
  <zeroOrMore>
985
1027
  <choice>
986
1028
  <ref name="TextElement"/>
@@ -1473,26 +1515,26 @@
1473
1515
  <optional>
1474
1516
  <ref name="section-title"/>
1475
1517
  </optional>
1476
- <group>
1518
+ <choice>
1477
1519
  <choice>
1478
1520
  <group>
1479
- <zeroOrMore>
1521
+ <oneOrMore>
1480
1522
  <ref name="BasicBlock"/>
1481
- </zeroOrMore>
1523
+ </oneOrMore>
1482
1524
  <zeroOrMore>
1483
1525
  <ref name="note"/>
1484
1526
  </zeroOrMore>
1485
1527
  </group>
1486
1528
  <ref name="amend"/>
1487
1529
  </choice>
1488
- <zeroOrMore>
1530
+ <oneOrMore>
1489
1531
  <choice>
1490
1532
  <ref name="clause-subsection"/>
1491
1533
  <ref name="terms"/>
1492
1534
  <ref name="definitions"/>
1493
1535
  </choice>
1494
- </zeroOrMore>
1495
- </group>
1536
+ </oneOrMore>
1537
+ </choice>
1496
1538
  </define>
1497
1539
  <define name="Annex-Section">
1498
1540
  <optional>
@@ -101,7 +101,11 @@
101
101
  <ref name="definitions"/>
102
102
  </optional>
103
103
  <oneOrMore>
104
- <ref name="clause"/>
104
+ <choice>
105
+ <ref name="clause"/>
106
+ <ref name="term-clause"/>
107
+ <ref name="terms"/>
108
+ </choice>
105
109
  </oneOrMore>
106
110
  </element>
107
111
  </define>
@@ -136,7 +140,7 @@
136
140
  <optional>
137
141
  <ref name="section-title"/>
138
142
  </optional>
139
- <group>
143
+ <choice>
140
144
  <choice>
141
145
  <group>
142
146
  <oneOrMore>
@@ -151,7 +155,7 @@
151
155
  <oneOrMore>
152
156
  <ref name="clause-subsection"/>
153
157
  </oneOrMore>
154
- </group>
158
+ </choice>
155
159
  </define>
156
160
  <define name="term">
157
161
  <element name="term">
@@ -33,6 +33,9 @@ module Asciidoctor
33
33
  def sectiontype(node, level = true)
34
34
  return nil if @amd
35
35
 
36
+ ret = sectiontype_streamline(sectiontype1(node))
37
+ return ret if ret == "terms and definitions" && @vocab
38
+
36
39
  super
37
40
  end
38
41
  end
@@ -32,7 +32,7 @@ module Asciidoctor
32
32
  root.xpath("//xref").each do |t|
33
33
  preceding = t.at("./preceding-sibling::text()[last()]")
34
34
  next unless !preceding.nil? &&
35
- /\b(see| refer to)\s*$/mi.match(preceding)
35
+ /\b(see| refer to)\s*\Z/mi.match(preceding)
36
36
 
37
37
  (target = root.at("//*[@id = '#{t['target']}']")) || next
38
38
  if target&.at("./ancestor-or-self::*[@obligation = 'normative']")
@@ -46,7 +46,7 @@ module Asciidoctor
46
46
  def see_erefs_validate(root)
47
47
  root.xpath("//eref").each do |t|
48
48
  prec = t.at("./preceding-sibling::text()[last()]")
49
- next unless !prec.nil? && /\b(see|refer to)\s*$/mi.match(prec)
49
+ next unless !prec.nil? && /\b(see|refer to)\s*\Z/mi.match(prec)
50
50
 
51
51
  unless target = root.at("//*[@id = '#{t['bibitemid']}']")
52
52
  @log.add("Bibliography", t,
@@ -80,23 +80,11 @@ module Asciidoctor
80
80
  xmldoc.xpath("//term").each do |t|
81
81
  para = t.at("./definition") || return
82
82
  term = t.at("./preferred").text
83
- termdef_warn(para.text, /^(the|a)\b/i, t, term,
83
+ termdef_warn(para.text, /\A(the|a)\b/i, t, term,
84
84
  "term definition starts with article")
85
- termdef_warn(para.text, /\.$/i, t, term,
85
+ termdef_warn(para.text, /\.\Z/i, t, term,
86
86
  "term definition ends with period")
87
87
  end
88
- cited_term_style(xmldoc)
89
- end
90
-
91
- # ISO/IEC DIR 2, 16.5.10
92
- def cited_term_style(xmldoc)
93
- xmldoc.xpath("//term//xref").each do |x|
94
- next unless xmldoc.at("//term[@id = '#{x['target']}']")
95
-
96
- x&.previous&.text == " (" and x&.previous&.previous&.name == "em" or
97
- style_warning(x, "term citation not preceded with italicised term",
98
- x.parent.text)
99
- end
100
88
  end
101
89
 
102
90
  def doctype_validate(xmldoc)
@@ -150,7 +138,6 @@ module Asciidoctor
150
138
  isosubgroup_validate(doc.root)
151
139
  onlychild_clause_validate(doc.root)
152
140
  termdef_style(doc.root)
153
- iev_validate(doc.root)
154
141
  see_xrefs_validate(doc.root)
155
142
  see_erefs_validate(doc.root)
156
143
  locality_erefs_validate(doc.root)
@@ -42,7 +42,7 @@ module Asciidoctor
42
42
  f.empty? && return
43
43
  (f.size == 1) || @log.add("Style", f.first, ONE_SYMBOLS_WARNING)
44
44
  f.first.elements.each do |e|
45
- unless e.name == "dl"
45
+ unless %w(title dl).include? e.name
46
46
  @log.add("Style", f.first, NON_DL_SYMBOLS_WARNING)
47
47
  return
48
48
  end
@@ -99,57 +99,73 @@ module Asciidoctor
99
99
  "//clause[descendant::references][not(parent::clause)]".freeze
100
100
 
101
101
  def sections_sequence_validate(root)
102
- vocab = root&.at("//bibdata/ext/subdoctype")&.text == "vocabulary"
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)
103
112
  names = root.xpath(SECTIONS_XPATH)
104
113
  names = seqcheck(names, SEQ[0][:msg], SEQ[0][:val])
105
114
  n = names[0]
106
115
  names = seqcheck(names, SEQ[1][:msg], SEQ[1][:val])
107
- if n&.at("./self::introduction")
116
+ n&.at("./self::introduction") and
108
117
  names = seqcheck(names, SEQ[2][:msg], SEQ[2][:val])
109
- end
110
118
  names = seqcheck(names, SEQ[3][:msg], SEQ[3][:val])
111
119
  n = names.shift
112
- if n&.at("./self::definitions")
113
- n = names.shift
114
- end
115
- if n.nil? || n.name != "clause"
116
- @log.add("Style", n, "Document must contain at least one clause")
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")
117
127
  end
118
- n&.at("./self::clause") ||
119
- @log.add("Style", n, "Document must contain clause after "\
128
+ elem&.at("./self::clause") ||
129
+ @log.add("Style", elem, "Document must contain clause after "\
120
130
  "Terms and Definitions")
121
- n&.at("./self::clause[@type = 'scope']") &&
122
- @log.add("Style", n, "Scope must occur before Terms and Definitions")
123
- n = names.shift
124
- while n&.name == "clause" || (vocab && n&.name == "terms")
125
- n&.at("./self::clause[@type = 'scope']")
126
- @log.add("Style", n, "Scope must occur before Terms and Definitions")
127
- n = names.shift
131
+ elem&.at("./self::clause[@type = 'scope']") &&
132
+ @log.add("Style", elem, "Scope must occur before Terms and Definitions")
133
+ elem = names.shift
134
+ while elem&.name == "clause"
135
+ elem&.at("./self::clause[@type = 'scope']")
136
+ @log.add("Style", elem, "Scope must occur before Terms and Definitions")
137
+ elem = names.shift
128
138
  end
129
- if vocab
130
- unless %w(annex references terms).include? n&.name
131
- @log.add("Style", n, "Only terms, annexes and references can follow clauses")
132
- end
133
- else
134
- unless %w(annex references).include? n&.name
135
- @log.add("Style", n, "Only annexes and references can follow clauses")
136
- end
139
+ %w(annex references).include? elem&.name or
140
+ @log.add("Style", elem, "Only annexes and references can follow clauses")
141
+ [names, elem]
142
+ end
143
+
144
+ def sections_sequence_validate_body_vocab(names, elem)
145
+ while elem && %w(clause terms).include?(elem.name)
146
+ elem = names.shift
137
147
  end
138
- while n&.name == "annex"
139
- n = names.shift
140
- if n.nil?
148
+ %w(annex references).include? elem&.name or
149
+ @log.add("Style", elem, "Only annexes and references can follow terms and clauses")
150
+ [names, elem]
151
+ end
152
+
153
+ def sections_sequence_validate_end(names, elem)
154
+ while elem&.name == "annex"
155
+ elem = names.shift
156
+ if elem.nil?
141
157
  @log.add("Style", nil, "Document must include (references) "\
142
158
  "Normative References")
143
159
  end
144
160
  end
145
- n&.at("./self::references[@normative = 'true']") ||
161
+ elem&.at("./self::references[@normative = 'true']") ||
146
162
  @log.add("Style", nil, "Document must include (references) "\
147
163
  "Normative References")
148
- n = names&.shift
149
- n&.at("./self::references[@normative = 'false']") ||
150
- @log.add("Style", n, "Final section must be (references) Bibliography")
164
+ elem = names&.shift
165
+ elem&.at("./self::references[@normative = 'false']") ||
166
+ @log.add("Style", elem, "Final section must be (references) Bibliography")
151
167
  names.empty? ||
152
- @log.add("Style", n, "There are sections after the final Bibliography")
168
+ @log.add("Style", elem, "There are sections after the final Bibliography")
153
169
  end
154
170
 
155
171
  def style_warning(node, msg, text = nil)
@@ -102,8 +102,8 @@ module Asciidoctor
102
102
  # ISO/IEC DIR 2, Table B.1
103
103
  def style_number(node, text)
104
104
  style_two_regex_not_prev(
105
- node, text, /^(?<num>-?[0-9]{4,}[,0-9]*)$/,
106
- %r{\b(ISO|IEC|IEEE/|(in|January|February|March|April|May|June|August|September|October|November|December)\b)$},
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
107
  "number not broken up in threes"
108
108
  )
109
109
  style_regex(/\b(?<num>[0-9]+\.[0-9]+)/i,
@@ -123,7 +123,7 @@ module Asciidoctor
123
123
  # ISO/IEC DIR 2, 8.4
124
124
  # ISO/IEC DIR 2, 9.3
125
125
  def style_abbrev(node, text)
126
- style_regex(/(^|\s)(?!e\.g\.|i\.e\.)
126
+ style_regex(/(\A|\s)(?!e\.g\.|i\.e\.)
127
127
  (?<num>[a-z]{1,2}\.([a-z]{1,2}|\.))\b/ix,
128
128
  "no dots in abbreviations", node, text)
129
129
  style_regex(/\b(?<num>ppm)\b/i,
@@ -13,8 +13,8 @@ module IsoDoc
13
13
  super
14
14
  end
15
15
 
16
- def implicit_reference(b)
17
- return true if b&.at(ns("./docidentifier"))&.text == "IEV"
16
+ def implicit_reference(bib)
17
+ return true if bib&.at(ns("./docidentifier"))&.text == "IEV"
18
18
 
19
19
  super
20
20
  end
@@ -32,7 +32,7 @@ module IsoDoc
32
32
  return if name.nil?
33
33
 
34
34
  div.span **{ class: "example_label" } do |p|
35
- name.children.each { |n| parse(n, div) }
35
+ name.children.each { |n| parse(n, p) }
36
36
  end
37
37
  end
38
38
 
@@ -89,7 +89,7 @@ module IsoDoc
89
89
  return unless insert = node.at(ns("./definition"))
90
90
 
91
91
  insert = insertall_after_here(node, insert, "termexample")
92
- insert = insertall_after_here(node, insert, "termnote")
92
+ insertall_after_here(node, insert, "termnote")
93
93
  end
94
94
 
95
95
  def termdef_parse(node, out)
@@ -110,26 +110,29 @@ module IsoDoc
110
110
  end
111
111
  end
112
112
 
113
- def formula_where(dl, out)
114
- return if dl.nil?
115
- return super unless (dl&.xpath(ns("./dt"))&.size == 1 &&
116
- dl&.at(ns("./dd"))&.elements&.size == 1 &&
117
- dl&.at(ns("./dd/p")))
113
+ def formula_where(dlist, out)
114
+ return if dlist.nil?
115
+ return super unless dlist&.xpath(ns("./dt"))&.size == 1 &&
116
+ dlist&.at(ns("./dd"))&.elements&.size == 1 &&
117
+ dlist&.at(ns("./dd/p"))
118
118
 
119
119
  out.span **{ class: "zzMoveToFollowing" } do |s|
120
120
  s << "#{@i18n.where} "
121
- dl.at(ns("./dt")).children.each { |n| parse(n, s) }
121
+ dlist.at(ns("./dt")).children.each { |n| parse(n, s) }
122
122
  s << " "
123
123
  end
124
- parse(dl.at(ns("./dd/p")), out)
124
+ parse(dlist.at(ns("./dd/p")), out)
125
125
  end
126
126
 
127
127
  def admonition_parse(node, out)
128
128
  type = node["type"]
129
129
  name = admonition_name(node, type)
130
130
  out.div **{ id: node["id"], class: admonition_class(node) } do |div|
131
- node.first_element_child.name == "p" ?
132
- admonition_p_parse(node, div, name) : admonition_parse1(node, div, name)
131
+ if node.first_element_child.name == "p"
132
+ admonition_p_parse(node, div, name)
133
+ else
134
+ admonition_parse1(node, div, name)
135
+ end
133
136
  end
134
137
  end
135
138
 
@@ -153,17 +156,39 @@ module IsoDoc
153
156
  div << " &mdash; "
154
157
  end
155
158
 
156
- def figure_name_parse(node, div, name)
159
+ def figure_name_parse(_node, div, name)
157
160
  div.p **{ class: "FigureTitle", style: "text-align:center;" } do |p|
158
- name&.children&.each { |n| parse(n, div) }
161
+ name&.children&.each { |n| parse(n, p) }
159
162
  end
160
163
  end
161
164
 
162
165
  def middle(isoxml, out)
163
- super
166
+ middle_title(isoxml, out)
167
+ middle_admonitions(isoxml, out)
168
+ i = scope isoxml, out, 0
169
+ i = norm_ref isoxml, out, i
170
+ # i = terms_defs isoxml, out, i
171
+ # symbols_abbrevs isoxml, out, i
172
+ clause_etc isoxml, out, i
173
+ annex isoxml, out
174
+ bibliography isoxml, out
164
175
  indexsect isoxml, out
165
176
  end
166
177
 
178
+ def clause_etc(isoxml, out, num)
179
+ isoxml.xpath(ns("//sections/clause[not(@type = 'scope')] | "\
180
+ "//sections/terms | //sections/definitions")).each do |f|
181
+ out.div **attr_code(id: f["id"],
182
+ class: f.name == "definitions" ? "Symbols" : nil) do |div|
183
+ num = num + 1
184
+ clause_name(num, f&.at(ns("./title")), div, nil)
185
+ f.elements.each do |e|
186
+ parse(e, div) unless %w{title source}.include? e.name
187
+ end
188
+ end
189
+ end
190
+ end
191
+
167
192
  def indexsect(isoxml, out)
168
193
  isoxml.xpath(ns("//indexsect")).each do |i|
169
194
  clause_parse(i, out)