xml-mixup 0.1.12 → 0.1.16

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: ce4b5cbf2235ee24e96cec12c0d65dbd7b40b9263ad0bddf5c3424f5ba6ce510
4
- data.tar.gz: 2cfaa1771ddbc17085b7f6544b3c8d6e8078861337fabfbf3c2dd678220d8cf1
3
+ metadata.gz: f2987df3a876da2b544c023d70a16dc8a44eb8bf391af07436263004b180f095
4
+ data.tar.gz: d04b0ad24255030ae51d50c7d198d95baf08570ec6a3e411b61119ef329a1542
5
5
  SHA512:
6
- metadata.gz: f7c179cbabe818107285b4ccf74be253cca2b6a4c887b0ecc29167f07ee8db48450ae1bf3a6cb560c653c59c9dc05b6a1b80aab45354c9fd055ce75199c40891
7
- data.tar.gz: d3013275de68a4e5a83df7afe9f4200808f8b9ccc09356d935d27807e2806ad2b5f61fedc0b9523ce1c610f69f9631343e9d2ec0e69b0cf794449e7ee26e034d
6
+ metadata.gz: 6537916b1380983c64e39aaf54048a0a08e6df07662c7319c07df566dee3320dd850b1153cfa705a7f18bacad12a26949d13b968f59c21a76270007889a2a3c2
7
+ data.tar.gz: 85d6a953e37ec44ca90f6b28dcb39483de885b094b17fa70caabf9ad18f52d6e723345391c264033df094f82f0db79e892231152615f9e305161badeca80dd8c
@@ -1,5 +1,5 @@
1
1
  module XML
2
2
  module Mixup
3
- VERSION = "0.1.12"
3
+ VERSION = "0.1.16"
4
4
  end
5
5
  end
data/lib/xml/mixup.rb CHANGED
@@ -3,12 +3,9 @@ require 'nokogiri'
3
3
  require 'set'
4
4
 
5
5
  module XML::Mixup
6
-
7
- #
8
-
9
6
  # these are node attachment protocols
10
7
  private
11
-
8
+
12
9
  ADJACENT = {
13
10
  parent: lambda do |node, parent|
14
11
  if parent.node_type == 9 and node.node_type == 1
@@ -31,8 +28,65 @@ module XML::Mixup
31
28
  RESERVED = Set.new(%w{comment cdata doctype dtd elem element
32
29
  pi processing-instruction tag}.map {|x| "##{x}"}).freeze
33
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
+
34
57
  public
35
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
+ args ||= []
69
+ # early bailout for most likely condition
70
+ if ATOMS.any? { |x| obj.is_a? x }
71
+ obj.to_s
72
+ elsif obj.is_a? Hash
73
+ tmp = obj.sort.map do |kv|
74
+ v = flatten_attr kv[1], args
75
+ v.nil? ? nil : "#{kv[0].to_s}: #{v}"
76
+ end.compact
77
+ tmp.empty? ? nil : tmp.join(' ')
78
+ elsif obj.respond_to? :call
79
+ flatten_attr obj.call(*args), args
80
+ elsif obj.respond_to? :map
81
+ tmp = obj.map { |x| flatten_attr x, args }.reject do |x|
82
+ x.nil? || x == ''
83
+ end
84
+ tmp.empty? ? nil : tmp.join(' ')
85
+ else
86
+ obj.to_s
87
+ end
88
+ end
89
+
36
90
  # Generate a handy blank document.
37
91
  #
38
92
  # @param version [Numeric, nil]
@@ -51,6 +105,8 @@ module XML::Mixup
51
105
  # include XML::Mixup
52
106
  # end
53
107
  #
108
+ # # note you can now also just call XML::Mixup.markup
109
+ #
54
110
  # something = Anything.new
55
111
  #
56
112
  # # generate a structure
@@ -73,18 +129,18 @@ module XML::Mixup
73
129
  # # case, it will be a text node containing 'lolwut'.
74
130
  #
75
131
  # doc = node.document
76
- # puts doc.to_xml
132
+ # puts doc.to_xml
77
133
  #
78
134
  # @param spec [Hash, Array, Nokogiri::XML::Node, Proc, #to_s] An XML
79
135
  # tree specification. May be composed of multiple hashes and
80
136
  # arrays. See the spec spec.
81
- #
137
+ #
82
138
  # @param doc [Nokogiri::XML::Document, nil] an optional XML document
83
- # instance; will be supplied if none given.
139
+ # instance; will be created if none given.
84
140
  #
85
141
  # @param args [#to_a] Any arguments to be passed to any callbacks
86
142
  # anywhere in the spec. Assumed to be an array.
87
- #
143
+ #
88
144
  # @param parent [Nokogiri::XML::Node] The node under which the
89
145
  # evaluation result of the spec is to be attached. This is the
90
146
  # default adjacent node, which in turn defaults to the document if
@@ -171,7 +227,7 @@ module XML::Mixup
171
227
  x = x.to_a
172
228
  name = x.shift
173
229
  children = x
174
- else
230
+ else
175
231
  name = x
176
232
  end
177
233
  elsif (compact = spec.select { |k, _| k.respond_to?(:to_a) or
@@ -180,10 +236,10 @@ module XML::Mixup
180
236
  raise %q{Spec can't have duplicate compact keys} if compact.count > 1
181
237
  children, name = compact.first
182
238
  children = children.is_a?(Hash) ||
183
- children.is_a?(Nokogiri::XML::Node) ? [children] : children.to_a
239
+ children.is_a?(Nokogiri::XML::Node) ? [children] : children.to_a
184
240
  elsif (special = spec.select { |k, _| k.respond_to? :to_s and
185
241
  k.to_s.start_with? ?# }) and !special.empty?
186
- # these are special keys
242
+ # these are special keys
187
243
  raise %q{Spec can't have multiple special keys} if special.count > 1
188
244
  name, children = special.first
189
245
 
@@ -203,7 +259,7 @@ module XML::Mixup
203
259
 
204
260
  # don't forget to reset the child nodes
205
261
  children = children.is_a?(Hash) || !children.respond_to?(:to_a) ?
206
- [children] : children.to_a
262
+ [children] : children.to_a
207
263
  end
208
264
 
209
265
  # note the name can be nil because it can be inferred
@@ -217,7 +273,7 @@ module XML::Mixup
217
273
  # now we dispatch based on the name
218
274
  if name == '#comment'
219
275
  # first up, comments
220
- node = doc.create_comment flatten(children, args).to_s
276
+ node = doc.create_comment flatten_attr(children, args).to_s
221
277
 
222
278
  # attach it
223
279
  ADJACENT[adj].call node, nodes[adj]
@@ -231,14 +287,14 @@ module XML::Mixup
231
287
  content = ''
232
288
  if (c = children[1..children.length]) and c.length > 0
233
289
  #warn c.inspect
234
- content = flatten(c, args).to_s
290
+ content = flatten_attr(c, args).to_s
235
291
  else
236
292
  content = attr.sort.map { |pair|
237
- v = flatten(pair[1], args) or next
293
+ v = flatten_attr(pair[1], args) or next
238
294
  "#{pair[0].to_s}=\"#{v}\""
239
295
  }.compact.join(' ')
240
296
  end
241
-
297
+
242
298
  node = Nokogiri::XML::ProcessingInstruction.new(doc, target, content)
243
299
 
244
300
  #warn node.inspect, content
@@ -274,14 +330,14 @@ module XML::Mixup
274
330
  #ADJACENT[adj].call node, nodes[adj]
275
331
  elsif name == '#cdata'
276
332
  # let's not forget cdata sections
277
- node = doc.create_cdata flatten(children, args)
333
+ node = doc.create_cdata flatten_attr(children, args)
278
334
  # attach it
279
335
  ADJACENT[adj].call node, nodes[adj]
280
336
 
281
337
  else
282
338
  # finally, an element
283
339
 
284
- raise 'Element name inference NOT IMPLEMENTED' unless name
340
+ raise "Element name inference NOT IMPLEMENTED: #{spec}" unless name
285
341
 
286
342
  # first check the name
287
343
  prefix = local = nil
@@ -295,7 +351,7 @@ module XML::Mixup
295
351
  at = {}
296
352
  attr.each do |k, v|
297
353
  k = k.to_s
298
- v = flatten(v, args) or next
354
+ v = flatten_attr(v, args) or next
299
355
  if (md = /^xmlns(?::(.*))?$/i.match(k))
300
356
  ns[md[1]] = v
301
357
  else
@@ -338,7 +394,7 @@ module XML::Mixup
338
394
  # generate the node
339
395
  node = element name, doc: doc, ns: ns, attr: at, args: args
340
396
 
341
- # attach it
397
+ # attach it
342
398
  ADJACENT[adj].call node, nodes[adj]
343
399
 
344
400
  # don't forget the children!
@@ -368,9 +424,9 @@ module XML::Mixup
368
424
  # Generates an XHTML stub, with optional RDFa attributes. All
369
425
  # parameters are optional.
370
426
  #
371
- # *This method is still under development.* I am still trying to
372
- # figure out how I want it to behave. Some parts may not work as
373
- # advertised.
427
+ # @note *This method is still under development.* I am still trying
428
+ # to figure out how I want it to behave. Some parts may not work as
429
+ # advertised.
374
430
  #
375
431
  # @param doc [Nokogiri::XML::Document, nil] an optional document.
376
432
  #
@@ -378,7 +434,7 @@ module XML::Mixup
378
434
  #
379
435
  # @param prefix [Hash] the contents of the root node's +prefix=+
380
436
  # and +xmlns:*+ attributes.
381
- #
437
+ #
382
438
  # @param vocab [#to_s] the contents of the root node's +vocab=+.
383
439
  #
384
440
  # @param lang [#to_s] the contents of +lang=+ and when applicable,
@@ -428,7 +484,7 @@ module XML::Mixup
428
484
  # namespaces. Defaults to +true+.
429
485
  #
430
486
  # @param args [#to_a] Arguments for any callbacks in the spec.
431
- #
487
+ #
432
488
  # @return [Nokogiri::XML::Node] the last node generated, in document order.
433
489
 
434
490
  def xhtml_stub doc: nil, base: nil, ns: {}, prefix: {}, vocab: nil,
@@ -458,7 +514,7 @@ module XML::Mixup
458
514
  elsif title.is_a? Hash
459
515
  # nothing
460
516
  elsif title.respond_to? :to_a
461
- title = title.to_a
517
+ title = title.to_a.dup
462
518
  text = title.shift
463
519
  props = title
464
520
  title = { '#title' => text }
@@ -478,7 +534,7 @@ module XML::Mixup
478
534
  # construct document tree
479
535
 
480
536
  head ||= {}
481
- if head.is_a? Hash and head.empty?
537
+ if head.is_a? Hash and head.empty?
482
538
  head[nil] = [:head, title, base, link, meta, style, script, extra]
483
539
  elsif head.is_a? Array
484
540
  # children of unmarked head element
@@ -530,55 +586,7 @@ module XML::Mixup
530
586
  markup spec: spec, doc: doc, args: args
531
587
  end
532
588
 
533
- private
534
-
535
- def element tag, doc: nil, ns: {}, attr: {}, args: []
536
- raise 'Document node must be present' unless doc
537
- pfx = nil
538
- if tag.respond_to? :to_a
539
- pfx = tag[0]
540
- tag = tag.to_a[0..1].join ':'
541
- elsif m = tag.match(/([^:]+):/)
542
- pfx = m[1]
543
- end
544
-
545
- elem = doc.create_element tag.to_s
546
- elem.default_namespace = ns[pfx] if ns[pfx]
547
-
548
- ns.keys.sort { |a, b| a.to_s <=> b.to_s }.each do |p|
549
- elem.add_namespace((p.nil? ? p : p.to_s), ns[p].to_s)
550
- end
551
- attr.sort.each do |k, v|
552
- v = flatten(v, args) or next
553
- elem[k.to_s] = v
554
- end
555
-
556
- elem
557
- end
558
-
559
- ATOMS = [String, Symbol, Numeric, FalseClass, TrueClass].freeze
560
-
561
- # yo dawg
562
-
563
- def flatten obj, args
564
- return if obj.nil?
565
- # early bailout for most likely condition
566
- if ATOMS.any? { |x| obj.is_a? x }
567
- obj.to_s
568
- elsif obj.is_a? Hash
569
- tmp = obj.sort.map do |kv|
570
- v = flatten(kv[1], args)
571
- v.nil? ? nil : "#{kv[0].to_s}: #{v}"
572
- end.compact
573
- tmp.empty? ? nil : tmp.join(' ')
574
- elsif obj.respond_to? :call
575
- flatten(obj.call(*args), args)
576
- elsif obj.respond_to? :map
577
- tmp = obj.map { |x| flatten(x, args) }.reject { |x| x.nil? || x == '' }
578
- tmp.empty? ? nil : tmp.join(' ')
579
- else
580
- obj.to_s
581
- end
582
- end
583
589
 
590
+ # add class methods too
591
+ extend self
584
592
  end
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.4"
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.12
4
+ version: 0.1.16
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.4
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.4
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,9 +104,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
104
  - !ruby/object:Gem::Version
105
105
  version: '0'
106
106
  requirements: []
107
- rubyforge_project:
108
- rubygems_version: 2.7.6.2
109
- signing_key:
107
+ rubygems_version: 3.3.11
108
+ signing_key:
110
109
  specification_version: 4
111
110
  summary: A mixin for (XML) markup
112
111
  test_files: []