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