metanorma-utils 1.6.4 → 1.7.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 +4 -4
- data/Gemfile +1 -3
- data/lib/utils/image.rb +43 -162
- data/lib/utils/log.rb +38 -17
- data/lib/utils/namespace.rb +26 -0
- data/lib/utils/version.rb +1 -1
- data/metanorma-utils.gemspec +1 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d976aa0a315c0de6418c649e96065e3b5f0792a232e55ed9b2a6044ed7257491
|
4
|
+
data.tar.gz: 50829e2e03b2c4da90cbccf7773309c4e6a88dfc5e3eaeb9d93f33608fe36539
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbee4963987764258501a416f9cf662612240b15f53f169fe2f104738d8bda20c83f9fa7a782077e9668b9764ea1ac968a6a155709e0bc4d04bc15f0a8a2507c
|
7
|
+
data.tar.gz: e25371b4a3c0efa083a7086495207fede9ac7c8df0524b49a5951f83557e8367ecbf52de7aea34d0cb73103180acc077e0afe9b6fe964816aa42c49d1cda339f
|
data/Gemfile
CHANGED
data/lib/utils/image.rb
CHANGED
@@ -1,187 +1,68 @@
|
|
1
1
|
require "tempfile"
|
2
2
|
require "marcel"
|
3
3
|
require "base64"
|
4
|
+
require "image_size"
|
5
|
+
require_relative "namespace"
|
4
6
|
|
5
7
|
module Metanorma
|
6
8
|
module Utils
|
7
9
|
class << self
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
path.gsub(%r{/([a-zA-z])}, "/xmlns:\\1")
|
17
|
-
.gsub(%r{::([a-zA-z])}, "::xmlns:\\1")
|
18
|
-
.gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]* ?=)}, "[xmlns:\\1")
|
19
|
-
.gsub(%r{\[([a-zA-z][a-z0-9A-Z@/]*\])}, "[xmlns:\\1")
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def save_dataimage(uri)
|
24
|
-
%r{^data:(?:image|application)/(?<imgtype>[^;]+);(?:charset=[^;]+;)?base64,(?<imgdata>.+)$} =~ uri
|
25
|
-
imgtype.sub!(/\+[a-z0-9]+$/, "") # svg+xml
|
26
|
-
imgtype = "png" unless /^[a-z0-9]+$/.match? imgtype
|
27
|
-
Tempfile.open(["image", ".#{imgtype}"]) do |f|
|
28
|
-
f.binmode
|
29
|
-
f.write(Base64.strict_decode64(imgdata))
|
30
|
-
f.path
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
SVG_NS = "http://www.w3.org/2000/svg".freeze
|
35
|
-
|
36
|
-
def svgmap_rewrite(xmldoc, localdirectory = "")
|
37
|
-
n = Namespace.new(xmldoc)
|
38
|
-
xmldoc.xpath(n.ns("//svgmap")).each_with_index do |s, i|
|
39
|
-
next unless svgmap_rewrite0(s, n, localdirectory, i)
|
40
|
-
next if s.at(n.ns("./target/eref"))
|
41
|
-
|
42
|
-
s.replace(s.at(n.ns("./figure")))
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def svgmap_rewrite0(svgmap, namespace, localdirectory, idx)
|
47
|
-
if (i = svgmap.at(namespace.ns(".//image"))) &&
|
48
|
-
(src = i["src"]) && !src.empty?
|
49
|
-
path = svgmap_rewrite0_path(src, localdirectory)
|
50
|
-
File.file?(path) or return false
|
51
|
-
svg = Nokogiri::XML(File.read(path, encoding: "utf-8"))
|
52
|
-
i.replace(svgmap_rewrite1(svgmap, svg.root, namespace, idx))
|
53
|
-
/^data:/.match(src) and i["src"] = datauri(path)
|
54
|
-
elsif i = svgmap.at(".//m:svg", "m" => SVG_NS)
|
55
|
-
i.replace(svgmap_rewrite1(svgmap, i, namespace, idx))
|
56
|
-
else return false
|
57
|
-
end
|
58
|
-
true
|
10
|
+
def image_resize(img, path, maxheight, maxwidth)
|
11
|
+
s, realsize = get_image_size(img, path)
|
12
|
+
img.name == "svg" && !img["viewBox"] && s[0] && s[1] and
|
13
|
+
img["viewBox"] = "0 0 #{s[0]} #{s[1]}"
|
14
|
+
s, skip = image_dont_resize(s, realsize)
|
15
|
+
skip and return s
|
16
|
+
s = image_size_fillin(s, realsize)
|
17
|
+
image_shrink(s, maxheight, maxwidth)
|
59
18
|
end
|
60
19
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
20
|
+
def image_dont_resize(dim, realsize)
|
21
|
+
dim.nil? and return [[nil, nil], true]
|
22
|
+
realsize.nil? and return [dim, true]
|
23
|
+
dim[0] == nil && dim[1] == nil and return [dim, true]
|
24
|
+
[dim, false]
|
67
25
|
end
|
68
26
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
27
|
+
def image_size_fillin(dim, realsize)
|
28
|
+
dim[1].zero? && !dim[0].zero? and
|
29
|
+
dim[1] = dim[0] * realsize[1] / realsize[0]
|
30
|
+
dim[0].zero? && !dim[1].zero? and
|
31
|
+
dim[0] = dim[1] * realsize[0] / realsize[1]
|
32
|
+
dim
|
74
33
|
end
|
75
34
|
|
76
|
-
def
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
35
|
+
def image_shrink(dim, maxheight, maxwidth)
|
36
|
+
dim[1] > maxheight and
|
37
|
+
dim = [(dim[0] * maxheight / dim[1]).ceil, maxheight]
|
38
|
+
dim[0] > maxwidth and
|
39
|
+
dim = [maxwidth, (dim[1] * maxwidth / dim[0]).ceil]
|
40
|
+
dim
|
83
41
|
end
|
84
42
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
m[File.expand_path(t["href"])] = "##{x['target']}"
|
90
|
-
x = t.at(namespace.ns("./link")) and
|
91
|
-
m[File.expand_path(t["href"])] = x["target"]
|
92
|
-
t.remove if t.at(namespace.ns("./xref | ./link"))
|
93
|
-
end
|
43
|
+
def get_image_size(img, path)
|
44
|
+
realsize = ImageSize.path(path).size
|
45
|
+
s = image_size_interpret(img, realsize || [nil, nil])
|
46
|
+
image_size_zeroes_complete(s, realsize)
|
94
47
|
end
|
95
48
|
|
96
|
-
def
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
svg_update_ids_attrs(svg, ids, idx)
|
102
|
-
svg_update_ids_css(svg, ids, idx)
|
49
|
+
def image_size_interpret(img, realsize)
|
50
|
+
w = image_size_percent(img["width"], realsize[0])
|
51
|
+
h = image_size_percent(img["height"], realsize[1])
|
52
|
+
[w, h]
|
103
53
|
end
|
104
54
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
end
|
110
|
-
end
|
55
|
+
def image_size_percent(value, real)
|
56
|
+
/%$/.match?(value) && !real.nil? and
|
57
|
+
value = real * (value.sub(/%$/, "").to_f / 100)
|
58
|
+
value.to_i
|
111
59
|
end
|
112
60
|
|
113
|
-
def
|
114
|
-
|
115
|
-
|
116
|
-
ids.each do |i|
|
117
|
-
c = c.gsub(%r[##{i}\b],
|
118
|
-
sprintf("#%<id>s_%<idx>09d", id: i, idx: idx))
|
119
|
-
.gsub(%r(\[id\s*=\s*['"]?#{i}['"]?\]),
|
120
|
-
sprintf("[id='%<id>s_%<idx>09d']", id: i, idx: idx))
|
121
|
-
end
|
122
|
-
s.children = c
|
61
|
+
def image_size_zeroes_complete(dim, realsize)
|
62
|
+
if dim[0].zero? && dim[1].zero?
|
63
|
+
dim = realsize
|
123
64
|
end
|
124
|
-
|
125
|
-
|
126
|
-
# sources/plantuml/plantuml20200524-90467-1iqek5i.png
|
127
|
-
# already includes localdir
|
128
|
-
# Check whether just the local path or the other specified relative path
|
129
|
-
# works.
|
130
|
-
def datauri(uri, local_dir = ".")
|
131
|
-
(datauri?(uri) || url?(uri)) and return uri
|
132
|
-
options = absolute_path?(uri) ? [uri] : [uri, File.join(local_dir, uri)]
|
133
|
-
path = options.detect do |p|
|
134
|
-
File.exist?(p) ? p : nil
|
135
|
-
end
|
136
|
-
path and return encode_datauri(path)
|
137
|
-
warn "Image specified at `#{uri}` does not exist."
|
138
|
-
uri # Return original provided location
|
139
|
-
end
|
140
|
-
|
141
|
-
def encode_datauri(path)
|
142
|
-
return nil unless File.exist?(path)
|
143
|
-
|
144
|
-
type = Marcel::MimeType.for(Pathname.new(path)) ||
|
145
|
-
'text/plain; charset="utf-8"'
|
146
|
-
|
147
|
-
bin = File.binread(path)
|
148
|
-
data = Base64.strict_encode64(bin)
|
149
|
-
"data:#{type};base64,#{data}"
|
150
|
-
rescue StandardError
|
151
|
-
warn "Data-URI encoding of `#{path}` failed."
|
152
|
-
nil
|
153
|
-
end
|
154
|
-
|
155
|
-
def datauri?(uri)
|
156
|
-
/^data:/.match?(uri)
|
157
|
-
end
|
158
|
-
|
159
|
-
def url?(url)
|
160
|
-
%r{^[A-Z]{2,}://}i.match?(url)
|
161
|
-
end
|
162
|
-
|
163
|
-
def absolute_path?(uri)
|
164
|
-
%r{^/}.match?(uri) || %r{^[A-Z]:/}.match?(uri)
|
165
|
-
end
|
166
|
-
|
167
|
-
def decode_datauri(uri)
|
168
|
-
%r{^data:(?<mimetype>[^;]+);base64,(?<mimedata>.+)$} =~ uri
|
169
|
-
return nil unless mimetype && mimedata
|
170
|
-
|
171
|
-
data = Base64.strict_decode64(mimedata)
|
172
|
-
{
|
173
|
-
type_declared: mimetype,
|
174
|
-
type_detected: Marcel::MimeType.for(data, declared_type: mimetype),
|
175
|
-
data: data,
|
176
|
-
}
|
177
|
-
end
|
178
|
-
|
179
|
-
# FIXME: This method should ONLY return 1 type, remove Array wrapper
|
180
|
-
def datauri2mime(uri)
|
181
|
-
output = decode_datauri(uri)
|
182
|
-
return nil unless output && output[:type_detected]
|
183
|
-
|
184
|
-
[output[:type_detected]]
|
65
|
+
[dim, realsize]
|
185
66
|
end
|
186
67
|
end
|
187
68
|
end
|
data/lib/utils/log.rb
CHANGED
@@ -11,23 +11,32 @@ module Metanorma
|
|
11
11
|
@mapid = {}
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
# severity: 0: abort; 1: serious; 2: not serious
|
15
|
+
def add(category, loc, msg, severity: 2)
|
15
16
|
@novalid and return
|
16
17
|
@log[category] ||= []
|
17
|
-
item = create_entry(loc, msg)
|
18
|
+
item = create_entry(loc, msg, severity)
|
18
19
|
@log[category] << item
|
19
20
|
loc = loc.nil? ? "" : "(#{current_location(loc)}): "
|
20
21
|
suppress_display?(category, loc, msg) or
|
21
22
|
warn "#{category}: #{loc}#{msg}"
|
22
23
|
end
|
23
24
|
|
25
|
+
def abort_messages
|
26
|
+
@log.values.each_with_object([]) do |v, m|
|
27
|
+
v.each do |e|
|
28
|
+
e[:severity].zero? and m << e[:message]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
24
33
|
def suppress_display?(category, _loc, _msg)
|
25
34
|
["Metanorma XML Syntax"].include?(category)
|
26
35
|
end
|
27
36
|
|
28
|
-
def create_entry(loc, msg)
|
37
|
+
def create_entry(loc, msg, severity)
|
29
38
|
msg = msg.encode("UTF-8", invalid: :replace, undef: :replace)
|
30
|
-
item = { location: current_location(loc),
|
39
|
+
item = { location: current_location(loc), severity: severity,
|
31
40
|
message: msg, context: context(loc), line: line(loc, msg) }
|
32
41
|
if item[:message].include?(" :: ")
|
33
42
|
a = item[:message].split(" :: ", 2)
|
@@ -101,7 +110,11 @@ module Metanorma
|
|
101
110
|
<<~HTML
|
102
111
|
<html><head><title>#{file} errors</title>
|
103
112
|
<meta charset="UTF-8"/>
|
104
|
-
<style> pre { white-space: pre-wrap; }
|
113
|
+
<style> pre { white-space: pre-wrap; }
|
114
|
+
thead th { font-weight: bold; background-color: aqua; }
|
115
|
+
.severity0 { font-weight: bold; background-color: lightpink }
|
116
|
+
.severity1 { font-weight: bold; }
|
117
|
+
.severity2 { } </style>
|
105
118
|
</head><body><h1>#{file} errors</h1>
|
106
119
|
HTML
|
107
120
|
end
|
@@ -118,25 +131,31 @@ module Metanorma
|
|
118
131
|
def write_key(file, key)
|
119
132
|
file.puts <<~HTML
|
120
133
|
<h2>#{key}</h2>\n<table border="1">
|
121
|
-
<thead><th width="5%">Line</th><th width="20%">ID</th
|
134
|
+
<thead><th width="5%">Line</th><th width="20%">ID</th>
|
135
|
+
<th width="30%">Message</th><th width="40%">Context</th><th width="5%">Severity</th></thead>
|
122
136
|
<tbody>
|
123
137
|
HTML
|
124
138
|
@log[key].sort_by { |a| [a[:line], a[:location], a[:message]] }
|
125
139
|
.each do |n|
|
126
|
-
|
140
|
+
write_entry(file, render_preproc_entry(n))
|
127
141
|
end
|
128
142
|
file.puts "</tbody></table>\n"
|
129
143
|
end
|
130
144
|
|
131
|
-
def
|
132
|
-
|
133
|
-
line = nil if line == "000000"
|
134
|
-
|
135
|
-
|
145
|
+
def render_preproc_entry(entry)
|
146
|
+
ret = entry.dup
|
147
|
+
ret[:line] = nil if ret[:line] == "000000"
|
148
|
+
ret[:location] = loc_link(entry)
|
149
|
+
ret[:message] = break_up_long_str(entry[:message], 10, 2)
|
136
150
|
.gsub(/`([^`]+)`/, "<code>\\1</code>")
|
137
|
-
|
151
|
+
ret[:context] = context_render(entry)
|
152
|
+
ret.compact
|
153
|
+
end
|
154
|
+
|
155
|
+
def context_render(entry)
|
156
|
+
entry[:context] or return nil
|
157
|
+
entry[:context].split("\n").first(5)
|
138
158
|
.join("\n").gsub("><", "> <")
|
139
|
-
write_entry(file, line, loc, msg, context)
|
140
159
|
end
|
141
160
|
|
142
161
|
def mapid(old, new)
|
@@ -160,10 +179,12 @@ module Metanorma
|
|
160
179
|
Metanorma::Utils.break_up_long_str(str, threshold, punct)
|
161
180
|
end
|
162
181
|
|
163
|
-
def write_entry(file,
|
164
|
-
context &&= @c.encode(break_up_long_str(context, 40, 2))
|
182
|
+
def write_entry(file, entry)
|
183
|
+
entry[:context] &&= @c.encode(break_up_long_str(entry[:context], 40, 2))
|
165
184
|
file.print <<~HTML
|
166
|
-
<tr
|
185
|
+
<tr class="severity#{entry[:severity]}">
|
186
|
+
<td>#{entry[:line]}</td><th><code>#{entry[:location]}</code></th>
|
187
|
+
<td>#{entry[:message]}</td><td><pre>#{entry[:context]}</pre></td><td>#{entry[:severity]}</td></tr>
|
167
188
|
HTML
|
168
189
|
end
|
169
190
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Metanorma
|
2
|
+
module Utils
|
3
|
+
class << self
|
4
|
+
# NOTE: It was used in methods of an eigenclass of Metanorma::Utils.
|
5
|
+
# Not sure if it's still used somewhere but could be.
|
6
|
+
class Namespace
|
7
|
+
def initialize(xmldoc)
|
8
|
+
@namespace = xmldoc.root.namespace
|
9
|
+
end
|
10
|
+
|
11
|
+
def ns(path)
|
12
|
+
return path if @namespace.nil?
|
13
|
+
|
14
|
+
path.gsub(%r{/([a-zA-Z])}, "/xmlns:\\1")
|
15
|
+
.gsub(%r{::([a-zA-Z])}, "::xmlns:\\1")
|
16
|
+
.gsub(%r{\[([a-zA-Z][a-z0-9A-Z@/]* ?=)}, "[xmlns:\\1")
|
17
|
+
.gsub(%r{\[([a-zA-Z][a-z0-9A-Z@/]*\])}, "[xmlns:\\1")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_namespace(xmldoc)
|
22
|
+
Namespace.new(xmldoc)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/utils/version.rb
CHANGED
data/metanorma-utils.gemspec
CHANGED
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_dependency "concurrent-ruby"
|
31
31
|
spec.add_dependency "csv"
|
32
32
|
spec.add_dependency "htmlentities", "~> 4.3.4"
|
33
|
+
spec.add_dependency "image_size", ">= 3.2.0"
|
33
34
|
spec.add_dependency "marcel", "~> 1.0.0"
|
34
35
|
spec.add_dependency "mime-types"
|
35
36
|
spec.add_dependency "nokogiri", ">= 1.11"
|
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.
|
4
|
+
version: 1.7.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:
|
11
|
+
date: 2024-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciidoctor
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 4.3.4
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: image_size
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.2.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.2.0
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: marcel
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -324,6 +338,7 @@ files:
|
|
324
338
|
- lib/utils/image.rb
|
325
339
|
- lib/utils/log.rb
|
326
340
|
- lib/utils/main.rb
|
341
|
+
- lib/utils/namespace.rb
|
327
342
|
- lib/utils/version.rb
|
328
343
|
- lib/utils/xml.rb
|
329
344
|
- metanorma-utils.gemspec
|