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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e6a6d6a98133ba0cf81631287aff2157906da7d0978899abe5c00c78f0da6b2d
4
- data.tar.gz: 81c33e16f952e56dcff81bd0485ead5ba998839b307e30eb8de500bf2448a600
3
+ metadata.gz: e1259358ae365bba52ab94c40d88b6cc9d4b1eb9b65a9f7fc8edef4bd77138e0
4
+ data.tar.gz: 6c348c7e3b1706287332368251d90fa277fee7e9a54a0fc0cd11e19f5464506b
5
5
  SHA512:
6
- metadata.gz: b36c1f1766233c69f9b5a63298d8f7cd8745cac7f7186f210500bc23a27983b3202a724ebd799f6d305b928377ed5d2ef28dcb43aac4e9c91f65b9300a98ac19
7
- data.tar.gz: e4b1be10928b81269486083791e7dd23fab26b2697d1b1a82fa607dfa4c6f46a00bdc4373403605c2807a993ab2f4015f34f643607610d10344cfbd95a6a83b3
6
+ metadata.gz: 602f12339e31a98c061ce7dc46d9fad6888b18e962942f110ebeea86f6739311b093578dbc8886a795bfcd01de790c40c134072449ff1e701779f2e29139a743
7
+ data.tar.gz: 39b93eb600aa0f18e21982174fc204eb36a9f28ae7e1e3b5a4a78ddfa9a05a440e6e3d6b94cdf7824dbd71b62880a193d5c88028ecd78d074c7c9361961966f6
@@ -10,6 +10,6 @@ on:
10
10
 
11
11
  jobs:
12
12
  rake:
13
- uses: metanorma/metanorma-build-scripts/.github/workflows/plantuml-rake.yml@main
13
+ uses: metanorma/ci/.github/workflows/plantuml-rake.yml@main
14
14
  secrets:
15
15
  pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
@@ -0,0 +1,24 @@
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
3
+ name: release
4
+
5
+ on:
6
+ workflow_dispatch:
7
+ inputs:
8
+ next_version:
9
+ description: |
10
+ Next release version. Possible values: x.y.z, major, minor, patch or pre|rc|etc
11
+ required: true
12
+ default: 'skip'
13
+ push:
14
+ tags: [ v* ]
15
+
16
+ jobs:
17
+ release:
18
+ uses: metanorma/ci/.github/workflows/rubygems-release.yml@main
19
+ with:
20
+ next_version: ${{ github.event.inputs.next_version }}
21
+ secrets:
22
+ rubygems-api-key: ${{ secrets.METANORMA_CI_RUBYGEMS_API_KEY }}
23
+ pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
24
+
@@ -9,6 +9,7 @@ require "fileutils"
9
9
  require "metanorma-utils"
10
10
  require "isodoc/xslfo_convert"
11
11
  require_relative "render"
12
+ require "mn-requirements"
12
13
 
13
14
  module Metanorma
14
15
  module Standoc
@@ -29,6 +30,7 @@ module Metanorma
29
30
  init_vars
30
31
  init_misc(node)
31
32
  init_processing(node)
33
+ init_reqt(node)
32
34
  init_toc(node)
33
35
  init_output(node)
34
36
  init_i18n(node)
@@ -42,7 +44,10 @@ module Metanorma
42
44
  @anchors = {}
43
45
  @internal_eref_namespaces = []
44
46
  @seen_headers = []
47
+ @seen_headers_canonical = []
45
48
  @embed_hdr = []
49
+ @reqt_model = nil
50
+ @preface = true
46
51
  end
47
52
 
48
53
  def init_misc(node)
@@ -63,6 +68,13 @@ module Metanorma
63
68
  @datauriimage = node.attr("data-uri-image") != "false"
64
69
  end
65
70
 
71
+ def init_reqt(node)
72
+ @default_requirement_model = (node.attr("requirements-model") ||
73
+ default_requirement_model)
74
+ @reqt_models = requirements_processor
75
+ .new({ default: @default_requirement_model })
76
+ end
77
+
66
78
  def init_toc(node)
67
79
  @htmltoclevels = node.attr("htmltoclevels")
68
80
  @doctoclevels = node.attr("doctoclevels")
@@ -100,6 +112,10 @@ module Metanorma
100
112
  init_iev_caches(node)
101
113
  end
102
114
 
115
+ def requirements_processor
116
+ Metanorma::Requirements
117
+ end
118
+
103
119
  def document(node)
104
120
  ret = document1(node)
105
121
  clean_exit
@@ -225,9 +225,9 @@
225
225
  <zeroOrMore>
226
226
  <ref name="forename"/>
227
227
  </zeroOrMore>
228
- <zeroOrMore>
229
- <ref name="initial"/>
230
- </zeroOrMore>
228
+ <optional>
229
+ <ref name="formatted-initials"/>
230
+ </optional>
231
231
  <ref name="surname"/>
232
232
  <zeroOrMore>
233
233
  <ref name="addition"/>
@@ -247,8 +247,8 @@
247
247
  <ref name="LocalizedString"/>
248
248
  </element>
249
249
  </define>
250
- <define name="initial">
251
- <element name="initial">
250
+ <define name="formatted-initials">
251
+ <element name="formatted-initials">
252
252
  <ref name="LocalizedString"/>
253
253
  </element>
254
254
  </define>
@@ -264,6 +264,9 @@
264
264
  </define>
265
265
  <define name="forename">
266
266
  <element name="forename">
267
+ <optional>
268
+ <attribute name="initial"/>
269
+ </optional>
267
270
  <ref name="LocalizedString"/>
268
271
  </element>
269
272
  </define>
@@ -15,7 +15,8 @@ module Metanorma
15
15
  attr_code(id_attr(node).merge(
16
16
  unnumbered: node.option?("unnumbered") ? "true" : nil,
17
17
  number: node.attr("number"),
18
- subsequence: node.attr("subsequence")))
18
+ subsequence: node.attr("subsequence"),
19
+ ))
19
20
  end
20
21
 
21
22
  def formula_attrs(node)
@@ -33,7 +34,7 @@ module Metanorma
33
34
  # We append each contained block to its parent
34
35
  def open(node)
35
36
  role = node.role || node.attr("style")
36
- reqt_subpart(role) and return requirement_subpart(node)
37
+ reqt_subpart?(role) and return requirement_subpart(node)
37
38
  role == "form" and return form(node)
38
39
  role == "definition" and return termdefinition(node)
39
40
  result = []
@@ -87,21 +88,33 @@ module Metanorma
87
88
  end
88
89
 
89
90
  def example(node)
90
- return term_example(node) if in_terms? || node.option?("termexample")
91
-
91
+ (in_terms? || node.option?("termexample")) and return term_example(node)
92
92
  role = node.role || node.attr("style")
93
- %w(recommendation requirement permission).include?(role) and
94
- return requirement(node, role)
95
- return pseudocode_example(node) if role == "pseudocode"
96
- return svgmap_example(node) if role == "svgmap"
97
- return form(node) if role == "form"
98
- return termdefinition(node) if role == "definition"
99
- return figure_example(node) if role == "figure"
100
-
101
- reqt_subpart(role) and return requirement_subpart(node)
93
+ ret = example_to_requirement(node, role) ||
94
+ example_by_role(node, role) and return ret
95
+ reqt_subpart?(role) and return requirement_subpart(node)
102
96
  example_proper(node)
103
97
  end
104
98
 
99
+ def example_by_role(node, role)
100
+ case role
101
+ when "pseudocode" then pseudocode_example(node)
102
+ when "svgmap" then svgmap_example(node)
103
+ when "form" then form(node)
104
+ when "definition" then termdefinition(node)
105
+ when "figure" then figure_example(node)
106
+ end
107
+ end
108
+
109
+ def example_to_requirement(node, role)
110
+ return unless @reqt_models.requirement_roles.key?(role&.to_sym)
111
+
112
+ # need to call here for proper recursion ordering
113
+ select_requirement_model(node)
114
+ requirement(node,
115
+ @reqt_models.requirement_roles[role.to_sym], role)
116
+ end
117
+
105
118
  def svgmap_attrs(node)
106
119
  attr_code(id_attr(node)
107
120
  .merge(id: node.id, number: node.attr("number"),
@@ -84,8 +84,8 @@ module Metanorma
84
84
  dl = clause.at("./dl") or return
85
85
  key = ""
86
86
  bib = dl.xpath("./dt | ./dd").each_with_object({}) do |dtd, m|
87
- (dtd.name == "dt" and key = dtd.text.sub(/:+$/, "")) or
88
- add_to_hash(m, key, dd_bib_extract(dtd))
87
+ (dtd.name == "dt" and key = dtd.text.sub(/:+$/, "")) and next
88
+ add_to_hash(m, key, dd_bib_extract(dtd))
89
89
  end
90
90
  clause.xpath("./clause").each do |c1|
91
91
  key = c1&.at("./title")&.text&.downcase&.strip
@@ -145,7 +145,7 @@ module Metanorma
145
145
  when "publisher"
146
146
  ret[:contributor] << { role: "publisher", entity: "organization",
147
147
  name: s[:val] }
148
- when "surname", "initials", "givenname"
148
+ when "surname", "initials", "givenname", "formatted-initials"
149
149
  ret[:contributor] = spans_preprocess_contrib(s, ret[:contributor])
150
150
  end
151
151
  end
@@ -153,6 +153,8 @@ module Metanorma
153
153
  end
154
154
 
155
155
  def spans_preprocess_contrib(span, contrib)
156
+ span[:key] = "formatted-initials" if span[:key] == "initials"
157
+
156
158
  spans_preprocess_new_contrib?(span, contrib) and
157
159
  contrib << { role: span[:type] || "author", entity: "person" }
158
160
  contrib[-1][span[:key].to_sym] = span[:val]
@@ -162,7 +164,7 @@ module Metanorma
162
164
  def spans_preprocess_new_contrib?(span, contrib)
163
165
  contrib.empty? ||
164
166
  (if span[:key] == "surname" then contrib[-1][:surname]
165
- else (contrib[-1][:initials] || contrib[-1][:givenname])
167
+ else (contrib[-1][:"formatted-initials"] || contrib[-1][:givenname])
166
168
  end) ||
167
169
  contrib[-1][:role] != (span[:type] || "author")
168
170
  end
@@ -190,15 +192,19 @@ module Metanorma
190
192
  def span_to_contrib(span)
191
193
  e = if span[:entity] == "organization"
192
194
  "<organization><name>#{span[:name]}</name></organization>"
193
- else
194
- pre = (span[:initials] and
195
- "<initial>#{span[:initials]}</initial>") ||
196
- "<forename>#{span[:givenname]}</forename>"
197
- "<person><name>#{pre}<surname>#{span[:surname]}</surname></name>"\
198
- "</person>"
195
+ else span_to_person(span)
199
196
  end
200
197
  "<contributor><role type='#{span[:role]}'/>#{e}</contributor>"
201
198
  end
199
+
200
+ def span_to_person(span)
201
+ pre = (span[:"formatted-initials"] and
202
+ "<formatted-initials>"\
203
+ "#{span[:"formatted-initials"]}</formatted-initials>") ||
204
+ "<forename>#{span[:givenname]}</forename>"
205
+ "<person><name>#{pre}<surname>#{span[:surname]}</surname></name>"\
206
+ "</person>"
207
+ end
202
208
  end
203
209
  end
204
210
  end
@@ -2,142 +2,9 @@ module Metanorma
2
2
  module Standoc
3
3
  module Cleanup
4
4
  def requirement_cleanup(xmldoc)
5
- requirement_metadata(xmldoc)
6
- requirement_inherit(xmldoc)
7
- requirement_descriptions(xmldoc)
8
- requirement_identifier(xmldoc)
9
- end
10
-
11
- REQRECPER = "//requirement | //recommendation | //permission".freeze
12
-
13
- def requirement_identifier(xmldoc)
14
- xmldoc.xpath(REQRECPER).each do |r|
15
- r.xpath("./identifier[link] | ./inherit[link]").each do |i|
16
- i.children = i.at("./link/@target").text
17
- end
18
- end
19
- end
20
-
21
- def requirement_inherit(xmldoc)
22
- xmldoc.xpath(REQRECPER).each do |r|
23
- ins = requirement_inherit_insert(r)
24
- r.xpath("./*//inherit").each { |i| ins.previous = i }
25
- end
26
- end
27
-
28
- def requirement_inherit_insert(reqt)
29
- ins = reqt.at("./classification") || reqt.at(
30
- "./description | ./measurementtarget | ./specification | "\
31
- "./verification | ./import | ./description | ./component | "\
32
- "./requirement | ./recommendation | ./permission",
33
- ) and return ins
34
- requirement_inherit_insert1(reqt)
35
- end
36
-
37
- def requirement_inherit_insert1(reqt)
38
- if t = reqt.at("./title")
39
- t.next = " "
40
- t.next
41
- else
42
- if reqt.children.empty? then reqt.add_child(" ")
43
- else reqt.children.first.previous = " "
44
- end
45
- reqt.children.first
46
- end
47
- end
48
-
49
- def requirement_descriptions(xmldoc)
50
- xmldoc.xpath(REQRECPER).each do |r|
51
- r.xpath(".//p[not(./*)][normalize-space(.)='']").each(&:remove)
52
- r.children.each do |e|
53
- requirement_description_wrap(r, e)
54
- end
55
- requirement_description_cleanup1(r)
56
- end
57
- end
58
-
59
- def requirement_description_wrap(reqt, text)
60
- return if (text.element? && (reqt_subpart(text.name) ||
61
- %w(requirement recommendation
62
- permission).include?(text.name))) ||
63
- (text.text.strip.empty? && !text.at(".//xref | .//eref | .//link"))
64
-
65
- t = Nokogiri::XML::Element.new("description", reqt.document)
66
- text.before(t)
67
- t.children = text.remove
68
- end
69
-
70
- def requirement_description_cleanup1(reqt)
71
- while d = reqt.at("./description[following-sibling::*[1]"\
72
- "[self::description]]")
73
- n = d.next.remove
74
- d << n.children
75
- end
76
- reqt.xpath("./description[normalize-space(.)='']").each do |r|
77
- r.replace("\n")
78
- end
79
- end
80
-
81
- def requirement_metadata(xmldoc)
82
- xmldoc.xpath(REQRECPER).each do |r|
83
- dl = r&.at("./dl[@metadata = 'true']")&.remove or next
84
- requirement_metadata1(r, dl, r.at("./title"))
85
- end
86
- end
87
-
88
- def requirement_metadata1_attrs
89
- %w(obligation model type)
90
- end
91
-
92
- def requirement_metadata1_tags
93
- %w(identifier subject inherit)
94
- end
95
-
96
- def requirement_metadata_component_tags
97
- []
98
- end
99
-
100
- def requirement_metadata1(reqt, dlist, ins)
101
- unless ins
102
- reqt.children.first.previous = " "
103
- ins = reqt.children.first
104
- end
105
- requirement_metadata1_attrs.each do |a|
106
- dl_to_attrs(reqt, dlist, a)
107
- end
108
- requirement_metadata1_tags.each do |a|
109
- ins = dl_to_elems(ins, reqt, dlist, a)
110
- end
111
- ins = reqt_dl_to_classif(ins, reqt, dlist)
112
- reqt_dl_to_classif1(ins, reqt, dlist)
113
- end
114
-
115
- def reqt_dl_to_classif(ins, reqt, dlist)
116
- if a = reqt.at("./classification[last()]") then ins = a end
117
- dlist.xpath("./dt[text()='classification']").each do |e|
118
- val = e.at("./following::dd/p") || e.at("./following::dd")
119
- req_classif_parse(val.children.to_xml).each do |r|
120
- ins.next = "<classification><tag>#{r[0]}</tag>"\
121
- "<value>#{r[1]}</value></classification>"
122
- ins = ins.next
123
- end
124
- end
125
- ins
126
- end
127
-
128
- def reqt_dl_to_classif1(ins, reqt, dlist)
129
- if a = reqt.at("./classification[last()]") then ins = a end
130
- dlist.xpath("./dt").each do |e|
131
- next if (requirement_metadata1_attrs + requirement_metadata1_tags +
132
- requirement_metadata_component_tags + %w(classification))
133
- .include?(e.text)
134
-
135
- val = e.at("./following::dd/p") || e.at("./following::dd")
136
- ins.next = "<classification><tag>#{e.text}</tag>"\
137
- "<value>#{val.children.to_xml}</value></classification>"
138
- ins = ins.next
139
- end
140
- ins
5
+ @reqt_models ||=
6
+ requirements_processor.new({ default: @default_requirement_model })
7
+ @reqt_models.requirement_cleanup(xmldoc)
141
8
  end
142
9
  end
143
10
  end
@@ -25,9 +25,6 @@ module Metanorma
25
25
  preprocessor Metanorma::Standoc::Datamodel::DiagramPreprocessor
26
26
  preprocessor Metanorma::Plugin::Datastruct::Json2TextPreprocessor
27
27
  preprocessor Metanorma::Plugin::Datastruct::Yaml2TextPreprocessor
28
- preprocessor Metanorma::Plugin::Lutaml::LutamlPreprocessor
29
- preprocessor Metanorma::Plugin::Lutaml::LutamlUmlAttributesTablePreprocessor
30
- preprocessor Metanorma::Plugin::Lutaml::LutamlUmlDatamodelDescriptionPreprocessor
31
28
  inline_macro Metanorma::Standoc::PreferredTermInlineMacro
32
29
  inline_macro Metanorma::Standoc::SpanInlineMacro
33
30
  inline_macro Metanorma::Standoc::AltTermInlineMacro
@@ -56,15 +53,11 @@ module Metanorma
56
53
  inline_macro Metanorma::Standoc::ToCInlineMacro
57
54
  inline_macro Metanorma::Standoc::PassInlineMacro
58
55
  inline_macro Metanorma::Standoc::StdLinkInlineMacro
59
- inline_macro Metanorma::Plugin::Lutaml::LutamlFigureInlineMacro
60
- inline_macro Metanorma::Plugin::Lutaml::LutamlTableInlineMacro
61
- block_macro Metanorma::Plugin::Lutaml::LutamlDiagramBlockMacro
62
56
  block Metanorma::Standoc::ToDoAdmonitionBlock
63
57
  block Metanorma::Standoc::EditorAdmonitionBlock
64
58
  treeprocessor Metanorma::Standoc::EditorInlineAdmonitionBlock
65
59
  treeprocessor Metanorma::Standoc::ToDoInlineAdmonitionBlock
66
60
  block Metanorma::Standoc::PlantUMLBlockMacro
67
- block Metanorma::Plugin::Lutaml::LutamlDiagramBlock
68
61
  block Metanorma::Standoc::PseudocodeBlockMacro
69
62
  preprocessor Metanorma::Standoc::EmbedIncludeProcessor
70
63
  preprocessor Metanorma::Standoc::NamedEscapePreprocessor
@@ -3,6 +3,7 @@ require "nokogiri"
3
3
  require "htmlentities"
4
4
  require "pathname"
5
5
  require_relative "./front_contributor"
6
+ require "isoics"
6
7
 
7
8
  module Metanorma
8
9
  module Standoc
@@ -48,7 +49,11 @@ module Metanorma
48
49
  def metadata_ics(node, xml)
49
50
  ics = node.attr("library-ics")
50
51
  ics&.split(/,\s*/)&.each do |i|
51
- xml.ics { |elem| elem.code i }
52
+ xml.ics do |elem|
53
+ elem.code i
54
+ icsdata = Isoics.fetch i
55
+ elem.text_ icsdata.description
56
+ end
52
57
  end
53
58
  end
54
59
 
@@ -44,16 +44,6 @@ module Metanorma
44
44
  node.attr("pub-uri") and person.uri node.attr("pub-uri")
45
45
  end
46
46
 
47
- # , " => ," : CSV definition does not deal with space followed by quote
48
- # at start of field
49
- def csv_split(text, delim = ";")
50
- return if text.nil?
51
-
52
- CSV.parse_line(text&.gsub(/#{delim} "(?!")/, "#{delim}\""),
53
- liberal_parsing: true,
54
- col_sep: delim)&.compact&.map(&:strip)
55
- end
56
-
57
47
  def metadata_author(node, xml)
58
48
  csv_split(node.attr("publisher") || default_publisher || "")
59
49
  &.each do |p|
@@ -103,16 +103,16 @@ module Metanorma
103
103
  class ConceptInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
104
104
  use_dsl
105
105
  named :concept
106
- match /\{\{(?<content>|.*?[^\\])\}\}/
106
+ match /\{\{(?<content>|.*?[^\\])\}\}/m
107
107
  using_format :short
108
108
 
109
109
  def preprocess_attrs(target)
110
- m = /^(?<id>&lt;&lt;.+?&gt;&gt;)?(?<rest>.*)$/.match(target)
110
+ m = /^(?<id>&lt;&lt;.+?&gt;&gt;)?(?<rest>.*)$/m.match(target)
111
111
  ret = { id: m[:id]&.sub(/^&lt;&lt;/, "")&.sub(/&gt;&gt;$/, "") }
112
- if m2 = /^(?<rest>.*?)(?<opt>,opt(?:ion)?s=.+)$/
112
+ if m2 = /^(?<rest>.*?)(?<opt>,opt(?:ion)?s=.+)$/m
113
113
  .match(m[:rest].sub(/^,/, ""))
114
114
  ret[:opt] = CSV.parse_line(m2[:opt].sub(/^,opt(ion)?s=/, "")
115
- .sub(/^"(.+)"$/, "\\1").sub(/^'(.+)'$/, "\\1"))
115
+ .sub(/^"(.+)"$/m, "\\1").sub(/^'(.+)'$/m, "\\1"))
116
116
  begin
117
117
  attrs = CSV.parse_line(m2[:rest]) || []
118
118
  rescue StandardError
@@ -125,6 +125,7 @@ module Metanorma
125
125
  raise "error processing #{m[:rest]} as CSV"
126
126
  end
127
127
  end
128
+ attrs.map! { |x| x.gsub(/\s+/, " ") }
128
129
  ret.merge(term: attrs[0], word: attrs[1] || attrs[0],
129
130
  render: attrs[2])
130
131
  end
@@ -1,91 +1,42 @@
1
- require "htmlentities"
2
- require "uri" if /^2\./.match?(RUBY_VERSION)
3
- require "mime/types"
4
- require "base64"
5
-
6
1
  module Metanorma
7
2
  module Standoc
8
3
  module Blocks
9
- def reqt_subpart(name)
10
- %w(specification measurement-target verification import identifier title
11
- description component subject inherit classification).include? name
12
- end
13
-
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))
4
+ def reqt_subpart?(name)
5
+ @reqt_model&.reqt_subpart?(name)
20
6
  end
21
7
 
22
8
  def requirement_subpart(node)
23
- name = node.role || node.attr("style")
24
- noko do |xml|
25
- xml.send name, **reqt_subpart_attrs(node, name) do |o|
26
- o << node.content
27
- end
28
- end
9
+ @reqt_model.requirement_subpart(node, keep_attrs(node))
29
10
  end
30
11
 
31
- def req_classif_parse(classif)
32
- ret = []
33
- @c.decode(classif).split(/;\s*/).each do |c|
34
- c1 = c.split(/:\s*/)
35
- next unless c1.size == 2
36
-
37
- c1[1].split(/,\s*/).each { |v| ret << [c1[0], v] }
38
- end
39
- ret
12
+ def default_requirement_model
13
+ :default
40
14
  end
41
15
 
42
- def requirement_classification(classif, out)
43
- req_classif_parse(classif).each do |r|
44
- out.classification do |c|
45
- c.tag { |t| t << r[0] }
46
- c.value { |v| v << r[1] }
47
- end
48
- end
49
- end
16
+ def select_requirement_model(node)
17
+ return if @reqt_model
50
18
 
51
- def reqt_attrs(node)
52
- attr_code(keep_attrs(node).merge(id_unnum_attrs(node)).merge(
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
- ))
19
+ @reqt_model_name = node.attr("model") || @default_requirement_model
20
+ @reqt_model = @reqt_models.model(@reqt_model_name)
62
21
  end
63
22
 
64
- def requirement_elems(node, out)
65
- node.title and out.title { |t| t << node.title }
66
- a = node.attr("identifier") and out.identifier do |l|
67
- l << out.text(a)
68
- end
69
- a = node.attr("subject") and csv_split(a)&.each do |subj|
70
- out.subject { |s| s << out.text(subj) }
71
- end
72
- a = @c.decode(node.attr("inherit")) and
73
- csv_split(a)&.each do |i|
74
- out.inherit do |inh|
75
- inh << @c.encode(i, :hexadecimal)
76
- end
77
- end
78
- classif = node.attr("classification") and
79
- requirement_classification(classif, out)
23
+ def requirement(node, obligation, type)
24
+ nested = @reqt_model
25
+ !node.attr("type") &&
26
+ !%w(requirement recommendation permission).include?(type) and
27
+ node.set_attr("type", type)
28
+ attrs = keep_attrs(node).merge(id_unnum_attrs(node))
29
+ .merge(model: @reqt_model_name)
30
+ ret = @reqt_model.requirement(node, obligation, attrs)
31
+ @reqt_model = nil unless nested
32
+ ret
80
33
  end
81
34
 
82
- def requirement(node, obligation)
83
- noko do |xml|
84
- xml.send obligation, **reqt_attrs(node) do |ex|
85
- requirement_elems(node, ex)
86
- wrap_in_para(node, ex)
87
- end
88
- end.join("\n")
35
+ def requirement_validate(docxml)
36
+ docxml.xpath("//requirement | //recommendation | //permission")
37
+ .each do |r|
38
+ @reqt_models.model(r["model"]).validate(r, @log)
39
+ end
89
40
  end
90
41
  end
91
42
  end