metanorma-standoc 2.2.0.1 → 2.2.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +1 -1
  3. data/.github/workflows/release.yml +24 -0
  4. data/lib/metanorma/standoc/base.rb +16 -0
  5. data/lib/metanorma/standoc/biblio.rng +8 -5
  6. data/lib/metanorma/standoc/blocks.rb +26 -13
  7. data/lib/metanorma/standoc/cleanup_biblio.rb +16 -10
  8. data/lib/metanorma/standoc/cleanup_reqt.rb +3 -136
  9. data/lib/metanorma/standoc/converter.rb +0 -7
  10. data/lib/metanorma/standoc/front.rb +6 -1
  11. data/lib/metanorma/standoc/front_contributor.rb +0 -10
  12. data/lib/metanorma/standoc/macros_terms.rb +5 -4
  13. data/lib/metanorma/standoc/reqt.rb +24 -73
  14. data/lib/metanorma/standoc/section.rb +35 -3
  15. data/lib/metanorma/standoc/terms.rb +13 -7
  16. data/lib/metanorma/standoc/utils.rb +9 -43
  17. data/lib/metanorma/standoc/validate.rb +18 -0
  18. data/lib/metanorma/standoc/version.rb +1 -1
  19. data/lib/metanorma-standoc.rb +1 -1
  20. data/metanorma-standoc.gemspec +5 -4
  21. data/spec/assets/correct.png +0 -0
  22. data/spec/assets/corrupt.png +0 -0
  23. data/spec/metanorma/base_spec.rb +6 -7
  24. data/spec/metanorma/biblio_spec.rb +8 -8
  25. data/spec/metanorma/blocks_spec.rb +20 -266
  26. data/spec/metanorma/cleanup_blocks_spec.rb +0 -168
  27. data/spec/metanorma/macros_concept_spec.rb +1052 -0
  28. data/spec/metanorma/macros_spec.rb +0 -1126
  29. data/spec/metanorma/reqt_spec.rb +130 -0
  30. data/spec/metanorma/section_spec.rb +5 -0
  31. data/spec/metanorma/validate_spec.rb +49 -0
  32. data/spec/requirements/default/blocks_spec.rb +250 -0
  33. data/spec/requirements/default/cleanup_spec.rb +173 -0
  34. data/spec/requirements/modspec/cleanup_spec.rb +333 -0
  35. data/spec/requirements/modspec/validate_spec.rb +330 -0
  36. data/spec/vcr_cassettes/bsi16341.yml +52 -36
  37. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +88 -88
  38. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +10 -10
  39. data/spec/vcr_cassettes/hide_refs.yml +65 -65
  40. data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
  41. data/spec/vcr_cassettes/isobib_get_123_1.yml +22 -22
  42. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +30 -30
  43. data/spec/vcr_cassettes/isobib_get_123_2.yml +21 -21
  44. data/spec/vcr_cassettes/isobib_get_123_2001.yml +11 -11
  45. data/spec/vcr_cassettes/isobib_get_124.yml +11 -11
  46. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +34 -58
  47. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +45 -45
  48. data/spec/vcr_cassettes/std-link.yml +11 -11
  49. metadata +50 -28
  50. data/lib/isodoc/html/htmlstyle.css +0 -998
@@ -0,0 +1,130 @@
1
+ require "spec_helper"
2
+ require "open3"
3
+
4
+ RSpec.describe Metanorma::Standoc do
5
+ it "processes recommendation" do
6
+ input = <<~"INPUT"
7
+ #{ASCIIDOC_BLANK_HDR}
8
+ [.recommendation,identifier="/ogc/recommendation/wfs/2",subject="user;developer, implementer",inherit="/ss/584/2015/level/1; /ss/584/2015/level/2",options="unnumbered",type=verification,model=ogc,tag=X,multilingual-rendering=common]
9
+ ====
10
+ I recommend this
11
+ ====
12
+ INPUT
13
+ output = <<~"OUTPUT"
14
+ #{BLANK_HDR}
15
+ <sections>
16
+ <recommendation id="_" unnumbered="true" type="verification" model="ogc" tag='X' multilingual-rendering='common'>
17
+ <identifier>/ogc/recommendation/wfs/2</identifier>
18
+ <subject>user</subject>
19
+ <subject>developer, implementer</subject>
20
+ <inherit>/ss/584/2015/level/1</inherit>
21
+ <inherit>/ss/584/2015/level/2</inherit>
22
+ <description><p id="_">I recommend this</p>
23
+ </description>
24
+ </recommendation>
25
+ </sections>
26
+ </standard-document>
27
+ OUTPUT
28
+
29
+ expect(xmlpp(strip_guid(Asciidoctor.convert(input, *OPTIONS))))
30
+ .to be_equivalent_to xmlpp(output)
31
+ end
32
+
33
+ it "applies default requirement model" do
34
+ mock_default_recommendation_model("ogc")
35
+ input = <<~"INPUT"
36
+ #{ASCIIDOC_BLANK_HDR}
37
+
38
+ [[A]]
39
+ [.permission]
40
+ ====
41
+ I permit this
42
+
43
+
44
+ [[B]]
45
+ [.permission]
46
+ =====
47
+ I also permit this
48
+
49
+ . List
50
+ . List
51
+ =====
52
+ ====
53
+ INPUT
54
+
55
+ xml = Nokogiri::XML(Asciidoctor.convert(input, *OPTIONS))
56
+ expect(xml.at("//xmlns:permission[@id = 'A']/@model").text).to eq("ogc")
57
+ expect(xml.at("//xmlns:permission/xmlns:permission/@model").text)
58
+ .to eq("ogc")
59
+ end
60
+
61
+ it "overrides default requirement model" do
62
+ mock_default_recommendation_model("ogc")
63
+ input = <<~"INPUT"
64
+ = Document title
65
+ Author
66
+ :docfile: test.adoc
67
+ :nodoc:
68
+ :novalid:
69
+ :no-isobib:
70
+ :data-uri-image: false
71
+ :requirements-model: default
72
+
73
+ [[A]]
74
+ [.permission]
75
+ ====
76
+ I permit this
77
+
78
+ [[B]]
79
+ [.permission]
80
+ =====
81
+ I also permit this
82
+
83
+ . List
84
+ . List
85
+ =====
86
+ ====
87
+ INPUT
88
+
89
+ xml = Nokogiri::XML(Asciidoctor.convert(input, *OPTIONS))
90
+ expect(xml.at("//xmlns:permission[@id = 'A']/@model").text).to eq("default")
91
+ expect(xml.at("//xmlns:permission/xmlns:permission/@model").text)
92
+ .to eq("default")
93
+ end
94
+
95
+ it "inherits requirement model from parent" do
96
+ mock_default_recommendation_model("ogc")
97
+ input = <<~"INPUT"
98
+
99
+ #{ASCIIDOC_BLANK_HDR}
100
+ [[A]]
101
+ [.permission,model=ogc]
102
+ ====
103
+ I permit this
104
+
105
+ [[B]]
106
+ [.permission,model=default]
107
+ =====
108
+ I also permit this
109
+
110
+ . List
111
+ . List
112
+ =====
113
+ ====
114
+ INPUT
115
+
116
+ xml = Nokogiri::XML(Asciidoctor.convert(input, *OPTIONS))
117
+ expect(xml.at("//xmlns:permission[@id = 'A']/@model").text).to eq("ogc")
118
+ expect(xml.at("//xmlns:permission/xmlns:permission/@model").text)
119
+ .to eq("ogc")
120
+ end
121
+
122
+ private
123
+
124
+ def mock_default_recommendation_model(model)
125
+ allow_any_instance_of(::Metanorma::Standoc::Blocks)
126
+ .to receive(:default_requirement_model).and_return(
127
+ model,
128
+ )
129
+ end
130
+ end
@@ -77,6 +77,8 @@ RSpec.describe Metanorma::Standoc do
77
77
 
78
78
  == Terms and Definitions
79
79
 
80
+ == Acknowledgements
81
+
80
82
  [appendix]
81
83
  == Annex
82
84
 
@@ -175,6 +177,9 @@ RSpec.describe Metanorma::Standoc do
175
177
  <clause id="_" inline-header="false" obligation="normative">
176
178
  <title>Terms and Definitions</title>
177
179
  </clause>
180
+ <clause id='_' inline-header='false' obligation='normative'>
181
+ <title>Acknowledgements</title>
182
+ </clause>
178
183
  </sections><annex id="_" inline-header="false" obligation="normative">
179
184
  <title>Annex</title>
180
185
  <clause id="_" inline-header="false" obligation="normative">
@@ -782,4 +782,53 @@ RSpec.describe Metanorma::Standoc do
782
782
  expect(File.read("test.err"))
783
783
  .not_to include "Symbol reference in `symbol[xyz]` missing:"
784
784
  end
785
+
786
+ it "warns and aborts if corrupt PNG" do
787
+ FileUtils.rm_f "test.xml"
788
+ FileUtils.rm_f "test.err"
789
+ begin
790
+ input = <<~INPUT
791
+ = Document title
792
+ Author
793
+ :docfile: test.adoc
794
+ :no-pdf:
795
+
796
+ == Clause
797
+ image::spec/assets/corrupt.png[]
798
+
799
+ INPUT
800
+ expect do
801
+ Asciidoctor.convert(input, *OPTIONS)
802
+ end.to raise_error(SystemExit)
803
+ rescue SystemExit, RuntimeError
804
+ end
805
+ warn File.read("test.err")
806
+ expect(File.read("test.err"))
807
+ .to include "Corrupt PNG image"
808
+ expect(File.exist?("test.xml")).to be false
809
+ end
810
+
811
+ it "does not warn and abort if not corrupt PNG" do
812
+ FileUtils.rm_f "test.xml"
813
+ FileUtils.rm_f "test.err"
814
+ begin
815
+ input = <<~INPUT
816
+ = Document title
817
+ Author
818
+ :docfile: test.adoc
819
+ :no-pdf:
820
+
821
+ == Clause
822
+ image::spec/assets/correct.png[]
823
+
824
+ INPUT
825
+ expect do
826
+ Asciidoctor.convert(input, *OPTIONS)
827
+ end.not_to raise_error
828
+ rescue SystemExit, RuntimeError
829
+ end
830
+ expect(File.read("test.err"))
831
+ .not_to include "Corrupt PNG image"
832
+ expect(File.exist?("test.xml")).to be true
833
+ end
785
834
  end
@@ -0,0 +1,250 @@
1
+ require "spec_helper"
2
+ require "open3"
3
+
4
+ RSpec.describe Metanorma::Requirements::Default do
5
+ it "processes recommendation" do
6
+ input = <<~"INPUT"
7
+ #{ASCIIDOC_BLANK_HDR}
8
+ [.recommendation,identifier="/ogc/recommendation/wfs/2",subject="user;developer, implementer",inherit="/ss/584/2015/level/1; /ss/584/2015/level/2",options="unnumbered",type=verification,model=ogc,tag=X,multilingual-rendering=common]
9
+ ====
10
+ I recommend this
11
+ ====
12
+ INPUT
13
+ output = <<~"OUTPUT"
14
+ #{BLANK_HDR}
15
+ <sections>
16
+ <recommendation id="_" unnumbered="true" type="verification" model="ogc" tag='X' multilingual-rendering='common'>
17
+ <identifier>/ogc/recommendation/wfs/2</identifier>
18
+ <subject>user</subject>
19
+ <subject>developer, implementer</subject>
20
+ <inherit>/ss/584/2015/level/1</inherit>
21
+ <inherit>/ss/584/2015/level/2</inherit>
22
+ <description><p id="_">I recommend this</p>
23
+ </description>
24
+ </recommendation>
25
+ </sections>
26
+ </standard-document>
27
+ OUTPUT
28
+
29
+ expect(xmlpp(strip_guid(Asciidoctor.convert(input, *OPTIONS))))
30
+ .to be_equivalent_to xmlpp(output)
31
+ end
32
+
33
+ it "processes requirement" do
34
+ input = <<~"INPUT"
35
+ #{ASCIIDOC_BLANK_HDR}
36
+ [[ABC]]
37
+ [.requirement,subsequence="A",inherit="/ss/584/2015/level/1 &amp; /ss/584/2015/level/2",number=3,keep-with-next=true,keep-lines-together=true,tag=X,multilingual-rendering=common]
38
+ .Title
39
+ ====
40
+ I recommend this
41
+
42
+ . http://www.example.com[]
43
+ . <<ABC>>
44
+ ====
45
+ INPUT
46
+ output = <<~OUTPUT
47
+ #{BLANK_HDR}
48
+ <sections>
49
+ <requirement id="ABC" subsequence="A" number="3" keep-with-next="true" keep-lines-together="true" tag='X' multilingual-rendering='common' model="default">
50
+ <title>Title</title>
51
+ <inherit>/ss/584/2015/level/1 &amp; /ss/584/2015/level/2</inherit>
52
+ <description><p id="_">I recommend this</p>
53
+ <ol id='_' type='arabic'>
54
+ <li>
55
+ <p id='_'>
56
+ <link target='http://www.example.com'/>
57
+ </p>
58
+ </li>
59
+ <li>
60
+ <p id='_'>
61
+ <xref target='ABC'/>
62
+ </p>
63
+ </li>
64
+ </ol>
65
+ </description>
66
+ </requirement>
67
+ </sections>
68
+ </standard-document>
69
+ OUTPUT
70
+
71
+ expect(xmlpp(strip_guid(Asciidoctor.convert(input, *OPTIONS))))
72
+ .to be_equivalent_to xmlpp(output)
73
+ end
74
+
75
+ it "processes permission" do
76
+ input = <<~"INPUT"
77
+ #{ASCIIDOC_BLANK_HDR}
78
+
79
+ [[ABC]]
80
+ [.permission,tag=X,multilingual-rendering=common]
81
+ ====
82
+ I recommend this
83
+ ====
84
+ INPUT
85
+ output = <<~"OUTPUT"
86
+ #{BLANK_HDR}
87
+ <sections>
88
+ <permission id="ABC" tag='X' multilingual-rendering='common' model="default">
89
+ <description><p id="_">I recommend this</p></description>
90
+ </permission>
91
+ </sections>
92
+ </standard-document>
93
+ OUTPUT
94
+
95
+ expect(xmlpp(strip_guid(Asciidoctor.convert(input, *OPTIONS))))
96
+ .to be_equivalent_to xmlpp(output)
97
+ end
98
+
99
+ it "processes nested permissions" do
100
+ input = <<~"INPUT"
101
+ #{ASCIIDOC_BLANK_HDR}
102
+ [.permission]
103
+ ====
104
+ I permit this
105
+
106
+ =====
107
+ Example 2
108
+ =====
109
+
110
+ [.permission]
111
+ =====
112
+ I also permit this
113
+
114
+ . List
115
+ . List
116
+ =====
117
+
118
+ [requirement,type="general",identifier="/req/core/quantities-uom"]
119
+ ======
120
+ ======
121
+ ====
122
+ INPUT
123
+ output = <<~"OUTPUT"
124
+ #{BLANK_HDR}
125
+ <sections>
126
+ <permission id="_" model="default"><description><p id="_">I permit this</p>
127
+ <example id="_">
128
+ <p id="_">Example 2</p>
129
+ </example></description>
130
+ <permission id="_" model="default">
131
+ <description><p id="_">I also permit this</p>
132
+ <ol id='_' type='arabic'>
133
+ <li>
134
+ <p id='_'>List</p>
135
+ </li>
136
+ <li>
137
+ <p id='_'>List</p>
138
+ </li>
139
+ </ol>
140
+ </description>
141
+ </permission>
142
+ <requirement id='_' type='general' model="default">
143
+ <identifier>/req/core/quantities-uom</identifier>
144
+ </requirement>
145
+ </permission>
146
+ </sections>
147
+ </standard-document>
148
+ OUTPUT
149
+
150
+ expect(xmlpp(strip_guid(Asciidoctor.convert(input, *OPTIONS))))
151
+ .to be_equivalent_to xmlpp(output)
152
+ end
153
+
154
+ it "processes recommendation with internal markup of structure" do
155
+ input = <<~"INPUT"
156
+ #{ASCIIDOC_BLANK_HDR}
157
+
158
+ [[ABC]]
159
+ [.recommendation,identifier="/ogc/recommendation/wfs/2",subject="user",classification="control-class:Technical;priority:P0;family:System &amp; Communications Protection,System and Communications Protocols",obligation="permission,recommendation",filename="reqt1.rq"]
160
+ ====
161
+ I recommend _this_.
162
+
163
+ [.specification,type="tabular",keep-with-next=true,keep-lines-together=true]
164
+ --
165
+ This is the object of the recommendation:
166
+ |===
167
+ |Object |Value
168
+ |Mission | Accomplished
169
+ |===
170
+ --
171
+
172
+ As for the measurement targets,
173
+
174
+ [.measurement-target]
175
+ --
176
+ The measurement target shall be measured as:
177
+ [stem]
178
+ ++++
179
+ r/1 = 0
180
+ ++++
181
+ --
182
+
183
+ [.verification]
184
+ --
185
+ The following code will be run for verification:
186
+
187
+ [source,CoreRoot]
188
+ ----
189
+ CoreRoot(success): HttpResponse
190
+ if (success)
191
+ recommendation(label: success-response)
192
+ end
193
+ ----
194
+ --
195
+
196
+ [.import%exclude]
197
+ --
198
+ [source,CoreRoot]
199
+ ----
200
+ success-response()
201
+ ----
202
+ --
203
+
204
+ [.component]
205
+ --
206
+ Hello
207
+ --
208
+
209
+ [.component,class=condition]
210
+ --
211
+ If this be thus
212
+ --
213
+ ====
214
+ INPUT
215
+ output = <<~"OUTPUT"
216
+ #{BLANK_HDR}
217
+ <sections>
218
+ <recommendation id="ABC" obligation="permission,recommendation" filename="reqt1.rq" model="default"><identifier>/ogc/recommendation/wfs/2</identifier><subject>user</subject>
219
+ <classification><tag>control-class</tag><value>Technical</value></classification><classification><tag>priority</tag><value>P0</value></classification><classification><tag>family</tag><value>System &amp; Communications Protection</value></classification><classification><tag>family</tag><value>System and Communications Protocols</value></classification>
220
+ <description><p id="_">I recommend <em>this</em>.</p>
221
+ </description><specification exclude="false" type="tabular" keep-with-next="true" keep-lines-together="true"><p id="_">This is the object of the recommendation:</p><table id="_"> <tbody> <tr> <td valign="top" align="left">Object</td> <td valign="top" align="left">Value</td> </tr> <tr> <td valign="top" align="left">Mission</td> <td valign="top" align="left">Accomplished</td> </tr> </tbody></table></specification><description>
222
+ <p id="_">As for the measurement targets,</p>
223
+ </description><measurement-target exclude="false"><p id="_">The measurement target shall be measured as:</p><formula id="_"> <stem type="MathML"><math xmlns="http://www.w3.org/1998/Math/MathML"><mfrac>
224
+ <mrow>
225
+ <mi>r</mi>
226
+ </mrow>
227
+ <mrow>
228
+ <mn>1</mn>
229
+ </mrow>
230
+ </mfrac><mo>=</mo><mn>0</mn></math></stem></formula></measurement-target>
231
+ <verification exclude="false"><p id="_">The following code will be run for verification:</p><sourcecode lang="CoreRoot" id="_">CoreRoot(success): HttpResponse
232
+ if (success)
233
+ recommendation(label: success-response)
234
+ end</sourcecode></verification>
235
+ <import exclude="true"> <sourcecode lang="CoreRoot" id="_">success-response()</sourcecode></import>
236
+ <component exclude='false' class='component'>
237
+ <p id='_'>Hello</p>
238
+ </component>
239
+ <component exclude='false' class='condition'>
240
+ <p id='_'>If this be thus</p>
241
+ </component>
242
+ </recommendation>
243
+ </sections>
244
+ </standard-document>
245
+ OUTPUT
246
+
247
+ expect(xmlpp(strip_guid(Asciidoctor.convert(input, *OPTIONS))))
248
+ .to be_equivalent_to xmlpp(output)
249
+ end
250
+ end
@@ -0,0 +1,173 @@
1
+ require "spec_helper"
2
+ require "fileutils"
3
+
4
+ RSpec.describe Metanorma::Requirements::Default do
5
+ it "moves requirement metadata deflist to correct location" do
6
+ input = <<~INPUT
7
+ #{ASCIIDOC_BLANK_HDR}
8
+
9
+ == Clause
10
+
11
+ [.requirement,subsequence="A",inherit="/ss/584/2015/level/1 &amp; /ss/584/2015/level/2"]
12
+ ====
13
+ [%metadata]
14
+ model:: ogc
15
+ type:: class
16
+ identifier:: http://www.opengis.net/spec/waterml/2.0/req/xsd-xml-rules[*req/core*]
17
+ subject:: Encoding of logical models
18
+ inherit:: urn:iso:dis:iso:19156:clause:7.2.2
19
+ inherit:: urn:iso:dis:iso:19156:clause:8
20
+ inherit:: http://www.opengis.net/doc/IS/GML/3.2/clause/2.4
21
+ inherit:: O&M Abstract model, OGC 10-004r3, clause D.3.4
22
+ inherit:: http://www.opengis.net/spec/SWE/2.0/req/core/core-concepts-used
23
+ inherit:: <<ref2>>
24
+ inherit:: <<ref3>>
25
+ target:: http://www.example.com
26
+ classification:: priority:P0
27
+ classification:: domain:Hydrology,Groundwater
28
+ classification:: control-class:Technical
29
+ obligation:: recommendation,requirement
30
+
31
+ I recommend this
32
+ ====
33
+ INPUT
34
+ output = <<~OUTPUT
35
+ #{BLANK_HDR}
36
+ <sections>
37
+ <clause id='_' inline-header='false' obligation='normative'>
38
+ <title>Clause</title>
39
+ <requirement id='_' subsequence='A' obligation='recommendation,requirement' model='ogc' type='class'>
40
+ <identifier>http://www.opengis.net/spec/waterml/2.0/req/xsd-xml-rules</identifier>
41
+ <subject>Encoding of logical models</subject>
42
+ <inherit>/ss/584/2015/level/1 &amp; /ss/584/2015/level/2</inherit>
43
+ <inherit>urn:iso:dis:iso:19156:clause:7.2.2</inherit>
44
+ <inherit>urn:iso:dis:iso:19156:clause:8</inherit>
45
+ <inherit>http://www.opengis.net/doc/IS/GML/3.2/clause/2.4</inherit>
46
+ <inherit>O&amp;M Abstract model, OGC 10-004r3, clause D.3.4</inherit>
47
+ <inherit>http://www.opengis.net/spec/SWE/2.0/req/core/core-concepts-used</inherit>
48
+ <inherit>
49
+ <xref target='ref2'/>
50
+ </inherit>
51
+ <inherit>
52
+ <xref target='ref3'/>
53
+ </inherit>
54
+ <classification>
55
+ <tag>priority</tag>
56
+ <value>P0</value>
57
+ </classification>
58
+ <classification>
59
+ <tag>domain</tag>
60
+ <value>Hydrology</value>
61
+ </classification>
62
+ <classification>
63
+ <tag>domain</tag>
64
+ <value>Groundwater</value>
65
+ </classification>
66
+ <classification>
67
+ <tag>control-class</tag>
68
+ <value>Technical</value>
69
+ </classification>
70
+ <classification>
71
+ <tag>target</tag>
72
+ <value><link target='http://www.example.com'/></value>
73
+ </classification>
74
+ <description>
75
+ <p id='_'>I recommend this</p>
76
+ </description>
77
+ </requirement>
78
+ </clause>
79
+ </sections>
80
+ </standard-document>
81
+ OUTPUT
82
+ expect(xmlpp(strip_guid(Asciidoctor.convert(input, *OPTIONS))))
83
+ .to be_equivalent_to xmlpp(output)
84
+ end
85
+
86
+ it "moves inherit macros to correct location" do
87
+ input = <<~INPUT
88
+ #{ASCIIDOC_BLANK_HDR}
89
+
90
+ == Clause
91
+
92
+ [.requirement,subsequence="A",inherit="/ss/584/2015/level/1 &amp; /ss/584/2015/level/2"]
93
+ .Title
94
+ ====
95
+ inherit:[A]
96
+ inherit:[B]
97
+ I recommend this
98
+ ====
99
+
100
+ [.requirement,subsequence="A",classification="X:Y"]
101
+ .Title
102
+ ====
103
+ inherit:[A]
104
+ I recommend this
105
+ ====
106
+
107
+ [.requirement,subsequence="A"]
108
+ .Title
109
+ ====
110
+ inherit:[A]
111
+ I recommend this
112
+ ====
113
+
114
+ [.requirement,subsequence="A"]
115
+ .Title
116
+ ====
117
+ inherit:[A]
118
+ ====
119
+
120
+ [.requirement,subsequence="A"]
121
+ ====
122
+ inherit:[A]
123
+ ====
124
+
125
+ INPUT
126
+ output = <<~OUTPUT
127
+ #{BLANK_HDR}
128
+ <sections>
129
+ <clause id='_' inline-header='false' obligation='normative'>
130
+ <title>Clause</title>
131
+ <requirement id='_' subsequence='A' model="default">
132
+ <title>Title</title>
133
+ <inherit>A</inherit>
134
+ <inherit>B</inherit>
135
+ <inherit>/ss/584/2015/level/1 &amp; /ss/584/2015/level/2</inherit>
136
+ <description>
137
+ <p id='_'> I recommend this</p>
138
+ </description>
139
+ </requirement>
140
+ <requirement id='_' subsequence='A' model="default">
141
+ <title>Title</title>
142
+ <inherit>A</inherit>
143
+ <classification>
144
+ <tag>X</tag>
145
+ <value>Y</value>
146
+ </classification>
147
+ <description>
148
+ <p id='_'> I recommend this</p>
149
+ </description>
150
+ </requirement>
151
+ <requirement id='_' subsequence='A' model="default">
152
+ <title>Title</title>
153
+ <inherit>A</inherit>
154
+ <description>
155
+ <p id='_'> I recommend this</p>
156
+ </description>
157
+ </requirement>
158
+ <requirement id='_' subsequence='A' model="default">
159
+ <title>Title</title>
160
+ <inherit>A</inherit>
161
+ </requirement>
162
+ <requirement id='_' subsequence='A' model="default">
163
+ <inherit>A</inherit>
164
+ </requirement>
165
+ </clause>
166
+ </sections>
167
+ </standard-document>
168
+ OUTPUT
169
+ expect(xmlpp(strip_guid(Asciidoctor.convert(input, *OPTIONS))))
170
+ .to be_equivalent_to xmlpp(output)
171
+ end
172
+ end
173
+