metanorma-standoc 2.8.11 → 2.9.1
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/anchor.rb +3 -3
- data/lib/metanorma/standoc/base.rb +1 -1
- data/lib/metanorma/standoc/blocks.rb +5 -5
- data/lib/metanorma/standoc/blocks_image.rb +1 -1
- data/lib/metanorma/standoc/blocks_notes.rb +6 -6
- data/lib/metanorma/standoc/cleanup.rb +15 -0
- data/lib/metanorma/standoc/cleanup_block.rb +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_ref.rb +0 -1
- data/lib/metanorma/standoc/cleanup_section.rb +5 -9
- data/lib/metanorma/standoc/cleanup_section_names.rb +5 -5
- data/lib/metanorma/standoc/cleanup_terms.rb +6 -5
- data/lib/metanorma/standoc/cleanup_xref.rb +6 -10
- data/lib/metanorma/standoc/converter.rb +1 -0
- data/lib/metanorma/standoc/init.rb +23 -2
- data/lib/metanorma/standoc/inline.rb +5 -5
- data/lib/metanorma/standoc/isodoc.rng +5 -5
- data/lib/metanorma/standoc/lists.rb +4 -4
- data/lib/metanorma/standoc/macros.rb +16 -44
- data/lib/metanorma/standoc/macros_embed.rb +14 -12
- data/lib/metanorma/standoc/macros_inline.rb +38 -75
- data/lib/metanorma/standoc/macros_link.rb +81 -0
- data/lib/metanorma/standoc/ref.rb +9 -12
- data/lib/metanorma/standoc/ref_queue.rb +2 -4
- data/lib/metanorma/standoc/ref_utility.rb +2 -2
- data/lib/metanorma/standoc/section.rb +3 -3
- data/lib/metanorma/standoc/terms.rb +2 -2
- data/lib/metanorma/standoc/utils.rb +22 -2
- data/lib/metanorma/standoc/validate.rb +14 -2
- data/lib/metanorma/standoc/validate_table.rb +7 -0
- data/lib/metanorma/standoc/version.rb +1 -1
- data/metanorma-standoc.gemspec +5 -4
- metadata +24 -9
@@ -41,7 +41,7 @@ module Metanorma
|
|
41
41
|
list_caption(node, xml_ul)
|
42
42
|
node.items.each { |item| ul_li(xml_ul, item) }
|
43
43
|
end
|
44
|
-
end.join("
|
44
|
+
end.join("")
|
45
45
|
end
|
46
46
|
|
47
47
|
def olist_style(style)
|
@@ -67,7 +67,7 @@ module Metanorma
|
|
67
67
|
list_caption(node, xml_ol)
|
68
68
|
node.items.each { |item| li(xml_ol, item) }
|
69
69
|
end
|
70
|
-
end.join("
|
70
|
+
end.join("")
|
71
71
|
end
|
72
72
|
|
73
73
|
def dt(terms, xml_dl)
|
@@ -107,7 +107,7 @@ module Metanorma
|
|
107
107
|
dd(dd, xml_dl)
|
108
108
|
end
|
109
109
|
end
|
110
|
-
end.join("
|
110
|
+
end.join("")
|
111
111
|
end
|
112
112
|
|
113
113
|
def colist(node)
|
@@ -117,7 +117,7 @@ module Metanorma
|
|
117
117
|
xml_li.p { |p| p << item.text }
|
118
118
|
end
|
119
119
|
end
|
120
|
-
end.join("
|
120
|
+
end.join("")
|
121
121
|
end
|
122
122
|
|
123
123
|
def list_caption(node, out)
|
@@ -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"
|
@@ -52,13 +53,19 @@ module Metanorma
|
|
52
53
|
class NamedEscapePreprocessor < Asciidoctor::Extensions::Preprocessor
|
53
54
|
def process(document, reader)
|
54
55
|
c = HTMLEntities.new
|
56
|
+
p = Metanorma::Utils::LineStatus.new
|
55
57
|
lines = reader.lines.map do |l|
|
56
|
-
|
57
|
-
|
58
|
-
end.join
|
58
|
+
p.process(l)
|
59
|
+
p.pass ? l : convert(l, c)
|
59
60
|
end
|
60
61
|
::Asciidoctor::PreprocessorReader.new document, lines
|
61
62
|
end
|
63
|
+
|
64
|
+
def convert(line, esc)
|
65
|
+
line.split(/(&[A-Za-z][^&;]*;)/).map do |s|
|
66
|
+
/^&[A-Za-z]/.match?(s) ? esc.encode(esc.decode(s), :hexadecimal) : s
|
67
|
+
end.join
|
68
|
+
end
|
62
69
|
end
|
63
70
|
|
64
71
|
class ColumnBreakBlockMacro < Asciidoctor::Extensions::BlockMacroProcessor
|
@@ -74,51 +81,16 @@ module Metanorma
|
|
74
81
|
# Not using TreeProcessor because that is still too close to
|
75
82
|
# inline expressions being processed on access (e.g. titles)
|
76
83
|
class LinkProtectPreprocessor < Asciidoctor::Extensions::Preprocessor
|
77
|
-
def init
|
78
|
-
pass = true # process as passthrough: init = true until
|
79
|
-
# hit end of doc header
|
80
|
-
is_delim = false # current line is a no-substititon block delimiter
|
81
|
-
pass_delim = false # current line is a passthrough delimiter
|
82
|
-
delimln = "" # delimiter line of current block(s);
|
83
|
-
# init value looks for end of doc header
|
84
|
-
{ pass: pass, is_delim: is_delim, pass_delim: pass_delim,
|
85
|
-
delimln: delimln }
|
86
|
-
end
|
87
|
-
|
88
84
|
def process(document, reader)
|
89
|
-
p =
|
85
|
+
p = Metanorma::Utils::LineStatus.new
|
90
86
|
lines = reader.lines.map do |t|
|
91
|
-
p
|
92
|
-
!p
|
87
|
+
p.process(t)
|
88
|
+
!p.pass && t.include?(":") and t = inlinelinkmacro(inlinelink(t))
|
93
89
|
t
|
94
90
|
end
|
95
91
|
::Asciidoctor::PreprocessorReader.new document, lines
|
96
92
|
end
|
97
93
|
|
98
|
-
def pass_status(status, text)
|
99
|
-
text == "++++" && !status[:delimln] and status[:pass] = !status[:pass]
|
100
|
-
status[:midline_docattr] && !/^:[^ :]+: /.match?(text) and
|
101
|
-
status[:midline_docattr] = false
|
102
|
-
if (status[:is_delim] && /^(-+|\*+|=+|_+)$/.match?(text)) ||
|
103
|
-
(!status[:is_delim] && !status[:delimln] && /^-----*$|^\.\.\.\.\.*$/.match?(text))
|
104
|
-
status[:delimln] = text
|
105
|
-
status[:pass] = true
|
106
|
-
elsif status[:pass_delim]
|
107
|
-
status[:delimln] = "" # end of paragraph for paragraph with [pass]
|
108
|
-
elsif status[:delimln] && text == status[:delimln]
|
109
|
-
status[:pass] = false
|
110
|
-
status[:delimln] = nil
|
111
|
-
elsif /^:[^ :]+: /.match?(text) &&
|
112
|
-
(status[:prev_line].empty? || status[:midline_docattr])
|
113
|
-
status[:pass] = true
|
114
|
-
status[:midline_docattr] = true
|
115
|
-
end
|
116
|
-
status[:is_delim] = /^\[(source|listing|literal|pass)\b/.match?(text)
|
117
|
-
status[:pass_delim] = /^\[(pass)\b/.match?(text)
|
118
|
-
status[:prev_line] = text.strip
|
119
|
-
status
|
120
|
-
end
|
121
|
-
|
122
94
|
PASS_INLINE_MACROS = %w(pass pass-format identifier std-link stem)
|
123
95
|
.join("|").freeze
|
124
96
|
|
@@ -132,7 +104,7 @@ module Metanorma
|
|
132
104
|
\\[.*?(?<!\\\\)\\] # [ ... ] not preceded by \\
|
133
105
|
)
|
134
106
|
REGEX
|
135
|
-
PASS_INLINE_MACRO_RX = /#{PASS_INLINE_MACRO_STR}/xo
|
107
|
+
PASS_INLINE_MACRO_RX = /#{PASS_INLINE_MACRO_STR}/xo
|
136
108
|
|
137
109
|
def pass_inline_split(text)
|
138
110
|
text.split(PASS_INLINE_MACRO_RX).each.map do |x|
|
@@ -142,7 +114,7 @@ module Metanorma
|
|
142
114
|
|
143
115
|
# InlineLinkRx = %r((^|link:|#{CG_BLANK}|<|[>\(\)\[\];"'])(\\?(?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)\[(|#{CC_ALL}*?[^\\])\]|([^\s\[\]<]*([^\s,.?!\[\]<\)]))))m
|
144
116
|
#
|
145
|
-
InlineLinkRx = %r((^|(?<![-\\])\blink:(?!\+)|\p{Blank}|<|[<>\(\)\[\];"'])((?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)(?:(\[(|.*?[^\\])\])|([^\s\[\]<]*([^\s,.?!\[\]<\)])))))m
|
117
|
+
InlineLinkRx = %r((^|(?<![-\\])\blink:(?!\+)|\p{Blank}|<|[<>\(\)\[\];"'])((?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)(?:(\[(|.*?[^\\])\])|([^\s\[\]<]*([^\s,.?!\[\]<\)])))))m
|
146
118
|
|
147
119
|
def inlinelink(text)
|
148
120
|
text.include?("://") or return text
|
@@ -172,7 +144,7 @@ module Metanorma
|
|
172
144
|
(|[^:\\s\\[][^\\s\\[]*) # link: ... up to [
|
173
145
|
(\\[(|.*?[^\\\\])\\]) # [ ... ], no ]
|
174
146
|
REGEX
|
175
|
-
InlineLinkMacroRx = /#{InlineLinkMacroRx1}/x
|
147
|
+
InlineLinkMacroRx = /#{InlineLinkMacroRx1}/x
|
176
148
|
|
177
149
|
def inlinelinkmacro(text)
|
178
150
|
(text.include?("[") &&
|
@@ -37,18 +37,19 @@ module Metanorma
|
|
37
37
|
def process(doc, reader)
|
38
38
|
reader.eof? and return reader
|
39
39
|
r = ::Asciidoctor::PreprocessorNoIfdefsReader.new doc, reader.lines
|
40
|
+
p = Metanorma::Utils::LineStatus.new
|
40
41
|
lines = r.readlines
|
41
42
|
headings = lines.grep(/^== /).map(&:strip)
|
42
43
|
ret = lines.each_with_object(embed_acc(doc, r)) do |line, m|
|
43
|
-
process_line(line, m, headings)
|
44
|
+
process_line(line, m, headings, p)
|
44
45
|
end
|
45
46
|
return_to_document(doc, ret)
|
46
47
|
end
|
47
48
|
|
48
49
|
def embed_acc(doc, reader)
|
49
50
|
{ lines: [], hdr: [], id: [],
|
50
|
-
orig: doc, doc
|
51
|
-
reader
|
51
|
+
orig: doc, doc:, file: nil, path: nil,
|
52
|
+
reader:, prev: nil }
|
52
53
|
end
|
53
54
|
|
54
55
|
# presupposes single embed
|
@@ -93,13 +94,14 @@ module Metanorma
|
|
93
94
|
|
94
95
|
def update_embeds(lines, acc, emb)
|
95
96
|
lines.empty? or
|
96
|
-
acc << { file: emb[:file], path: emb[:path], lines:
|
97
|
+
acc << { file: emb[:file], path: emb[:path], lines: }
|
97
98
|
[[], acc]
|
98
99
|
end
|
99
100
|
|
100
|
-
def process_line(line, acc, headings)
|
101
|
-
|
102
|
-
|
101
|
+
def process_line(line, acc, headings, status)
|
102
|
+
status.process(line)
|
103
|
+
if !status.pass && /^embed::/.match?(line)
|
104
|
+
e = embed(line, acc, headings, status)
|
103
105
|
acc = process_embed(acc, e, acc[:prev])
|
104
106
|
else
|
105
107
|
acc[:lines] << line
|
@@ -148,7 +150,7 @@ module Metanorma
|
|
148
150
|
end
|
149
151
|
end
|
150
152
|
|
151
|
-
def embed(line, acc, headings)
|
153
|
+
def embed(line, acc, headings, status)
|
152
154
|
fname, inc_path = filename(line, acc)
|
153
155
|
lines = filter_sections(read(inc_path), headings)
|
154
156
|
n = Asciidoctor::Document
|
@@ -158,12 +160,12 @@ module Metanorma
|
|
158
160
|
.merge(file: fname, path: inc_path, orig: acc[:orig])
|
159
161
|
ret[:hdr] or
|
160
162
|
raise "Embedding an incomplete document with no header: #{ret[:path]}"
|
161
|
-
embed_recurse(ret, n, r, headings)
|
163
|
+
embed_recurse(ret, n, r, headings, status)
|
162
164
|
end
|
163
165
|
|
164
|
-
def embed_recurse(ret, doc, reader, headings)
|
166
|
+
def embed_recurse(ret, doc, reader, headings, status)
|
165
167
|
ret1 = ret[:lines].each_with_object(embed_acc(doc, reader)) do |line, m|
|
166
|
-
process_line(line, m, headings)
|
168
|
+
process_line(line, m, headings, status)
|
167
169
|
end
|
168
170
|
ret.merge(
|
169
171
|
{ lines: ret1[:lines], id: ret[:id] + ret1[:id],
|
@@ -172,7 +174,7 @@ module Metanorma
|
|
172
174
|
end
|
173
175
|
|
174
176
|
def strip_header(lines)
|
175
|
-
return { lines
|
177
|
+
return { lines:, hdr: nil } unless !lines.empty? &&
|
176
178
|
lines.first.start_with?("= ")
|
177
179
|
|
178
180
|
skip = true
|
@@ -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
|
@@ -27,7 +27,7 @@ module Metanorma
|
|
27
27
|
def isorefmatchescode(match, _item)
|
28
28
|
code = analyse_ref_code(match[:code])
|
29
29
|
yr = norm_year(match[:year])
|
30
|
-
{ code: match[:code], year: yr, match
|
30
|
+
{ code: match[:code], year: yr, match:,
|
31
31
|
title: match[:text], usrlbl: match[:usrlbl] || code[:usrlabel],
|
32
32
|
analyse_code: code, lang: @lang || :all }
|
33
33
|
end
|
@@ -47,7 +47,7 @@ module Metanorma
|
|
47
47
|
def isorefmatches2code(match, _item)
|
48
48
|
code = analyse_ref_code(match[:code])
|
49
49
|
{ code: match[:code], no_year: true, lang: @lang || :all,
|
50
|
-
note: match[:fn], year: nil, match
|
50
|
+
note: match[:fn], year: nil, match:, analyse_code: code,
|
51
51
|
title: match[:text], usrlbl: match[:usrlbl] || code[:usrlabel] }
|
52
52
|
end
|
53
53
|
|
@@ -77,7 +77,7 @@ module Metanorma
|
|
77
77
|
code = analyse_ref_code(match[:code])
|
78
78
|
yr = norm_year(match[:year])
|
79
79
|
hasyr = !yr.nil? && yr != "--"
|
80
|
-
{ code: match[:code], match
|
80
|
+
{ code: match[:code], match:, yr:, hasyr:,
|
81
81
|
year: hasyr ? yr : nil, lang: @lang || :all,
|
82
82
|
all_parts: true, no_year: yr == "--",
|
83
83
|
title: match[:text], usrlbl: match[:usrlbl] || code[:usrlabel] }
|
@@ -162,11 +162,11 @@ module Metanorma
|
|
162
162
|
def refitem1code(_item, match)
|
163
163
|
code = analyse_ref_code(match[:code])
|
164
164
|
((code[:id] && code[:numeric]) || code[:nofetch]) and
|
165
|
-
return { code: nil, match
|
165
|
+
return { code: nil, match:, analyse_code: code,
|
166
166
|
hidden: code[:hidden] }
|
167
167
|
{ code: code[:id], analyse_code: code, localfile: code[:localfile],
|
168
168
|
year: (m = refitem1yr(code[:id])) ? m[:year] : nil,
|
169
|
-
title: match[:text], match
|
169
|
+
title: match[:text], match:, hidden: code[:hidden],
|
170
170
|
usrlbl: match[:usrlbl] || code[:usrlabel], lang: @lang || :all }
|
171
171
|
end
|
172
172
|
|
@@ -187,29 +187,26 @@ module Metanorma
|
|
187
187
|
ISO_REF =
|
188
188
|
%r{^<ref\sid="(?<anchor>[^"]+)">
|
189
189
|
\[(?<usrlbl>\([^)]+\))?(?<code>(?:ISO|IEC)[^0-9]*\s[0-9-]+|IEV)
|
190
|
-
(?::(?<year>[0-9][0-9-]+))?\]</ref>,?\s*(?<text>.*)$}xm
|
190
|
+
(?::(?<year>[0-9][0-9-]+))?\]</ref>,?\s*(?<text>.*)$}xm
|
191
191
|
|
192
192
|
ISO_REF_NO_YEAR =
|
193
193
|
%r{^<ref\sid="(?<anchor>[^"]+)">
|
194
194
|
\[(?<usrlbl>\([^)]+\))?(?<code>(?:ISO|IEC)[^0-9]*\s[0-9-]+):
|
195
|
-
(
|
195
|
+
(?:--|–|—|&\#821[12];)\]</ref>,?\s*
|
196
196
|
(?:<fn[^>]*>\s*<p>(?<fn>[^\]]+)</p>\s*</fn>)?,?\s?(?<text>.*)$}xm
|
197
|
-
.freeze
|
198
197
|
|
199
198
|
ISO_REF_ALL_PARTS =
|
200
199
|
%r{^<ref\sid="(?<anchor>[^"]+)">
|
201
200
|
\[(?<usrlbl>\([^)]+\))?(?<code>(?:ISO|IEC)[^0-9]*\s[0-9]+)
|
202
|
-
(?::(?<year
|
201
|
+
(?::(?<year>--|–|—|&\#821[12];|[0-9][0-9-]+))?\s
|
203
202
|
\(all\sparts\)\]</ref>,?\s*
|
204
|
-
(?:<fn[^>]*>\s*<p>(?<fn>[^\]]+)</p>\s*</fn>,?\s?)?(?<text>.*)$}xm
|
203
|
+
(?:<fn[^>]*>\s*<p>(?<fn>[^\]]+)</p>\s*</fn>,?\s?)?(?<text>.*)$}xm
|
205
204
|
|
206
205
|
NON_ISO_REF = %r{^<ref\sid="(?<anchor>[^"]+)">
|
207
206
|
\[(?<usrlbl>\([^)]+\))?(?<code>.+?)\]</ref>,?\s*(?<text>.*)$}xm
|
208
|
-
.freeze
|
209
207
|
|
210
208
|
NON_ISO_REF1 = %r{^<ref\sid="(?<anchor>[^"]+)">
|
211
209
|
(?<usrlbl>\([^)]+\))?(?<code>.+?)</ref>,?\s*(?<text>.*)$}xm
|
212
|
-
.freeze
|
213
210
|
|
214
211
|
def reference1_matches(item)
|
215
212
|
matched = ISO_REF.match item
|
@@ -122,16 +122,14 @@ module Metanorma
|
|
122
122
|
end
|
123
123
|
|
124
124
|
def local_ievcache_name(cachename)
|
125
|
-
|
126
|
-
|
125
|
+
cachename.nil? and return nil
|
127
126
|
cachename += "_iev" unless cachename.empty?
|
128
127
|
cachename = "iev" if cachename.empty?
|
129
128
|
"#{cachename}/cache"
|
130
129
|
end
|
131
130
|
|
132
131
|
def fetch_ref(xml, code, year, **opts)
|
133
|
-
|
134
|
-
|
132
|
+
opts[:no_year] and return nil
|
135
133
|
code = code.sub(/^\([^)]+\)/, "")
|
136
134
|
hit = fetch_ref1(code, year, opts) or return nil
|
137
135
|
xml.parent.add_child(smart_render_xml(hit, code, opts))
|
@@ -200,8 +200,8 @@ module Metanorma
|
|
200
200
|
|
201
201
|
MALFORMED_REF = <<~REF.freeze
|
202
202
|
no anchor on reference, markup may be malformed: see
|
203
|
-
https://www.metanorma.
|
204
|
-
https://www.metanorma.
|
203
|
+
https://www.metanorma.org/author/topics/sections/bibliography/ ,
|
204
|
+
https://www.metanorma.org/author/iso/topics/markup/#bibliographies
|
205
205
|
REF
|
206
206
|
|
207
207
|
def ref_normalise(ref)
|
@@ -16,8 +16,7 @@ module Metanorma
|
|
16
16
|
.gsub(%r{<index>.*?</index>}m, "")
|
17
17
|
.gsub(%r{<fn[^>]*>.*?</fn>}m, "")
|
18
18
|
.gsub(/<[^>]+>/, "")
|
19
|
-
.strip.downcase
|
20
|
-
.sub(/\.$/, "")
|
19
|
+
.strip.downcase.sub(/\.$/, "")
|
21
20
|
end
|
22
21
|
|
23
22
|
def sectiontype(node, level = true)
|
@@ -41,7 +40,8 @@ module Metanorma
|
|
41
40
|
"terms, definitions and abbreviated terms"
|
42
41
|
"terms and definitions"
|
43
42
|
when "symbols and abbreviated terms",
|
44
|
-
"symbols", "abbreviated terms", "abbreviations"
|
43
|
+
"symbols", "abbreviated terms", "abbreviations",
|
44
|
+
"symbols and abbreviations"
|
45
45
|
"symbols and abbreviated terms"
|
46
46
|
when "acknowledgements", "acknowledgments"
|
47
47
|
"acknowledgements"
|
@@ -170,7 +170,7 @@ module Metanorma
|
|
170
170
|
seen_xref = Nokogiri::XML.fragment(matched[:xref])
|
171
171
|
add_term_source(node, xml_t, seen_xref, matched)
|
172
172
|
end
|
173
|
-
end.join("
|
173
|
+
end.join("")
|
174
174
|
end
|
175
175
|
|
176
176
|
def termdefinition(node)
|
@@ -178,7 +178,7 @@ module Metanorma
|
|
178
178
|
xml.definition **attr_code(type: node.attr("type")) do |d|
|
179
179
|
d << node.content
|
180
180
|
end
|
181
|
-
end.join("
|
181
|
+
end.join("")
|
182
182
|
end
|
183
183
|
end
|
184
184
|
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
|
@@ -48,7 +48,6 @@ module Metanorma
|
|
48
48
|
def mathml_sanitise(math)
|
49
49
|
math.to_xml(encoding: "US-ASCII").gsub(/ xmlns=["'][^"']+["']/, "")
|
50
50
|
.gsub(%r{<[^:/>]+:}, "<").gsub(%r{</[^:/>]+:}, "</")
|
51
|
-
# .gsub(/&#([^;]+);/) { |x| "&#x#{$1.to_i.to_s(16)};" }
|
52
51
|
end
|
53
52
|
|
54
53
|
def math_validate_error(math, elem, error)
|
@@ -133,7 +132,7 @@ module Metanorma
|
|
133
132
|
doc.xpath(WILDCARD_ATTRS, "m" => SVG_NS).each do |n|
|
134
133
|
n.elements.each do |e|
|
135
134
|
e.traverse do |e1|
|
136
|
-
e1.element? and e1.each { |k, _v| e1.delete(k) }
|
135
|
+
e1.element? and e1.each { |k, _v| e1.delete(k) } # rubocop:disable Style/HashEachMethods
|
137
136
|
end
|
138
137
|
end
|
139
138
|
end
|
@@ -143,6 +142,7 @@ module Metanorma
|
|
143
142
|
|
144
143
|
def image_validate(doc)
|
145
144
|
image_exists(doc)
|
145
|
+
image_toobig(doc)
|
146
146
|
png_validate(doc)
|
147
147
|
end
|
148
148
|
|
@@ -183,6 +183,18 @@ module Metanorma
|
|
183
183
|
"Corrupt PNG image detected: #{e.message}")
|
184
184
|
end
|
185
185
|
|
186
|
+
TOO_BIG_IMG_ERR = <<~ERR.freeze
|
187
|
+
Image too large for Data URI encoding: disable Data URI encoding (`:data-uri-image: false`), or set `:data-uri-maxsize: 0`
|
188
|
+
ERR
|
189
|
+
|
190
|
+
def image_toobig(doc)
|
191
|
+
@dataurimaxsize.zero? and return
|
192
|
+
doc.xpath("//image").each do |i|
|
193
|
+
i["src"].size > @dataurimaxsize and
|
194
|
+
@log.add("Images", i.parent, TOO_BIG_IMG_ERR, severity: 0)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
186
198
|
def validate(doc)
|
187
199
|
content_validate(doc)
|
188
200
|
schema_validate(formattedstr_strip(doc.dup),
|