xml-mixup 0.1.13 → 0.1.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/xml/mixup/version.rb +1 -1
- data/lib/xml/mixup.rb +79 -71
- data/xml-mixup.gemspec +5 -5
- metadata +17 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83154ccf54f91484833c4f3b6990bce856635bc95864eeae11edb5b791d1118c
|
4
|
+
data.tar.gz: 6cc3737aedbaf7b5c9c04dc621b003c3047b6f86c16f9ab954da4a5bb4c774d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4591665e4d05cbe1b5d3d638f37f54d5e39a8ff79f4037814783c954cdeebb7809f4f3890f481148f4ff24c7a42d981df97b0d361965f078ba5b1f5f49876de
|
7
|
+
data.tar.gz: 7fe10c1db99f7fdf143f7fb49b20cdf68b4c157758c72cfb31cd8ba71cbbbad4647b574e3353c61ea9bd4169b2f9d8b2000c27d3b1f28a667929f8fd62f7ac56
|
data/lib/xml/mixup/version.rb
CHANGED
data/lib/xml/mixup.rb
CHANGED
@@ -5,7 +5,7 @@ require 'set'
|
|
5
5
|
module XML::Mixup
|
6
6
|
# these are node attachment protocols
|
7
7
|
private
|
8
|
-
|
8
|
+
|
9
9
|
ADJACENT = {
|
10
10
|
parent: lambda do |node, parent|
|
11
11
|
if parent.node_type == 9 and node.node_type == 1
|
@@ -28,8 +28,64 @@ module XML::Mixup
|
|
28
28
|
RESERVED = Set.new(%w{comment cdata doctype dtd elem element
|
29
29
|
pi processing-instruction tag}.map {|x| "##{x}"}).freeze
|
30
30
|
|
31
|
+
ATOMS = [String, Symbol, Numeric, FalseClass, TrueClass].freeze
|
32
|
+
|
33
|
+
def element tag, doc: nil, ns: {}, attr: {}, args: []
|
34
|
+
raise 'Document node must be present' unless doc
|
35
|
+
pfx = nil
|
36
|
+
if tag.respond_to? :to_a
|
37
|
+
pfx = tag[0]
|
38
|
+
tag = tag.to_a[0..1].join ':'
|
39
|
+
elsif m = tag.match(/([^:]+):/)
|
40
|
+
pfx = m[1]
|
41
|
+
end
|
42
|
+
|
43
|
+
elem = doc.create_element tag.to_s
|
44
|
+
elem.default_namespace = ns[pfx] if ns[pfx]
|
45
|
+
|
46
|
+
ns.keys.sort { |a, b| a.to_s <=> b.to_s }.each do |p|
|
47
|
+
elem.add_namespace((p.nil? ? p : p.to_s), ns[p].to_s)
|
48
|
+
end
|
49
|
+
attr.sort.each do |k, v|
|
50
|
+
v = flatten_attr(v, args) or next
|
51
|
+
elem[k.to_s] = v
|
52
|
+
end
|
53
|
+
|
54
|
+
elem
|
55
|
+
end
|
56
|
+
|
31
57
|
public
|
32
58
|
|
59
|
+
# Returns a string suitable for an XML attribute.
|
60
|
+
#
|
61
|
+
# @param obj [Object] the object to be flattened
|
62
|
+
# @param args [Array, nil] callback arguments
|
63
|
+
#
|
64
|
+
# @return [String] the attribute in question.
|
65
|
+
#
|
66
|
+
def flatten_attr obj, args
|
67
|
+
return if obj.nil?
|
68
|
+
# early bailout for most likely condition
|
69
|
+
if ATOMS.any? { |x| obj.is_a? x }
|
70
|
+
obj.to_s
|
71
|
+
elsif obj.is_a? Hash
|
72
|
+
tmp = obj.sort.map do |kv|
|
73
|
+
v = flatten_attr kv[1], args
|
74
|
+
v.nil? ? nil : "#{kv[0].to_s}: #{v}"
|
75
|
+
end.compact
|
76
|
+
tmp.empty? ? nil : tmp.join(' ')
|
77
|
+
elsif obj.respond_to? :call
|
78
|
+
flatten_attr obj.call(*args), args
|
79
|
+
elsif obj.respond_to? :map
|
80
|
+
tmp = obj.map { |x| flatten_attr x, args }.reject do |x|
|
81
|
+
x.nil? || x == ''
|
82
|
+
end
|
83
|
+
tmp.empty? ? nil : tmp.join(' ')
|
84
|
+
else
|
85
|
+
obj.to_s
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
33
89
|
# Generate a handy blank document.
|
34
90
|
#
|
35
91
|
# @param version [Numeric, nil]
|
@@ -48,6 +104,8 @@ module XML::Mixup
|
|
48
104
|
# include XML::Mixup
|
49
105
|
# end
|
50
106
|
#
|
107
|
+
# # note you can now also just call XML::Mixup.markup
|
108
|
+
#
|
51
109
|
# something = Anything.new
|
52
110
|
#
|
53
111
|
# # generate a structure
|
@@ -70,18 +128,18 @@ module XML::Mixup
|
|
70
128
|
# # case, it will be a text node containing 'lolwut'.
|
71
129
|
#
|
72
130
|
# doc = node.document
|
73
|
-
# puts doc.to_xml
|
131
|
+
# puts doc.to_xml
|
74
132
|
#
|
75
133
|
# @param spec [Hash, Array, Nokogiri::XML::Node, Proc, #to_s] An XML
|
76
134
|
# tree specification. May be composed of multiple hashes and
|
77
135
|
# arrays. See the spec spec.
|
78
|
-
#
|
136
|
+
#
|
79
137
|
# @param doc [Nokogiri::XML::Document, nil] an optional XML document
|
80
|
-
# instance; will be
|
138
|
+
# instance; will be created if none given.
|
81
139
|
#
|
82
140
|
# @param args [#to_a] Any arguments to be passed to any callbacks
|
83
141
|
# anywhere in the spec. Assumed to be an array.
|
84
|
-
#
|
142
|
+
#
|
85
143
|
# @param parent [Nokogiri::XML::Node] The node under which the
|
86
144
|
# evaluation result of the spec is to be attached. This is the
|
87
145
|
# default adjacent node, which in turn defaults to the document if
|
@@ -168,7 +226,7 @@ module XML::Mixup
|
|
168
226
|
x = x.to_a
|
169
227
|
name = x.shift
|
170
228
|
children = x
|
171
|
-
else
|
229
|
+
else
|
172
230
|
name = x
|
173
231
|
end
|
174
232
|
elsif (compact = spec.select { |k, _| k.respond_to?(:to_a) or
|
@@ -177,10 +235,10 @@ module XML::Mixup
|
|
177
235
|
raise %q{Spec can't have duplicate compact keys} if compact.count > 1
|
178
236
|
children, name = compact.first
|
179
237
|
children = children.is_a?(Hash) ||
|
180
|
-
children.is_a?(Nokogiri::XML::Node) ? [children] : children.to_a
|
238
|
+
children.is_a?(Nokogiri::XML::Node) ? [children] : children.to_a
|
181
239
|
elsif (special = spec.select { |k, _| k.respond_to? :to_s and
|
182
240
|
k.to_s.start_with? ?# }) and !special.empty?
|
183
|
-
# these are special keys
|
241
|
+
# these are special keys
|
184
242
|
raise %q{Spec can't have multiple special keys} if special.count > 1
|
185
243
|
name, children = special.first
|
186
244
|
|
@@ -200,7 +258,7 @@ module XML::Mixup
|
|
200
258
|
|
201
259
|
# don't forget to reset the child nodes
|
202
260
|
children = children.is_a?(Hash) || !children.respond_to?(:to_a) ?
|
203
|
-
[children] : children.to_a
|
261
|
+
[children] : children.to_a
|
204
262
|
end
|
205
263
|
|
206
264
|
# note the name can be nil because it can be inferred
|
@@ -214,7 +272,7 @@ module XML::Mixup
|
|
214
272
|
# now we dispatch based on the name
|
215
273
|
if name == '#comment'
|
216
274
|
# first up, comments
|
217
|
-
node = doc.create_comment
|
275
|
+
node = doc.create_comment flatten_attr(children, args).to_s
|
218
276
|
|
219
277
|
# attach it
|
220
278
|
ADJACENT[adj].call node, nodes[adj]
|
@@ -228,14 +286,14 @@ module XML::Mixup
|
|
228
286
|
content = ''
|
229
287
|
if (c = children[1..children.length]) and c.length > 0
|
230
288
|
#warn c.inspect
|
231
|
-
content =
|
289
|
+
content = flatten_attr(c, args).to_s
|
232
290
|
else
|
233
291
|
content = attr.sort.map { |pair|
|
234
|
-
v =
|
292
|
+
v = flatten_attr(pair[1], args) or next
|
235
293
|
"#{pair[0].to_s}=\"#{v}\""
|
236
294
|
}.compact.join(' ')
|
237
295
|
end
|
238
|
-
|
296
|
+
|
239
297
|
node = Nokogiri::XML::ProcessingInstruction.new(doc, target, content)
|
240
298
|
|
241
299
|
#warn node.inspect, content
|
@@ -271,14 +329,14 @@ module XML::Mixup
|
|
271
329
|
#ADJACENT[adj].call node, nodes[adj]
|
272
330
|
elsif name == '#cdata'
|
273
331
|
# let's not forget cdata sections
|
274
|
-
node = doc.create_cdata
|
332
|
+
node = doc.create_cdata flatten_attr(children, args)
|
275
333
|
# attach it
|
276
334
|
ADJACENT[adj].call node, nodes[adj]
|
277
335
|
|
278
336
|
else
|
279
337
|
# finally, an element
|
280
338
|
|
281
|
-
raise
|
339
|
+
raise "Element name inference NOT IMPLEMENTED: #{spec}" unless name
|
282
340
|
|
283
341
|
# first check the name
|
284
342
|
prefix = local = nil
|
@@ -292,7 +350,7 @@ module XML::Mixup
|
|
292
350
|
at = {}
|
293
351
|
attr.each do |k, v|
|
294
352
|
k = k.to_s
|
295
|
-
v =
|
353
|
+
v = flatten_attr(v, args) or next
|
296
354
|
if (md = /^xmlns(?::(.*))?$/i.match(k))
|
297
355
|
ns[md[1]] = v
|
298
356
|
else
|
@@ -335,7 +393,7 @@ module XML::Mixup
|
|
335
393
|
# generate the node
|
336
394
|
node = element name, doc: doc, ns: ns, attr: at, args: args
|
337
395
|
|
338
|
-
# attach it
|
396
|
+
# attach it
|
339
397
|
ADJACENT[adj].call node, nodes[adj]
|
340
398
|
|
341
399
|
# don't forget the children!
|
@@ -375,7 +433,7 @@ module XML::Mixup
|
|
375
433
|
#
|
376
434
|
# @param prefix [Hash] the contents of the root node's +prefix=+
|
377
435
|
# and +xmlns:*+ attributes.
|
378
|
-
#
|
436
|
+
#
|
379
437
|
# @param vocab [#to_s] the contents of the root node's +vocab=+.
|
380
438
|
#
|
381
439
|
# @param lang [#to_s] the contents of +lang=+ and when applicable,
|
@@ -425,7 +483,7 @@ module XML::Mixup
|
|
425
483
|
# namespaces. Defaults to +true+.
|
426
484
|
#
|
427
485
|
# @param args [#to_a] Arguments for any callbacks in the spec.
|
428
|
-
#
|
486
|
+
#
|
429
487
|
# @return [Nokogiri::XML::Node] the last node generated, in document order.
|
430
488
|
|
431
489
|
def xhtml_stub doc: nil, base: nil, ns: {}, prefix: {}, vocab: nil,
|
@@ -455,7 +513,7 @@ module XML::Mixup
|
|
455
513
|
elsif title.is_a? Hash
|
456
514
|
# nothing
|
457
515
|
elsif title.respond_to? :to_a
|
458
|
-
title = title.to_a
|
516
|
+
title = title.to_a.dup
|
459
517
|
text = title.shift
|
460
518
|
props = title
|
461
519
|
title = { '#title' => text }
|
@@ -475,7 +533,7 @@ module XML::Mixup
|
|
475
533
|
# construct document tree
|
476
534
|
|
477
535
|
head ||= {}
|
478
|
-
if head.is_a? Hash and head.empty?
|
536
|
+
if head.is_a? Hash and head.empty?
|
479
537
|
head[nil] = [:head, title, base, link, meta, style, script, extra]
|
480
538
|
elsif head.is_a? Array
|
481
539
|
# children of unmarked head element
|
@@ -527,56 +585,6 @@ module XML::Mixup
|
|
527
585
|
markup spec: spec, doc: doc, args: args
|
528
586
|
end
|
529
587
|
|
530
|
-
private
|
531
|
-
|
532
|
-
def element tag, doc: nil, ns: {}, attr: {}, args: []
|
533
|
-
raise 'Document node must be present' unless doc
|
534
|
-
pfx = nil
|
535
|
-
if tag.respond_to? :to_a
|
536
|
-
pfx = tag[0]
|
537
|
-
tag = tag.to_a[0..1].join ':'
|
538
|
-
elsif m = tag.match(/([^:]+):/)
|
539
|
-
pfx = m[1]
|
540
|
-
end
|
541
|
-
|
542
|
-
elem = doc.create_element tag.to_s
|
543
|
-
elem.default_namespace = ns[pfx] if ns[pfx]
|
544
|
-
|
545
|
-
ns.keys.sort { |a, b| a.to_s <=> b.to_s }.each do |p|
|
546
|
-
elem.add_namespace((p.nil? ? p : p.to_s), ns[p].to_s)
|
547
|
-
end
|
548
|
-
attr.sort.each do |k, v|
|
549
|
-
v = flatten(v, args) or next
|
550
|
-
elem[k.to_s] = v
|
551
|
-
end
|
552
|
-
|
553
|
-
elem
|
554
|
-
end
|
555
|
-
|
556
|
-
ATOMS = [String, Symbol, Numeric, FalseClass, TrueClass].freeze
|
557
|
-
|
558
|
-
# yo dawg
|
559
|
-
|
560
|
-
def flatten obj, args
|
561
|
-
return if obj.nil?
|
562
|
-
# early bailout for most likely condition
|
563
|
-
if ATOMS.any? { |x| obj.is_a? x }
|
564
|
-
obj.to_s
|
565
|
-
elsif obj.is_a? Hash
|
566
|
-
tmp = obj.sort.map do |kv|
|
567
|
-
v = flatten(kv[1], args)
|
568
|
-
v.nil? ? nil : "#{kv[0].to_s}: #{v}"
|
569
|
-
end.compact
|
570
|
-
tmp.empty? ? nil : tmp.join(' ')
|
571
|
-
elsif obj.respond_to? :call
|
572
|
-
flatten(obj.call(*args), args)
|
573
|
-
elsif obj.respond_to? :map
|
574
|
-
tmp = obj.map { |x| flatten(x, args) }.reject { |x| x.nil? || x == '' }
|
575
|
-
tmp.empty? ? nil : tmp.join(' ')
|
576
|
-
else
|
577
|
-
obj.to_s
|
578
|
-
end
|
579
|
-
end
|
580
588
|
|
581
589
|
# add class methods too
|
582
590
|
extend self
|
data/xml-mixup.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.summary = %q{A mixin for (XML) markup}
|
13
13
|
spec.description = %q{XML::Mixup uses declarative data structures to incrementally generate XML.}
|
14
14
|
spec.homepage = "https://github.com/doriantaylor/rb-xml-mixup"
|
15
|
-
spec.required_ruby_version = "
|
15
|
+
spec.required_ruby_version = ">= 2.0"
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
18
|
f.match(%r{^(test|spec|features)/})
|
@@ -21,9 +21,9 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
|
-
spec.add_development_dependency "bundler", "~> 1
|
25
|
-
spec.add_development_dependency "rake", "~>
|
26
|
-
spec.add_development_dependency "rspec", "~> 3.
|
24
|
+
spec.add_development_dependency "bundler", "~> 2.1"
|
25
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.9"
|
27
27
|
|
28
|
-
spec.add_dependency "nokogiri", "
|
28
|
+
spec.add_dependency "nokogiri", ">= 1.13.6"
|
29
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xml-mixup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dorian Taylor
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-06-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,56 +16,56 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1
|
19
|
+
version: '2.1'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1
|
26
|
+
version: '2.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '13.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '13.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '3.
|
47
|
+
version: '3.9'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '3.
|
54
|
+
version: '3.9'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: nokogiri
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 1.13.6
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 1.13.6
|
69
69
|
description: XML::Mixup uses declarative data structures to incrementally generate
|
70
70
|
XML.
|
71
71
|
email:
|
@@ -89,13 +89,13 @@ homepage: https://github.com/doriantaylor/rb-xml-mixup
|
|
89
89
|
licenses:
|
90
90
|
- Apache-2.0
|
91
91
|
metadata: {}
|
92
|
-
post_install_message:
|
92
|
+
post_install_message:
|
93
93
|
rdoc_options: []
|
94
94
|
require_paths:
|
95
95
|
- lib
|
96
96
|
required_ruby_version: !ruby/object:Gem::Requirement
|
97
97
|
requirements:
|
98
|
-
- - "
|
98
|
+
- - ">="
|
99
99
|
- !ruby/object:Gem::Version
|
100
100
|
version: '2.0'
|
101
101
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
@@ -104,8 +104,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
104
|
- !ruby/object:Gem::Version
|
105
105
|
version: '0'
|
106
106
|
requirements: []
|
107
|
-
rubygems_version: 3.
|
108
|
-
signing_key:
|
107
|
+
rubygems_version: 3.3.11
|
108
|
+
signing_key:
|
109
109
|
specification_version: 4
|
110
110
|
summary: A mixin for (XML) markup
|
111
111
|
test_files: []
|