metanorma-utils 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d7146df13587bfd1597f42bdbd573dd3800ac166bebddc6348025fa1d69cac0
4
- data.tar.gz: e4f4da08e4ecdb617055fa24f39ece4c0565d32ce96f24c363185b30ec9597d0
3
+ metadata.gz: a355e89f8c66d323f0ca9954226b2255c1c4706ab9346db5004aa7984ceade6c
4
+ data.tar.gz: cc240e1eec9ea056d87b38bae0fea45ac16f1e6f2cef1a6cb2d04c2d20de50e9
5
5
  SHA512:
6
- metadata.gz: 933433fa3ae2c0d9bdca247a12c98de3a274ec2085248db3253d8b54ebdb2e84123ac7b2bd851c9cbcb29b629450d36204dc4710ba67c340cc722982450dd4c2
7
- data.tar.gz: 59c93891f1d349a2b6338c27a38a48a1f84cf81aa9609d649715461ae9b3c6e30a643e77a92eb0a7efc8551a8c1588ba7e9edda15a0e65d13f99e4b7582fe096
6
+ metadata.gz: 20d8d717e2113249d060bf15f15faf1150cf5e06d29368f9faf00b0a496aa7c3e711a80c83dbb6fd328cf39ac2e65359825a6632199fb6cdf13cb882934ac11f
7
+ data.tar.gz: be4fe517ccc3731678ebaa5fedf2b7ec0923e510c83193a5f73d26db3b9a290cbe3be3aaeda4dbfa90fd76fd8c1bf14099f283b6bd158b00c5138d488c2fdf14
@@ -1,3 +1,4 @@
1
1
  require_relative "utils/version"
2
2
  require_relative "utils/main"
3
+ require_relative "utils/image"
3
4
  require_relative "utils/log"
@@ -0,0 +1,143 @@
1
+ require "asciidoctor"
2
+ require "tempfile"
3
+ require "marcel"
4
+ require "mime/types"
5
+ require "base64"
6
+
7
+ module Metanorma
8
+ module Utils
9
+ class << self
10
+ class Namespace
11
+ def initialize(xmldoc)
12
+ @namespace = xmldoc.root.namespace
13
+ end
14
+
15
+ def ns(path)
16
+ return path if @namespace.nil?
17
+
18
+ path.gsub(%r{/([a-zA-z])}, "/xmlns:\\1")
19
+ .gsub(%r{::([a-zA-z])}, "::xmlns:\\1")
20
+ .gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]* ?=)}, "[xmlns:\\1")
21
+ .gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]*\])}, "[xmlns:\\1")
22
+ end
23
+ end
24
+
25
+ def save_dataimage(uri)
26
+ %r{^data:(image|application)/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
27
+ imgtype.sub!(/\+[a-z0-9]+$/, "") # svg+xml
28
+ imgtype = "png" unless /^[a-z0-9]+$/.match? imgtype
29
+ Tempfile.open(["image", ".#{imgtype}"]) do |f|
30
+ f.binmode
31
+ f.write(Base64.strict_decode64(imgdata))
32
+ f.path
33
+ end
34
+ end
35
+
36
+ SVG_NS = "http://www.w3.org/2000/svg".freeze
37
+
38
+ def svgmap_rewrite(xmldoc, localdirectory = "")
39
+ n = Namespace.new(xmldoc)
40
+ xmldoc.xpath(n.ns("//svgmap")).each do |s|
41
+ next unless svgmap_rewrite0(s, n, localdirectory)
42
+ next if s.at(n.ns("./target/eref"))
43
+
44
+ s.replace(s.at(n.ns("./figure")))
45
+ end
46
+ end
47
+
48
+ def svgmap_rewrite0(svgmap, namespace, localdirectory)
49
+ if (i = svgmap.at(namespace.ns(".//image"))) && (src = i["src"])
50
+ path = svgmap_rewrite0_path(src, localdirectory)
51
+ File.file?(path) or return false
52
+ svg = Nokogiri::XML(File.read(path, encoding: "utf-8"))
53
+ i.replace(svgmap_rewrite1(svgmap, svg, namespace))
54
+ /^data:/.match(src) and i["src"] = datauri(path)
55
+ elsif i = svgmap.at(".//m:svg", "m" => SVG_NS)
56
+ i.replace(svgmap_rewrite1(svgmap, i, namespace))
57
+ else
58
+ return false
59
+ end
60
+ true
61
+ end
62
+
63
+ def svgmap_rewrite0_path(src, localdirectory)
64
+ if /^data:/.match?(src)
65
+ save_dataimage(src)
66
+ else
67
+ File.file?(src) ? src : localdirectory + src
68
+ end
69
+ end
70
+
71
+ def svgmap_rewrite1(svgmap, svg, namespace)
72
+ targ = svgmap_rewrite1_targets(svgmap, namespace)
73
+ svg.xpath(".//m:a", "m" => SVG_NS).each do |a|
74
+ ["xlink:href", "href"].each do |p|
75
+ a[p] and x = targ[File.expand_path(a[p])] and a[p] = x
76
+ end
77
+ end
78
+ svg.to_xml
79
+ end
80
+
81
+ def svgmap_rewrite1_targets(svgmap, namespace)
82
+ svgmap.xpath(namespace.ns("./target"))
83
+ .each_with_object({}) do |t, m|
84
+ x = t.at(namespace.ns("./xref")) and
85
+ m[File.expand_path(t["href"])] = "##{x['target']}"
86
+ x = t.at(namespace.ns("./link")) and
87
+ m[File.expand_path(t["href"])] = x["target"]
88
+ t.remove if t.at(namespace.ns("./xref | ./link"))
89
+ end
90
+ end
91
+
92
+ # sources/plantuml/plantuml20200524-90467-1iqek5i.png
93
+ # already includes localdir
94
+ def datauri(uri, localdirectory = ".")
95
+ return uri if /^data:/.match?(uri)
96
+
97
+ path = datauri_path(uri, localdirectory)
98
+ return path unless File.exist?(path)
99
+
100
+ types = MIME::Types.type_for(path)
101
+ type = types ? types.first.to_s : 'text/plain; charset="utf-8"'
102
+ bin = File.open(path, "rb", &:read)
103
+ data = Base64.strict_encode64(bin)
104
+ "data:#{type};base64,#{data}"
105
+ end
106
+
107
+ def datauri_path(uri, localdirectory)
108
+ path = if %r{^([A-Z]:)?/}.match?(uri) then uri
109
+ else
110
+ File.exist?(uri) ? uri : File.join(localdirectory, uri)
111
+ end
112
+ unless File.exist?(path)
113
+ warn "image at #{path} not found"
114
+ return uri
115
+ end
116
+ path
117
+ end
118
+
119
+ def datauri2mime(uri)
120
+ %r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
121
+ type = nil
122
+ imgtype = "png" unless /^[a-z0-9]+$/.match? imgtype
123
+ ::Tempfile.open(["imageuri", ".#{imgtype}"]) do |file|
124
+ type = datauri2mime1(file, imgdata)
125
+ end
126
+ [type]
127
+ end
128
+
129
+ def datauri2mime1(file, imgdata)
130
+ type = nil
131
+ begin
132
+ file.binmode
133
+ file.write(Base64.strict_decode64(imgdata))
134
+ file.rewind
135
+ type = Marcel::MimeType.for file
136
+ ensure
137
+ file.close!
138
+ end
139
+ type
140
+ end
141
+ end
142
+ end
143
+ end
data/lib/utils/log.rb CHANGED
@@ -7,48 +7,51 @@ module Metanorma
7
7
 
8
8
  def add(category, loc, msg)
9
9
  return if @novalid
10
+
10
11
  @log[category] = [] unless @log[category]
11
12
  @log[category] << { location: current_location(loc), message: msg,
12
13
  context: context(loc) }
13
14
  loc = loc.nil? ? "" : "(#{current_location(loc)}): "
14
- warn "#{category}: #{loc}#{msg}"
15
+ warn "#{category}: #{loc}#{msg}"
15
16
  end
16
17
 
17
- def current_location(n)
18
- return "" if n.nil?
19
- return n if n.is_a? String
20
- return "Asciidoctor Line #{"%06d" % n.lineno}" if n.respond_to?(:lineno) &&
21
- !n.lineno.nil? && !n.lineno.empty?
22
- return "XML Line #{"%06d" % n.line}" if n.respond_to?(:line) &&
23
- !n.line.nil?
24
- return "ID #{n.id}" if n.respond_to?(:id) && !n.id.nil?
25
- while !n.nil? &&
26
- (!n.respond_to?(:level) || n.level.positive?) &&
27
- (!n.respond_to?(:context) || n.context != :section)
28
- n = n.parent
29
- return "Section: #{n.title}" if n&.respond_to?(:context) &&
30
- n&.context == :section
18
+ def current_location(node)
19
+ if node.nil? then ""
20
+ elsif node.is_a? String then node
21
+ elsif node.respond_to?(:lineno) && !node.lineno.nil? &&
22
+ !node.lineno.empty?
23
+ "Asciidoctor Line #{'%06d' % node.lineno}"
24
+ elsif node.respond_to?(:line) && !node.line.nil?
25
+ "XML Line #{'%06d' % node.line}"
26
+ elsif node.respond_to?(:id) && !node.id.nil? then "ID #{node.id}"
27
+ else
28
+ while !node.nil? &&
29
+ (!node.respond_to?(:level) || node.level.positive?) &&
30
+ (!node.respond_to?(:context) || node.context != :section)
31
+ node = node.parent
32
+ return "Section: #{node.title}" if node&.respond_to?(:context) &&
33
+ node&.context == :section
34
+ end
35
+ "??"
31
36
  end
32
- "??"
33
37
  end
34
38
 
35
- def context(n)
36
- return nil if n.is_a? String
37
- n.respond_to?(:to_xml) and return n.to_xml
38
- n.respond_to?(:to_s) and return n.to_s
39
+ def context(node)
40
+ return nil if node.is_a? String
41
+
42
+ node.respond_to?(:to_xml) and return node.to_xml
43
+ node.respond_to?(:to_s) and return node.to_s
39
44
  nil
40
45
  end
41
46
 
42
47
  def write(file)
43
48
  File.open(file, "w:UTF-8") do |f|
44
49
  f.puts "#{file} errors"
45
- @log.keys.each do |key|
50
+ @log.each_key do |key|
46
51
  f.puts "\n\n== #{key}\n\n"
47
- @log[key].sort do |a, b|
48
- a[:location] <=> b[:location]
49
- end.each do |n|
52
+ @log[key].sort_by { |a| a[:location] }.each do |n|
50
53
  loc = n[:location] ? "(#{n[:location]}): " : ""
51
- f.puts "#{loc}#{n[:message]}"
54
+ f.puts "#{loc}#{n[:message]}"
52
55
  n[:context]&.split(/\n/)&.first(5)&.each { |l| f.puts "\t#{l}" }
53
56
  end
54
57
  end
data/lib/utils/main.rb CHANGED
@@ -2,56 +2,61 @@ require "asciidoctor"
2
2
  require "tempfile"
3
3
  require "sterile"
4
4
  require "uuidtools"
5
- require "marcel"
6
- require "mime/types"
7
- require "base64"
8
5
 
9
6
  module Metanorma
10
7
  module Utils
11
- NAMECHAR = "\u0000-\u0022\u0024\u002c\u002f\u003a-\u0040\\u005b-\u005e"\
12
- "\u0060\u007b-\u00b6\u00b8-\u00bf\u00d7\u00f7\u037e\u2000-\u200b"\
13
- "\u200e-\u203e\u2041-\u206f\u2190-\u2bff\u2ff0-\u3000".freeze
14
- #"\ud800-\uf8ff\ufdd0-\ufdef\ufffe-\uffff".freeze
15
- NAMESTARTCHAR = "\\u002d\u002e\u0030-\u0039\u00b7\u0300-\u036f"\
16
- "\u203f-\u2040".freeze
8
+ NAMECHAR = "\u0000-\u0022\u0024\u002c\u002f\u003a-\u0040\\u005b-\u005e"\
9
+ "\u0060\u007b-\u00b6\u00b8-\u00bf\u00d7\u00f7\u037e\u2000-\u200b"\
10
+ "\u200e-\u203e\u2041-\u206f\u2190-\u2bff\u2ff0-\u3000".freeze
11
+ NAMESTARTCHAR = "\\u002d\u002e\u0030-\u0039\u00b7\u0300-\u036f"\
12
+ "\u203f-\u2040".freeze
17
13
 
18
14
  class << self
19
- def to_ncname(s)
20
- start = s[0]
21
- ret1 = %r([#{NAMECHAR}#]).match(start) ? "_" :
22
- (%r([#{NAMESTARTCHAR}#]).match(start) ? "_#{start}" : start)
23
- ret2 = s[1..-1] || ""
24
- ret = (ret1 || "") + ret2.gsub(%r([#{NAMECHAR}#]), "_")
25
- ret
15
+ def to_ncname(tag)
16
+ start = tag[0]
17
+ ret1 = if %r([#{NAMECHAR}#]).match?(start)
18
+ "_"
19
+ else
20
+ (%r([#{NAMESTARTCHAR}#]).match?(start) ? "_#{start}" : start)
21
+ end
22
+ ret2 = tag[1..-1] || ""
23
+ (ret1 || "") + ret2.gsub(%r([#{NAMECHAR}#]), "_")
26
24
  end
27
25
 
28
26
  def anchor_or_uuid(node = nil)
29
27
  uuid = UUIDTools::UUID.random_create
30
- node.nil? || node.id.nil? || node.id.empty? ? "_" + uuid : node.id
28
+ node.nil? || node.id.nil? || node.id.empty? ? "_#{uuid}" : node.id
31
29
  end
32
30
 
33
- def asciidoc_sub(x, flavour = :standoc)
34
- return nil if x.nil?
35
- return "" if x.empty?
36
- d = Asciidoctor::Document.new(x.lines.entries, { header_footer: false, backend: flavour })
31
+ def asciidoc_sub(text, flavour = :standoc)
32
+ return nil if text.nil?
33
+ return "" if text.empty?
34
+
35
+ d = Asciidoctor::Document.new(
36
+ text.lines.entries,
37
+ { header_footer: false, backend: flavour }
38
+ )
37
39
  b = d.parse.blocks.first
38
40
  b.apply_subs(b.source)
39
41
  end
40
42
 
41
43
  def localdir(node)
42
44
  docfile = node.attr("docfile")
43
- docfile.nil? ? './' : Pathname.new(docfile).parent.to_s + '/'
45
+ docfile.nil? ? "./" : "#{Pathname.new(docfile).parent}/"
44
46
  end
45
47
 
46
48
  # TODO needs internationalisation
47
- def smartformat(n)
48
- n.gsub(/ --? /, "&#8201;&#8212;&#8201;").
49
- gsub(/--/, "&#8212;").smart_format.gsub(/</, "&lt;").gsub(/>/, "&gt;")
49
+ def smartformat(text)
50
+ text.gsub(/ --? /, "&#8201;&#8212;&#8201;")
51
+ .gsub(/--/, "&#8212;").smart_format.gsub(/</, "&lt;")
52
+ .gsub(/>/, "&gt;")
50
53
  end
51
54
 
52
55
  def endash_date(elem)
53
56
  elem.traverse do |n|
54
- n.text? and n.replace(n.text.gsub(/\s+--?\s+/, "&#8211;").gsub(/--/, "&#8211;"))
57
+ next unless n.text?
58
+
59
+ n.replace(n.text.gsub(/\s+--?\s+/, "&#8211;").gsub(/--/, "&#8211;"))
55
60
  end
56
61
  end
57
62
 
@@ -60,95 +65,34 @@ module Metanorma
60
65
  def set_nested_value(hash, keys, new_val)
61
66
  key = keys[0]
62
67
  if keys.length == 1
63
- hash[key] = hash[key].is_a?(Array) ? (hash[key] << new_val) :
64
- hash[key].nil? ? new_val : [hash[key], new_val]
68
+ hash[key] = if hash[key].is_a?(Array)
69
+ (hash[key] << new_val)
70
+ else
71
+ hash[key].nil? ? new_val : [hash[key], new_val]
72
+ end
73
+ elsif hash[key].is_a?(Array)
74
+ hash[key][-1] = {} if !hash[key].empty? && hash[key][-1].nil?
75
+ hash[key] << {} if hash[key].empty? || !hash[key][-1].is_a?(Hash)
76
+ set_nested_value(hash[key][-1], keys[1..-1], new_val)
77
+ elsif hash[key].nil? || hash[key].empty?
78
+ hash[key] = {}
79
+ set_nested_value(hash[key], keys[1..-1], new_val)
80
+ elsif hash[key].is_a?(Hash) && !hash[key][keys[1]]
81
+ set_nested_value(hash[key], keys[1..-1], new_val)
82
+ elsif !hash[key][keys[1]]
83
+ hash[key] = [hash[key], {}]
84
+ set_nested_value(hash[key][-1], keys[1..-1], new_val)
65
85
  else
66
- if hash[key].is_a?(Array)
67
- hash[key][-1] = {} if !hash[key].empty? && hash[key][-1].nil?
68
- hash[key] << {} if hash[key].empty? || !hash[key][-1].is_a?(Hash)
69
- set_nested_value(hash[key][-1], keys[1..-1], new_val)
70
- elsif hash[key].nil? || hash[key].empty?
71
- hash[key] = {}
72
- set_nested_value(hash[key], keys[1..-1], new_val)
73
- elsif hash[key].is_a?(Hash) && !hash[key][keys[1]]
74
- set_nested_value(hash[key], keys[1..-1], new_val)
75
- elsif !hash[key][keys[1]]
76
- hash[key] = [hash[key], {}]
77
- set_nested_value(hash[key][-1], keys[1..-1], new_val)
78
- else
79
- set_nested_value(hash[key], keys[1..-1], new_val)
80
- end
86
+ set_nested_value(hash[key], keys[1..-1], new_val)
81
87
  end
82
88
  hash
83
89
  end
84
90
 
85
- class Namespace
86
- def initialize(xmldoc)
87
- @namespace = xmldoc.root.namespace
88
- end
89
-
90
- def ns(path)
91
- return path if @namespace.nil?
92
- path.gsub(%r{/([a-zA-z])}, "/xmlns:\\1").
93
- gsub(%r{::([a-zA-z])}, "::xmlns:\\1").
94
- gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]* ?=)}, "[xmlns:\\1").
95
- gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]*\])}, "[xmlns:\\1")
96
- end
97
- end
98
-
99
- def save_dataimage(uri)
100
- %r{^data:(image|application)/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
101
- imgtype.sub!(/\+[a-z0-9]+$/, '') # svg+xml
102
- imgtype = 'png' unless /^[a-z0-9]+$/.match imgtype
103
- Tempfile.open(['image', ".#{imgtype}"]) do |f|
104
- f.binmode
105
- f.write(Base64.strict_decode64(imgdata))
106
- f.path
107
- end
108
- end
109
-
110
- SVG_NS = "http://www.w3.org/2000/svg".freeze
111
-
112
- def svgmap_rewrite(xmldoc, localdirectory = "")
113
- n = Namespace.new(xmldoc)
114
- xmldoc.xpath(n.ns("//svgmap")).each do |s|
115
- next unless svgmap_rewrite0(s, n, localdirectory)
116
- next if s.at(n.ns("./target/eref"))
117
- s.replace(s.at(n.ns("./figure")))
118
- end
119
- end
120
-
121
- def svgmap_rewrite0(s, n, localdirectory)
122
- if i = s.at(n.ns(".//image")) and src = i["src"]
123
- path = /^data:/.match(src) ? save_dataimage(src) : File.file?(src) ? src : localdirectory + src
124
- File.file?(path) or return false
125
- svgmap_rewrite1(s, Nokogiri::XML(File.read(path, encoding: "utf-8")), path, n)
126
- /^data:/.match(src) and i["src"] = datauri(path)
127
- elsif i = s.at(".//m:svg", "m" => SVG_NS)
128
- svgmap_rewrite1(s, i, nil, n)
129
- else
130
- return false
131
- end
132
- true
133
- end
134
-
135
- def svgmap_rewrite1(s, svg, path, n)
136
- targets = s.xpath(n.ns("./target")).each_with_object({}) do |t, m|
137
- x = t.at(n.ns("./xref")) and m[File.expand_path(t["href"])] = "##{x['target']}"
138
- x = t.at(n.ns("./link")) and m[File.expand_path(t["href"])] = x['target']
139
- t.remove if t.at(n.ns("./xref | ./link"))
140
- end
141
- svg.xpath(".//m:a", "m" => SVG_NS).each do |a|
142
- a["xlink:href"] and x = targets[File.expand_path(a["xlink:href"])] and a["xlink:href"] = x
143
- a["href"] and x = targets[File.expand_path(a["href"])] and a["href"] = x
144
- end
145
- path and File.open(path, "w", encoding: "utf-8") { |f| f.write(svg.to_xml) }
146
- end
147
-
148
91
  # not currently used
149
92
  def flatten_rawtext_lines(node, result)
150
93
  node.lines.each do |x|
151
- if node.respond_to?(:context) && (node.context == :literal || node.context == :listing)
94
+ if node.respond_to?(:context) &&
95
+ (node.context == :literal || node.context == :listing)
152
96
  result << x.gsub(/</, "&lt;").gsub(/>/, "&gt;")
153
97
  else
154
98
  # strip not only HTML <tag>, and Asciidoc xrefs <<xref>>
@@ -174,45 +118,6 @@ module Metanorma
174
118
  end
175
119
  result.reject(&:empty?)
176
120
  end
177
-
178
- # sources/plantuml/plantuml20200524-90467-1iqek5i.png already includes localdir
179
- def datauri(uri, localdirectory = ".")
180
- return uri if /^data:/.match(uri)
181
- path = %r{^([A-Z]:)?/}.match?(uri) ? uri :
182
- File.exist?(uri) ? uri : File.join(localdirectory, uri)
183
- unless File.exist?(path)
184
- warn "image at #{path} not found"
185
- return uri
186
- end
187
- types = MIME::Types.type_for(path)
188
- type = types ? types.first.to_s : 'text/plain; charset="utf-8"'
189
- bin = File.open(path, 'rb', &:read)
190
- data = Base64.strict_encode64(bin)
191
- "data:#{type};base64,#{data}"
192
- end
193
-
194
- def datauri2mime(uri)
195
- %r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
196
- type = nil
197
- imgtype = "png" unless /^[a-z0-9]+$/.match imgtype
198
- ::Tempfile.open(["imageuri", ".#{imgtype}"]) do |file|
199
- type = datauri2mime1(file, imgdata)
200
- end
201
- [type]
202
- end
203
-
204
- def datauri2mime1(file, imgdata)
205
- type = nil
206
- begin
207
- file.binmode
208
- file.write(Base64.strict_decode64(imgdata))
209
- file.rewind
210
- type = Marcel::MimeType.for file
211
- ensure
212
- file.close!
213
- end
214
- type
215
- end
216
121
  end
217
122
  end
218
123
  end
data/lib/utils/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Metanorma
2
2
  module Utils
3
- VERSION = "1.1.0".freeze
3
+ VERSION = "1.2.0".freeze
4
4
  end
5
5
  end
data/spec/utils_spec.rb CHANGED
@@ -11,7 +11,7 @@ RSpec.describe Metanorma::Utils do
11
11
  end
12
12
 
13
13
  it "sets metanorma IDs if not provided" do
14
- expect(Metanorma::Utils.anchor_or_uuid()).to match (/^_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/)
14
+ expect(Metanorma::Utils.anchor_or_uuid).to match (/^_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/)
15
15
  expect(Metanorma::Utils.anchor_or_uuid(Dummy.new(nil))).to match (/^_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/)
16
16
  expect(Metanorma::Utils.anchor_or_uuid(Dummy.new(""))).to match (/^_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/)
17
17
  expect(Metanorma::Utils.anchor_or_uuid(Dummy.new("A"))).to eq "A"
@@ -31,20 +31,20 @@ RSpec.describe Metanorma::Utils do
31
31
  end
32
32
 
33
33
  it "applies smart formatting" do
34
- expect(Metanorma::Utils.smartformat("A - B A -- B A--B '80s '80' <A>")).to eq "A&#8201;&#8212;&#8201;B A&#8201;&#8212;&#8201;B A&#8212;B ’80s ‘80’ &lt;A&gt;"
34
+ expect(Metanorma::Utils.smartformat("A - B A -- B A--B '80s '80' <A>")).to eq "A&#8201;&#8212;&#8201;B A&#8201;&#8212;&#8201;B A&#8212;B ’80s ‘80’ &lt;A&gt;"
35
35
  end
36
36
 
37
37
  it "applies en-dash normalisation" do
38
38
  a = Nokogiri::XML(<<~INPUT)
39
- <container>
40
- <a>A -- B A - B</a>
41
- <b>A--B</b>
42
- </container>
39
+ <container>
40
+ <a>A -- B A - B</a>
41
+ <b>A--B</b>
42
+ </container>
43
43
  INPUT
44
44
  Metanorma::Utils.endash_date(a)
45
45
  expect(a.to_xml).to be_equivalent_to <<~OUTPUT
46
- <?xml version=\"1.0\"?>
47
- <container><a>A&#x2013;B A&#x2013;B</a><b>A&#x2013;B</b></container>
46
+ <?xml version=\"1.0\"?>
47
+ <container><a>A&#x2013;B A&#x2013;B</a><b>A&#x2013;B</b></container>
48
48
  OUTPUT
49
49
  end
50
50
 
@@ -53,14 +53,14 @@ RSpec.describe Metanorma::Utils do
53
53
  a = Metanorma::Utils.set_nested_value(a, ["X"], "x")
54
54
  a = Metanorma::Utils.set_nested_value(a, ["X1"], 9)
55
55
  a = Metanorma::Utils.set_nested_value(a, ["X2"], [3])
56
- a = Metanorma::Utils.set_nested_value(a, ["X3"], {"a" =>"b"})
56
+ a = Metanorma::Utils.set_nested_value(a, ["X3"], { "a" => "b" })
57
57
  expect(a.to_s).to be_equivalent_to <<~OUTPUT
58
- {"X"=>"x", "X1"=>9, "X2"=>[3], "X3"=>{"a"=>"b"}}
58
+ {"X"=>"x", "X1"=>9, "X2"=>[3], "X3"=>{"a"=>"b"}}
59
59
  OUTPUT
60
60
  a = Metanorma::Utils.set_nested_value(a, ["X2"], 4)
61
61
  a = Metanorma::Utils.set_nested_value(a, ["X1"], 4)
62
62
  expect(a.to_s).to be_equivalent_to <<~OUTPUT
63
- {"X"=>"x", "X1"=>[9, 4], "X2"=>[3, 4], "X3"=>{"a"=>"b"}}
63
+ {"X"=>"x", "X1"=>[9, 4], "X2"=>[3, 4], "X3"=>{"a"=>"b"}}
64
64
  OUTPUT
65
65
  a = Metanorma::Utils.set_nested_value(a, ["X2", "A"], 5)
66
66
  a = Metanorma::Utils.set_nested_value(a, ["X2a"], [])
@@ -70,98 +70,140 @@ RSpec.describe Metanorma::Utils do
70
70
  a = Metanorma::Utils.set_nested_value(a, ["X3", "a"], 8)
71
71
  a = Metanorma::Utils.set_nested_value(a, ["X1", "a"], 11)
72
72
  expect(a.to_s).to be_equivalent_to <<~OUTPUT
73
- {"X"=>"x", "X1"=>[9, 4, {"a"=>11}], "X2"=>[3, 4, {"A"=>5}], "X3"=>{"a"=>["b", 8], "A"=>7}, "X2a"=>[{"A"=>6}], "X4"=>{"A"=>10}}
73
+ {"X"=>"x", "X1"=>[9, 4, {"a"=>11}], "X2"=>[3, 4, {"A"=>5}], "X3"=>{"a"=>["b", 8], "A"=>7}, "X2a"=>[{"A"=>6}], "X4"=>{"A"=>10}}
74
74
  OUTPUT
75
75
  end
76
76
 
77
77
  it "rewrites SVGs" do
78
78
  FileUtils.cp "spec/fixtures/action_schemaexpg1.svg", "action_schemaexpg1.svg"
79
- FileUtils.cp "spec/fixtures/action_schemaexpg1.svg", "action_schemaexpg2.svg"
80
- xmldoc = Nokogiri::XML(<<~INPUT)
81
- <standard-document type="semantic" version="1.8.2">
82
- <bibdata type="standard">
83
- <title language="en" format="text/plain">Document title</title>
84
- <docidentifier/>
85
- <docnumber/>
86
- <version/>
87
- <language>en</language>
88
- <script>Latn</script>
89
- <status>
90
- <stage>published</stage>
91
- </status>
92
- <copyright>
93
- <from>2021</from>
94
- </copyright>
95
- <ext>
96
- <doctype>article</doctype>
97
- </ext>
98
- </bibdata>
99
- <sections>
100
- <svgmap id="_d5b5049a-dd53-4ea0-bc6f-e8773bd59052"><target href="mn://action_schema"><xref target="ref1">Computer</xref></target></svgmap>
101
- <svgmap id="_4072bdcb-5895-4821-b636-5795b96787cb">
102
- <figure><image src="action_schemaexpg1.svg"/></figure>
103
- <target href="mn://action_schema"><xref target="ref1">Computer</xref></target><target href="http://www.example.com"><link target="http://www.example.com">Phone</link></target>
104
- </svgmap>
105
- <svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
106
- <figure><image src="action_schemaexpg2.svg" alt="Workmap"/></figure>
107
- <target href="href1.htm"><xref target="ref1">Computer</xref></target><target href="mn://basic_attribute_schema"><link target="http://www.example.com">Phone</link></target><target href="mn://support_resource_schema"><eref type="express" bibitemid="express_action_schema" citeas=""><localityStack><locality type="anchor"><referenceFrom>action_schema.basic</referenceFrom></locality></localityStack>Coffee</eref></target></svgmap>
108
- <svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
109
- <figure>
110
- <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' viewBox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve'>
111
- <a href="mn://action_schema" >
112
- <rect x="123.28" y="273.93" class="st0" width="88.05" height="41.84"/>
113
- </a>
114
- <a href="mn://basic_attribute_schema" >
115
- <rect x="324.69" y="450.52" class="st0" width="132.62" height="40.75"/>
116
- </a>
117
- <a xlink:href="mn://support_resource_schema" >
118
- <rect x="324.69" y="528.36" class="st0" width="148.16" height="40.75"/>
119
- </a>
120
- </svg>
121
- </figure>
122
- <target href="mn://action_schema"><xref target="ref1">Computer</xref></target><target href="http://www.example.com"><link target="http://www.example.com">Phone</link></target>
123
- </svgmap>
124
- <svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
125
- <figure>
79
+ FileUtils.cp "spec/fixtures/action_schemaexpg1.svg", "action_schemaexpg2.svg"
80
+ xmldoc = Nokogiri::XML(<<~INPUT)
81
+ <standard-document type="semantic" version="1.8.2">
82
+ <bibdata type="standard">
83
+ <title language="en" format="text/plain">Document title</title>
84
+ <docidentifier/>
85
+ <docnumber/>
86
+ <version/>
87
+ <language>en</language>
88
+ <script>Latn</script>
89
+ <status>
90
+ <stage>published</stage>
91
+ </status>
92
+ <copyright>
93
+ <from>2021</from>
94
+ </copyright>
95
+ <ext>
96
+ <doctype>article</doctype>
97
+ </ext>
98
+ </bibdata>
99
+ <sections>
100
+ <svgmap id="_d5b5049a-dd53-4ea0-bc6f-e8773bd59052"><target href="mn://action_schema"><xref target="ref1">Computer</xref></target></svgmap>
101
+ <svgmap id="_4072bdcb-5895-4821-b636-5795b96787cb">
102
+ <figure><image src="action_schemaexpg1.svg"/></figure>
103
+ <target href="mn://action_schema"><xref target="ref1">Computer</xref></target><target href="http://www.example.com"><link target="http://www.example.com">Phone</link></target>
104
+ </svgmap>
105
+ <svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
106
+ <figure><image src="action_schemaexpg2.svg" alt="Workmap"/></figure>
107
+ <target href="href1.htm"><xref target="ref1">Computer</xref></target><target href="mn://basic_attribute_schema"><link target="http://www.example.com">Phone</link></target><target href="mn://support_resource_schema"><eref type="express" bibitemid="express_action_schema" citeas=""><localityStack><locality type="anchor"><referenceFrom>action_schema.basic</referenceFrom></locality></localityStack>Coffee</eref></target></svgmap>
108
+ <svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
109
+ <figure>
110
+ <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' viewBox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve'>
111
+ <a href="mn://action_schema" >
112
+ <rect x="123.28" y="273.93" class="st0" width="88.05" height="41.84"/>
113
+ </a>
114
+ <a href="mn://basic_attribute_schema" >
115
+ <rect x="324.69" y="450.52" class="st0" width="132.62" height="40.75"/>
116
+ </a>
117
+ <a xlink:href="mn://support_resource_schema" >
118
+ <rect x="324.69" y="528.36" class="st0" width="148.16" height="40.75"/>
119
+ </a>
120
+ </svg>
121
+ </figure>
122
+ <target href="mn://action_schema"><xref target="ref1">Computer</xref></target><target href="http://www.example.com"><link target="http://www.example.com">Phone</link></target>
123
+ </svgmap>
124
+ <svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
125
+ <figure>
126
126
 
127
- <image src='data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI1LjAuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCA1OTUuMjggODQxLjg5IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1OTUuMjggODQxLjg5OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Cgkuc3Qwe2ZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9Cjwvc3R5bGU+CjxpbWFnZSBzdHlsZT0ib3ZlcmZsb3c6dmlzaWJsZTsiIHdpZHRoPSIzNjgiIGhlaWdodD0iMzE1IiB4bGluazpocmVmPSJkYXRhOmltYWdlL2dpZjtiYXNlNjQsUjBsR09EbGhjQUU3QWZmL0FBQUFBQUFBTXdBQVpnQUFtUUFBekFBQS93QXpBQUF6TXdBelpnQXptUUF6ekFBei93Qm1BQUJtTXdCbQpaZ0JtbVFCbXpBQm0vd0NaQUFDWk13Q1paZ0NabVFDWnpBQ1ovd0RNQUFETU13RE1aZ0RNbVFETXpBRE0vd0QvQUFEL013RC9aZ0QvCm1RRC96QUQvL3pNQUFETUFNek1BWmpNQW1UTUF6RE1BL3pNekFETXpNek16WmpNem1UTXp6RE16L3pObUFETm1Nek5tWmpObW1UTm0KekRObS96T1pBRE9aTXpPWlpqT1ptVE9aekRPWi96UE1BRFBNTXpQTVpqUE1tVFBNekRQTS96UC9BRFAvTXpQL1pqUC9tVFAvekRQLwovMllBQUdZQU0yWUFabVlBbVdZQXpHWUEvMll6QUdZek0yWXpabVl6bVdZenpHWXovMlptQUdabU0yWm1abVptbVdabXpHWm0vMmFaCkFHYVpNMmFaWm1hWm1XYVp6R2FaLzJiTUFHYk1NMmJNWm1iTW1XYk16R2JNLzJiL0FHYi9NMmIvWm1iL21XYi96R2IvLzVrQUFKa0EKTTVrQVpwa0FtWmtBekprQS81a3pBSmt6TTVrelpwa3ptWmt6ekprei81bG1BSmxtTTVsbVpwbG1tWmxtekpsbS81bVpBSm1aTTVtWgpacG1abVptWnpKbVovNW5NQUpuTU01bk1acG5NbVpuTXpKbk0vNW4vQUpuL001bi9acG4vbVpuL3pKbi8vOHdBQU13QU04d0Fac3dBCm1jd0F6TXdBLzh3ekFNd3pNOHd6WnN3em1jd3p6TXd6Lzh4bUFNeG1NOHhtWnN4bW1jeG16TXhtLzh5WkFNeVpNOHlaWnN5Wm1jeVoKek15Wi84ek1BTXpNTTh6TVpzek1tY3pNek16TS84ei9BTXovTTh6L1pzei9tY3ovek16Ly8vOEFBUDhBTS84QVp2OEFtZjhBelA4QQovLzh6QVA4ek0vOHpadjh6bWY4enpQOHovLzltQVA5bU0vOW1adjltbWY5bXpQOW0vLytaQVArWk0vK1paditabWYrWnpQK1ovLy9NCkFQL01NLy9NWnYvTW1mL016UC9NLy8vL0FQLy9NLy8vWnYvL21mLy96UC8vLy9qNCtQTHk4dXZyNitYbDVkL2YzOWpZMk5MUzBzek0Kek1YRnhiKy92N2k0dUxLeXNxeXNyS1dscForZm41bVptWktTa295TWpJV0ZoWDkvZjNsNWVYSnljbXhzYkdabVpsOWZYMWxaV1ZKUwpVa3hNVEVaR1JqOC9Qems1T1RNek15d3NMQ1ltSmg4Zkh4a1pHUk1URXd3TURBWUdCZ0FBQUN3QUFBQUFjQUU3QVFBSS9nQ3ZDUnhJCnNLREJnd2dUS2x6SXNLSERoeEFqU3B4SXNhTEZpeGd6YXR6SXNhUEhqeUJEaWh4SnNxVEpreWhUcWx6SnNxWExsekJqeXB4SnM2Yk4KbXpoejZ0ekpzNmZQbjBDRENoMUt0S2pSbzBpVEtsM0t0S25UcDFDalNwMUt0ZXJJZS8reWF0M0t0YXZYcjJERGloM3I5WjdWczJncAovcXU2TnEzYnR3cmJUcFVMdDI1ZHVsSHgydDE3VnU5VHYzd0Q1MlVydURCVndBcXRJU2tUVWpIampZZ05TejRhdWFDenh5S3R5Zm1ICk9XUGx5YUNEZmhhb3VYUGp4UnhIaDE2OVV5Nm5yQkFFT3N1YVFOYm1meENlbFVoMFRmRy9BTHgxSTBLQ08rRW8yck91emY2WFlKWmkKTXB1YlgzdEc0cDhPNVFtTzY5QXU4SFh4Z2FwWi9vdTMyZlpaaTFuUFRLQlg3N2c5RXVDbHIzRVNJSXU0Z0ZuT2dCKzBwaVE1cS9YTwpMYVlZY0xvbFlzMGNCaVl4bkhYVTZaQWVldWM5Q041NEZBSkYxMnozalhMZFFJNU50MXVCSGlZQ0lvZ0h2YmFoaGdSMTZCaDFXcFh4CjRJdnF5ZmJQZlJOV2FHTnJwQ0VCQVgrempCSWJoNmdWbUY5d0grNFdZa0tLWmZoampveXRHS05BTUFLbzJJNzkxWGpqbGVRSjVHTnYKL1kzb1JZY0ZUb2tkZWthU1dKQTFnZ2pVaVlobGZvbGFlM0pjZDFtVUQyN0pvNVZZNWhsVGVkVWh0eHlOcnowUUhYclYzYWZaakxZeApsOXlaeEgzMzV5eXZBZmZhZlN6dXVCbDBuQjJYVzUrS0NoU2VucUNHOUdsUm80WnFLbVNFbmFycVNhVkN4T0pXL3ZxbDFPcXF0RVkwCnEyaTE1Z3JTclJicTZtdHFaQVVyN0xERWl2WHJzUmp4K3BPeXlQN0tiRS9QTnB0cnREaEthKzFEMU9xVTdiV21ib3VUdDl6cUNXNlcKNFpaNzBMZzFvV3R1aGVyTzFPNjY0cjI3Sjd6MHlndVR2ZlJPaHE5TCsrWmJXTDhzQWV3dlh3S3JWUERBZDZXSzhMVUhvOVR3d21rOQpiSkxFRUZ0Rk1Va1hWenlYd2hvZm03RklIM2Y4RjhjaTY4cFBzU2luckxKWC9KVHM4a1QxdkN5enRqUFhUSzdOT04rYjg4Nzg4dXl6ClNqSC9MUFRRUkJkdDlORklsNXRQMGt3L0ZEUkJJVGR0clY1UlM5MHMxUWVaT1ZHSGlhRm0wb3BHV2gyeFFYb055QnRJbDZIOVdOb0cKbWMwUTIySW5oYlZCV25NVW4wZngzVTEzL3RoSXltRmEzRVU5amVlaHZ3VlgzWW5JS1llY2JvRDgwMFdSaDFSWEJ1RzVHZW1iZnNJUgp0NlJCM2xtYWxhQ3dNZTQ0NUllYlBTQWl0OFhHNG9hQUkwVVhKN0VOZVdDQ0JsYjUzNFBQYVg0NmNjMk5ZcWlBN3hub3QzejAyWWRmCnJBV1pKK1did09ObU5uWE5VZWRpbWJ1cGlLQTFTWnpkdWxGeVlVK2tpSnd5WnFLV3JCOVpJSWp1TVhZKzlXeCtueENHQVRZWkpQc2sKY3VJZysyQ0d2ejFsQTBrZm9vUXBRb0tTQ0RLaUl2SEdlMkRhelpEK3g3Nzk2SWhIS3ByZjkrcDN2KytCNlVuNzR4OXA1QkM5NnNWSgpPWk5MMHpYVzVLVUNnbzh4em1oT0FnMmtvekdaOENCMjZrOEUxVWUvTXJFSE5iSjcwd2ZobHNHZENNNVQvZ1NzemdGSVFLbnF4TVkzCmpzb0tmVGF6Uk9hc29rODBrczgvUUJlOVFqbUhpWW1TVHZJNDFaelh4Q1pRV0l4T29tYTBLTzhNOFQ1ZW5JNFJlK2lUdVlXa2JteVUKbGh0QkFzYzRJbXVPZURQZVJWNmxGZVRaOFY5aysyUFNmbmlOcWdtU1ZvWThwS3I4VXNlSGNBMUpYaXNKMkxSWGtrWXE4aU5sQzE1SQplTWdSdG5FeVIzNUV5Q2UzcHNtMy9lMlN0c29hM3pxaU43c05yNVVFWE9WK2hwY1JTM0tJbHFoc0NDSHBRampNSFU1TGlWdE9CeHYzCk9EWkZqak9VUXg5eE1GZUNCVzJ1SUowakhPaHdJN3BpNnVhWU9qRGRlMUFIR3pWYXh6aUpXNTM1ZnFrNDVvenhtYmxFeUJ4aHB4ejQKWEM5N2Q3cmREY21ndTIzeXJrZS8vcHRjOE9Jem4vcVFjWUYwaTlBTjVhZFA1d1VQZW9TYW5nWGY5RTVLY3NoMnptbG9tQ1E2MEVlbQpNeTZCSkUzMi9xZS84VjBEUmYycjRRR0JSOFAyTWRCOW9pVGpETTFud081VU1FVDVheEZDUE1wSGhkWVVwRXk2S0VQYzZML3pZVEJICkF3enBCQzBIVHdrdWNIMG9aUlNWNHRjYkNaN1VwU2E4NEtLNlJpa00rblNxV3dMU0tYVUt0WXoyaG9Oa0VwNmNRcWdta3o3REN5YjAKWHdxWkdxWVdydldGQm9raFUxZjRWTnpoRUQ0NkhPdCtSTGdtell3MVREdFU2SFRjdEZXdUNtU1hRZnpIR1FsVkhDVCs2RStKYW1JQwpucWpFTWs1eFVDd3lWQmc3dFVXdGRMRTRZRVNVR0c4VFJUTVNFVkxGcVJSQ0hBc2xJeDZxaUVray9xTVUwV25ZaExUTGxyWHQxa2h3Cm0xdFFxY3MzVWF3SUg3TVNTcE1NdDNDOU5WaHlhNGJZNWNvTWo4N3RHSFJyS2N1SVdOU0JoYVd1UTZQTEtxODZaSlFCTE81R3dNdksKVW5KWFZ0NWxDQ3hWdVYyTnJKZU8xVDB2U1pvckk2MWNaM1dVVysxdGZQbk5qd1p6Y1NVZ0p1bVFtVHBsSWpkejMrSGNQMEhiemN6aApsYi9saysrdU9MUlJPelgwdWdSaHArd3VERkc3MHRPZ0FWaFE3L0pwdXVIMTAzZ0FQUk10U3dFaEFDRVZwZzJWTU1nNGhLQ1BxaTU4CkdOYm9CRHZhWDV5eTFLVHBxMnRMRy9sVzdjSHZ4ZWZUbjR3bjNEOHJUZ2VET1ZaalNRRUlwS0JDU2FTOUtXcEpqenJrK0g2MURDeHUKNmxLUi9LR2ZMaG1USElyQy9sUy9PdFlvYTZhRFlnVWhtc3BhUXZxUkFJVXFsS0NZM3RyQWxENUdybTFGSVh3Q2UyYU0wSmR3V1ZIZgpHbWVMRUJZdFZyV3NMV2NUSlV0WjJVcVJpb3pWckdnNTJ6WTZMSXFQQ0hBQ0dVMExXOW9XT3BVRjZSNHIra2VEbVBEMjFCcnNLdmtHCk1vcnNudVRWc0NhVlZ4RWQ0YzdDcXIwWEFlNmFKM0pjOGVZYXZhaytkcjdvcTJ5RUpiTFpicUdXUlhHOU4yQkQyeW1qSWkrampMMFEKdDEzN01CQjViNk85ekJCcWY5c256RjVPVnU1YnV0U3g5NnZFYmUrazhNUGcxRFp6bjVvVTU3bVh0ZXNLSC9IQ2tRd3ZielFzM3J1eApXSGt2NnJLQllyeHZhTzI2eGx1cWFaVER0RkVpUjgvSVpDUXorR1RhY0o3TU1iUEpvZkxFL2o5MDV5UE5Fc3pKbVJLUE5FN2xqbnQ4CjEycE9VV0JITGp3NHY0OHpXanBpbDZwMzF6aHIyK1V4T2ZSdEV1M05INlZSeFlweTlHbFg2K25XYWlYVW84N0tveGNOOUY2Ulp0VlEKYW5YVmRTVVhuTlo2NjF5L3BYMFZVbXhnbHgzczBVYTdyNWl0OWxWTnQrMmhldnRRekExM2o4aGRsTFptaWJmcnZwSzd0dzJYTmFFNwozemVTN3EydzJ6cjUzWnN6dTlQTkZHcUhPOTdzTmVQdk01c3ZOdmplRHpaY2Z3ZVBNUXJ6eHNLMHk3R3doNFJ3RS9qVFFTUndFSHNZCnJ1TEhIRnlnWVkwcTZ6a3ZLaHAvL3NZdG9ybkpqNndlT2luWklFVWV5SkVWWGxQYWo0UXVJSC95VkhYZjFqSDMvdmtBNnJiZndxenkKblp1MXpNTTJQcE43L2hQelc3WTU0TEg4SHFDaGp6dEMrem5uWEFwcmgyUm5mdTBiZXRkRHg3bHFHWTEwU25NSzZwZ3FnNmFLbnBpbQplek1yVUlkR1VuZGE4K2QreWJKcldEY2RXbWVBb09GR1hwZDNEQWdYYnNSclpNY3A4YVlSWnhlQjg1SnNHbWdqYk5lQlYvSnNJRmd0ClRkVVpnb2RkSnppQzZRSkozR1laYTNOS2UvYytFS2lDQVVOMjVDWnpUUUo0NFNkOU0waURJMEZmNkxOZndCWk50ekZObFNOZ3hsUTYKK0JaaTdxWnZQdWd3R2VVMkJOZGVwVGRYemJNakIwVUNWU1JZZ2RZYnMvZUVuY2VCTUZWeDVBWS9LNVZXWVdNL1VSVWt2d2VHWVNocgpIRlZTRHJSVVo0aGw4dkZTWGRoeWJsZ1NQT1ZCTmhkWE9tZUZjb2hrQTlWT0xKU0QvbnExaC9NVmhaZ2xSRXZuYTRxU1JxRWxXV05VCldnTW9nTGhuYW9yNGhwc1lHaUxZaVMveEdSa0lpbEx4aWFSWUVoOTRpbWtuaHFvb2dic1djQ25JS0lKMWF6ZElpbklYZ3dyaFNUQm8KWGpLWUViaUlkM3Q0ZDYrV056b29WRHlJZ2JYNFpYc0loSllqaERNRkc5SlVZQUUyT2ttSWVFdklUYWxGVGpBVVRyODBJdVFrVE9kMAppbTBoaGJFalhsVTRRNzZCaFFTaWhRbTFoazN5aGFRQlViUGpQUk5GTzNhbFR6MElnbkpCY1VrRmZDckZQSVBZVW5mb2p2K0hjeVhTClh6V1ZaQzNpWTFIbWh2dEljbkxZTmc4a1F3RDVZeFJFa0hyb1FGVTFWVmRGYTV2VGtHRDRrRFVYVmpBVWlIVTRWTUZSaURtRWlDQzAKVjJYbFZ5QUUvbGgvMVNZZ3FZSE5kU2hWcEZpUG1GaklJWW1YdFdtMVFWcVdwWk9ZeUg4TzFFMUY5MXFNOVZpVlJYOVA2SGV0dURHcwpHSlZqTTVWWlk0SElwUktqU0pVUUFaVmMrUlNwK0pXcktKWjJZVWlUUkphMXh4SzY2RUF0S0J2NWlKWkF0QkxFdUZXNEpXNXdlVmhlCmhXQkcxM2paWVIyUTU0UUs1anhGS0kxSWVFMUsrR0RZaUh1U0o1WnpNM29FSWxDbjF5QzRBNC9UQVh2b1dFL3J1SVVFT1k4YmRaZUYKbEpkOXhuc3UxbnR0YUJuL1NGQVdtWVo0eUhPS3huRjMyWWNMNVh5akdYMlFSSWNWaVlabm80YjRFeVJtOXBxZ0tYNkJTQ2ZzMFg0RQpJVmNuV1ZjcWlWY3MrWE90ZUpPYk5WbjNKMnI1dDM4RkNJbWZaWG1nUTRsQy9zbDRSSWxhbWVpWnRnV2VZeW1lRnVNUlcwbWVMV0dLCjZBa3o2YldlU3VHVjdva3JWaWtUWjBtTDFzYUE4UGtSYXltUmJkbVNHUEdMQjhHY0xwZWZyUFJLeFhobDk2bU0ycVZlQjJvUldMRXkKRUJxaEVqcWhZbUVXVE1HTWl5ZEZ4ZUY0Zm9tUTJoaVludk9UMURTTjFsUUMyS1JOVE5oZ0gxb1F4OUVwNHVTTi9RV083b1lxVndOdQpUZlZQajdrZWtabDZrMGs3V1dPWkFKbU96OE9PMHJPWmxCbFBFV1dQMVVOUjhWT1RFcUdlM0dPalB5WWpHK2w3cnVtUCtWU0NxWm1iCnEzbUlCYmxWTkJVK0NwbG9EQWwrQjFpalV2bGoxVGViVWRJMXRvbWF1QWxWdTZrK3ZTbVJHeWxVVkpaVk9aVWFjaVNsSmpSK3N3bVQKbzJTYy9yZUpaZmRvaUNwQ25CekNWejZuVUlMS2hZVFZFVkNxYXhmS2lFQlphZitBZjV1aGY5bVlZTmJwblpmMm5KVTRsSXVWUnRVWgpRRWhaS1VvNWY0L2lsSjZCb09GbXByNjRHTEZJU20rNUVKUGFFQVE2TlUzVm4rUDFnbXlab1A0WmJKdktwMHl4cTMxcWNpUXhsK09XCm9IWnBYYkphRWJtNlUrMkpFZWRwWEZqcHErbDVaZGpFblQvU29qWW5UTm5ucmRFWU9pUTZZTmwwalUyNG9zWDVYNHJ5SElNU2VkangKZVAzVk9YRDRudGZ3b0YxaG9mN0NKNXBwbWJaVEh3UlNpQUcxUEFRbHBGbW9tWFBxaFQ3YU5oMVdVUWUxcEFteUlLaW5laTFHWmRPNgpFREZERGw5QkRzNEdxM2RJcGNsQlU3dmhZemVYcFhUMVlnTzVzTVYzL3BBblVqNHpsSkRrOXlUd2d5ZE1vYTlhd2EvOUNyTDJzNlpBCkZWWjZ1bG9US1loYktxY0xSYWZqeWloV3BxVk93cEV6R3lCTFpiTkx3YkZjNGJFZmF6N3FZWnlNaW1SZVVKTHBkNXlFeUZRcnlXYkQKbWlKYlM1TkJHbGpDMlNPQktMVkxnYk02dTdQd0psdDhWQnVONGpuTjBhcDB3MFdnT29sWk5LcmNXYXFkYW1xUjlpaVJrZ2p6cHFxWApzcW1hVXJlTGtyRU9RYlZaWWJWWGUwZE5JVGdQR3JkeWE3bkhTaEJVUzdud3NnM3hVQS95MEEzYmNxMlZsSzNDYW5kTmdSZFk0Uy9iCm9BL2xFQTdrOExwb3VoUjR3YkgrRWcvbE1CRGdBTGxXaDd0YnNRN1hvQThDc1E3RFN4RElxeFhFT3hETG14WE5lN3pKNjd6VEs3M00KL3F1ODFYc056L3NQMGF1OTJidTkzUXUrMkh1OTFFdSsxZ3U5eXNzUDJ3QTFGTnErN3Z1K0tOTVUzYnN3OVJBT0E4RU53TXR2SFJjTwo5ckMrMlVBUCtkdEdRQ2NPKy9BUC9GQU9BZXh3YUpmQUw3ZkF5Ym9VOHlzeURFeUMrUHBjRDF6QkJMRTBGVFBCTk5PNTg1a3ZISndUCklmeVpIMXd2RjV3VUVTeVNtK3N4TmdxZ0VpR2dEd0hEcm5QQ0l3T3lGdkdzMXRXZzJFYkRPOHl0NUdTdjViUnVmOWRObDJOdDRCcHkKN1lhVWFjckNhWXBRUldxWi9pYTBPU2crd1pVaThnaHd0MG9VSTN3VEk1ekN4aGl5aW1Nb0VFZTRUdFZJWVpwNzBkckRuSXU3ditsUwpQcHQ4MkdXSXltcW50S21sSk9Nckl3eWJ5bWVjM1FkSjhoTTcvbHAwSm96NnFFNkt3VXpNeG1KSU9EUlN0Mk5FZEFlSmUxV01xdDh4CmYwZTN4TTdTdXRXS0pBbjREQXVJU0R4c0ZGNzhFQTlvTXZCYnlxWjh5bG5STXBZc2ZmYUZ1azczYS9GNWZMRzh5clBzd2JXTUZLRnMKeHpic0VCSDBEdzZReHJkOHB2ZTZiYXRidHJOVHE4R01xNW04eTMxamdzbVl6QmVoeDcya2VmZDFiNEpwcnNjMG90VHNJWTJUeGREYwptSm8waFp5NUlKU25uTS9EYys0MHNab0R6UldSeS96SVVTMkNrY1FucHMvTXpnNGhrajJGZmNhWWg4Um5WZlZzejlTS29HK21mbXJMCnNncjNxTWdNMEhHSms0dzFkZGNzV2FnRk9rT1VGWmlTazU0VHlRcjlwQmtkRkxtODBRbzh6Qjdkd1NBZDB0K3l6Q1JORThoNi90SXEKNGM3VlpVc0pyZEwzREVvTzVjSzlXc3d3SGMxZnZJTUo4ZEkzcmN5d2FxK0c2YUhmeE5NOUhaNElXb1ZPZkdlY2FWSkZyUkVzZlRiRAp4NlVKK2M5TjdkTncySHdycDVwVVJ0UkZEWnVBWmtOWE5KTTJYZFVZeFlHdmhhbEIyWlJKeVVSSlM5YllZdEp1blJJZEhkY3JTTmRjCmJOZDNqZGQxcmRjc01kZDhEWVdzS0tBeS9OZnFCSDk1aDhPZ2dyT292TmlNamNxYVc5Sm12YTZJZHlsSW9BTXpPaTBRbzU0VHlGQ2gKcHlCcFVzaDVzc1dVeWhPNUhGTkVwMHplUEI2aXJjV2pMVlVFcEFMWEFkcFlzdHBEQWJ6ZGsxY3hTUVB6Q014eGw5bWp6V2lLdXlsRgpHWFo1SXR1Nit0dVZheEtEalJPSGt0cm40aE4rdmNMTC9xckRRR0hjQWQzQUl3M0N0RVliQXN0Q0JHS2lrdU1oeC9RWVJjek5XMEZiCm91TWk1SFRFTjVwNTU5ek40aXF2Q01IZTRncXZMdnBMSExvZDlhckVKUHh5aXAyelY0dWtCU1JpK09SUEkzWkZWT3hQUnlTcjZjaXcKQ0NTUEprWXAxTE40OTdqVSsvR3dUUnF4QzZmT0RNS2p2UWQ3Ym52WGtsdTFsVXV5S0ZtQ3FCMm56TWRqR3hLbkwrWmpMYXRnTHh0QQpCQ1d6c3lteUlVNHUvLzNZNjhKTEFrU1NMMGFQUkpVSVhBWmswVG9pWnBZa3gzUGlMNzQ1R1VuSFFSdXpWdlcwUGh1WHBDMFFJejY1CkN6T09nOXh6YXJXRlk3Sm5OcWQ3aE56bGdDeTIzKzArWi9Xb0xqbENaaFdwY1BKWFR5dFhPWjRUY092Yk4vb2RwRlpwL29zTVJaOW0KUlVycHFodEV0MnNVYVhCc1dnR2dBckxWcXFjS0pFaHB1SVdUdUs2MXVKbENUWHhyNVQ4eDRxQXIzVFpJU1Z4ZGxrT1J1UnY4RUZyego2UWtqRko4THU2TmJ1cW9oYkRsaWFhU3V1aXpoeWpQV0UvTnJ1L1FTdTdOYnU3UXRGSnBkRUxxYkw3enJ1NzB1bnp4UkQ4bHJ2TjVyCnZzdU92dVhyN09mTHZlTUw3YzB1N2M5dTdkRWV2dCs3N2N3dXZ0ZXU3ZDJ1dnV6YjJPUmU3dTk3WnZWN3Y4VWV2QkxHdi80THdIaSsKWkFSc3dBZ2M3N0MyN3ZxYmEvZ3V3TWUyN3g5OTcvWithdjZPM1FDLzVjbzI4QlFzOEFGZmFBZ3YwZ1dmM0FwdjhQMis4R2ZXOENKOAo4QlMvWkJZUDJmcWU4VEsyOFhtZGF5ZGo3aVJmRnZJcG84cUVuZklxdi9JczMvSXUvL0l3SC9PaEVSQUFPdz09IiB0cmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAxIDExNCAyNjMuODg5OCkiPgo8L2ltYWdlPgo8YSB4bGluazpocmVmPSJtbjovL2FjdGlvbl9zY2hlbWEiID4KCTxyZWN0IHg9IjEyMy4yOCIgeT0iMjczLjkzIiBjbGFzcz0ic3QwIiB3aWR0aD0iODguMDUiIGhlaWdodD0iNDEuODQiLz4KPC9hPgo8YSB4bGluazpocmVmPSJtbjovL2Jhc2ljX2F0dHJpYnV0ZV9zY2hlbWEiID4KCTxyZWN0IHg9IjMyNC42OSIgeT0iNDUwLjUyIiBjbGFzcz0ic3QwIiB3aWR0aD0iMTMyLjYyIiBoZWlnaHQ9IjQwLjc1Ii8+CjwvYT4KPGEgeGxpbms6aHJlZj0ibW46Ly9zdXBwb3J0X3Jlc291cmNlX3NjaGVtYSIgPgoJPHJlY3QgeD0iMzI0LjY5IiB5PSI1MjguMzYiIGNsYXNzPSJzdDAiIHdpZHRoPSIxNDguMTYiIGhlaWdodD0iNDAuNzUiLz4KPC9hPgo8L3N2Zz4K' id='__ISO_17301-1_2016' mimetype='image/svg+xml' height='auto' width='auto' alt='Workmap1'/>
128
- </figure>
129
- <target href="href1.htm"><xref target="ref1">Computer</xref></target><target href="mn://basic_attribute_schema"><link target="http://www.example.com">Phone</link></target><target href="mn://support_resource_schema"><eref type="express" bibitemid="express_action_schema" citeas=""><localityStack><locality type="anchor"><referenceFrom>action_schema.basic</referenceFrom></locality></localityStack>Coffee</eref></target></svgmap>
130
- </sections>
131
- </standard-document>
132
- INPUT
133
- Metanorma::Utils.svgmap_rewrite(xmldoc)
134
- xmldoc1 = xmldoc.dup
135
- xmldoc&.at("//image[@alt = 'Workmap1']")&.remove
136
- expect(xmlpp(xmldoc.to_xml)).to be_equivalent_to xmlpp(<<~OUTPUT)
137
- <standard-document type="semantic" version="1.8.2">
138
- <bibdata type="standard">
139
- <title language="en" format="text/plain">Document title</title>
140
- <docidentifier/>
141
- <docnumber/>
142
- <version/>
143
- <language>en</language>
144
- <script>Latn</script>
145
- <status>
146
- <stage>published</stage>
147
- </status>
148
- <copyright>
149
- <from>2021</from>
150
- </copyright>
151
- <ext>
152
- <doctype>article</doctype>
153
- </ext>
154
- </bibdata>
155
- <sections><svgmap id="_d5b5049a-dd53-4ea0-bc6f-e8773bd59052"><target href="mn://action_schema"><xref target="ref1">Computer</xref></target></svgmap>
156
- <figure>
157
- <image src='action_schemaexpg1.svg'/>
158
- </figure>
159
- <svgmap id='_60dadf08-48d4-4164-845c-b4e293e00abd'>
160
- <figure>
161
- <image src='action_schemaexpg2.svg' alt='Workmap'/>
162
- </figure>
163
- <target href="mn://support_resource_schema"><eref type="express" bibitemid="express_action_schema" citeas=""><localityStack><locality type="anchor"><referenceFrom>action_schema.basic</referenceFrom></locality></localityStack>Coffee</eref></target></svgmap>
164
- <figure>
127
+ <image src='data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI1LjAuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCA1OTUuMjggODQxLjg5IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1OTUuMjggODQxLjg5OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+Cgkuc3Qwe2ZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9Cjwvc3R5bGU+CjxpbWFnZSBzdHlsZT0ib3ZlcmZsb3c6dmlzaWJsZTsiIHdpZHRoPSIzNjgiIGhlaWdodD0iMzE1IiB4bGluazpocmVmPSJkYXRhOmltYWdlL2dpZjtiYXNlNjQsUjBsR09EbGhjQUU3QWZmL0FBQUFBQUFBTXdBQVpnQUFtUUFBekFBQS93QXpBQUF6TXdBelpnQXptUUF6ekFBei93Qm1BQUJtTXdCbQpaZ0JtbVFCbXpBQm0vd0NaQUFDWk13Q1paZ0NabVFDWnpBQ1ovd0RNQUFETU13RE1aZ0RNbVFETXpBRE0vd0QvQUFEL013RC9aZ0QvCm1RRC96QUQvL3pNQUFETUFNek1BWmpNQW1UTUF6RE1BL3pNekFETXpNek16WmpNem1UTXp6RE16L3pObUFETm1Nek5tWmpObW1UTm0KekRObS96T1pBRE9aTXpPWlpqT1ptVE9aekRPWi96UE1BRFBNTXpQTVpqUE1tVFBNekRQTS96UC9BRFAvTXpQL1pqUC9tVFAvekRQLwovMllBQUdZQU0yWUFabVlBbVdZQXpHWUEvMll6QUdZek0yWXpabVl6bVdZenpHWXovMlptQUdabU0yWm1abVptbVdabXpHWm0vMmFaCkFHYVpNMmFaWm1hWm1XYVp6R2FaLzJiTUFHYk1NMmJNWm1iTW1XYk16R2JNLzJiL0FHYi9NMmIvWm1iL21XYi96R2IvLzVrQUFKa0EKTTVrQVpwa0FtWmtBekprQS81a3pBSmt6TTVrelpwa3ptWmt6ekprei81bG1BSmxtTTVsbVpwbG1tWmxtekpsbS81bVpBSm1aTTVtWgpacG1abVptWnpKbVovNW5NQUpuTU01bk1acG5NbVpuTXpKbk0vNW4vQUpuL001bi9acG4vbVpuL3pKbi8vOHdBQU13QU04d0Fac3dBCm1jd0F6TXdBLzh3ekFNd3pNOHd6WnN3em1jd3p6TXd6Lzh4bUFNeG1NOHhtWnN4bW1jeG16TXhtLzh5WkFNeVpNOHlaWnN5Wm1jeVoKek15Wi84ek1BTXpNTTh6TVpzek1tY3pNek16TS84ei9BTXovTTh6L1pzei9tY3ovek16Ly8vOEFBUDhBTS84QVp2OEFtZjhBelA4QQovLzh6QVA4ek0vOHpadjh6bWY4enpQOHovLzltQVA5bU0vOW1adjltbWY5bXpQOW0vLytaQVArWk0vK1paditabWYrWnpQK1ovLy9NCkFQL01NLy9NWnYvTW1mL016UC9NLy8vL0FQLy9NLy8vWnYvL21mLy96UC8vLy9qNCtQTHk4dXZyNitYbDVkL2YzOWpZMk5MUzBzek0Kek1YRnhiKy92N2k0dUxLeXNxeXNyS1dscForZm41bVptWktTa295TWpJV0ZoWDkvZjNsNWVYSnljbXhzYkdabVpsOWZYMWxaV1ZKUwpVa3hNVEVaR1JqOC9Qems1T1RNek15d3NMQ1ltSmg4Zkh4a1pHUk1URXd3TURBWUdCZ0FBQUN3QUFBQUFjQUU3QVFBSS9nQ3ZDUnhJCnNLREJnd2dUS2x6SXNLSERoeEFqU3B4SXNhTEZpeGd6YXR6SXNhUEhqeUJEaWh4SnNxVEpreWhUcWx6SnNxWExsekJqeXB4SnM2Yk4KbXpoejZ0ekpzNmZQbjBDRENoMUt0S2pSbzBpVEtsM0t0S25UcDFDalNwMUt0ZXJJZS8reWF0M0t0YXZYcjJERGloM3I5WjdWczJncAovcXU2TnEzYnR3cmJUcFVMdDI1ZHVsSHgydDE3VnU5VHYzd0Q1MlVydURCVndBcXRJU2tUVWpIampZZ05TejRhdWFDenh5S3R5Zm1ICk9XUGx5YUNEZmhhb3VYUGp4UnhIaDE2OVV5Nm5yQkFFT3N1YVFOYm1meENlbFVoMFRmRy9BTHgxSTBLQ08rRW8yck91emY2WFlKWmkKTXB1YlgzdEc0cDhPNVFtTzY5QXU4SFh4Z2FwWi9vdTMyZlpaaTFuUFRLQlg3N2c5RXVDbHIzRVNJSXU0Z0ZuT2dCKzBwaVE1cS9YTwpMYVlZY0xvbFlzMGNCaVl4bkhYVTZaQWVldWM5Q041NEZBSkYxMnozalhMZFFJNU50MXVCSGlZQ0lvZ0h2YmFoaGdSMTZCaDFXcFh4CjRJdnF5ZmJQZlJOV2FHTnJwQ0VCQVgrempCSWJoNmdWbUY5d0grNFdZa0tLWmZoampveXRHS05BTUFLbzJJNzkxWGpqbGVRSjVHTnYKL1kzb1JZY0ZUb2tkZWthU1dKQTFnZ2pVaVlobGZvbGFlM0pjZDFtVUQyN0pvNVZZNWhsVGVkVWh0eHlOcnowUUhYclYzYWZaakxZeApsOXlaeEgzMzV5eXZBZmZhZlN6dXVCbDBuQjJYVzUrS0NoU2VucUNHOUdsUm80WnFLbVNFbmFycVNhVkN4T0pXL3ZxbDFPcXF0RVkwCnEyaTE1Z3JTclJicTZtdHFaQVVyN0xERWl2WHJzUmp4K3BPeXlQN0tiRS9QTnB0cnREaEthKzFEMU9xVTdiV21ib3VUdDl6cUNXNlcKNFpaNzBMZzFvV3R1aGVyTzFPNjY0cjI3Sjd6MHlndVR2ZlJPaHE5TCsrWmJXTDhzQWV3dlh3S3JWUERBZDZXSzhMVUhvOVR3d21rOQpiSkxFRUZ0Rk1Va1hWenlYd2hvZm03RklIM2Y4RjhjaTY4cFBzU2luckxKWC9KVHM4a1QxdkN5enRqUFhUSzdOT04rYjg4Nzg4dXl6ClNqSC9MUFRRUkJkdDlORklsNXRQMGt3L0ZEUkJJVGR0clY1UlM5MHMxUWVaT1ZHSGlhRm0wb3BHV2gyeFFYb055QnRJbDZIOVdOb0cKbWMwUTIySW5oYlZCV25NVW4wZngzVTEzL3RoSXltRmEzRVU5amVlaHZ3VlgzWW5JS1llY2JvRDgwMFdSaDFSWEJ1RzVHZW1iZnNJUgp0NlJCM2xtYWxhQ3dNZTQ0NUllYlBTQWl0OFhHNG9hQUkwVVhKN0VOZVdDQ0JsYjUzNFBQYVg0NmNjMk5ZcWlBN3hub3QzejAyWWRmCnJBV1pKK1did09ObU5uWE5VZWRpbWJ1cGlLQTFTWnpkdWxGeVlVK2tpSnd5WnFLV3JCOVpJSWp1TVhZKzlXeCtueENHQVRZWkpQc2sKY3VJZysyQ0d2ejFsQTBrZm9vUXBRb0tTQ0RLaUl2SEdlMkRhelpEK3g3Nzk2SWhIS3ByZjkrcDN2KytCNlVuNzR4OXA1QkM5NnNWSgpPWk5MMHpYVzVLVUNnbzh4em1oT0FnMmtvekdaOENCMjZrOEUxVWUvTXJFSE5iSjcwd2ZobHNHZENNNVQvZ1NzemdGSVFLbnF4TVkzCmpzb0tmVGF6Uk9hc29rODBrczgvUUJlOVFqbUhpWW1TVHZJNDFaelh4Q1pRV0l4T29tYTBLTzhNOFQ1ZW5JNFJlK2lUdVlXa2JteVUKbGh0QkFzYzRJbXVPZURQZVJWNmxGZVRaOFY5aysyUFNmbmlOcWdtU1ZvWThwS3I4VXNlSGNBMUpYaXNKMkxSWGtrWXE4aU5sQzE1SQplTWdSdG5FeVIzNUV5Q2UzcHNtMy9lMlN0c29hM3pxaU43c05yNVVFWE9WK2hwY1JTM0tJbHFoc0NDSHBRampNSFU1TGlWdE9CeHYzCk9EWkZqak9VUXg5eE1GZUNCVzJ1SUowakhPaHdJN3BpNnVhWU9qRGRlMUFIR3pWYXh6aUpXNTM1ZnFrNDVvenhtYmxFeUJ4aHB4ejQKWEM5N2Q3cmREY21ndTIzeXJrZS8vcHRjOE9Jem4vcVFjWUYwaTlBTjVhZFA1d1VQZW9TYW5nWGY5RTVLY3NoMnptbG9tQ1E2MEVlbQpNeTZCSkUzMi9xZS84VjBEUmYycjRRR0JSOFAyTWRCOW9pVGpETTFud081VU1FVDVheEZDUE1wSGhkWVVwRXk2S0VQYzZML3pZVEJICkF3enBCQzBIVHdrdWNIMG9aUlNWNHRjYkNaN1VwU2E4NEtLNlJpa00rblNxV3dMU0tYVUt0WXoyaG9Oa0VwNmNRcWdta3o3REN5YjAKWHdxWkdxWVdydldGQm9raFUxZjRWTnpoRUQ0NkhPdCtSTGdtell3MVREdFU2SFRjdEZXdUNtU1hRZnpIR1FsVkhDVCs2RStKYW1JQwpucWpFTWs1eFVDd3lWQmc3dFVXdGRMRTRZRVNVR0c4VFJUTVNFVkxGcVJSQ0hBc2xJeDZxaUVray9xTVUwV25ZaExUTGxyWHQxa2h3Cm0xdFFxY3MzVWF3SUg3TVNTcE1NdDNDOU5WaHlhNGJZNWNvTWo4N3RHSFJyS2N1SVdOU0JoYVd1UTZQTEtxODZaSlFCTE81R3dNdksKVW5KWFZ0NWxDQ3hWdVYyTnJKZU8xVDB2U1pvckk2MWNaM1dVVysxdGZQbk5qd1p6Y1NVZ0p1bVFtVHBsSWpkejMrSGNQMEhiemN6aApsYi9saysrdU9MUlJPelgwdWdSaHArd3VERkc3MHRPZ0FWaFE3L0pwdXVIMTAzZ0FQUk10U3dFaEFDRVZwZzJWTU1nNGhLQ1BxaTU4CkdOYm9CRHZhWDV5eTFLVHBxMnRMRy9sVzdjSHZ4ZWZUbjR3bjNEOHJUZ2VET1ZaalNRRUlwS0JDU2FTOUtXcEpqenJrK0g2MURDeHUKNmxLUi9LR2ZMaG1USElyQy9sUy9PdFlvYTZhRFlnVWhtc3BhUXZxUkFJVXFsS0NZM3RyQWxENUdybTFGSVh3Q2UyYU0wSmR3V1ZIZgpHbWVMRUJZdFZyV3NMV2NUSlV0WjJVcVJpb3pWckdnNTJ6WTZMSXFQQ0hBQ0dVMExXOW9XT3BVRjZSNHIra2VEbVBEMjFCcnNLdmtHCk1vcnNudVRWc0NhVlZ4RWQ0YzdDcXIwWEFlNmFKM0pjOGVZYXZhaytkcjdvcTJ5RUpiTFpicUdXUlhHOU4yQkQyeW1qSWkrampMMFEKdDEzN01CQjViNk85ekJCcWY5c256RjVPVnU1YnV0U3g5NnZFYmUrazhNUGcxRFp6bjVvVTU3bVh0ZXNLSC9IQ2tRd3ZielFzM3J1eApXSGt2NnJLQllyeHZhTzI2eGx1cWFaVER0RkVpUjgvSVpDUXorR1RhY0o3TU1iUEpvZkxFL2o5MDV5UE5Fc3pKbVJLUE5FN2xqbnQ4CjEycE9VV0JITGp3NHY0OHpXanBpbDZwMzF6aHIyK1V4T2ZSdEV1M05INlZSeFlweTlHbFg2K25XYWlYVW84N0tveGNOOUY2Ulp0VlEKYW5YVmRTVVhuTlo2NjF5L3BYMFZVbXhnbHgzczBVYTdyNWl0OWxWTnQrMmhldnRRekExM2o4aGRsTFptaWJmcnZwSzd0dzJYTmFFNwozemVTN3EydzJ6cjUzWnN6dTlQTkZHcUhPOTdzTmVQdk01c3ZOdmplRHpaY2Z3ZVBNUXJ6eHNLMHk3R3doNFJ3RS9qVFFTUndFSHNZCnJ1TEhIRnlnWVkwcTZ6a3ZLaHAvL3NZdG9ybkpqNndlT2luWklFVWV5SkVWWGxQYWo0UXVJSC95VkhYZjFqSDMvdmtBNnJiZndxenkKblp1MXpNTTJQcE43L2hQelc3WTU0TEg4SHFDaGp6dEMrem5uWEFwcmgyUm5mdTBiZXRkRHg3bHFHWTEwU25NSzZwZ3FnNmFLbnBpbQplek1yVUlkR1VuZGE4K2QreWJKcldEY2RXbWVBb09GR1hwZDNEQWdYYnNSclpNY3A4YVlSWnhlQjg1SnNHbWdqYk5lQlYvSnNJRmd0ClRkVVpnb2RkSnppQzZRSkozR1laYTNOS2UvYytFS2lDQVVOMjVDWnpUUUo0NFNkOU0waURJMEZmNkxOZndCWk50ekZObFNOZ3hsUTYKK0JaaTdxWnZQdWd3R2VVMkJOZGVwVGRYemJNakIwVUNWU1JZZ2RZYnMvZUVuY2VCTUZWeDVBWS9LNVZXWVdNL1VSVWt2d2VHWVNocgpIRlZTRHJSVVo0aGw4dkZTWGRoeWJsZ1NQT1ZCTmhkWE9tZUZjb2hrQTlWT0xKU0QvbnExaC9NVmhaZ2xSRXZuYTRxU1JxRWxXV05VCldnTW9nTGhuYW9yNGhwc1lHaUxZaVMveEdSa0lpbEx4aWFSWUVoOTRpbWtuaHFvb2dic1djQ25JS0lKMWF6ZElpbklYZ3dyaFNUQm8KWGpLWUViaUlkM3Q0ZDYrV056b29WRHlJZ2JYNFpYc0loSllqaERNRkc5SlVZQUUyT2ttSWVFdklUYWxGVGpBVVRyODBJdVFrVE9kMAppbTBoaGJFalhsVTRRNzZCaFFTaWhRbTFoazN5aGFRQlViUGpQUk5GTzNhbFR6MElnbkpCY1VrRmZDckZQSVBZVW5mb2p2K0hjeVhTClh6V1ZaQzNpWTFIbWh2dEljbkxZTmc4a1F3RDVZeFJFa0hyb1FGVTFWVmRGYTV2VGtHRDRrRFVYVmpBVWlIVTRWTUZSaURtRWlDQzAKVjJYbFZ5QUUvbGgvMVNZZ3FZSE5kU2hWcEZpUG1GaklJWW1YdFdtMVFWcVdwWk9ZeUg4TzFFMUY5MXFNOVZpVlJYOVA2SGV0dURHcwpHSlZqTTVWWlk0SElwUktqU0pVUUFaVmMrUlNwK0pXcktKWjJZVWlUUkphMXh4SzY2RUF0S0J2NWlKWkF0QkxFdUZXNEpXNXdlVmhlCmhXQkcxM2paWVIyUTU0UUs1anhGS0kxSWVFMUsrR0RZaUh1U0o1WnpNM29FSWxDbjF5QzRBNC9UQVh2b1dFL3J1SVVFT1k4YmRaZUYKbEpkOXhuc3UxbnR0YUJuL1NGQVdtWVo0eUhPS3huRjMyWWNMNVh5akdYMlFSSWNWaVlabm80YjRFeVJtOXBxZ0tYNkJTQ2ZzMFg0RQpJVmNuV1ZjcWlWY3MrWE90ZUpPYk5WbjNKMnI1dDM4RkNJbWZaWG1nUTRsQy9zbDRSSWxhbWVpWnRnV2VZeW1lRnVNUlcwbWVMV0dLCjZBa3o2YldlU3VHVjdva3JWaWtUWjBtTDFzYUE4UGtSYXltUmJkbVNHUEdMQjhHY0xwZWZyUFJLeFhobDk2bU0ycVZlQjJvUldMRXkKRUJxaEVqcWhZbUVXVE1HTWl5ZEZ4ZUY0Zm9tUTJoaVludk9UMURTTjFsUUMyS1JOVE5oZ0gxb1F4OUVwNHVTTi9RV083b1lxVndOdQpUZlZQajdrZWtabDZrMGs3V1dPWkFKbU96OE9PMHJPWmxCbFBFV1dQMVVOUjhWT1RFcUdlM0dPalB5WWpHK2w3cnVtUCtWU0NxWm1iCnEzbUlCYmxWTkJVK0NwbG9EQWwrQjFpalV2bGoxVGViVWRJMXRvbWF1QWxWdTZrK3ZTbVJHeWxVVkpaVk9aVWFjaVNsSmpSK3N3bVQKbzJTYy9yZUpaZmRvaUNwQ25CekNWejZuVUlMS2hZVFZFVkNxYXhmS2lFQlphZitBZjV1aGY5bVlZTmJwblpmMm5KVTRsSXVWUnRVWgpRRWhaS1VvNWY0L2lsSjZCb09GbXByNjRHTEZJU20rNUVKUGFFQVE2TlUzVm4rUDFnbXlab1A0WmJKdktwMHl4cTMxcWNpUXhsK09XCm9IWnBYYkphRWJtNlUrMkpFZWRwWEZqcHErbDVaZGpFblQvU29qWW5UTm5ucmRFWU9pUTZZTmwwalUyNG9zWDVYNHJ5SElNU2VkangKZVAzVk9YRDRudGZ3b0YxaG9mN0NKNXBwbWJaVEh3UlNpQUcxUEFRbHBGbW9tWFBxaFQ3YU5oMVdVUWUxcEFteUlLaW5laTFHWmRPNgpFREZERGw5QkRzNEdxM2RJcGNsQlU3dmhZemVYcFhUMVlnTzVzTVYzL3BBblVqNHpsSkRrOXlUd2d5ZE1vYTlhd2EvOUNyTDJzNlpBCkZWWjZ1bG9US1loYktxY0xSYWZqeWloV3BxVk93cEV6R3lCTFpiTkx3YkZjNGJFZmF6N3FZWnlNaW1SZVVKTHBkNXlFeUZRcnlXYkQKbWlKYlM1TkJHbGpDMlNPQktMVkxnYk02dTdQd0psdDhWQnVONGpuTjBhcDB3MFdnT29sWk5LcmNXYXFkYW1xUjlpaVJrZ2p6cHFxWApzcW1hVXJlTGtyRU9RYlZaWWJWWGUwZE5JVGdQR3JkeWE3bkhTaEJVUzdud3NnM3hVQS95MEEzYmNxMlZsSzNDYW5kTmdSZFk0Uy9iCm9BL2xFQTdrOExwb3VoUjR3YkgrRWcvbE1CRGdBTGxXaDd0YnNRN1hvQThDc1E3RFN4RElxeFhFT3hETG14WE5lN3pKNjd6VEs3M00KL3F1ODFYc056L3NQMGF1OTJidTkzUXUrMkh1OTFFdSsxZ3U5eXNzUDJ3QTFGTnErN3Z1K0tOTVUzYnN3OVJBT0E4RU53TXR2SFJjTwo5ckMrMlVBUCtkdEdRQ2NPKy9BUC9GQU9BZXh3YUpmQUw3ZkF5Ym9VOHlzeURFeUMrUHBjRDF6QkJMRTBGVFBCTk5PNTg1a3ZISndUCklmeVpIMXd2RjV3VUVTeVNtK3N4TmdxZ0VpR2dEd0hEcm5QQ0l3T3lGdkdzMXRXZzJFYkRPOHl0NUdTdjViUnVmOWRObDJOdDRCcHkKN1lhVWFjckNhWXBRUldxWi9pYTBPU2crd1pVaThnaHd0MG9VSTN3VEk1ekN4aGl5aW1Nb0VFZTRUdFZJWVpwNzBkckRuSXU3ditsUwpQcHQ4MkdXSXltcW50S21sSk9Nckl3eWJ5bWVjM1FkSjhoTTcvbHAwSm96NnFFNkt3VXpNeG1KSU9EUlN0Mk5FZEFlSmUxV01xdDh4CmYwZTN4TTdTdXRXS0pBbjREQXVJU0R4c0ZGNzhFQTlvTXZCYnlxWjh5bG5STXBZc2ZmYUZ1azczYS9GNWZMRzh5clBzd2JXTUZLRnMKeHpic0VCSDBEdzZReHJkOHB2ZTZiYXRidHJOVHE4R01xNW04eTMxamdzbVl6QmVoeDcya2VmZDFiNEpwcnNjMG90VHNJWTJUeGREYwptSm8waFp5NUlKU25uTS9EYys0MHNab0R6UldSeS96SVVTMkNrY1FucHMvTXpnNGhrajJGZmNhWWg4Um5WZlZzejlTS29HK21mbXJMCnNncjNxTWdNMEhHSms0dzFkZGNzV2FnRk9rT1VGWmlTazU0VHlRcjlwQmtkRkxtODBRbzh6Qjdkd1NBZDB0K3l6Q1JORThoNi90SXEKNGM3VlpVc0pyZEwzREVvTzVjSzlXc3d3SGMxZnZJTUo4ZEkzcmN5d2FxK0c2YUhmeE5NOUhaNElXb1ZPZkdlY2FWSkZyUkVzZlRiRAp4NlVKK2M5TjdkTncySHdycDVwVVJ0UkZEWnVBWmtOWE5KTTJYZFVZeFlHdmhhbEIyWlJKeVVSSlM5YllZdEp1blJJZEhkY3JTTmRjCmJOZDNqZGQxcmRjc01kZDhEWVdzS0tBeS9OZnFCSDk1aDhPZ2dyT292TmlNamNxYVc5Sm12YTZJZHlsSW9BTXpPaTBRbzU0VHlGQ2gKcHlCcFVzaDVzc1dVeWhPNUhGTkVwMHplUEI2aXJjV2pMVlVFcEFMWEFkcFlzdHBEQWJ6ZGsxY3hTUVB6Q014eGw5bWp6V2lLdXlsRgpHWFo1SXR1Nit0dVZheEtEalJPSGt0cm40aE4rdmNMTC9xckRRR0hjQWQzQUl3M0N0RVliQXN0Q0JHS2lrdU1oeC9RWVJjek5XMEZiCm91TWk1SFRFTjVwNTU5ek40aXF2Q01IZTRncXZMdnBMSExvZDlhckVKUHh5aXAyelY0dWtCU1JpK09SUEkzWkZWT3hQUnlTcjZjaXcKQ0NTUEprWXAxTE40OTdqVSsvR3dUUnF4QzZmT0RNS2p2UWQ3Ym52WGtsdTFsVXV5S0ZtQ3FCMm56TWRqR3hLbkwrWmpMYXRnTHh0QQpCQ1d6c3lteUlVNHUvLzNZNjhKTEFrU1NMMGFQUkpVSVhBWmswVG9pWnBZa3gzUGlMNzQ1R1VuSFFSdXpWdlcwUGh1WHBDMFFJejY1CkN6T09nOXh6YXJXRlk3Sm5OcWQ3aE56bGdDeTIzKzArWi9Xb0xqbENaaFdwY1BKWFR5dFhPWjRUY092Yk4vb2RwRlpwL29zTVJaOW0KUlVycHFodEV0MnNVYVhCc1dnR2dBckxWcXFjS0pFaHB1SVdUdUs2MXVKbENUWHhyNVQ4eDRxQXIzVFpJU1Z4ZGxrT1J1UnY4RUZyego2UWtqRko4THU2TmJ1cW9oYkRsaWFhU3V1aXpoeWpQV0UvTnJ1L1FTdTdOYnU3UXRGSnBkRUxxYkw3enJ1NzB1bnp4UkQ4bHJ2TjVyCnZzdU92dVhyN09mTHZlTUw3YzB1N2M5dTdkRWV2dCs3N2N3dXZ0ZXU3ZDJ1dnV6YjJPUmU3dTk3WnZWN3Y4VWV2QkxHdi80THdIaSsKWkFSc3dBZ2M3N0MyN3ZxYmEvZ3V3TWUyN3g5OTcvWithdjZPM1FDLzVjbzI4QlFzOEFGZmFBZ3YwZ1dmM0FwdjhQMis4R2ZXOENKOAo4QlMvWkJZUDJmcWU4VEsyOFhtZGF5ZGo3aVJmRnZJcG84cUVuZklxdi9JczMvSXUvL0l3SC9PaEVSQUFPdz09IiB0cmFuc2Zvcm09Im1hdHJpeCgxIDAgMCAxIDExNCAyNjMuODg5OCkiPgo8L2ltYWdlPgo8YSB4bGluazpocmVmPSJtbjovL2FjdGlvbl9zY2hlbWEiID4KCTxyZWN0IHg9IjEyMy4yOCIgeT0iMjczLjkzIiBjbGFzcz0ic3QwIiB3aWR0aD0iODguMDUiIGhlaWdodD0iNDEuODQiLz4KPC9hPgo8YSB4bGluazpocmVmPSJtbjovL2Jhc2ljX2F0dHJpYnV0ZV9zY2hlbWEiID4KCTxyZWN0IHg9IjMyNC42OSIgeT0iNDUwLjUyIiBjbGFzcz0ic3QwIiB3aWR0aD0iMTMyLjYyIiBoZWlnaHQ9IjQwLjc1Ii8+CjwvYT4KPGEgeGxpbms6aHJlZj0ibW46Ly9zdXBwb3J0X3Jlc291cmNlX3NjaGVtYSIgPgoJPHJlY3QgeD0iMzI0LjY5IiB5PSI1MjguMzYiIGNsYXNzPSJzdDAiIHdpZHRoPSIxNDguMTYiIGhlaWdodD0iNDAuNzUiLz4KPC9hPgo8L3N2Zz4K' id='__ISO_17301-1_2016' mimetype='image/svg+xml' height='auto' width='auto' alt='Workmap1'/>
128
+ </figure>
129
+ <target href="href1.htm"><xref target="ref1">Computer</xref></target><target href="mn://basic_attribute_schema"><link target="http://www.example.com">Phone</link></target><target href="mn://support_resource_schema"><eref type="express" bibitemid="express_action_schema" citeas=""><localityStack><locality type="anchor"><referenceFrom>action_schema.basic</referenceFrom></locality></localityStack>Coffee</eref></target></svgmap>
130
+ </sections>
131
+ </standard-document>
132
+ INPUT
133
+ Metanorma::Utils.svgmap_rewrite(xmldoc)
134
+ expect(xmlpp(xmldoc.to_xml.gsub(%r{<image.*?</image>}m, "<image/>").gsub(%r{<style.*?</style>}m, "<style/>"))).to be_equivalent_to xmlpp(<<~OUTPUT)
135
+ <?xml version='1.0'?>
136
+ <standard-document type='semantic' version='1.8.2'>
137
+ <bibdata type='standard'>
138
+ <title language='en' format='text/plain'>Document title</title>
139
+ <docidentifier/>
140
+ <docnumber/>
141
+ <version/>
142
+ <language>en</language>
143
+ <script>Latn</script>
144
+ <status>
145
+ <stage>published</stage>
146
+ </status>
147
+ <copyright>
148
+ <from>2021</from>
149
+ </copyright>
150
+ <ext>
151
+ <doctype>article</doctype>
152
+ </ext>
153
+ </bibdata>
154
+ <sections>
155
+ <svgmap id='_d5b5049a-dd53-4ea0-bc6f-e8773bd59052'>
156
+ <target href='mn://action_schema'>
157
+ <xref target='ref1'>Computer</xref>
158
+ </target>
159
+ </svgmap>
160
+ <figure>
161
+ <?xml version="1.0" encoding="utf-8"??>
162
+ <!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
163
+ <svg xmlns='http://www.w3.org/2000/svg' version='1.1' id='Layer_1' x='0px' y='0px' viewbox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve' xmlns:xlink='http://www.w3.org/1999/xlink'>
164
+ <style/>
165
+ <image/>
166
+ <a xlink:href='#ref1'>
167
+ <rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
168
+ </a>
169
+ <a xlink:href='mn://basic_attribute_schema'>
170
+ <rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
171
+ </a>
172
+ <a xlink:href='mn://support_resource_schema'>
173
+ <rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
174
+ </a>
175
+ </svg>
176
+ </figure>
177
+ <svgmap id='_60dadf08-48d4-4164-845c-b4e293e00abd'>
178
+ <figure>
179
+ <?xml version="1.0" encoding="utf-8"??>
180
+ <!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
181
+ <svg xmlns='http://www.w3.org/2000/svg' version='1.1' id='Layer_1' x='0px' y='0px' viewbox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve' xmlns:xlink='http://www.w3.org/1999/xlink'>
182
+ <style/>
183
+ <image/>
184
+ <a xlink:href='mn://action_schema'>
185
+ <rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
186
+ </a>
187
+ <a xlink:href='http://www.example.com'>
188
+ <rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
189
+ </a>
190
+ <a xlink:href='mn://support_resource_schema'>
191
+ <rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
192
+ </a>
193
+ </svg>
194
+ </figure>
195
+ <target href='mn://support_resource_schema'>
196
+ <eref type='express' bibitemid='express_action_schema' citeas=''>
197
+ <localityStack>
198
+ <locality type='anchor'>
199
+ <referenceFrom>action_schema.basic</referenceFrom>
200
+ </locality>
201
+ </localityStack>
202
+ Coffee
203
+ </eref>
204
+ </target>
205
+ </svgmap>
206
+ <figure>
165
207
  <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' viewBox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve'>
166
208
  <a href='#ref1'>
167
209
  <rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
@@ -174,8 +216,23 @@ RSpec.describe Metanorma::Utils do
174
216
  </a>
175
217
  </svg>
176
218
  </figure>
177
- <svgmap id='_60dadf08-48d4-4164-845c-b4e293e00abd'>
219
+ <svgmap id='_60dadf08-48d4-4164-845c-b4e293e00abd'>
178
220
  <figure>
221
+ <?xml version="1.0" encoding="utf-8"??>
222
+ <!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
223
+ <svg xmlns='http://www.w3.org/2000/svg' version='1.1' id='Layer_1' x='0px' y='0px' viewbox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve' xmlns:xlink='http://www.w3.org/1999/xlink'>
224
+ <style/>
225
+ <image/>
226
+ <a xlink:href='mn://action_schema'>
227
+ <rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
228
+ </a>
229
+ <a xlink:href='http://www.example.com'>
230
+ <rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
231
+ </a>
232
+ <a xlink:href='mn://support_resource_schema'>
233
+ <rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
234
+ </a>
235
+ </svg>
179
236
  </figure>
180
237
  <target href='mn://support_resource_schema'>
181
238
  <eref type='express' bibitemid='express_action_schema' citeas=''>
@@ -188,134 +245,115 @@ RSpec.describe Metanorma::Utils do
188
245
  </eref>
189
246
  </target>
190
247
  </svgmap>
191
- </sections>
248
+ </sections>
192
249
  </standard-document>
193
- OUTPUT
194
- expect(xmlpp(File.read("action_schemaexpg1.svg", encoding: "utf-8").sub(%r{<image .*</image>}m, ""))).to be_equivalent_to <<~OUTPUT
195
- <?xml version='1.0' encoding='UTF-8'?>
196
- <!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
197
- <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' viewBox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve'>
198
- <style type='text/css'> .st0{fill:none;stroke:#000000;stroke-miterlimit:10;} </style>
199
- <a xlink:href='#ref1'>
200
- <rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
201
- </a>
202
- <a xlink:href='mn://basic_attribute_schema'>
203
- <rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
204
- </a>
205
- <a xlink:href='mn://support_resource_schema'>
206
- <rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
207
- </a>
208
- </svg>
209
- OUTPUT
210
- expect(xmlpp(File.read("action_schemaexpg2.svg", encoding: "utf-8").sub(%r{<image .*</image>}m, ""))).to be_equivalent_to <<~OUTPUT
211
- <?xml version='1.0' encoding='UTF-8'?>
212
- <!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
213
- <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' viewBox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve'>
214
- <style type='text/css'> .st0{fill:none;stroke:#000000;stroke-miterlimit:10;} </style>
215
- <a xlink:href='mn://action_schema'>
216
- <rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
217
- </a>
218
- <a xlink:href='http://www.example.com'>
219
- <rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
220
- </a>
221
- <a xlink:href='mn://support_resource_schema'>
222
- <rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
223
- </a>
224
- </svg>
225
- OUTPUT
226
- expect(xmlpp(File.read(Metanorma::Utils.save_dataimage(xmldoc1.at("//image[@alt = 'Workmap1']/@src"))))).to be_equivalent_to <<~OUTPUT
227
- <?xml version='1.0' encoding='UTF-8'?>
228
- <!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
229
- <svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' viewBox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve'>
230
- <style type='text/css'> .st0{fill:none;stroke:#000000;stroke-miterlimit:10;} </style>
231
- <image style='overflow:visible;' width='368' height='315' xlink:href='data:image/gif;base64,R0lGODlhcAE7Aff/AAAAAAAAMwAAZgAAmQAAzAAA/wAzAAAzMwAzZgAzmQAzzAAz/wBmAABmMwBm ZgBmmQBmzABm/wCZAACZMwCZZgCZmQCZzACZ/wDMAADMMwDMZgDMmQDMzADM/wD/AAD/MwD/ZgD/ mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMzADMzMzMzZjMzmTMzzDMz/zNmADNmMzNmZjNmmTNm zDNm/zOZADOZMzOZZjOZmTOZzDOZ/zPMADPMMzPMZjPMmTPMzDPM/zP/ADP/MzP/ZjP/mTP/zDP/ /2YAAGYAM2YAZmYAmWYAzGYA/2YzAGYzM2YzZmYzmWYzzGYz/2ZmAGZmM2ZmZmZmmWZmzGZm/2aZ AGaZM2aZZmaZmWaZzGaZ/2bMAGbMM2bMZmbMmWbMzGbM/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkA M5kAZpkAmZkAzJkA/5kzAJkzM5kzZpkzmZkzzJkz/5lmAJlmM5lmZplmmZlmzJlm/5mZAJmZM5mZ ZpmZmZmZzJmZ/5nMAJnMM5nMZpnMmZnMzJnM/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwAM8wAZswA mcwAzMwA/8wzAMwzM8wzZswzmcwzzMwz/8xmAMxmM8xmZsxmmcxmzMxm/8yZAMyZM8yZZsyZmcyZ zMyZ/8zMAMzMM8zMZszMmczMzMzM/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A //8zAP8zM/8zZv8zmf8zzP8z//9mAP9mM/9mZv9mmf9mzP9m//+ZAP+ZM/+ZZv+Zmf+ZzP+Z///M AP/MM//MZv/Mmf/MzP/M////AP//M///Zv//mf//zP////j4+PLy8uvr6+Xl5d/f39jY2NLS0szM zMXFxb+/v7i4uLKysqysrKWlpZ+fn5mZmZKSkoyMjIWFhX9/f3l5eXJycmxsbGZmZl9fX1lZWVJS UkxMTEZGRj8/Pzk5OTMzMywsLCYmJh8fHxkZGRMTEwwMDAYGBgAAACwAAAAAcAE7AQAI/gCvCRxI sKDBgwgTKlzIsKHDhxAjSpxIsaLFixgzatzIsaPHjyBDihxJsqTJkyhTqlzJsqXLlzBjypxJs6bN mzhz6tzJs6fPn0CDCh1KtKjRo0iTKl3KtKnTp1CjSp1KterIe/+yat3KtavXr2DDih3r9Z7Vs2gp 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' transform='matrix(1 0 0 1 114 263.8898)'> </image>
232
- <a xlink:href='mn://action_schema'>
233
- <rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
234
- </a>
235
- <a xlink:href='http://www.example.com'>
236
- <rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
237
- </a>
238
- <a xlink:href='mn://support_resource_schema'>
239
- <rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
240
- </a>
241
- </svg>
242
- OUTPUT
250
+ OUTPUT
243
251
  end
244
252
 
245
253
  it "rewrites SVGs with namespaces" do
246
- FileUtils.cp "spec/fixtures/action_schemaexpg1.svg", "action_schemaexpg1.svg"
247
- FileUtils.cp "spec/fixtures/action_schemaexpg1.svg", "action_schemaexpg2.svg"
248
- xmldoc = Nokogiri::XML(<<~INPUT)
249
- <standard-document type="semantic" version="1.8.2" xmlns="http://www.example.com">
250
- <bibdata type="standard">
251
- <title language="en" format="text/plain">Document title</title>
252
- <docidentifier/>
253
- <docnumber/>
254
- <version/>
255
- <language>en</language>
256
- <script>Latn</script>
257
- <status>
258
- <stage>published</stage>
259
- </status>
260
- <copyright>
261
- <from>2021</from>
262
- </copyright>
263
- <ext>
264
- <doctype>article</doctype>
265
- </ext>
266
- </bibdata>
267
- <sections>
268
- <svgmap id="_d5b5049a-dd53-4ea0-bc6f-e8773bd59052"><target href="mn://action_schema"><xref target="ref1">Computer</xref></target></svgmap>
269
- <svgmap id="_4072bdcb-5895-4821-b636-5795b96787cb">
270
- <figure><image src="action_schemaexpg1.svg"/></figure>
271
- <target href="mn://action_schema"><xref target="ref1">Computer</xref></target><target href="http://www.example.com"><link target="http://www.example.com">Phone</link></target>
272
- </svgmap>
273
- <svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
274
- <figure><image src="action_schemaexpg2.svg" alt="Workmap"/></figure>
275
- <target href="href1.htm"><xref target="ref1">Computer</xref></target><target href="mn://basic_attribute_schema"><link target="http://www.example.com">Phone</link></target><target href="mn://support_resource_schema"><eref type="express" bibitemid="express_action_schema" citeas=""><localityStack><locality type="anchor"><referenceFrom>action_schema.basic</referenceFrom></locality></localityStack>Coffee</eref></target></svgmap></sections>
276
- </standard-document>
277
- INPUT
278
- Metanorma::Utils.svgmap_rewrite(xmldoc)
279
- expect(xmlpp(xmldoc.to_xml)).to be_equivalent_to xmlpp(<<~OUTPUT)
280
- <standard-document type="semantic" version="1.8.2" xmlns="http://www.example.com">
281
- <bibdata type="standard">
282
- <title language="en" format="text/plain">Document title</title>
283
- <docidentifier/>
284
- <docnumber/>
285
- <version/>
286
- <language>en</language>
287
- <script>Latn</script>
288
- <status>
289
- <stage>published</stage>
290
- </status>
291
- <copyright>
292
- <from>2021</from>
293
- </copyright>
294
- <ext>
295
- <doctype>article</doctype>
296
- </ext>
297
- </bibdata>
298
- <sections><svgmap id="_d5b5049a-dd53-4ea0-bc6f-e8773bd59052"><target href="mn://action_schema"><xref target="ref1">Computer</xref></target></svgmap>
299
- <figure>
300
- <image src='action_schemaexpg1.svg'/>
301
- </figure>
302
- <svgmap id='_60dadf08-48d4-4164-845c-b4e293e00abd'>
303
- <figure>
304
- <image src='action_schemaexpg2.svg' alt='Workmap'/>
305
- </figure>
306
- <target href="mn://support_resource_schema"><eref type="express" bibitemid="express_action_schema" citeas=""><localityStack><locality type="anchor"><referenceFrom>action_schema.basic</referenceFrom></locality></localityStack>Coffee</eref></target></svgmap></sections>
307
- </standard-document>
308
- OUTPUT
254
+ FileUtils.cp "spec/fixtures/action_schemaexpg1.svg",
255
+ "action_schemaexpg1.svg"
256
+ FileUtils.cp "spec/fixtures/action_schemaexpg1.svg",
257
+ "action_schemaexpg2.svg"
258
+ xmldoc = Nokogiri::XML(<<~INPUT)
259
+ <standard-document type="semantic" version="1.8.2" xmlns="http://www.example.com">
260
+ <bibdata type="standard">
261
+ <title language="en" format="text/plain">Document title</title>
262
+ <docidentifier/>
263
+ <docnumber/>
264
+ <version/>
265
+ <language>en</language>
266
+ <script>Latn</script>
267
+ <status>
268
+ <stage>published</stage>
269
+ </status>
270
+ <copyright>
271
+ <from>2021</from>
272
+ </copyright>
273
+ <ext>
274
+ <doctype>article</doctype>
275
+ </ext>
276
+ </bibdata>
277
+ <sections>
278
+ <svgmap id="_d5b5049a-dd53-4ea0-bc6f-e8773bd59052"><target href="mn://action_schema"><xref target="ref1">Computer</xref></target></svgmap>
279
+ <svgmap id="_4072bdcb-5895-4821-b636-5795b96787cb">
280
+ <figure><image src="action_schemaexpg1.svg"/></figure>
281
+ <target href="mn://action_schema"><xref target="ref1">Computer</xref></target><target href="http://www.example.com"><link target="http://www.example.com">Phone</link></target>
282
+ </svgmap>
283
+ <svgmap id="_60dadf08-48d4-4164-845c-b4e293e00abd">
284
+ <figure><image src="action_schemaexpg2.svg" alt="Workmap"/></figure>
285
+ <target href="href1.htm"><xref target="ref1">Computer</xref></target><target href="mn://basic_attribute_schema"><link target="http://www.example.com">Phone</link></target><target href="mn://support_resource_schema"><eref type="express" bibitemid="express_action_schema" citeas=""><localityStack><locality type="anchor"><referenceFrom>action_schema.basic</referenceFrom></locality></localityStack>Coffee</eref></target></svgmap></sections>
286
+ </standard-document>
287
+ INPUT
288
+ Metanorma::Utils.svgmap_rewrite(xmldoc)
289
+ expect(xmlpp(xmldoc.to_xml.gsub(%r{<image.*?</image>}m, "<image/>").gsub(%r{<style.*?</style>}m, "<style/>"))).to be_equivalent_to xmlpp(<<~OUTPUT)
290
+ <standard-document type="semantic" version="1.8.2" xmlns="http://www.example.com">
291
+ <bibdata type="standard">
292
+ <title language="en" format="text/plain">Document title</title>
293
+ <docidentifier/>
294
+ <docnumber/>
295
+ <version/>
296
+ <language>en</language>
297
+ <script>Latn</script>
298
+ <status>
299
+ <stage>published</stage>
300
+ </status>
301
+ <copyright>
302
+ <from>2021</from>
303
+ </copyright>
304
+ <ext>
305
+ <doctype>article</doctype>
306
+ </ext>
307
+ </bibdata>
308
+ <sections><svgmap id="_d5b5049a-dd53-4ea0-bc6f-e8773bd59052"><target href="mn://action_schema"><xref target="ref1">Computer</xref></target></svgmap>
309
+ <figure>
310
+ <?xml version="1.0" encoding="utf-8"??>
311
+ <!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
312
+ <svg xmlns='http://www.w3.org/2000/svg' version='1.1' id='Layer_1' x='0px' y='0px' viewbox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve' xmlns:xlink='http://www.w3.org/1999/xlink'>
313
+ <style/>
314
+ <image/>
315
+ <a xlink:href='#ref1'>
316
+ <rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
317
+ </a>
318
+ <a xlink:href='mn://basic_attribute_schema'>
319
+ <rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
320
+ </a>
321
+ <a xlink:href='mn://support_resource_schema'>
322
+ <rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
323
+ </a>
324
+ </svg>
325
+ </figure>
326
+ <svgmap id='_60dadf08-48d4-4164-845c-b4e293e00abd'>
327
+ <figure>
328
+ <?xml version="1.0" encoding="utf-8"??>
329
+ <!-- Generator: Adobe Illustrator 25.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
330
+ <svg xmlns='http://www.w3.org/2000/svg' version='1.1' id='Layer_1' x='0px' y='0px' viewbox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve' xmlns:xlink='http://www.w3.org/1999/xlink'>
331
+ <style/>
332
+ <image/>
333
+ <a xlink:href='mn://action_schema'>
334
+ <rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
335
+ </a>
336
+ <a xlink:href='http://www.example.com'>
337
+ <rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
338
+ </a>
339
+ <a xlink:href='mn://support_resource_schema'>
340
+ <rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
341
+ </a>
342
+ </svg>
343
+ </figure>
344
+ <target href="mn://support_resource_schema"><eref type="express" bibitemid="express_action_schema" citeas=""><localityStack><locality type="anchor"><referenceFrom>action_schema.basic</referenceFrom></locality></localityStack>Coffee</eref></target></svgmap></sections>
345
+ </standard-document>
346
+ OUTPUT
309
347
  end
310
348
 
311
349
  # not testing Asciidoctor log extraction here
312
350
  it "generates log" do
313
351
  xml = Nokogiri::XML(<<~INPUT)
314
- <xml>
315
- <a>
316
- <b>
317
- c
318
- </b></a></xml>
352
+ <xml>
353
+ <a>
354
+ <b>
355
+ c
356
+ </b></a></xml>
319
357
  INPUT
320
358
  FileUtils.rm_f("log.txt")
321
359
  log = Metanorma::Utils::Log.new
@@ -326,34 +364,34 @@ OUTPUT
326
364
  expect(File.exist?("log.txt")).to be true
327
365
  file = File.read("log.txt", encoding: "utf-8")
328
366
  expect(file).to eq <<~OUTPUT
329
- log.txt errors
367
+ log.txt errors
330
368
 
331
369
 
332
- == Category 1
370
+ == Category 1
333
371
 
334
- (): Message 1
335
- (node): Message 2
372
+ (): Message 1
373
+ (node): Message 2
336
374
 
337
375
 
338
- == Category 2
376
+ == Category 2
339
377
 
340
- (XML Line 000003): Message 3
341
- <b>
342
- c
343
- </b>
378
+ (XML Line 000003): Message 3
379
+ <b>
380
+ c
381
+ </b>
344
382
  OUTPUT
345
383
  end
346
384
 
347
- def datauri(uri, localdir = "")
348
- return uri if /^data:/.match(uri)
349
- path = File.join(localdir, uri)
350
- types = MIME::Types.type_for(path)
351
- type = types ? types.first.to_s : 'text/plain; charset="utf-8"'
352
- bin = File.open(path, 'rb', &:read)
353
- data = Base64.strict_encode64(bin)
354
- "data:#{type};base64,#{data}"
355
- end
385
+ def datauri(uri, localdir = "")
386
+ return uri if /^data:/.match?(uri)
356
387
 
388
+ path = File.join(localdir, uri)
389
+ types = MIME::Types.type_for(path)
390
+ type = types ? types.first.to_s : 'text/plain; charset="utf-8"'
391
+ bin = File.open(path, "rb", &:read)
392
+ data = Base64.strict_encode64(bin)
393
+ "data:#{type};base64,#{data}"
394
+ end
357
395
 
358
396
  it "generates data uris" do
359
397
  expect(Metanorma::Utils.datauri("data:xyz")).to eq "data:xyz"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.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: 2021-03-29 00:00:00.000000000 Z
11
+ date: 2021-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sterile
@@ -295,6 +295,7 @@ files:
295
295
  - bin/rspec
296
296
  - lib/metanorma-utils.rb
297
297
  - lib/utils/hash_transform_keys.rb
298
+ - lib/utils/image.rb
298
299
  - lib/utils/log.rb
299
300
  - lib/utils/main.rb
300
301
  - lib/utils/version.rb