metanorma-standoc 2.2.0 → 2.2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/metanorma/standoc/base.rb +12 -0
  3. data/lib/metanorma/standoc/blocks.rb +25 -15
  4. data/lib/metanorma/standoc/cleanup_biblio.rb +14 -8
  5. data/lib/metanorma/standoc/cleanup_reqt.rb +3 -136
  6. data/lib/metanorma/standoc/front.rb +6 -1
  7. data/lib/metanorma/standoc/front_contributor.rb +0 -10
  8. data/lib/metanorma/standoc/macros_inline.rb +1 -1
  9. data/lib/metanorma/standoc/reqt.rb +19 -75
  10. data/lib/metanorma/standoc/section.rb +35 -3
  11. data/lib/metanorma/standoc/utils.rb +9 -43
  12. data/lib/metanorma/standoc/validate.rb +1 -69
  13. data/lib/metanorma/standoc/validate_table.rb +91 -0
  14. data/lib/metanorma/standoc/version.rb +1 -1
  15. data/metanorma-standoc.gemspec +2 -2
  16. data/spec/metanorma/biblio_spec.rb +9 -9
  17. data/spec/metanorma/blocks_spec.rb +20 -266
  18. data/spec/metanorma/cleanup_blocks_spec.rb +0 -168
  19. data/spec/metanorma/macros_concept_spec.rb +1033 -0
  20. data/spec/metanorma/macros_spec.rb +1 -1031
  21. data/spec/metanorma/refs_spec.rb +0 -2
  22. data/spec/metanorma/reqt_spec.rb +130 -0
  23. data/spec/metanorma/section_spec.rb +5 -0
  24. data/spec/metanorma/validate_spec.rb +46 -6
  25. data/spec/vcr_cassettes/bsi16341.yml +80 -52
  26. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +94 -94
  27. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +10 -10
  28. data/spec/vcr_cassettes/hide_refs.yml +74 -74
  29. data/spec/vcr_cassettes/isobib_get_123.yml +11 -11
  30. data/spec/vcr_cassettes/isobib_get_123_1.yml +22 -22
  31. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +30 -30
  32. data/spec/vcr_cassettes/isobib_get_123_2.yml +23 -23
  33. data/spec/vcr_cassettes/isobib_get_123_2001.yml +9 -9
  34. data/spec/vcr_cassettes/isobib_get_124.yml +10 -10
  35. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +30 -60
  36. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +45 -45
  37. data/spec/vcr_cassettes/std-link.yml +11 -11
  38. metadata +10 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d1015766df2dd6accbfd8de285d762403a1d874fcac93a3d6829055602f2904
4
- data.tar.gz: b185321cbbbcb6de4bfb9cea996dec314e585f54fbdf7baf31fcce616be60ef5
3
+ metadata.gz: 90287c74936b7e6fa5c54537833e425fdc78deb260ce3a9f083cc53530ad66fc
4
+ data.tar.gz: 273eb7dcaf62e8b9a8578f932b3ab45377bdf0b57ad254cab80b16b10e584586
5
5
  SHA512:
6
- metadata.gz: 9aa957125f263ab18defd53ff0086519c43de991346bbf1775ae10907a9a06e551b3b3ddc5bf078dc968f6cbbfb863f6690643d093ad8d29b22f490815e745cc
7
- data.tar.gz: d687658d8b5d8e6194655f3e40605d9f5e610c599631e5bf13de586daaeefa0f57a22614884e71321abdc248f55dd42113fdc068e4ceb296cc88102f27db6acf
6
+ metadata.gz: 167db30a6cbf87a30f2e1d97eeaafffb63e94699a7f077556ec23604de443fcfabc1a1de091e7fbb93ddf528482e980e0b23c976abbf2e7aae8ebbfbddbb686c
7
+ data.tar.gz: 1925f23438f2cc30fcd898c4ceeb8aea39442a8b0575d2cf8fa91954e229a2384b954670e75a66fe052486ff12a6b3394512d49ae84d38ac5f5253cde3591715
@@ -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 = Metanorma::Requirements
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")
@@ -34,7 +34,7 @@ module Metanorma
34
34
  # We append each contained block to its parent
35
35
  def open(node)
36
36
  role = node.role || node.attr("style")
37
- reqt_subpart(role) and return requirement_subpart(node)
37
+ reqt_subpart?(role) and return requirement_subpart(node)
38
38
  role == "form" and return form(node)
39
39
  role == "definition" and return termdefinition(node)
40
40
  result = []
@@ -88,26 +88,37 @@ module Metanorma
88
88
  end
89
89
 
90
90
  def example(node)
91
- return term_example(node) if in_terms? || node.option?("termexample")
92
-
91
+ (in_terms? || node.option?("termexample")) and return term_example(node)
93
92
  role = node.role || node.attr("style")
94
- %w(recommendation requirement permission).include?(role) and
95
- return requirement(node, role)
96
- return pseudocode_example(node) if role == "pseudocode"
97
- return svgmap_example(node) if role == "svgmap"
98
- return form(node) if role == "form"
99
- return termdefinition(node) if role == "definition"
100
- return figure_example(node) if role == "figure"
101
-
102
- 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)
103
96
  example_proper(node)
104
97
  end
105
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
+
106
118
  def svgmap_attrs(node)
107
119
  attr_code(id_attr(node)
108
- .merge(id: node.id,
120
+ .merge(id: node.id, number: node.attr("number"),
109
121
  unnumbered: node.option?("unnumbered") ? "true" : nil,
110
- number: node.attr("number"),
111
122
  subsequence: node.attr("subsequence"))
112
123
  .merge(keep_attrs(node)))
113
124
  end
@@ -225,7 +236,6 @@ module Metanorma
225
236
  filename: node.attr("filename"))))
226
237
  end
227
238
 
228
- # NOTE: html escaping is performed by Nokogiri
229
239
  def listing(node)
230
240
  fragment = ::Nokogiri::XML::Builder.new do |xml|
231
241
  xml.sourcecode **listing_attrs(node) do |s|
@@ -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
+ Metanorma::Requirements.new({ default: @default_requirement_model })
7
+ @reqt_models.requirement_cleanup(xmldoc)
141
8
  end
142
9
  end
143
10
  end
@@ -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|
@@ -182,7 +182,7 @@ module Metanorma
182
182
 
183
183
  class SpanInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
184
184
  use_dsl
185
- named :s
185
+ named :span
186
186
  parse_content_as :text
187
187
 
188
188
  def process(parent, target, attrs)
@@ -1,91 +1,35 @@
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
50
-
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
- ))
62
- end
16
+ def select_requirement_model(node)
17
+ return if @reqt_model
63
18
 
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)
19
+ @reqt_model_name = node.attr("model") || @default_requirement_model
20
+ @reqt_model = @reqt_models.model(@reqt_model_name)
80
21
  end
81
22
 
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")
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
89
33
  end
90
34
  end
91
35
  end
@@ -10,19 +10,26 @@ module Metanorma
10
10
  @norm_ref = false
11
11
 
12
12
  def sectiontype1(node)
13
+ return "abstract" if node.attr("style") == "abstract"
14
+
13
15
  node&.attr("heading")&.downcase ||
14
- node.title.gsub(%r{<index>.*?</index>}m, "").gsub(/<[^>]+>/, "")
16
+ node.title
17
+ .gsub(%r{<index>.*?</index>}m, "")
18
+ .gsub(%r{<fn[^>]*>.*?</fn>}m, "")
19
+ .gsub(/<[^>]+>/, "")
15
20
  .strip.downcase
21
+ .sub(/\.$/, "")
16
22
  end
17
23
 
18
24
  def sectiontype(node, level = true)
19
25
  ret = sectiontype1(node)
20
- ret1 = sectiontype_streamline(ret)
26
+ ret1 = preface_main_filter(sectiontype_streamline(ret), node)
21
27
  return ret1 if ret1 == "symbols and abbreviated terms"
22
28
  return nil unless !level || node.level == 1
23
29
  return nil if @seen_headers.include? ret
24
30
 
25
- @seen_headers << ret
31
+ @seen_headers << ret unless ret1.nil?
32
+ @seen_headers_canonical << ret1 unless ret1.nil?
26
33
  ret1
27
34
  end
28
35
 
@@ -45,6 +52,31 @@ module Metanorma
45
52
  end
46
53
  end
47
54
 
55
+ PREFACE_CLAUSE_NAMES = %w(abstract foreword introduction
56
+ acknowledgements).freeze
57
+
58
+ MAIN_CLAUSE_NAMES =
59
+ ["normative references", "terms and definitions", "scope",
60
+ "symbols and abbreviated terms", "clause", "bibliography"].freeze
61
+
62
+ def start_main_section(ret, node)
63
+ @preface = false if self.class::MAIN_CLAUSE_NAMES.include?(ret) &&
64
+ node.role != "preface" && node.attr("style") != "preface"
65
+ @preface = false if (self.class::PREFACE_CLAUSE_NAMES)
66
+ .intersection(@seen_headers_canonical + [ret]).empty?
67
+ end
68
+
69
+ def preface_main_filter(ret, node)
70
+ start_main_section(ret, node)
71
+ if @preface
72
+ self.class::MAIN_CLAUSE_NAMES.include?(ret) and return nil
73
+ else
74
+ self.class::PREFACE_CLAUSE_NAMES.include?(ret) and return nil
75
+ end
76
+
77
+ ret
78
+ end
79
+
48
80
  def section_attributes(node)
49
81
  ret = { id: Metanorma::Utils::anchor_or_uuid(node),
50
82
  language: node.attributes["language"],
@@ -17,43 +17,20 @@ module Metanorma
17
17
  nil
18
18
  end
19
19
 
20
- NOKOHEAD = <<~HERE.freeze
21
- <!DOCTYPE html SYSTEM
22
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
23
- <html xmlns="http://www.w3.org/1999/xhtml">
24
- <head> <title></title> <meta charset="UTF-8" /> </head>
25
- <body> </body> </html>
26
- HERE
27
-
28
- # block for processing XML document fragments as XHTML,
29
- # to allow for HTMLentities
30
- # Unescape special chars used in Asciidoctor substitution processing
31
20
  def noko(&block)
32
- doc = ::Nokogiri::XML.parse(NOKOHEAD)
33
- fragment = doc.fragment("")
34
- ::Nokogiri::XML::Builder.with fragment, &block
35
- fragment.to_xml(encoding: "US-ASCII", indent: 0,
36
- save_with: Nokogiri::XML::Node::SaveOptions::AS_XML)
37
- .lines.map do |l|
38
- l.gsub(/>\n$/, ">").gsub(/\s*\n$/m, " ").gsub("&#150;", "\u0096")
39
- .gsub("&#151;", "\u0097").gsub("&#x96;", "\u0096")
40
- .gsub("&#x97;", "\u0097")
41
- end
21
+ Metanorma::Utils::noko(&block)
42
22
  end
43
23
 
44
24
  def attr_code(attributes)
45
- attributes.compact.transform_values do |v|
46
- v.is_a?(String) ? HTMLEntities.new.decode(v) : v
47
- end
25
+ Metanorma::Utils::attr_code(attributes)
26
+ end
27
+
28
+ def csv_split(text, delim = ";")
29
+ Metanorma::Utils::csv_split(text, delim)
48
30
  end
49
31
 
50
- # if the contents of node are blocks, output them to out;
51
- # else, wrap them in <p>
52
32
  def wrap_in_para(node, out)
53
- if node.blocks? then out << node.content
54
- else
55
- out.p { |p| p << node.content }
56
- end
33
+ Metanorma::Utils::wrap_in_para(node, out)
57
34
  end
58
35
 
59
36
  SUBCLAUSE_XPATH = "//clause[not(parent::sections)]"\
@@ -67,22 +44,11 @@ module Metanorma
67
44
  end
68
45
 
69
46
  def dl_to_attrs(elem, dlist, name)
70
- e = dlist.at("./dt[text()='#{name}']") or return
71
- val = e.at("./following::dd/p") || e.at("./following::dd") or return
72
- elem[name] = val.text
47
+ Metanorma::Utils::dl_to_attrs(elem, dlist, name)
73
48
  end
74
49
 
75
50
  def dl_to_elems(ins, elem, dlist, name)
76
- a = elem.at("./#{name}[last()]")
77
- ins = a if a
78
- dlist.xpath("./dt[text()='#{name}']").each do |e|
79
- v = e.at("./following::dd")
80
- e = v.elements and e.size == 1 && e.first.name == "p" and v = e.first
81
- v.name = name
82
- ins.next = v
83
- ins = ins.next
84
- end
85
- ins
51
+ Metanorma::Utils::dl_to_elems(ins, elem, dlist, name)
86
52
  end
87
53
 
88
54
  def term_expr(elem)