metanorma-standoc 1.10.2 → 1.10.4.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/asciidoctor/standoc/base.rb +13 -5
  3. data/lib/asciidoctor/standoc/blocks.rb +35 -31
  4. data/lib/asciidoctor/standoc/cleanup.rb +61 -0
  5. data/lib/asciidoctor/standoc/cleanup_block.rb +6 -3
  6. data/lib/asciidoctor/standoc/cleanup_reqt.rb +59 -14
  7. data/lib/asciidoctor/standoc/converter.rb +4 -0
  8. data/lib/asciidoctor/standoc/datamodel/diagram_preprocessor.rb +22 -21
  9. data/lib/asciidoctor/standoc/isodoc.rng +12 -0
  10. data/lib/asciidoctor/standoc/lists.rb +9 -6
  11. data/lib/asciidoctor/standoc/macros.rb +18 -0
  12. data/lib/asciidoctor/standoc/ref.rb +60 -56
  13. data/lib/asciidoctor/standoc/reqt.rb +39 -27
  14. data/lib/asciidoctor/standoc/reqt.rng +15 -4
  15. data/lib/asciidoctor/standoc/validate_section.rb +2 -1
  16. data/lib/isodoc/base.standard.xsl +6003 -0
  17. data/lib/isodoc/pdf_convert.rb +20 -0
  18. data/lib/metanorma-standoc.rb +1 -0
  19. data/lib/metanorma/standoc/processor.rb +5 -1
  20. data/lib/metanorma/standoc/version.rb +1 -1
  21. data/metanorma-standoc.gemspec +1 -1
  22. data/spec/asciidoctor/base_spec.rb +6 -0
  23. data/spec/asciidoctor/blocks_spec.rb +45 -25
  24. data/spec/asciidoctor/cleanup_sections_spec.rb +899 -864
  25. data/spec/asciidoctor/cleanup_spec.rb +136 -2
  26. data/spec/asciidoctor/macros_plantuml_spec.rb +165 -104
  27. data/spec/asciidoctor/macros_spec.rb +208 -0
  28. data/spec/asciidoctor/validate_spec.rb +4 -0
  29. data/spec/examples/datamodel/address_class_profile.adoc +1 -0
  30. data/spec/examples/datamodel/address_component_profile.adoc +1 -0
  31. data/spec/examples/datamodel/blank_definition_profile.adoc +1 -0
  32. data/spec/examples/datamodel/common_models_diagram.adoc +2 -1
  33. data/spec/examples/datamodel/top_down_diagram.adoc +2 -1
  34. data/spec/fixtures/datamodel_description_sections_tree.xml +327 -0
  35. data/spec/fixtures/test.xmi +9250 -0
  36. data/spec/metanorma/processor_spec.rb +50 -50
  37. data/spec/support/shared_examples/structured_data_2_text_preprocessor.rb +34 -34
  38. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +50 -50
  39. data/spec/vcr_cassettes/isobib_get_123.yml +11 -11
  40. data/spec/vcr_cassettes/isobib_get_123_1.yml +23 -23
  41. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +35 -35
  42. data/spec/vcr_cassettes/isobib_get_123_2001.yml +12 -12
  43. data/spec/vcr_cassettes/isobib_get_124.yml +11 -11
  44. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +14 -14
  45. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +46 -46
  46. metadata +8 -4
@@ -1011,8 +1011,14 @@
1011
1011
  <ref name="imagemap"/>
1012
1012
  <ref name="svgmap"/>
1013
1013
  <ref name="inputform"/>
1014
+ <ref name="toc"/>
1014
1015
  </choice>
1015
1016
  </define>
1017
+ <define name="toc">
1018
+ <element name="toc">
1019
+ <ref name="ul"/>
1020
+ </element>
1021
+ </define>
1016
1022
  <define name="inputform">
1017
1023
  <element name="form">
1018
1024
  <attribute name="id">
@@ -1254,6 +1260,12 @@
1254
1260
  <optional>
1255
1261
  <attribute name="type"/>
1256
1262
  </optional>
1263
+ <optional>
1264
+ <attribute name="identifier"/>
1265
+ </optional>
1266
+ <optional>
1267
+ <attribute name="prefix"/>
1268
+ </optional>
1257
1269
  <text/>
1258
1270
  </define>
1259
1271
  <define name="ics">
@@ -31,7 +31,7 @@ module Asciidoctor
31
31
  c = node.attr?("checked")
32
32
  attr_code(
33
33
  uncheckedcheckbox: node.attr?("checkbox") ? !c : nil,
34
- checkedcheckbox: node.attr?("checkbox") ? c : nil
34
+ checkedcheckbox: node.attr?("checkbox") ? c : nil,
35
35
  )
36
36
  end
37
37
 
@@ -52,12 +52,14 @@ module Asciidoctor
52
52
  return "roman" if style == "lowerroman"
53
53
  return "roman_upper" if style == "upperroman"
54
54
  return "alphabet_upper" if style == "upperalpha"
55
+
55
56
  style
56
57
  end
57
58
 
58
59
  def ol_attrs(node)
59
- attr_code(keep_attrs(node).merge(id: Metanorma::Utils::anchor_or_uuid(node),
60
- type: olist_style(node.style)))
60
+ attr_code(keep_attrs(node)
61
+ .merge(id: Metanorma::Utils::anchor_or_uuid(node),
62
+ type: olist_style(node.style)))
61
63
  end
62
64
 
63
65
  def olist(node)
@@ -89,9 +91,10 @@ module Asciidoctor
89
91
  end
90
92
 
91
93
  def dl_attrs(node)
92
- attr_code(keep_attrs(node).
93
- merge(id: Metanorma::Utils::anchor_or_uuid(node),
94
- key: node.option?("key") ? "true" : nil))
94
+ attr_code(keep_attrs(node)
95
+ .merge(id: Metanorma::Utils::anchor_or_uuid(node),
96
+ metadata: node.option?("metadata") ? "true" : nil,
97
+ key: node.option?("key") ? "true" : nil))
95
98
  end
96
99
 
97
100
  def dlist(node)
@@ -2,6 +2,7 @@ require "asciidoctor/extensions"
2
2
  require "fileutils"
3
3
  require "uuidtools"
4
4
  require "yaml"
5
+ require "csv"
5
6
  require_relative "./macros_plantuml"
6
7
  require_relative "./macros_terms"
7
8
  require_relative "./macros_form"
@@ -211,5 +212,22 @@ module Asciidoctor
211
212
  %{<del>#{out}</del>}
212
213
  end
213
214
  end
215
+
216
+ class ToCInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
217
+ use_dsl
218
+ named :toc
219
+ parse_content_as :text
220
+ using_format :short
221
+
222
+ def process(parent, _target, attrs)
223
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
224
+ content = CSV.parse_line(out).map do |x|
225
+ x.sub!(/^(["'])(.+)\1/, "\\2")
226
+ m = /^(.*?)(:\d+)?$/.match(x)
227
+ %{<toc-xpath depth='#{m[2]&.sub(/:/, '') || 1}'>#{m[1]}</toc-xpath>}
228
+ end.join
229
+ "<toc>#{content}</toc>"
230
+ end
231
+ end
214
232
  end
215
233
  end
@@ -4,7 +4,7 @@ module Asciidoctor
4
4
  module Standoc
5
5
  module Refs
6
6
  def iso_publisher(bib, code)
7
- code.sub(/ .*$/, "").split(/\//).each do |abbrev|
7
+ code.sub(/ .*$/, "").split("/").each do |abbrev|
8
8
  bib.contributor do |c|
9
9
  c.role **{ type: "publisher" }
10
10
  c.organization do |org|
@@ -18,75 +18,78 @@ module Asciidoctor
18
18
  { format: "text/plain" }
19
19
  end
20
20
 
21
- def ref_attributes(m)
22
- { id: m[:anchor], type: "standard" }
21
+ def ref_attributes(match)
22
+ { id: match[:anchor], type: "standard" }
23
23
  end
24
24
 
25
- def isorefrender1(bib, m, yr, allp = "")
26
- bib.title(**plaintxt) { |i| i << ref_normalise(m[:text]) }
27
- docid(bib, m[:usrlbl]) if m[:usrlbl]
28
- docid(bib, id_and_year(m[:code], yr) + allp)
29
- docnumber(bib, m[:code])
25
+ def isorefrender1(bib, match, yr, allp = "")
26
+ bib.title(**plaintxt) { |i| i << ref_normalise(match[:text]) }
27
+ docid(bib, match[:usrlbl]) if match[:usrlbl]
28
+ docid(bib, id_and_year(match[:code], yr) + allp)
29
+ docnumber(bib, match[:code])
30
30
  end
31
31
 
32
- def isorefmatches(xml, m)
33
- yr = norm_year(m[:year])
34
- ref = fetch_ref xml, m[:code], yr, title: m[:text], usrlbl: m[:usrlbl],
35
- lang: (@lang || :all)
36
- return use_my_anchor(ref, m[:anchor]) if ref
32
+ def isorefmatches(xml, match)
33
+ yr = norm_year(match[:year])
34
+ ref = fetch_ref xml, match[:code], yr,
35
+ title: match[:text], usrlbl: match[:usrlbl],
36
+ lang: (@lang || :all)
37
+ return use_my_anchor(ref, match[:anchor]) if ref
37
38
 
38
- xml.bibitem **attr_code(ref_attributes(m)) do |t|
39
- isorefrender1(t, m, yr)
39
+ xml.bibitem **attr_code(ref_attributes(match)) do |t|
40
+ isorefrender1(t, match, yr)
40
41
  yr and t.date **{ type: "published" } do |d|
41
42
  set_date_range(d, yr)
42
43
  end
43
- iso_publisher(t, m[:code])
44
+ iso_publisher(t, match[:code])
44
45
  end
45
46
  end
46
47
 
47
- def isorefmatches2(xml, m)
48
- ref = fetch_ref xml, m[:code], nil, no_year: true, note: m[:fn],
49
- title: m[:text], usrlbl: m[:usrlbl], lang: (@lang || :all)
50
- return use_my_anchor(ref, m[:anchor]) if ref
48
+ def isorefmatches2(xml, match)
49
+ ref = fetch_ref xml, match[:code], nil,
50
+ no_year: true, note: match[:fn],
51
+ title: match[:text], usrlbl: match[:usrlbl],
52
+ lang: (@lang || :all)
53
+ return use_my_anchor(ref, match[:anchor]) if ref
51
54
 
52
- isorefmatches2_1(xml, m)
55
+ isorefmatches2_1(xml, match)
53
56
  end
54
57
 
55
- def isorefmatches2_1(xml, m)
56
- xml.bibitem **attr_code(ref_attributes(m)) do |t|
57
- isorefrender1(t, m, "--")
58
+ def isorefmatches2_1(xml, match)
59
+ xml.bibitem **attr_code(ref_attributes(match)) do |t|
60
+ isorefrender1(t, match, "--")
58
61
  t.date **{ type: "published" } do |d|
59
62
  d.on "--"
60
63
  end
61
- iso_publisher(t, m[:code])
62
- unless m[:fn].nil?
64
+ iso_publisher(t, match[:code])
65
+ unless match[:fn].nil?
63
66
  t.note(**plaintxt.merge(type: "Unpublished-Status")) do |p|
64
- p << (m[:fn]).to_s
67
+ p << (match[:fn]).to_s
65
68
  end
66
69
  end
67
70
  end
68
71
  end
69
72
 
70
- def isorefmatches3(xml, m)
71
- yr = norm_year(m[:year])
73
+ def isorefmatches3(xml, match)
74
+ yr = norm_year(match[:year])
72
75
  hasyr = !yr.nil? && yr != "--"
73
- ref = fetch_ref(xml, m[:code], hasyr ? yr : nil,
74
- all_parts: true,
75
- no_year: yr == "--", text: m[:text], usrlbl: m[:usrlbl],
76
+ ref = fetch_ref(xml, match[:code], hasyr ? yr : nil,
77
+ all_parts: true, no_year: yr == "--",
78
+ text: match[:text], usrlbl: match[:usrlbl],
76
79
  lang: (@lang || :all))
77
- return use_my_anchor(ref, m[:anchor]) if ref
80
+ return use_my_anchor(ref, match[:anchor]) if ref
78
81
 
79
- isorefmatches3_1(xml, m, yr, hasyr, ref)
82
+ isorefmatches3_1(xml, match, yr, hasyr, ref)
80
83
  end
81
84
 
82
- def isorefmatches3_1(xml, m, yr, _hasyr, _ref)
83
- xml.bibitem(**attr_code(ref_attributes(m))) do |t|
84
- isorefrender1(t, m, yr, " (all parts)")
85
- conditional_date(t, m, yr == "--")
86
- iso_publisher(t, m[:code])
87
- if m.names.include?("fn") && m[:fn]
85
+ def isorefmatches3_1(xml, match, yr, _hasyr, _ref)
86
+ xml.bibitem(**attr_code(ref_attributes(match))) do |t|
87
+ isorefrender1(t, match, yr, " (all parts)")
88
+ conditional_date(t, match, yr == "--")
89
+ iso_publisher(t, match[:code])
90
+ if match.names.include?("fn") && match[:fn]
88
91
  t.note(**plaintxt.merge(type: "Unpublished-Status")) do |p|
89
- p << (m[:fn]).to_s
92
+ p << (match[:fn]).to_s
90
93
  end
91
94
  end
92
95
  t.extent **{ type: "part" } do |e|
@@ -95,23 +98,23 @@ module Asciidoctor
95
98
  end
96
99
  end
97
100
 
98
- def refitem_render1(m, code, bib)
101
+ def refitem_render1(match, code, bib)
99
102
  if code[:type] == "path"
100
103
  bib.uri code[:key].sub(/\.[a-zA-Z0-9]+$/, ""), **{ type: "URI" }
101
104
  bib.uri code[:key].sub(/\.[a-zA-Z0-9]+$/, ""), **{ type: "citation" }
102
105
  end
103
- docid(bib, m[:usrlbl]) if m[:usrlbl]
106
+ docid(bib, match[:usrlbl]) if match[:usrlbl]
104
107
  docid(bib, /^\d+$/.match?(code[:id]) ? "[#{code[:id]}]" : code[:id])
105
108
  code[:type] == "repo" and
106
109
  bib.docidentifier code[:key], **{ type: "repository" }
107
110
  end
108
111
 
109
- def refitem_render(xml, m, code)
110
- xml.bibitem **attr_code(id: m[:anchor]) do |t|
112
+ def refitem_render(xml, match, code)
113
+ xml.bibitem **attr_code(id: match[:anchor]) do |t|
111
114
  t.formattedref **{ format: "application/x-isodoc+xml" } do |i|
112
- i << ref_normalise_no_format(m[:text])
115
+ i << ref_normalise_no_format(match[:text])
113
116
  end
114
- refitem_render1(m, code, t)
117
+ refitem_render1(match, code, t)
115
118
  docnumber(t, code[:id]) unless /^\d+$|^\(.+\)$/.match?(code[:id])
116
119
  end
117
120
  end
@@ -128,7 +131,7 @@ module Asciidoctor
128
131
 
129
132
  def analyse_ref_repo_path(ret)
130
133
  return ret unless m =
131
- /^(?<type>repo|path):\((?<key>[^,]+),?(?<id>.*)\)$/.match(ret[:id])
134
+ /^(?<type>repo|path):\((?<key>[^,]+),?(?<id>.*)\)$/.match(ret[:id])
132
135
 
133
136
  id = m[:id].empty? ? m[:key].sub(%r{^[^/]+/}, "") : m[:id]
134
137
  ret.merge(id: id, type: m[:type], key: m[:key], nofetch: true)
@@ -156,16 +159,17 @@ module Asciidoctor
156
159
  nil
157
160
  end
158
161
 
159
- def refitem1(xml, _item, m)
160
- code = analyse_ref_code(m[:code])
162
+ def refitem1(xml, _item, match)
163
+ code = analyse_ref_code(match[:code])
161
164
  unless code[:id] && code[:numeric] || code[:nofetch]
162
165
  ref = fetch_ref(xml, code[:id],
163
- m.names.include?("year") ? m[:year] : nil,
164
- title: m[:text],
165
- usrlbl: m[:usrlbl], lang: (@lang || :all))
166
- return use_my_anchor(ref, m[:anchor]) if ref
166
+ match.names.include?("year") ? match[:year] : nil,
167
+ title: match[:text],
168
+ usrlbl: match[:usrlbl], lang: (@lang || :all)) and
169
+ return use_my_anchor(ref, match[:anchor])
167
170
  end
168
- refitem_render(xml, m, code)
171
+
172
+ refitem_render(xml, match, code)
169
173
  end
170
174
 
171
175
  def ref_normalise(ref)
@@ -186,7 +190,7 @@ module Asciidoctor
186
190
  \[(?<usrlbl>\([^)]+\))?(?<code>(ISO|IEC)[^0-9]*\s[0-9-]+):
187
191
  (--|&\#821[12];)\]</ref>,?\s*
188
192
  (<fn[^>]*>\s*<p>(?<fn>[^\]]+)</p>\s*</fn>)?,?\s?(?<text>.*)$}xm
189
- .freeze
193
+ .freeze
190
194
 
191
195
  ISO_REF_ALL_PARTS =
192
196
  %r{^<ref\sid="(?<anchor>[^"]+)">
@@ -6,20 +6,23 @@ require "base64"
6
6
  module Asciidoctor
7
7
  module Standoc
8
8
  module Blocks
9
- def reqt_subpart(x)
9
+ def reqt_subpart(name)
10
10
  %w(specification measurement-target verification import label
11
- subject inherit classification title).include? x
11
+ component subject inherit classification title).include? name
12
12
  end
13
13
 
14
- def reqt_subpart_attrs(node)
15
- attr_code(keep_attrs(node).merge(exclude: node.option?("exclude"),
16
- type: node.attr("type")))
14
+ def reqt_subpart_attrs(node, name)
15
+ klass = node.attr("class") || "component"
16
+ attr_code(keep_attrs(node)
17
+ .merge(exclude: node.option?("exclude"),
18
+ type: node.attr("type"),
19
+ class: name == "component" ? klass : nil))
17
20
  end
18
21
 
19
22
  def requirement_subpart(node)
20
23
  name = node.role || node.attr("style")
21
24
  noko do |xml|
22
- xml.send name, **reqt_subpart_attrs(node) do |o|
25
+ xml.send name, **reqt_subpart_attrs(node, name) do |o|
23
26
  o << node.content
24
27
  end
25
28
  end
@@ -30,14 +33,15 @@ module Asciidoctor
30
33
  HTMLEntities.new.decode(classif).split(/;\s*/).each do |c|
31
34
  c1 = c.split(/:\s*/)
32
35
  next unless c1.size == 2
33
- c1[1].split(/,\s*/).each { |v| ret << [ c1[0], v ] }
36
+
37
+ c1[1].split(/,\s*/).each { |v| ret << [c1[0], v] }
34
38
  end
35
39
  ret
36
40
  end
37
41
 
38
- def requirement_classification(classif, ex)
42
+ def requirement_classification(classif, out)
39
43
  req_classif_parse(classif).each do |r|
40
- ex.classification do |c|
44
+ out.classification do |c|
41
45
  c.tag { |t| t << r[0] }
42
46
  c.value { |v| v << r[1] }
43
47
  end
@@ -46,29 +50,37 @@ module Asciidoctor
46
50
 
47
51
  def reqt_attrs(node)
48
52
  attr_code(keep_attrs(node).merge(id_unnum_attrs(node)).merge(
49
- id: Metanorma::Utils::anchor_or_uuid(node),
50
- unnumbered: node.option?("unnumbered") ? "true" : nil,
51
- number: node.attr("number"),
52
- subsequence: node.attr("subsequence"),
53
- obligation: node.attr("obligation"),
54
- filename: node.attr("filename"),
55
- type: node.attr("type"),
56
- model: node.attr("model"),
57
- ))
53
+ id: Metanorma::Utils::anchor_or_uuid(node),
54
+ unnumbered: node.option?("unnumbered") ? "true" : nil,
55
+ number: node.attr("number"),
56
+ subsequence: node.attr("subsequence"),
57
+ obligation: node.attr("obligation"),
58
+ filename: node.attr("filename"),
59
+ type: node.attr("type"),
60
+ model: node.attr("model"),
61
+ ))
62
+ end
63
+
64
+ def requirement_elems(node, out)
65
+ node.title and out.title { |t| t << node.title }
66
+ a = node.attr("label") and out.label do |l|
67
+ l << a
68
+ end
69
+ a = node.attr("subject") and csv_split(a)&.each do |subj|
70
+ out.subject { |s| s << subj }
71
+ end
72
+ a = HTMLEntities.new.decode(node.attr("inherit")) and
73
+ csv_split(a)&.each do |i|
74
+ out.inherit { |inh| inh << i }
75
+ end
76
+ classif = node.attr("classification") and
77
+ requirement_classification(classif, out)
58
78
  end
59
79
 
60
80
  def requirement(node, obligation)
61
- classif = node.attr("classification")
62
81
  noko do |xml|
63
82
  xml.send obligation, **reqt_attrs(node) do |ex|
64
- node.title and ex.title { |t| t << node.title }
65
- node.attr("label") and ex.label { |l| l << node.attr("label") }
66
- node.attr("subject") and ex.subject { |s| s << node.attr("subject") }
67
- i = HTMLEntities.new.decode(node.attr("inherit"))
68
- i&.split(/;\s*/)&.each do |i|
69
- ex.inherit { |inh| inh << i }
70
- end
71
- requirement_classification(classif, ex) if classif
83
+ requirement_elems(node, ex)
72
84
  wrap_in_para(node, ex)
73
85
  end
74
86
  end.join("\n")
@@ -64,9 +64,9 @@
64
64
  <optional>
65
65
  <ref name="label"/>
66
66
  </optional>
67
- <optional>
67
+ <zeroOrMore>
68
68
  <ref name="subject"/>
69
- </optional>
69
+ </zeroOrMore>
70
70
  <zeroOrMore>
71
71
  <ref name="reqinherit"/>
72
72
  </zeroOrMore>
@@ -80,6 +80,7 @@
80
80
  <ref name="verification"/>
81
81
  <ref name="import"/>
82
82
  <ref name="description"/>
83
+ <ref name="component"/>
83
84
  </choice>
84
85
  </zeroOrMore>
85
86
  <optional>
@@ -105,12 +106,16 @@
105
106
  </define>
106
107
  <define name="subject">
107
108
  <element name="subject">
108
- <text/>
109
+ <oneOrMore>
110
+ <ref name="TextElement"/>
111
+ </oneOrMore>
109
112
  </element>
110
113
  </define>
111
114
  <define name="reqinherit">
112
115
  <element name="inherit">
113
- <text/>
116
+ <oneOrMore>
117
+ <ref name="TextElement"/>
118
+ </oneOrMore>
114
119
  </element>
115
120
  </define>
116
121
  <define name="measurementtarget">
@@ -138,6 +143,12 @@
138
143
  <ref name="RequirementSubpart"/>
139
144
  </element>
140
145
  </define>
146
+ <define name="component">
147
+ <element name="component">
148
+ <attribute name="class"/>
149
+ <ref name="RequirementSubpart"/>
150
+ </element>
151
+ </define>
141
152
  <define name="reqt_references">
142
153
  <element name="references">
143
154
  <oneOrMore>