metanorma-utils 1.0.8 → 1.2.2
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 +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +10 -2
- data/lib/metanorma-utils.rb +1 -0
- data/lib/utils/image.rb +177 -0
- data/lib/utils/log.rb +28 -25
- data/lib/utils/main.rb +51 -146
- data/lib/utils/version.rb +1 -1
- data/metanorma-utils.gemspec +3 -2
- data/spec/fixtures/action_schemaexpg1.svg +3 -1
- data/spec/utils_spec.rb +273 -236
- metadata +27 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52b94adefc23d35f664e35438604432f951f29d15ccb5622f64447a79eaa14d0
|
4
|
+
data.tar.gz: 5e68045ce2aaf9c6a34ec8793d8f75b1e3bb065fe4a733db84101f4bee31cf2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5e47154cf50378f9960ddd1f782d3ec35c4c92395d3e74a0f734ad7f77c510c401ad26e46fa4aae96b30784e0263e407e93b6d58daf97070b9f2628a72b57ff
|
7
|
+
data.tar.gz: adec26a807cb648a9b6ad5d6cc3e6251f0b79eba52e1901f99cf102ef61db425bb6ea3e1676e51af1a5d9ab9a0b5aeda1e0c6f071ff48238e2fa103fae0b7d48
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.rubocop-https--*
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
# This project follows the Ribose OSS style guide.
|
2
2
|
# https://github.com/riboseinc/oss-guides
|
3
3
|
# All project-specific additions and overrides should be specified in this file.
|
4
|
-
|
5
4
|
inherit_from:
|
6
|
-
- https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
|
5
|
+
- https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
|
6
|
+
|
7
|
+
# local repo-specific modifications
|
8
|
+
|
9
|
+
AllCops:
|
10
|
+
DisplayCopNames: false
|
11
|
+
StyleGuideCopsOnly: false
|
12
|
+
TargetRubyVersion: 2.4
|
13
|
+
Rails:
|
14
|
+
Enabled: true
|
data/lib/metanorma-utils.rb
CHANGED
data/lib/utils/image.rb
ADDED
@@ -0,0 +1,177 @@
|
|
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_with_index do |s, i|
|
41
|
+
next unless svgmap_rewrite0(s, n, localdirectory, i)
|
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, idx)
|
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.root, namespace, idx))
|
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, idx))
|
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, idx)
|
72
|
+
svg_update_href(svgmap, svg, namespace)
|
73
|
+
svg_update_ids(svg, idx)
|
74
|
+
svg.xpath("processing-instruction()|.//processing-instruction()").remove
|
75
|
+
svg.to_xml
|
76
|
+
end
|
77
|
+
|
78
|
+
def svg_update_href(svgmap, svg, namespace)
|
79
|
+
targ = svgmap_rewrite1_targets(svgmap, namespace)
|
80
|
+
svg.xpath(".//m:a", "m" => SVG_NS).each do |a|
|
81
|
+
["xlink:href", "href"].each do |p|
|
82
|
+
a[p] and x = targ[File.expand_path(a[p])] and a[p] = x
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def svgmap_rewrite1_targets(svgmap, namespace)
|
88
|
+
svgmap.xpath(namespace.ns("./target"))
|
89
|
+
.each_with_object({}) do |t, m|
|
90
|
+
x = t.at(namespace.ns("./xref")) and
|
91
|
+
m[File.expand_path(t["href"])] = "##{x['target']}"
|
92
|
+
x = t.at(namespace.ns("./link")) and
|
93
|
+
m[File.expand_path(t["href"])] = x["target"]
|
94
|
+
t.remove if t.at(namespace.ns("./xref | ./link"))
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def svg_update_ids(svg, idx)
|
99
|
+
ids = svg.xpath("./@id | .//@id")
|
100
|
+
.each_with_object([]) { |i, m| m << i.value }
|
101
|
+
return if ids.empty?
|
102
|
+
|
103
|
+
svg_update_ids_attrs(svg, ids, idx)
|
104
|
+
svg_update_ids_css(svg, ids, idx)
|
105
|
+
end
|
106
|
+
|
107
|
+
def svg_update_ids_attrs(svg, ids, idx)
|
108
|
+
svg.xpath(". | .//*[@*]").each do |a|
|
109
|
+
a.attribute_nodes.each do |x|
|
110
|
+
ids.include?(x.value) and x.value += sprintf("_%09d", idx)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def svg_update_ids_css(svg, ids, idx)
|
116
|
+
svg.xpath("//m:style", "m" => SVG_NS).each do |s|
|
117
|
+
c = s.children.to_xml
|
118
|
+
ids.each do |i|
|
119
|
+
c = c.gsub(%r[##{i}\b], sprintf("#%s_%09d", i, idx))
|
120
|
+
.gsub(%r(\[id\s*=\s*['"]?#{i}['"]?\]), sprintf("[id='%s_%09d']", i, idx))
|
121
|
+
end
|
122
|
+
s.children = c
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# sources/plantuml/plantuml20200524-90467-1iqek5i.png
|
127
|
+
# already includes localdir
|
128
|
+
def datauri(uri, localdirectory = ".")
|
129
|
+
return uri if /^data:/.match?(uri)
|
130
|
+
|
131
|
+
path = datauri_path(uri, localdirectory)
|
132
|
+
return path unless File.exist?(path)
|
133
|
+
|
134
|
+
types = MIME::Types.type_for(path)
|
135
|
+
type = types ? types.first.to_s : 'text/plain; charset="utf-8"'
|
136
|
+
bin = File.open(path, "rb", &:read)
|
137
|
+
data = Base64.strict_encode64(bin)
|
138
|
+
"data:#{type};base64,#{data}"
|
139
|
+
end
|
140
|
+
|
141
|
+
def datauri_path(uri, localdirectory)
|
142
|
+
path = if %r{^([A-Z]:)?/}.match?(uri) then uri
|
143
|
+
else
|
144
|
+
File.exist?(uri) ? uri : File.join(localdirectory, uri)
|
145
|
+
end
|
146
|
+
unless File.exist?(path)
|
147
|
+
warn "image at #{path} not found"
|
148
|
+
return uri
|
149
|
+
end
|
150
|
+
path
|
151
|
+
end
|
152
|
+
|
153
|
+
def datauri2mime(uri)
|
154
|
+
%r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
|
155
|
+
type = nil
|
156
|
+
imgtype = "png" unless /^[a-z0-9]+$/.match? imgtype
|
157
|
+
::Tempfile.open(["imageuri", ".#{imgtype}"]) do |file|
|
158
|
+
type = datauri2mime1(file, imgdata)
|
159
|
+
end
|
160
|
+
[type]
|
161
|
+
end
|
162
|
+
|
163
|
+
def datauri2mime1(file, imgdata)
|
164
|
+
type = nil
|
165
|
+
begin
|
166
|
+
file.binmode
|
167
|
+
file.write(Base64.strict_decode64(imgdata))
|
168
|
+
file.rewind
|
169
|
+
type = Marcel::MimeType.for file
|
170
|
+
ensure
|
171
|
+
file.close!
|
172
|
+
end
|
173
|
+
type
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
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(
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
!
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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(
|
36
|
-
return nil if
|
37
|
-
|
38
|
-
|
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.
|
50
|
+
@log.each_key do |key|
|
46
51
|
f.puts "\n\n== #{key}\n\n"
|
47
|
-
@log[key].
|
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 "mimemagic"
|
6
|
-
require "mime/types"
|
7
|
-
require "base64"
|
8
5
|
|
9
6
|
module Metanorma
|
10
7
|
module Utils
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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(
|
20
|
-
start =
|
21
|
-
ret1 = %r([#{NAMECHAR}#]).match(start)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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? ? "_"
|
28
|
+
node.nil? || node.id.nil? || node.id.empty? ? "_#{uuid}" : node.id
|
31
29
|
end
|
32
30
|
|
33
|
-
def asciidoc_sub(
|
34
|
-
return nil if
|
35
|
-
return "" if
|
36
|
-
|
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? ?
|
45
|
+
docfile.nil? ? "./" : "#{Pathname.new(docfile).parent}/"
|
44
46
|
end
|
45
47
|
|
46
48
|
# TODO needs internationalisation
|
47
|
-
def smartformat(
|
48
|
-
|
49
|
-
gsub(/--/, "—").smart_format.gsub(/</, "<")
|
49
|
+
def smartformat(text)
|
50
|
+
text.gsub(/ --? /, " — ")
|
51
|
+
.gsub(/--/, "—").smart_format.gsub(/</, "<")
|
52
|
+
.gsub(/>/, ">")
|
50
53
|
end
|
51
54
|
|
52
55
|
def endash_date(elem)
|
53
56
|
elem.traverse do |n|
|
54
|
-
|
57
|
+
next unless n.text?
|
58
|
+
|
59
|
+
n.replace(n.text.gsub(/\s+--?\s+/, "–").gsub(/--/, "–"))
|
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)
|
64
|
-
|
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
|
-
|
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) &&
|
94
|
+
if node.respond_to?(:context) &&
|
95
|
+
(node.context == :literal || node.context == :listing)
|
152
96
|
result << x.gsub(/</, "<").gsub(/>/, ">")
|
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 = MimeMagic.by_magic(file)
|
211
|
-
ensure
|
212
|
-
file.close!
|
213
|
-
end
|
214
|
-
type
|
215
|
-
end
|
216
121
|
end
|
217
122
|
end
|
218
123
|
end
|