xml-mixup 0.1.13 → 0.1.15

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: 78712630063acefe9860899c3ef4c7ec89551fe508a9fb3e588642afed153fb7
4
- data.tar.gz: 7b66b844418700e275d170424e7fc7fe91ab3645f5e0d2f063b9be589c2325a0
3
+ metadata.gz: 83154ccf54f91484833c4f3b6990bce856635bc95864eeae11edb5b791d1118c
4
+ data.tar.gz: 6cc3737aedbaf7b5c9c04dc621b003c3047b6f86c16f9ab954da4a5bb4c774d0
5
5
  SHA512:
6
- metadata.gz: 0b89a5ccf232b99adc00df21e92f047c6899c7e3e130195f2609f9e61d455f199571e5fa46cff2dbd691f2da5381d7e2f393a1a02fa2b4f67bbcdcf6f528b5a4
7
- data.tar.gz: cc3b89b5067275ae27cc496cbeb5fb451727e46ad7801a7a5dbfcd36a0e65253e813765ebce19514aa1da45dea7b6daf832abc224f834ead2e469ad70a2310e6
6
+ metadata.gz: f4591665e4d05cbe1b5d3d638f37f54d5e39a8ff79f4037814783c954cdeebb7809f4f3890f481148f4ff24c7a42d981df97b0d361965f078ba5b1f5f49876de
7
+ data.tar.gz: 7fe10c1db99f7fdf143f7fb49b20cdf68b4c157758c72cfb31cd8ba71cbbbad4647b574e3353c61ea9bd4169b2f9d8b2000c27d3b1f28a667929f8fd62f7ac56
@@ -1,5 +1,5 @@
1
1
  module XML
2
2
  module Mixup
3
- VERSION = "0.1.13"
3
+ VERSION = "0.1.15"
4
4
  end
5
5
  end
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 supplied if none given.
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 flatten(children, args).to_s
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 = flatten(c, args).to_s
289
+ content = flatten_attr(c, args).to_s
232
290
  else
233
291
  content = attr.sort.map { |pair|
234
- v = flatten(pair[1], args) or next
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 flatten(children, args)
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 'Element name inference NOT IMPLEMENTED' unless name
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 = flatten(v, args) or next
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 = "~> 2.0"
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.16"
25
- spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "rspec", "~> 3.0"
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", "~> 1.10"
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.13
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: 2019-12-12 00:00:00.000000000 Z
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.16'
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.16'
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: '10.0'
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: '10.0'
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.0'
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.0'
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: '1.10'
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: '1.10'
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.0.6
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: []