ayril 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +4 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +19 -0
- data/LICENSE +19 -0
- data/README.md +88 -0
- data/Rakefile +40 -0
- data/ayril.gemspec +55 -0
- data/lib/ayril.rb +48 -0
- data/lib/ayril/core_ext/core_ext.rb +96 -0
- data/lib/ayril/selector.rb +250 -0
- data/lib/ayril/version.rb +30 -0
- data/lib/ayril/xml_document.rb +54 -0
- data/lib/ayril/xml_element.rb +75 -0
- data/lib/ayril/xml_element/element_attribute_manipulation.rb +61 -0
- data/lib/ayril/xml_element/element_classname_manipulation.rb +34 -0
- data/lib/ayril/xml_element/element_manipulation.rb +85 -0
- data/lib/ayril/xml_element/element_style_manipulation.rb +11 -0
- data/lib/ayril/xml_element/xml_attribute_hash.rb +60 -0
- data/lib/ayril/xml_element/xml_css_hash.rb +47 -0
- data/lib/ayril/xml_node.rb +118 -0
- data/lib/ayril/xml_node/node_manipulation.rb +73 -0
- data/lib/ayril/xml_node/node_traversal.rb +158 -0
- data/test/invoke_ayril_selector.rb +3 -0
- data/test/invoke_prototype_selector.js +4 -0
- data/test/sanity.xml +124 -0
- data/test/selector.js +521 -0
- data/test/test_sanity.rb +27 -0
- data/test/test_selector.rb +78 -0
- metadata +129 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
# Copyright (C) 2011 by Robert Lowe <rob[!]iblargz.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module Ayril
|
22
|
+
module Version
|
23
|
+
MAJOR = 0
|
24
|
+
MINOR = 1
|
25
|
+
PATCH = 0
|
26
|
+
BUILD = nil
|
27
|
+
|
28
|
+
STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright (C) 2011 by Wilson Lee <kourge[!]gmail.com>, Robert Lowe <rob[!]iblargz.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module Ayril
|
22
|
+
class XMLDocument < NSXMLDocument
|
23
|
+
include XMLNode::NodeManipulation
|
24
|
+
include XMLNode::NodeTraversal
|
25
|
+
|
26
|
+
def self.new(data, error=nil)
|
27
|
+
path = data.dup
|
28
|
+
path = NSURL.fileURLWithPath data.path if data.kind_of? File
|
29
|
+
if path.kind_of? NSURL
|
30
|
+
XMLDocument.alloc.initWithContentsOfURL path, options: 0, error: error
|
31
|
+
elsif path.kind_of? XMLElement
|
32
|
+
XMLDocument.alloc.initWithRootElement path
|
33
|
+
elsif path.kind_of? String
|
34
|
+
XMLDocument.alloc.initWithXMLString path, options: 0, error: error
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.replacementClassForClass(currentClass)
|
39
|
+
return {
|
40
|
+
NSXMLNode => XMLNode,
|
41
|
+
NSXMLElement => XMLElement,
|
42
|
+
NSXMLDocument => XMLDocument,
|
43
|
+
NSXMLDTD => XMLDTD,
|
44
|
+
NSXMLDTDNode => XMLDTDNode
|
45
|
+
}[currentClass]
|
46
|
+
end
|
47
|
+
|
48
|
+
forward :to_s, :XMLString
|
49
|
+
|
50
|
+
def inspect
|
51
|
+
"#<#{self.class}:0x#{self.object_id.to_s(16)}>"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Copyright (C) 2011 by Wilson Lee <kourge[!]gmail.com>, Robert Lowe <rob[!]iblargz.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module Ayril
|
22
|
+
class XMLElement < NSXMLElement
|
23
|
+
|
24
|
+
autoload :XMLCSSHash, 'ayril/xml_element/xml_css_hash'
|
25
|
+
autoload :XMLAttributeHash, 'ayril/xml_element/xml_attribute_hash'
|
26
|
+
|
27
|
+
autoload :ElementManipulation, 'ayril/xml_element/element_manipulation'
|
28
|
+
autoload :ElementAttributeManipulation, 'ayril/xml_element/element_attribute_manipulation'
|
29
|
+
autoload :ElementClassnameManipulation, 'ayril/xml_element/element_classname_manipulation'
|
30
|
+
autoload :ElementStyleManipulation, 'ayril/xml_element/element_style_manipulation'
|
31
|
+
|
32
|
+
include XMLNode::NodeManipulation
|
33
|
+
include XMLNode::NodeTraversal
|
34
|
+
|
35
|
+
include ElementManipulation
|
36
|
+
include ElementAttributeManipulation
|
37
|
+
include ElementClassnameManipulation
|
38
|
+
include ElementStyleManipulation
|
39
|
+
|
40
|
+
@@id_counter = 0
|
41
|
+
attr_accessor :id_counter
|
42
|
+
|
43
|
+
def self.new(name, attributes={})
|
44
|
+
if attributes.empty? and name.include? "<"
|
45
|
+
self.alloc.initWithXMLString name, error: nil
|
46
|
+
else
|
47
|
+
XMLNode.elementWithName name, children: nil, attributes: attributes
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def kind; NSXMLElementKind end
|
52
|
+
|
53
|
+
def initWithName(name)
|
54
|
+
self.class.alloc.tap { |e| e.name = name }
|
55
|
+
end
|
56
|
+
|
57
|
+
def initWithName(name, stringValue: string)
|
58
|
+
self.initWithName(name).tap { |e| e.stringValue = string }
|
59
|
+
end
|
60
|
+
|
61
|
+
def initWithName(name, URI: uri)
|
62
|
+
self.initWithName(name).tap { |e| e.URI = uri }
|
63
|
+
end
|
64
|
+
|
65
|
+
def initWithXMLString(string, error: error)
|
66
|
+
d = XMLDocument.alloc.initWithXMLString(string, options: 0, error: nil)
|
67
|
+
d.maybe(:rootElement).tap { |n| n.maybe :detach }
|
68
|
+
end
|
69
|
+
|
70
|
+
def inspect
|
71
|
+
attributes = self.attribute.tap { |a| a.sync }
|
72
|
+
"#<#{self.class}<#{self.name}#{attributes.maybe(:empty?) ? '' : ' '}#{attributes}>>"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Copyright (C) 2011 by Wilson Lee <kourge[!]gmail.com>, Robert Lowe <rob[!]iblargz.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module Ayril
|
22
|
+
class XMLElement
|
23
|
+
module ElementAttributeManipulation
|
24
|
+
def attribute
|
25
|
+
@attributes.nil? ? (@attributes = XMLElement::XMLAttributeHash.new self) : @attributes
|
26
|
+
end
|
27
|
+
alias :attr :attribute
|
28
|
+
|
29
|
+
def attribute=(hash); self.setAttributesAsDictionary hash end
|
30
|
+
alias :attr= :attribute=
|
31
|
+
alias :set :attribute=
|
32
|
+
|
33
|
+
def read_attribute(k); self.attributeForName(k.to_s).maybe(:stringValue) end
|
34
|
+
alias :get_attribute :read_attribute
|
35
|
+
alias :[] :read_attribute
|
36
|
+
|
37
|
+
def write_attribute(k, v=nil)
|
38
|
+
if v.nil? and k.kind_of? Hash
|
39
|
+
k.each { |a, b| self.write_attribute a.to_s, b } unless k.empty?
|
40
|
+
return self
|
41
|
+
end
|
42
|
+
attr = self.attributeForName(k)
|
43
|
+
if attr.nil?
|
44
|
+
self.addAttribute XMLNode.attributeWithName(k.to_s, stringValue: v)
|
45
|
+
else
|
46
|
+
attr.stringValue = v
|
47
|
+
end
|
48
|
+
self
|
49
|
+
end
|
50
|
+
alias :add_attribute :write_attribute
|
51
|
+
alias :set_attribute :write_attribute
|
52
|
+
alias :[]= :write_attribute
|
53
|
+
|
54
|
+
def remove_attribute(a) self.removeAttributeForName(a.to_s); self.sync end
|
55
|
+
alias :delete_attribute :remove_attribute
|
56
|
+
|
57
|
+
def has_attribute?(k); not self.attributeForName(k.to_s).nil? end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Ayril
|
2
|
+
class XMLElement
|
3
|
+
module ElementClassnameManipulation
|
4
|
+
def has_class_name?(class_name)
|
5
|
+
classes = self.read_attribute "class"
|
6
|
+
!!(classes.length > 0 and (classes == class_name or
|
7
|
+
classes =~ /(^|\s)#{class_name}(\s|$)/))
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_class_name(class_name)
|
11
|
+
if not self.has_class_name? class_name
|
12
|
+
current = if not self.has_attribute? "class" then ''
|
13
|
+
else self.read_attribute("class") end
|
14
|
+
end
|
15
|
+
self.write_attribute "class", (current + ((current == '') ? '' : ' ') + class_name)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def remove_class_name(class_name)
|
20
|
+
return self if not self.has_attribute? "class"
|
21
|
+
string_value = self.read_attribute("class").sub(/(^|\s+)#{class_name}(\s+|$)/, ' ').strip
|
22
|
+
string_value == '' ? self.remove_attribute("class")
|
23
|
+
: self.write_attribute("class", string_value)
|
24
|
+
self.tap { |s| s.attribute.sync; s.class_names.sync }
|
25
|
+
end
|
26
|
+
|
27
|
+
def toggle_class_name(class_name)
|
28
|
+
if self.has_class_name? class_name
|
29
|
+
then self.remove_class_name class_name
|
30
|
+
else self.add_class_name class_name end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Copyright (C) 2011 by Wilson Lee <kourge[!]gmail.com>, Robert Lowe <rob[!]iblargz.com>
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module Ayril
|
22
|
+
class XMLElement
|
23
|
+
module ElementManipulation
|
24
|
+
def insert(insertions)
|
25
|
+
insertions = { :bottom => insertions } if insertions.kind_of? String or
|
26
|
+
insertions.kind_of? Integer or insertions.kind_of? XMLElement or
|
27
|
+
(insertions.respond_to? :to_element or insertions.respond_to? :to_html)
|
28
|
+
|
29
|
+
insertions.each do |position, content|
|
30
|
+
position.downcase! if position.kind_of? String
|
31
|
+
insert = {
|
32
|
+
:before => lambda { |element, node|
|
33
|
+
element.parent.insertChild node, atIndex: element.index
|
34
|
+
},
|
35
|
+
:top => lambda { |element, node|
|
36
|
+
element.insertChild node, atIndex: 0
|
37
|
+
},
|
38
|
+
:bottom => lambda { |element, node|
|
39
|
+
element.addChild node
|
40
|
+
},
|
41
|
+
:after => lambda { |element, node|
|
42
|
+
element.parent.insertChild node, atIndex: element.index + 1
|
43
|
+
}
|
44
|
+
}[position = position.to_sym]
|
45
|
+
|
46
|
+
content = content.to_element if content.respond_to? :to_element
|
47
|
+
(insert.call(self, content); next) if content.kind_of? XMLElement
|
48
|
+
|
49
|
+
content = content.respond_to?(:to_html) ? content.to_html : content.to_s
|
50
|
+
children = XMLElement.alloc.initWithXMLString("<root>#{content}</root>", error: nil).children
|
51
|
+
|
52
|
+
children.reverse! if position == :top or position == :after
|
53
|
+
children.each { |child| child.detach; insert.call self, child }
|
54
|
+
end
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def append(e) self.insert :bottom => e end
|
59
|
+
def prepend(e) self.insert :top => e end
|
60
|
+
|
61
|
+
def wrap(wrapper=nil, attributes={})
|
62
|
+
if wrapper.kind_of? XMLElement
|
63
|
+
wrapper.write_attribute attributes
|
64
|
+
elsif wrapper.kind_of? String
|
65
|
+
wrapper = XMLElement.new wrapper, attributes
|
66
|
+
else
|
67
|
+
wrapper = XMLElement.new 'div', attributes
|
68
|
+
end
|
69
|
+
self.replace wrapper if self.parent
|
70
|
+
wrapper.addChild self
|
71
|
+
wrapper
|
72
|
+
end
|
73
|
+
|
74
|
+
def identify
|
75
|
+
id = self.read_attribute "id"
|
76
|
+
return id unless id.nil?
|
77
|
+
begin
|
78
|
+
id = "anonymous_element_#{XMLElement::id_counter += 1}"
|
79
|
+
end while self.rootDocument.select("##{id}").any?
|
80
|
+
self.write_attribute "id", id
|
81
|
+
id
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Ayril
|
2
|
+
class XMLElement
|
3
|
+
module ElementStyleManipulation
|
4
|
+
def style; XMLElement::XMLCSSHash.new self end
|
5
|
+
def style=(h) self.style.replace h end
|
6
|
+
|
7
|
+
def get_style(prop) self.style[style] end
|
8
|
+
def set_style(style, value) self.style[style] = value end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Ayril
|
2
|
+
class XMLElement
|
3
|
+
class XMLAttributeHash < Hash
|
4
|
+
def initialize(element)
|
5
|
+
@element = element
|
6
|
+
self.sync
|
7
|
+
end
|
8
|
+
|
9
|
+
def sync
|
10
|
+
cache = {}
|
11
|
+
@element.attributes.each { |a| cache[a.name] = a.stringValue } if not @element.attributes.nil?
|
12
|
+
self.delete_if { true }.merge! cache
|
13
|
+
end
|
14
|
+
|
15
|
+
def store(k, v)
|
16
|
+
attr = @element.attributeForName k
|
17
|
+
if not attr.nil?
|
18
|
+
attr.stringValue = v
|
19
|
+
else
|
20
|
+
@element.addAttribute XMLNode.attributeWithName(k, stringValue: v)
|
21
|
+
end
|
22
|
+
super k, v
|
23
|
+
end
|
24
|
+
alias :set :store
|
25
|
+
alias :[]= :store
|
26
|
+
|
27
|
+
def fetch(k); @element.attributeForName(k).maybe :stringValue end
|
28
|
+
alias :get :fetch
|
29
|
+
alias :[] :fetch
|
30
|
+
|
31
|
+
def has_key?(k); not @element.attributeForName(k).nil? end
|
32
|
+
alias :has? :has_key?
|
33
|
+
alias :include? :has_key?
|
34
|
+
alias :key? :has_key?
|
35
|
+
alias :member? :has_key?
|
36
|
+
|
37
|
+
def delete(k); @element.removeAttributeForName k; super k end
|
38
|
+
alias :remove :delete
|
39
|
+
alias :- :delete
|
40
|
+
|
41
|
+
def _delete_if(&blk); self.each { |k, v| self.delete k if blk.call k, v } end
|
42
|
+
def delete_if(&blk); self._delete_if &blk; self end
|
43
|
+
|
44
|
+
def reject!(&blk)
|
45
|
+
old = self.dup; self._delete_if &blk
|
46
|
+
(self == old) ? nil : self
|
47
|
+
end
|
48
|
+
|
49
|
+
def replace(hash); @element.setAttributesAsDictionary hash; super hash end
|
50
|
+
def clear; self.replace {} end
|
51
|
+
|
52
|
+
def merge!(hash); hash.each { |k, v| self[k] = v }; self end
|
53
|
+
alias :update! :merge!
|
54
|
+
alias :+ :merge!
|
55
|
+
|
56
|
+
def to_s; self.map { |k, v| "#{k}=\"#{v}\"" }.join ' ' end
|
57
|
+
def inspect; "#<#{self.class} #{self.to_s}>" end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Ayril
|
2
|
+
class XMLElement
|
3
|
+
class XMLCSSHash < Hash
|
4
|
+
def initialize(element)
|
5
|
+
if not (@element = element).has_attribute? "style"
|
6
|
+
@element.write_attribute "style", ''
|
7
|
+
end
|
8
|
+
css = @element.read_attribute "style"
|
9
|
+
css.gsub(/\n/, '').split(';').invoke(:strip).compact.each do |property|
|
10
|
+
property.split(':').tap { |p| self[p.shift] = p.join(':').strip }
|
11
|
+
end.tap { sync }
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_css; self.map { |k, v| "#{k}: #{v}" }.join "; " end
|
15
|
+
alias :to_s :to_css
|
16
|
+
|
17
|
+
def inspect; "#<#{self.class} {#{self.to_css}}>" end
|
18
|
+
|
19
|
+
def store(k, v) super(k, v).tap { sync } end
|
20
|
+
alias :[]= :store
|
21
|
+
|
22
|
+
def fetch(k) super(k).tap { sync } end
|
23
|
+
alias :[] :fetch
|
24
|
+
|
25
|
+
def delete(k) super(k).tap { sync } end
|
26
|
+
alias :- :delete
|
27
|
+
|
28
|
+
def delete_if(&blk) super(&blk).tap { sync } end
|
29
|
+
def reject!(&blk) super(&blk).tap { sync } end
|
30
|
+
def replace(h) super(h).tap { sync } end
|
31
|
+
def clear; super.tap { sync } end
|
32
|
+
|
33
|
+
def merge!(h) super(h).tap { sync } end
|
34
|
+
alias :update! :merge!
|
35
|
+
alias :+ :merge!
|
36
|
+
|
37
|
+
def sync
|
38
|
+
@element.removeAttributeForName("style") and return if self.size == 0
|
39
|
+
@element.write_attribute "style", self.to_css
|
40
|
+
end
|
41
|
+
|
42
|
+
alias :include? :has_key?
|
43
|
+
alias :key? :has_key?
|
44
|
+
alias :member? :has_key?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|