metanorma-standoc 2.2.0.1 → 2.2.2

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