metanorma-utils 1.2.9 → 1.3.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/lib/metanorma-utils.rb +1 -0
- data/lib/utils/hash_transform_keys.rb +16 -0
- data/lib/utils/main.rb +44 -49
- data/lib/utils/version.rb +1 -1
- data/lib/utils/xml.rb +66 -0
- data/spec/hash_transform_keys_spec.rb +7 -0
- data/spec/img_spec.rb +297 -0
- data/spec/utils_spec.rb +82 -307
- data/spec/xml_spec.rb +75 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb766833ae078338bdac8e0954736f83dfc5feee9de6cbc15c03bd1998848529
|
4
|
+
data.tar.gz: 93ee70fa9e268f252c5c9c3f5dd58e2859c2b794b13d50e117f374ae8e80efde
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8572ae07eb6b970d0b00c1289b0652c293690b241b4d39a91b4df235a77ef29809dba122be75795bd7f8bde1fcebd59deeee9cb4f001259675626f73e0cd5869
|
7
|
+
data.tar.gz: 63f761a6ada0d87f7663811b89f594eb23dafb9d9da9c130d158bd58671648fc5b6cd8a3ed9db895345b1267e3c02141937bda7141e414971dabafa9ec93bbaa
|
data/lib/metanorma-utils.rb
CHANGED
@@ -48,4 +48,20 @@ class Hash
|
|
48
48
|
end
|
49
49
|
result
|
50
50
|
end
|
51
|
+
|
52
|
+
def deep_merge(second)
|
53
|
+
merger = proc { |_, v1, v2|
|
54
|
+
if Hash === v1 && Hash === v2
|
55
|
+
v1.merge(v2, &merger)
|
56
|
+
elsif Array === v1 && Array === v2
|
57
|
+
v1 | v2
|
58
|
+
elsif [:undefined, nil,
|
59
|
+
:nil].include?(v2)
|
60
|
+
v1
|
61
|
+
else
|
62
|
+
v2
|
63
|
+
end
|
64
|
+
}
|
65
|
+
merge(second.to_h, &merger)
|
66
|
+
end
|
51
67
|
end
|
data/lib/utils/main.rb
CHANGED
@@ -1,34 +1,35 @@
|
|
1
1
|
require "asciidoctor"
|
2
2
|
require "tempfile"
|
3
3
|
require "sterile"
|
4
|
-
require "uuidtools"
|
5
4
|
require "htmlentities"
|
5
|
+
require "nokogiri"
|
6
6
|
|
7
7
|
module Metanorma
|
8
8
|
module Utils
|
9
|
-
NAMECHAR = "\u0000-\u002c\u002f\u003a-\u0040\\u005b-\u005e"\
|
10
|
-
"\u0060\u007b-\u00b6\u00b8-\u00bf\u00d7\u00f7\u037e"\
|
11
|
-
"\u2000-\u200b"\
|
12
|
-
"\u200e-\u203e\u2041-\u206f\u2190-\u2bff\u2ff0-\u3000".freeze
|
13
|
-
NAMESTARTCHAR = "\\u002d\u002e\u0030-\u0039\u00b7\u0300-\u036f"\
|
14
|
-
"\u203f-\u2040".freeze
|
15
|
-
|
16
9
|
class << self
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
"_"
|
22
|
-
else
|
23
|
-
(%r([#{NAMESTARTCHAR}#])o.match?(start) ? "_#{start}" : start)
|
24
|
-
end
|
25
|
-
ret2 = tag[1..-1] || ""
|
26
|
-
(ret1 || "") + ret2.gsub(%r([#{NAMECHAR}#])o, "_")
|
10
|
+
def attr_code(attributes)
|
11
|
+
attributes.compact.transform_values do |v|
|
12
|
+
v.is_a?(String) ? HTMLEntities.new.decode(v) : v
|
13
|
+
end
|
27
14
|
end
|
28
15
|
|
29
|
-
|
30
|
-
|
31
|
-
|
16
|
+
# , " => ," : CSV definition does not deal with space followed by quote
|
17
|
+
# at start of field
|
18
|
+
def csv_split(text, delim = ";")
|
19
|
+
return if text.nil?
|
20
|
+
|
21
|
+
CSV.parse_line(text&.gsub(/#{delim} "(?!")/, "#{delim}\""),
|
22
|
+
liberal_parsing: true,
|
23
|
+
col_sep: delim)&.compact&.map(&:strip)
|
24
|
+
end
|
25
|
+
|
26
|
+
# if the contents of node are blocks, output them to out;
|
27
|
+
# else, wrap them in <p>
|
28
|
+
def wrap_in_para(node, out)
|
29
|
+
if node.blocks? then out << node.content
|
30
|
+
else
|
31
|
+
out.p { |p| p << node.content }
|
32
|
+
end
|
32
33
|
end
|
33
34
|
|
34
35
|
def asciidoc_sub(text, flavour = :standoc)
|
@@ -140,35 +141,29 @@ module Metanorma
|
|
140
141
|
%w(Arab Aran Hebr).include? script
|
141
142
|
end
|
142
143
|
|
143
|
-
#
|
144
|
-
def
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
# not currently used
|
158
|
-
# if node contains blocks, flatten them into a single line;
|
159
|
-
# and extract only raw text
|
160
|
-
def flatten_rawtext(node)
|
161
|
-
result = []
|
162
|
-
if node.respond_to?(:blocks) && node.blocks?
|
163
|
-
node.blocks.each { |b| result << flatten_rawtext(b) }
|
164
|
-
elsif node.respond_to?(:lines)
|
165
|
-
result = flatten_rawtext_lines(node, result)
|
166
|
-
elsif node.respond_to?(:text)
|
167
|
-
result << node.text.gsub(/<[^>]*>+/, "")
|
168
|
-
else
|
169
|
-
result << node.content.gsub(/<[^>]*>+/, "")
|
144
|
+
# convert definition list term/value pair into Nokogiri XML attribute
|
145
|
+
def dl_to_attrs(elem, dlist, name)
|
146
|
+
e = dlist.at("./dt[text()='#{name}']") or return
|
147
|
+
val = e.at("./following::dd/p") || e.at("./following::dd") or return
|
148
|
+
elem[name] = val.text
|
149
|
+
end
|
150
|
+
|
151
|
+
# convert definition list term/value pairs into Nokogiri XML elements
|
152
|
+
def dl_to_elems(ins, elem, dlist, name)
|
153
|
+
a = elem.at("./#{name}[last()]")
|
154
|
+
ins = a if a
|
155
|
+
dlist.xpath("./dt[text()='#{name}']").each do |e|
|
156
|
+
ins = dl_to_elems1(e, name, ins)
|
170
157
|
end
|
171
|
-
|
158
|
+
ins
|
159
|
+
end
|
160
|
+
|
161
|
+
def dl_to_elems1(term, name, ins)
|
162
|
+
v = term.at("./following::dd")
|
163
|
+
e = v.elements and e.size == 1 && e.first.name == "p" and v = e.first
|
164
|
+
v.name = name
|
165
|
+
ins.next = v
|
166
|
+
ins.next
|
172
167
|
end
|
173
168
|
end
|
174
169
|
end
|
data/lib/utils/version.rb
CHANGED
data/lib/utils/xml.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require "asciidoctor"
|
2
|
+
require "tempfile"
|
3
|
+
require "uuidtools"
|
4
|
+
require "htmlentities"
|
5
|
+
require "nokogiri"
|
6
|
+
|
7
|
+
module Metanorma
|
8
|
+
module Utils
|
9
|
+
NAMECHAR = "\u0000-\u002c\u002f\u003a-\u0040\\u005b-\u005e"\
|
10
|
+
"\u0060\u007b-\u00b6\u00b8-\u00bf\u00d7\u00f7\u037e"\
|
11
|
+
"\u2000-\u200b"\
|
12
|
+
"\u200e-\u203e\u2041-\u206f\u2190-\u2bff\u2ff0-\u3000".freeze
|
13
|
+
NAMESTARTCHAR = "\\u002d\u002e\u0030-\u0039\u00b7\u0300-\u036f"\
|
14
|
+
"\u203f-\u2040".freeze
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def to_ncname(tag, asciionly: true)
|
18
|
+
asciionly and tag = HTMLEntities.new.encode(tag, :basic, :hexadecimal)
|
19
|
+
start = tag[0]
|
20
|
+
ret1 = if %r([#{NAMECHAR}#])o.match?(start)
|
21
|
+
"_"
|
22
|
+
else
|
23
|
+
(%r([#{NAMESTARTCHAR}#])o.match?(start) ? "_#{start}" : start)
|
24
|
+
end
|
25
|
+
ret2 = tag[1..-1] || ""
|
26
|
+
(ret1 || "") + ret2.gsub(%r([#{NAMECHAR}#])o, "_")
|
27
|
+
end
|
28
|
+
|
29
|
+
def anchor_or_uuid(node = nil)
|
30
|
+
uuid = UUIDTools::UUID.random_create
|
31
|
+
node.nil? || node.id.nil? || node.id.empty? ? "_#{uuid}" : node.id
|
32
|
+
end
|
33
|
+
|
34
|
+
NOKOHEAD = <<~HERE.freeze
|
35
|
+
<!DOCTYPE html SYSTEM
|
36
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
37
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
38
|
+
<head> <title></title> <meta charset="UTF-8" /> </head>
|
39
|
+
<body> </body> </html>
|
40
|
+
HERE
|
41
|
+
|
42
|
+
# block for processing XML document fragments as XHTML,
|
43
|
+
# to allow for HTMLentities
|
44
|
+
# Unescape special chars used in Asciidoctor substitution processing
|
45
|
+
def noko(&block)
|
46
|
+
doc = ::Nokogiri::XML.parse(NOKOHEAD)
|
47
|
+
fragment = doc.fragment("")
|
48
|
+
::Nokogiri::XML::Builder.with fragment, &block
|
49
|
+
fragment.to_xml(encoding: "US-ASCII", indent: 0,
|
50
|
+
save_with: Nokogiri::XML::Node::SaveOptions::AS_XML)
|
51
|
+
.lines.map do |l|
|
52
|
+
l.gsub(/>\n$/, ">").gsub(/\s*\n$/m, " ").gsub("–", "\u0096")
|
53
|
+
.gsub("—", "\u0097").gsub("–", "\u0096")
|
54
|
+
.gsub("—", "\u0097")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def ns(xpath)
|
59
|
+
xpath.gsub(%r{/([a-zA-z])}, "/xmlns:\\1")
|
60
|
+
.gsub(%r{::([a-zA-z])}, "::xmlns:\\1")
|
61
|
+
.gsub(%r{\[([a-zA-z][a-z0-9A-Z@/-]* ?=)}, "[xmlns:\\1")
|
62
|
+
.gsub(%r{\[([a-zA-z][a-z0-9A-Z@/-]*[/\[\]])}, "[xmlns:\\1")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -49,4 +49,11 @@ RSpec.describe Metanorma::Utils do
|
|
49
49
|
expect(result[:test4][0]).to include(:test41)
|
50
50
|
expect(result[:test4][0][:test41]).to eq("test41")
|
51
51
|
end
|
52
|
+
|
53
|
+
it "deep merges hashes" do
|
54
|
+
hash1 = { a: [1, 2], b: "c", c: 4, e: { f: { g: "1" } } }
|
55
|
+
hash2 = { a: [3], b: "d", d: 5, e: { f: { h: "2" } } }
|
56
|
+
expect(hash1.deep_merge(hash2)).to eq({ a: [1, 2, 3], b: "d", c: 4,
|
57
|
+
d: 5, e: { f: { g: "1", h: "2" } } })
|
58
|
+
end
|
52
59
|
end
|