metanorma-standoc 2.8.11 → 2.9.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e6a03a5dfead99850405d6b949a0103367ff0c280aa22d55e9c637eb34d1fe2c
4
- data.tar.gz: '06098dc9ad34cc0fdbd3df1ccaeedd51ef3b79e89a645e0ccb66979f582f82bf'
3
+ metadata.gz: 629fbf02985b771b385ed63f1ebcfecbd7f5031d1f476b5a5902e1b930b15a77
4
+ data.tar.gz: d89624a478853541b6cb07fe76b126f0e3e78001ac43ab63907d67481a3b05cf
5
5
  SHA512:
6
- metadata.gz: a35bd65e87ae978c0e34694b94365d364a528168e8aad39aa2733f6e900a14f219a85a38a275f9c24d00001fd0e19b5931a24578063dd1d45d1016066d744677
7
- data.tar.gz: 9e8e5215b27ba6b2e11fe50d0a544084afb32aa7d74fabde539844ff38797bd3217c48b8f980e97cfdd93f446bb4ef44e9cd80e610081996d45941cfc10f2357
6
+ metadata.gz: 6aa6a1c220c69aae4eb245b2d744d03356a30ed89bfe94c8c316415934041899fa0a68e2b86fe4b026ac294cede284f4d4ff1977eecb4272914ceb4ab2b7f87f
7
+ data.tar.gz: 26f1f58f773930cdf01d08c9c09aaa4e0f2e31392746cfb199cfb629299ec4500a9dd4e62bc999b9a5b65bea8ee568076431b82de79d323dfe654b891ffafc7f
data/.rubocop.yml CHANGED
@@ -7,4 +7,4 @@ inherit_from:
7
7
  # ...
8
8
 
9
9
  AllCops:
10
- TargetRubyVersion: 2.5
10
+ TargetRubyVersion: 3.4
@@ -2,19 +2,15 @@ module Metanorma
2
2
  module Standoc
3
3
  module Cleanup
4
4
  def external_terms_boilerplate(sources)
5
- @i18n.l10n(
6
- @i18n.external_terms_boilerplate.gsub(/%(?=\p{P}|\p{Z}|$)/,
7
- sources || "???"),
8
- @lang, @script, @locale
9
- )
5
+ e = @i18n.external_terms_boilerplate
6
+ @i18n.l10n(e.gsub(/%(?=\p{P}|\p{Z}|$)/, sources || "???"),
7
+ @lang, @script, @locale)
10
8
  end
11
9
 
12
10
  def internal_external_terms_boilerplate(sources)
13
- @i18n.l10n(
14
- @i18n.internal_external_terms_boilerplate.gsub(/%(?=\p{P}|\p{Z}|$)/,
15
- sources || "??"),
16
- @lang, @script
17
- )
11
+ e = @i18n.internal_external_terms_boilerplate
12
+ @i18n.l10n(e.gsub(/%(?=\p{P}|\p{Z}|$)/, sources || "??"),
13
+ @lang, @script)
18
14
  end
19
15
 
20
16
  def term_defs_boilerplate(div, source, term, _preface, isodoc)
@@ -26,8 +22,7 @@ module Metanorma
26
22
  end
27
23
  a = if source.empty? && term.nil? then @i18n.no_terms_boilerplate
28
24
  else term_defs_boilerplate_cont(source, term, isodoc)
29
- end
30
- a and div.next = a
25
+ end and div.next = a
31
26
  end
32
27
 
33
28
  def term_defs_boilerplate_cont(src, term, isodoc)
@@ -42,19 +37,42 @@ module Metanorma
42
37
  end
43
38
 
44
39
  def norm_ref_preface(ref)
45
- if ref.at("./note[@type = 'boilerplate']")
46
- unwrap_boilerplate_clauses(ref, ".")
47
- else
48
- refs = ref.elements.select do |e|
49
- %w(references bibitem).include? e.name
50
- end
51
- pref = refs.empty? ? @i18n.norm_empty_pref : @i18n.norm_with_refs_pref
52
- ref.at("./title").next = "<p>#{pref}</p>"
40
+ ins = norm_ref_boilerplate_insert_location(ref)
41
+ ins2 = norm_ref_process_boilerplate_note(ref)
42
+ ins2 == :populated and return
43
+ ins2 == :missing or ins = ins2
44
+ refs = ref.elements.select do |e|
45
+ %w(references bibitem).include? e.name
46
+ end
47
+ pref = refs.empty? ? @i18n.norm_empty_pref : @i18n.norm_with_refs_pref
48
+ ins.next = "<p>#{pref}</p>"
49
+ end
50
+
51
+ def norm_ref_process_boilerplate_note(ref)
52
+ ins2 = ref.at("./note[@type = 'boilerplate']") or return :missing
53
+ if ins2 && ins2.text.strip.downcase == "(default)"
54
+ ins2.children = " "
55
+ ins2.children.first
56
+ else :populated
57
+ end
58
+ end
59
+
60
+ def norm_ref_boilerplate_insert_location(ref)
61
+ while (n = ref.parent) && %w(clause references).include?(n&.name)
62
+ n.elements.detect do |e|
63
+ !%(title references).include?(e.name) &&
64
+ !e.at("./self::clause[@type = 'boilerplate']") &&
65
+ !e.at("./self::clause[.//references][not(.//clause[not(.//bibitem)])]")
66
+ end and break
67
+ ref = n
53
68
  end
69
+ ref.at("./title")
54
70
  end
55
71
 
56
- TERM_CLAUSE = "//sections/terms | " \
57
- "//sections/clause[descendant::terms]".freeze
72
+ TERM_CLAUSE =
73
+ "//sections//terms[not(.//ancestor::clause[@type = 'terms'])] | " \
74
+ "//sections/clause[descendant::terms][@type = 'terms'] | " \
75
+ "//sections/clause[not(@type = 'terms')]//terms".freeze
58
76
 
59
77
  NORM_REF =
60
78
  "//bibliography/references[@normative = 'true'][not(@hidden)] | " \
@@ -100,18 +118,33 @@ module Metanorma
100
118
 
101
119
  def termdef_boilerplate_insert_location(xmldoc)
102
120
  f = xmldoc.at(self.class::TERM_CLAUSE)
103
- root = xmldoc.at("//sections/terms | //sections/clause[.//terms]")
104
- !f || !root and return f || root
105
- f.at("./following::terms") and return root
106
- f.at("./preceding-sibling::clause") and return root
121
+ root = xmldoc.at("//sections/terms | //sections/clause[@type = 'terms']")
122
+ if f && root && f["id"] != root["id"]
123
+ f = termdef_boilerplate_climb_up(f, root)
124
+ elsif !f && root then f = root
125
+ end
107
126
  f
108
127
  end
109
128
 
129
+ def termdef_boilerplate_climb_up(clause, container)
130
+ container.at(".//*[@id = '#{clause['id']}']") or return clause
131
+ while (n = clause.parent)
132
+ n.at(".//definitions") and break
133
+ clause = n
134
+ n["id"] == container["id"] and break
135
+ end
136
+ clause
137
+ end
138
+
110
139
  def termdef_boilerplate_insert1(sect, xmldoc, isodoc)
111
- sect.at("./clause[@type = 'boilerplate'] | " \
112
- "./note[@type = 'boilerplate']") and return
113
- term_defs_boilerplate(sect.at("./title"),
114
- xmldoc.xpath(".//termdocsource"),
140
+ ins = sect.at("./title")
141
+ if (ins2 = sect.at("./clause[@type = 'boilerplate'] | " \
142
+ "./note[@type = 'boilerplate']"))
143
+ ins2.text.strip.downcase == "(default)" or return
144
+ ins2.children = " "
145
+ ins = ins2.children.first
146
+ end
147
+ term_defs_boilerplate(ins, xmldoc.xpath(".//termdocsource"),
115
148
  sect.at(".//term"), sect.at(".//p"), isodoc)
116
149
  end
117
150
 
@@ -120,7 +153,10 @@ module Metanorma
120
153
  termdef_boilerplate_cleanup(xmldoc)
121
154
  termdef_boilerplate_insert(xmldoc, isodoc)
122
155
  unwrap_boilerplate_clauses(xmldoc, self.class::TERM_CLAUSE)
123
- f = xmldoc.at(self.class::NORM_REF) and norm_ref_preface(f)
156
+ if f = xmldoc.at(self.class::NORM_REF)
157
+ norm_ref_preface(f)
158
+ unwrap_boilerplate_clauses(f, ".")
159
+ end
124
160
  initial_boilerplate(xmldoc, isodoc)
125
161
  end
126
162
 
@@ -27,7 +27,7 @@ module Metanorma
27
27
  end
28
28
 
29
29
  # https://medium.com/@rickwang_wxc/in-ruby-given-a-string-detect-if-it-is-valid-numeric-c58275eace60
30
- NUMERIC_REGEX = %r{^((\+|-)?\d*\.?\d+)([eE](\+|-){1}\d+)?$}.freeze
30
+ NUMERIC_REGEX = %r{^((\+|-)?\d*\.?\d+)([eE](\+|-){1}\d+)?$}
31
31
 
32
32
  MATHML_NS = "http://www.w3.org/1998/Math/MathML".freeze
33
33
 
@@ -204,6 +204,28 @@ module Metanorma
204
204
  end
205
205
  end
206
206
 
207
+ def mathml_mn_format(math)
208
+ math.xpath(".//m:mn", "m" => MATHML_NS).each do |m|
209
+ profile = mathml_mn_profile(m)
210
+ attr = profile.each_with_object([]) do |(k, v), acc|
211
+ v == "nil" and next
212
+ acc << "#{k}='#{v}'"
213
+ end.join(",")
214
+ attr.empty? or m["data-metanorma-numberformat"] = attr
215
+ end
216
+ end
217
+
218
+ def mathml_mn_profile(mnum)
219
+ fmt = @numberfmt_default&.dup || {}
220
+ fmt1 = {}
221
+ fmt2 = kv_parse(mnum["data-metanorma-numberformat"] || "")
222
+ if fmt2["profile"]
223
+ fmt1 = @numberfmt_prof[fmt2["profile"]] || {}
224
+ fmt2.delete("profile")
225
+ end
226
+ fmt.merge(fmt1).merge(fmt2)
227
+ end
228
+
207
229
  def mathml_cleanup(xmldoc)
208
230
  unitsml = Asciimath2UnitsML::Conv.new(asciimath2unitsml_options)
209
231
  xmldoc.xpath("//stem[@type = 'MathML'][not(@validate = 'false')]")
@@ -214,6 +236,7 @@ module Metanorma
214
236
  unitsml.MathML2UnitsML(x)
215
237
  mathml_mathvariant(x)
216
238
  mathml_italicise(x)
239
+ mathml_mn_format(x)
217
240
  end
218
241
  mathml_unitsML(xmldoc)
219
242
  end
@@ -84,15 +84,15 @@ module Metanorma
84
84
 
85
85
  def section_names_terms1_cleanup(xml)
86
86
  auto_name_terms(xml) or return
87
- replace_title(xml, "//terms#{SYMnoABBR} | //clause[.//terms]#{SYMnoABBR}",
87
+ replace_title(xml, "//terms#{SYMnoABBR} | //clause[@type = 'terms']#{SYMnoABBR}",
88
88
  @i18n&.termsdefsymbols, true)
89
- replace_title(xml, "//terms#{ABBRnoSYM} | //clause[.//terms]#{ABBRnoSYM}",
89
+ replace_title(xml, "//terms#{ABBRnoSYM} | //clause[@type = 'terms']#{ABBRnoSYM}",
90
90
  @i18n&.termsdefabbrev, true)
91
- replace_title(xml, "//terms#{SYMABBR} | //clause[.//terms]#{SYMABBR}",
91
+ replace_title(xml, "//terms#{SYMABBR} | //clause[@type = 'terms']#{SYMABBR}",
92
92
  @i18n&.termsdefsymbolsabbrev, true)
93
- replace_title(xml, "//terms#{NO_SYMABBR} | //clause[.//terms]#{NO_SYMABBR}",
93
+ replace_title(xml, "//terms#{NO_SYMABBR} | //clause[@type = 'terms']#{NO_SYMABBR}",
94
94
  @i18n&.termsdefsymbolsabbrev, true)
95
- replace_title(xml, "//terms[not(.//definitions)] | //clause[.//terms][not(.//definitions)]",
95
+ replace_title(xml, "//terms[not(.//definitions)] | //clause[@type = 'terms'][not(.//definitions)]",
96
96
  @i18n&.termsdef, true)
97
97
  end
98
98
 
@@ -74,7 +74,10 @@ module Metanorma
74
74
  end
75
75
 
76
76
  def term_children_cleanup(xmldoc)
77
- xmldoc.xpath("//terms[terms][not(term)]").each { |t| t.name = "clause" }
77
+ xmldoc.xpath("//terms[terms][not(term)]").each do |t|
78
+ t.name = "clause"
79
+ t["type"] = "terms"
80
+ end
78
81
  xmldoc.xpath("//term").each do |t|
79
82
  %w(termnote termexample termsource term).each do |w|
80
83
  t.xpath("./#{w}").each { |n| t << n.remove }
@@ -122,8 +125,7 @@ module Metanorma
122
125
  end
123
126
 
124
127
  def term_index_cleanup(xmldoc)
125
- return unless @index_terms
126
-
128
+ @index_terms or return
127
129
  xmldoc.xpath("//preferred").each do |p|
128
130
  index_cleanup1(p.at("./expression/name | ./letter-symbol/name"),
129
131
  p.xpath("./field-of-application | ./usage-info")
@@ -135,8 +137,7 @@ module Metanorma
135
137
  end
136
138
 
137
139
  def index_cleanup1(term, fieldofappl)
138
- return unless term
139
-
140
+ term or return
140
141
  idx = term.children.dup
141
142
  fieldofappl.empty? or idx << ", &#x3c;#{fieldofappl}&#x3e;"
142
143
  term << "<index><primary>#{idx.to_xml}</primary></index>"
@@ -67,6 +67,7 @@ module Metanorma
67
67
  inline_macro Metanorma::Standoc::ToCInlineMacro
68
68
  inline_macro Metanorma::Standoc::PassInlineMacro
69
69
  inline_macro Metanorma::Standoc::StdLinkInlineMacro
70
+ inline_macro Metanorma::Standoc::NumberInlineMacro
70
71
  block Metanorma::Standoc::ToDoAdmonitionBlock
71
72
  block Metanorma::Standoc::EditorAdmonitionBlock
72
73
  treeprocessor Metanorma::Standoc::EditorInlineAdmonitionBlock
@@ -1,3 +1,5 @@
1
+ require_relative "utils"
2
+
1
3
  module Metanorma
2
4
  module Standoc
3
5
  module Base
@@ -10,6 +12,7 @@ module Metanorma
10
12
  init_output(node) # feeds init_biblio
11
13
  init_i18n(node)
12
14
  init_biblio(node)
15
+ init_math(node)
13
16
  @metadata_attrs = metadata_attrs(node)
14
17
  end
15
18
 
@@ -42,8 +45,6 @@ module Metanorma
42
45
  def init_processing(node)
43
46
  @novalid = node.attr("novalid")
44
47
  @smartquotes = node.attr("smartquotes") != "false"
45
- @keepasciimath = node.attr("mn-keep-asciimath") &&
46
- node.attr("mn-keep-asciimath") != "false"
47
48
  @sourcecode_markup_start = node.attr("sourcecode-markup-start") || "{{{"
48
49
  @sourcecode_markup_end = node.attr("sourcecode-markup-end") || "}}}"
49
50
  @datauriimage = node.attr("data-uri-image") != "false"
@@ -108,6 +109,16 @@ module Metanorma
108
109
  ::Metanorma::Standoc::LocalBiblio.new(node, @localdir, self)
109
110
  end
110
111
 
112
+ def init_math(node)
113
+ @keepasciimath = node.attr("mn-keep-asciimath") &&
114
+ node.attr("mn-keep-asciimath") != "false"
115
+ @numberfmt_default = kv_parse(node.attr("number-presentation"))
116
+ @numberfmt_prof = node.attributes.each_with_object({}) do |(k, v), m|
117
+ p = /^number-presentation-profile-(.*)$/.match(k) or next
118
+ m[p[1]] = kv_parse(v)
119
+ end
120
+ end
121
+
111
122
  def requirements_processor
112
123
  Metanorma::Requirements
113
124
  end
@@ -7,6 +7,7 @@ require_relative "macros_terms"
7
7
  require_relative "macros_form"
8
8
  require_relative "macros_note"
9
9
  require_relative "macros_embed"
10
+ require_relative "macros_link"
10
11
  require_relative "datamodel/attributes_table_preprocessor"
11
12
  require_relative "datamodel/diagram_preprocessor"
12
13
  require "metanorma-plugin-datastruct"
@@ -1,3 +1,5 @@
1
+ require_relative "utils"
2
+
1
3
  module Metanorma
2
4
  module Standoc
3
5
  class InheritInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
@@ -12,49 +14,6 @@ module Metanorma
12
14
  end
13
15
  end
14
16
 
15
- class IndexXrefInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
16
- use_dsl
17
- named :index
18
-
19
- def preprocess_attrs(attrs)
20
- ret = { primary: attrs[1], target: attrs[attrs.size] }
21
- ret[:secondary] = attrs[2] if attrs.size > 2
22
- ret[:tertiary] = attrs[3] if attrs.size > 3
23
- ret
24
- end
25
-
26
- def validate(parent, target, attrs)
27
- attrs.size > 1 && attrs.size < 5 and return true
28
- e = "invalid index \"#{target}\" cross-reference: wrong number of " \
29
- "attributes in `index:#{target}[#{attrs.values.join(',')}]`"
30
- parent.converter.log.add("Crossreferences", parent, e, severity: 0)
31
- false
32
- end
33
-
34
- def process(parent, target, attr)
35
- validate(parent, target, attr) or return
36
- args = preprocess_attrs(attr)
37
- ret = "<index-xref also='#{target == 'also'}'>" \
38
- "<primary>#{args[:primary]}</primary>"
39
- ret += "<secondary>#{args[:secondary]}</secondary>" if args[:secondary]
40
- ret += "<tertiary>#{args[:tertiary]}</tertiary>" if args[:tertiary]
41
- ret + "<target>#{args[:target]}</target></index-xref>"
42
- end
43
- end
44
-
45
- class IndexRangeInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
46
- use_dsl
47
- named :"index-range"
48
- parse_content_as :text
49
-
50
- def process(parent, target, attr)
51
- text = attr["text"]
52
- text = "((#{text}))" unless /^\(\(.+\)\)$/.match?(text)
53
- out = parent.sub_macros(text)
54
- out.sub("<index>", "<index to='#{target}'>")
55
- end
56
- end
57
-
58
17
  class HTML5RubyMacro < Asciidoctor::Extensions::InlineMacroProcessor
59
18
  use_dsl
60
19
  named :ruby
@@ -151,23 +110,6 @@ module Metanorma
151
110
  end
152
111
  end
153
112
 
154
- class ToCInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
155
- use_dsl
156
- named :toc
157
- parse_content_as :text
158
- using_format :short
159
-
160
- def process(parent, _target, attrs)
161
- out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
162
- content = CSV.parse_line(out).map do |x|
163
- x.sub!(/^(["'])(.+)\1/, "\\2")
164
- m = /^(.*?)(:\d+)?$/.match(x)
165
- %{<toc-xpath depth='#{m[2]&.sub(':', '') || 1}'>#{m[1]}</toc-xpath>}
166
- end.join
167
- "<toc>#{content}</toc>"
168
- end
169
- end
170
-
171
113
  # inject ZWNJ to prevent Asciidoctor from attempting regex substitutions
172
114
  class PassInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
173
115
  use_dsl
@@ -194,32 +136,53 @@ module Metanorma
194
136
  end
195
137
  end
196
138
 
197
- class StdLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
139
+ class SpanInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
198
140
  use_dsl
199
- named :"std-link"
141
+ named :span
200
142
  parse_content_as :text
201
- using_format :short
202
143
 
203
- def process(parent, _target, attrs)
204
- t = attrs["text"]
205
- t = if /,/.match?(t)
206
- t.sub(/,/, "%")
207
- else
208
- "#{t}%"
209
- end
210
- create_anchor(parent, "hidden=#{t}",
211
- type: :xref, target: "_#{UUIDTools::UUID.random_create}")
144
+ def process(parent, target, attrs)
145
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
146
+ %{<span class="#{target}">#{out}</span>}
212
147
  end
213
148
  end
214
149
 
215
- class SpanInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
150
+ class NumberInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
151
+ include ::Metanorma::Standoc::Utils
152
+
216
153
  use_dsl
217
- named :span
154
+ named :number
218
155
  parse_content_as :text
219
156
 
157
+ MATHML_NS = "http://www.w3.org/1998/Math/MathML".freeze
158
+
159
+ def unquote(str)
160
+ str.sub(/^(["'])(.+)\1$/, "\\2")
161
+ end
162
+
163
+ def format(attrs)
164
+ # a="," => "a=,"
165
+ quoted_csv_split(attrs || "", ",").map do |x|
166
+ m = /^(.+?)=(.+)?$/.match(x) or next
167
+ "#{m[1]}='#{m[2]}'"
168
+ end.join(",")
169
+ end
170
+
171
+ def number(text)
172
+ n = BigDecimal(text)
173
+ trailing_zeroes = 0
174
+ m = /\.[1-9]*(0+)/.match(text) and trailing_zeroes += m[1].size
175
+ n.to_s("E").sub("e", "0" * trailing_zeroes + "e")
176
+ end
177
+
220
178
  def process(parent, target, attrs)
221
179
  out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
222
- %{<span class="#{target}">#{out}</span>}
180
+ fmt = format(out)
181
+ fmt.empty? and fmt = "notation='basic'"
182
+ fmt = %( data-metanorma-numberformat="#{fmt}")
183
+ <<~OUTPUT
184
+ <stem type="MathML"><math xmlns='#{MATHML_NS}'><mn#{fmt}>#{number(target)}</mn></math></stem>
185
+ OUTPUT
223
186
  end
224
187
  end
225
188
  end
@@ -0,0 +1,81 @@
1
+ module Metanorma
2
+ module Standoc
3
+ class IndexXrefInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
4
+ use_dsl
5
+ named :index
6
+
7
+ def preprocess_attrs(attrs)
8
+ ret = { primary: attrs[1], target: attrs[attrs.size] }
9
+ ret[:secondary] = attrs[2] if attrs.size > 2
10
+ ret[:tertiary] = attrs[3] if attrs.size > 3
11
+ ret
12
+ end
13
+
14
+ def validate(parent, target, attrs)
15
+ attrs.size > 1 && attrs.size < 5 and return true
16
+ e = "invalid index \"#{target}\" cross-reference: wrong number of " \
17
+ "attributes in `index:#{target}[#{attrs.values.join(',')}]`"
18
+ parent.converter.log.add("Crossreferences", parent, e, severity: 0)
19
+ false
20
+ end
21
+
22
+ def process(parent, target, attr)
23
+ validate(parent, target, attr) or return
24
+ args = preprocess_attrs(attr)
25
+ ret = "<index-xref also='#{target == 'also'}'>" \
26
+ "<primary>#{args[:primary]}</primary>"
27
+ ret += "<secondary>#{args[:secondary]}</secondary>" if args[:secondary]
28
+ ret += "<tertiary>#{args[:tertiary]}</tertiary>" if args[:tertiary]
29
+ ret + "<target>#{args[:target]}</target></index-xref>"
30
+ end
31
+ end
32
+
33
+ class IndexRangeInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
34
+ use_dsl
35
+ named :"index-range"
36
+ parse_content_as :text
37
+
38
+ def process(parent, target, attr)
39
+ text = attr["text"]
40
+ text = "((#{text}))" unless /^\(\(.+\)\)$/.match?(text)
41
+ out = parent.sub_macros(text)
42
+ out.sub("<index>", "<index to='#{target}'>")
43
+ end
44
+ end
45
+
46
+ class ToCInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
47
+ use_dsl
48
+ named :toc
49
+ parse_content_as :text
50
+ using_format :short
51
+
52
+ def process(parent, _target, attrs)
53
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
54
+ content = CSV.parse_line(out).map do |x|
55
+ x.sub!(/^(["'])(.+)\1/, "\\2")
56
+ m = /^(.*?)(:\d+)?$/.match(x)
57
+ %{<toc-xpath depth='#{m[2]&.sub(':', '') || 1}'>#{m[1]}</toc-xpath>}
58
+ end.join
59
+ "<toc>#{content}</toc>"
60
+ end
61
+ end
62
+
63
+ class StdLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
64
+ use_dsl
65
+ named :"std-link"
66
+ parse_content_as :text
67
+ using_format :short
68
+
69
+ def process(parent, _target, attrs)
70
+ t = attrs["text"]
71
+ t = if /,/.match?(t)
72
+ t.sub(/,/, "%")
73
+ else
74
+ "#{t}%"
75
+ end
76
+ create_anchor(parent, "hidden=#{t}",
77
+ type: :xref, target: "_#{UUIDTools::UUID.random_create}")
78
+ end
79
+ end
80
+ end
81
+ end
@@ -17,8 +17,8 @@ module Metanorma
17
17
  nil
18
18
  end
19
19
 
20
- def noko(&block)
21
- Metanorma::Utils::noko(@script, &block)
20
+ def noko(&)
21
+ Metanorma::Utils::noko(@script, &)
22
22
  end
23
23
 
24
24
  def attr_code(attributes)
@@ -30,6 +30,26 @@ module Metanorma
30
30
  .map { |x| @c.encode(x, :basic, :hexadecimal) }
31
31
  end
32
32
 
33
+ def quoted_csv_split(text, delim = ",", eql = "=")
34
+ # quoted strings: key="va,lue",
35
+ c = HTMLEntities.new
36
+ text = c.decode(text).gsub(/([a-zA-Z_]+)#{eql}(["'])(.+?)\2/,
37
+ %("\\1#{eql}\\3"))
38
+ Metanorma::Utils::csv_split(text, delim)
39
+ .map do |x|
40
+ c.encode(x.sub(/^(["'])(.+)\1$/, "\\2"), :basic, :hexadecimal)
41
+ end
42
+ end
43
+
44
+ def kv_parse(text, delim = ",", eql = "=")
45
+ text or return {}
46
+ c = HTMLEntities.new
47
+ quoted_csv_split(text, delim).each_with_object({}) do |k, m|
48
+ x = k.split(eql, 2)
49
+ m[x[0]] = c.decode(x[1])
50
+ end
51
+ end
52
+
33
53
  def wrap_in_para(node, out)
34
54
  Metanorma::Utils::wrap_in_para(node, out)
35
55
  end
@@ -2,6 +2,7 @@ module Metanorma
2
2
  module Standoc
3
3
  module Validate
4
4
  def table_validate(doc)
5
+ empty_table_validate(doc)
5
6
  doc.xpath("//table[colgroup]").each do |t|
6
7
  maxrowcols_validate(t, t.xpath("./colgroup/col").size)
7
8
  end
@@ -13,6 +14,12 @@ module Metanorma
13
14
  end
14
15
  end
15
16
 
17
+ def empty_table_validate(doc)
18
+ doc.xpath("//table[not(.//tr)]").each do |t|
19
+ @log.add("Table", t, "Empty table", severity: 0)
20
+ end
21
+ end
22
+
16
23
  def max_td_count(table)
17
24
  max = 0
18
25
  table.xpath("./tr").each do |tr|
@@ -19,6 +19,6 @@ module Metanorma
19
19
  end
20
20
 
21
21
  module Standoc
22
- VERSION = "2.8.11".freeze
22
+ VERSION = "2.9.0".freeze
23
23
  end
24
24
  end
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  f.match(%r{^(test|spec|features|bin|.github)/}) \
27
27
  || f.match(%r{Rakefile|bin/rspec})
28
28
  end
29
- spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
29
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0")
30
30
 
31
31
  spec.add_dependency "addressable", "~> 2.8.0"
32
32
  spec.add_dependency "asciidoctor", "~> 2.0.0"
@@ -36,13 +36,13 @@ Gem::Specification.new do |spec|
36
36
  spec.add_dependency "metanorma", ">= 1.6.0"
37
37
  spec.add_dependency "metanorma-plugin-datastruct", "~> 0.3.0"
38
38
  spec.add_dependency "metanorma-plugin-glossarist", "~> 0.2.0"
39
- spec.add_dependency "metanorma-plugin-lutaml", "~> 0.6.0"
39
+ spec.add_dependency "metanorma-plugin-lutaml", "~> 0.7.0"
40
40
  spec.add_dependency "ruby-jing"
41
41
  # relaton-cli not just relaton, to avoid circular reference in metanorma
42
42
  spec.add_dependency "asciimath2unitsml", "~> 0.4.0"
43
43
  spec.add_dependency "concurrent-ruby"
44
44
  spec.add_dependency "pngcheck"
45
- spec.add_dependency "relaton-cli", "~> 1.18.1"
45
+ spec.add_dependency "relaton-cli", "~> 1.19.0"
46
46
  spec.add_dependency "relaton-iev", "~> 1.2.0"
47
47
  spec.add_dependency "unicode2latex", "~> 0.0.1"
48
48
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-standoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.11
4
+ version: 2.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-17 00:00:00.000000000 Z
11
+ date: 2024-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 0.6.0
131
+ version: 0.7.0
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 0.6.0
138
+ version: 0.7.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: ruby-jing
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -198,14 +198,14 @@ dependencies:
198
198
  requirements:
199
199
  - - "~>"
200
200
  - !ruby/object:Gem::Version
201
- version: 1.18.1
201
+ version: 1.19.0
202
202
  type: :runtime
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - "~>"
207
207
  - !ruby/object:Gem::Version
208
- version: 1.18.1
208
+ version: 1.19.0
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: relaton-iev
211
211
  requirement: !ruby/object:Gem::Requirement
@@ -528,6 +528,7 @@ files:
528
528
  - lib/metanorma/standoc/macros_embed.rb
529
529
  - lib/metanorma/standoc/macros_form.rb
530
530
  - lib/metanorma/standoc/macros_inline.rb
531
+ - lib/metanorma/standoc/macros_link.rb
531
532
  - lib/metanorma/standoc/macros_note.rb
532
533
  - lib/metanorma/standoc/macros_plantuml.rb
533
534
  - lib/metanorma/standoc/macros_terms.rb
@@ -567,7 +568,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
567
568
  requirements:
568
569
  - - ">="
569
570
  - !ruby/object:Gem::Version
570
- version: 2.7.0
571
+ version: 3.1.0
571
572
  required_rubygems_version: !ruby/object:Gem::Requirement
572
573
  requirements:
573
574
  - - ">="