metanorma-standoc 2.8.11 → 2.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/lib/metanorma/standoc/cleanup_boilerplate.rb +67 -31
- data/lib/metanorma/standoc/cleanup_maths.rb +24 -1
- data/lib/metanorma/standoc/cleanup_section_names.rb +5 -5
- data/lib/metanorma/standoc/cleanup_terms.rb +6 -5
- data/lib/metanorma/standoc/converter.rb +1 -0
- data/lib/metanorma/standoc/init.rb +13 -2
- data/lib/metanorma/standoc/macros.rb +1 -0
- data/lib/metanorma/standoc/macros_inline.rb +38 -75
- data/lib/metanorma/standoc/macros_link.rb +81 -0
- data/lib/metanorma/standoc/utils.rb +22 -2
- data/lib/metanorma/standoc/validate_table.rb +7 -0
- data/lib/metanorma/standoc/version.rb +1 -1
- data/metanorma-standoc.gemspec +3 -3
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 629fbf02985b771b385ed63f1ebcfecbd7f5031d1f476b5a5902e1b930b15a77
|
4
|
+
data.tar.gz: d89624a478853541b6cb07fe76b126f0e3e78001ac43ab63907d67481a3b05cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6aa6a1c220c69aae4eb245b2d744d03356a30ed89bfe94c8c316415934041899fa0a68e2b86fe4b026ac294cede284f4d4ff1977eecb4272914ceb4ab2b7f87f
|
7
|
+
data.tar.gz: 26f1f58f773930cdf01d08c9c09aaa4e0f2e31392746cfb199cfb629299ec4500a9dd4e62bc999b9a5b65bea8ee568076431b82de79d323dfe654b891ffafc7f
|
data/.rubocop.yml
CHANGED
@@ -2,19 +2,15 @@ module Metanorma
|
|
2
2
|
module Standoc
|
3
3
|
module Cleanup
|
4
4
|
def external_terms_boilerplate(sources)
|
5
|
-
@i18n.
|
6
|
-
|
7
|
-
|
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.
|
14
|
-
|
15
|
-
|
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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
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 =
|
57
|
-
|
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[
|
104
|
-
|
105
|
-
|
106
|
-
f
|
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("./
|
112
|
-
|
113
|
-
|
114
|
-
|
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)
|
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+)?$}
|
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[
|
87
|
+
replace_title(xml, "//terms#{SYMnoABBR} | //clause[@type = 'terms']#{SYMnoABBR}",
|
88
88
|
@i18n&.termsdefsymbols, true)
|
89
|
-
replace_title(xml, "//terms#{ABBRnoSYM} | //clause[
|
89
|
+
replace_title(xml, "//terms#{ABBRnoSYM} | //clause[@type = 'terms']#{ABBRnoSYM}",
|
90
90
|
@i18n&.termsdefabbrev, true)
|
91
|
-
replace_title(xml, "//terms#{SYMABBR} | //clause[
|
91
|
+
replace_title(xml, "//terms#{SYMABBR} | //clause[@type = 'terms']#{SYMABBR}",
|
92
92
|
@i18n&.termsdefsymbolsabbrev, true)
|
93
|
-
replace_title(xml, "//terms#{NO_SYMABBR} | //clause[
|
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[
|
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
|
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
|
-
|
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
|
-
|
139
|
-
|
140
|
+
term or return
|
140
141
|
idx = term.children.dup
|
141
142
|
fieldofappl.empty? or idx << ", <#{fieldofappl}>"
|
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
|
139
|
+
class SpanInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
198
140
|
use_dsl
|
199
|
-
named :
|
141
|
+
named :span
|
200
142
|
parse_content_as :text
|
201
|
-
using_format :short
|
202
143
|
|
203
|
-
def process(parent,
|
204
|
-
|
205
|
-
|
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
|
150
|
+
class NumberInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
|
151
|
+
include ::Metanorma::Standoc::Utils
|
152
|
+
|
216
153
|
use_dsl
|
217
|
-
named :
|
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
|
-
|
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(&
|
21
|
-
Metanorma::Utils::noko(@script, &
|
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|
|
data/metanorma-standoc.gemspec
CHANGED
@@ -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(">=
|
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.
|
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.
|
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.
|
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-
|
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.
|
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.
|
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.
|
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.
|
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:
|
571
|
+
version: 3.1.0
|
571
572
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
572
573
|
requirements:
|
573
574
|
- - ">="
|