metanorma-standoc 1.10.2 → 1.10.4.1

Sign up to get free protection for your applications and to get access to all the features.
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>