xml-mixup 0.1.11 → 0.1.15

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: 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: []