metanorma-utils 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 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