xml-mixup 0.1.12 → 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
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: []