csspool 0.1.0 → 0.1.1
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.
- data/.DS_Store +0 -0
- data/CHANGELOG.txt +10 -0
- data/Manifest.txt +36 -2
- data/README.txt +4 -4
- data/Rakefile +1 -1
- data/lib/css/sac/conditions/attribute_condition.rb +52 -0
- data/lib/css/sac/conditions/begin_hyphen_condition.rb +22 -0
- data/lib/css/sac/conditions/class_condition.rb +22 -0
- data/lib/css/sac/conditions/combinator_condition.rb +36 -0
- data/lib/css/sac/conditions/condition.rb +27 -0
- data/lib/css/sac/conditions/id_condition.rb +27 -0
- data/lib/css/sac/conditions/one_of_condition.rb +22 -0
- data/lib/css/sac/conditions/pseudo_class_condition.rb +24 -0
- data/lib/css/sac/conditions.rb +5 -0
- data/lib/css/sac/document_handler.rb +1 -1
- data/lib/css/sac/parser.rb +5 -3
- data/lib/css/sac/selectors/child_selector.rb +36 -0
- data/lib/css/sac/selectors/conditional_selector.rb +43 -0
- data/lib/css/sac/selectors/descendant_selector.rb +36 -0
- data/lib/css/sac/selectors/element_selector.rb +35 -0
- data/lib/css/sac/selectors/selector.rb +23 -0
- data/lib/css/sac/selectors/sibling_selector.rb +35 -0
- data/lib/css/sac/selectors/simple_selector.rb +25 -0
- data/lib/css/sac/selectors.rb +3 -85
- data/lib/css/sac/visitable.rb +104 -0
- data/lib/parser.y +24 -15
- data/test/condition_test_case.rb +6 -0
- data/test/helper.rb +2 -0
- data/test/selector_test_case.rb +20 -0
- data/test/test_attribute_condition.rb +30 -0
- data/test/test_begin_hyphen_condition.rb +15 -0
- data/test/test_child_selector.rb +48 -0
- data/test/test_class_condition.rb +15 -0
- data/test/test_combinator_condition.rb +29 -0
- data/test/test_condition.rb +13 -0
- data/test/test_conditional_selector.rb +29 -0
- data/test/test_descendant_selector.rb +52 -0
- data/test/test_element_selector.rb +22 -0
- data/test/test_id_condition.rb +16 -0
- data/test/test_one_of_condition.rb +15 -0
- data/test/test_parser.rb +58 -0
- data/test/test_selector.rb +19 -0
- data/test/test_selector_as_string.rb +11 -0
- data/test/test_selector_parser.rb +2 -2
- data/test/test_sibling_selector.rb +33 -0
- data/test/test_simple_selector.rb +9 -0
- data/test/test_specificity.rb +76 -0
- data/test/test_xpath.rb +105 -0
- metadata +38 -4
- data/lib/css/sac/attribute_condition.rb +0 -78
- data/lib/css/sac/condition.rb +0 -21
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
class SelectorTest < SelectorTestCase
|
4
|
+
class MySelector < Selector; end
|
5
|
+
|
6
|
+
def test_equals2
|
7
|
+
first = Selector.new(1)
|
8
|
+
second = Selector.new(1)
|
9
|
+
assert_equal first, second
|
10
|
+
|
11
|
+
|
12
|
+
third = Selector.new(2)
|
13
|
+
assert_not_equal first, third
|
14
|
+
|
15
|
+
fourth = MySelector.new(1)
|
16
|
+
assert_equal first, fourth
|
17
|
+
assert_not_equal first, 1
|
18
|
+
end
|
19
|
+
end
|
@@ -11,6 +11,17 @@ class SelectorAsStringTest < Test::Unit::TestCase
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
def test_equal2
|
15
|
+
@sac.parse('h1 > h2 { }')
|
16
|
+
selectors = @sac.document_handler.selectors
|
17
|
+
@sac.document_handler.selectors = []
|
18
|
+
|
19
|
+
@sac.parse('h1 > h2 { }')
|
20
|
+
selectors2 = @sac.document_handler.selectors
|
21
|
+
|
22
|
+
assert_equal selectors, selectors2
|
23
|
+
end
|
24
|
+
|
14
25
|
def test_any_node_selector
|
15
26
|
@sac.parse('* { }')
|
16
27
|
selectors = @sac.document_handler.selectors
|
@@ -71,7 +71,7 @@ class SelectorParserTest < Test::Unit::TestCase
|
|
71
71
|
@@single_selector_tests = {
|
72
72
|
:id => {
|
73
73
|
:css => '#foo { }',
|
74
|
-
:value => '
|
74
|
+
:value => 'foo',
|
75
75
|
:type => :SAC_ID_CONDITION,
|
76
76
|
},
|
77
77
|
:class => {
|
@@ -94,7 +94,7 @@ class SelectorParserTest < Test::Unit::TestCase
|
|
94
94
|
@@multiple_selector_tests = {
|
95
95
|
:ids => {
|
96
96
|
:css => '#foo#bar#baz { }',
|
97
|
-
:values => %w{
|
97
|
+
:values => %w{ foo bar baz },
|
98
98
|
:types => [:SAC_ID_CONDITION] * 3,
|
99
99
|
},
|
100
100
|
:classes => {
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
class SiblingSelectorTest < SelectorTestCase
|
4
|
+
def test_equals2
|
5
|
+
first = SiblingSelector.new(1,1)
|
6
|
+
second = SiblingSelector.new(1,1)
|
7
|
+
assert_equal first, second
|
8
|
+
|
9
|
+
third = SiblingSelector.new(1,2)
|
10
|
+
assert_not_equal first, third
|
11
|
+
|
12
|
+
fourth = SiblingSelector.new(2,1)
|
13
|
+
assert_not_equal first, fourth
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_equals_tilde
|
17
|
+
selector = ElementSelector.new('div')
|
18
|
+
sibling = ElementSelector.new('p')
|
19
|
+
sel = SiblingSelector.new(selector, sibling)
|
20
|
+
|
21
|
+
sibling = Node.new('p', nil, nil, nil)
|
22
|
+
node = Node.new('div', nil, nil, sibling)
|
23
|
+
assert sel =~ node
|
24
|
+
|
25
|
+
sibling1 = Node.new('div', nil, nil, nil)
|
26
|
+
node1 = Node.new('p', nil, nil, sibling)
|
27
|
+
assert(! (sel =~ node1))
|
28
|
+
|
29
|
+
assert(! (sel =~ NoParentNode.new('div')))
|
30
|
+
assert(! (sel =~ Node.new('div', nil, nil)))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
# http://www.w3.org/TR/REC-CSS2/cascade.html#specificity
|
4
|
+
# * {} /* a=0 b=0 c=0 -> specificity = 0 */
|
5
|
+
# LI {} /* a=0 b=0 c=1 -> specificity = 1 */
|
6
|
+
# UL LI {} /* a=0 b=0 c=2 -> specificity = 2 */
|
7
|
+
# UL OL+LI {} /* a=0 b=0 c=3 -> specificity = 3 */
|
8
|
+
# H1 + *[REL=up]{} /* a=0 b=1 c=1 -> specificity = 11 */
|
9
|
+
# UL OL LI.red {} /* a=0 b=1 c=3 -> specificity = 13 */
|
10
|
+
# LI.red.level {} /* a=0 b=2 c=1 -> specificity = 21 */
|
11
|
+
# #x34y {} /* a=1 b=0 c=0 -> specificity = 100 */
|
12
|
+
class SpecificityTest < Test::Unit::TestCase
|
13
|
+
def setup
|
14
|
+
@sac = CSS::SAC::Parser.new()
|
15
|
+
class << @sac.document_handler
|
16
|
+
attr_accessor :selectors
|
17
|
+
alias :start_selector :selectors=
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_star
|
22
|
+
@sac.parse('* {}')
|
23
|
+
selector = @sac.document_handler.selectors.first
|
24
|
+
assert_not_nil selector
|
25
|
+
assert_equal 0, selector.specificity
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_li
|
29
|
+
@sac.parse('li {}')
|
30
|
+
selector = @sac.document_handler.selectors.first
|
31
|
+
assert_not_nil selector
|
32
|
+
assert_equal 1, selector.specificity
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_ul_li
|
36
|
+
@sac.parse('ul li {}')
|
37
|
+
selector = @sac.document_handler.selectors.first
|
38
|
+
assert_not_nil selector
|
39
|
+
assert_equal 2, selector.specificity
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_ul_ol_plus_li
|
43
|
+
@sac.parse('ul ol+li {}')
|
44
|
+
selector = @sac.document_handler.selectors.first
|
45
|
+
assert_not_nil selector
|
46
|
+
assert_equal 3, selector.specificity
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_h1_attributes
|
50
|
+
@sac.parse('h1 + *[REL=up] {}')
|
51
|
+
selector = @sac.document_handler.selectors.first
|
52
|
+
assert_not_nil selector
|
53
|
+
assert_equal 11, selector.specificity
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_one_class_selector
|
57
|
+
@sac.parse('ul ol li.red {}')
|
58
|
+
selector = @sac.document_handler.selectors.first
|
59
|
+
assert_not_nil selector
|
60
|
+
assert_equal 13, selector.specificity
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_two_class_selectors
|
64
|
+
@sac.parse('li.red.level {}')
|
65
|
+
selector = @sac.document_handler.selectors.first
|
66
|
+
assert_not_nil selector
|
67
|
+
assert_equal 21, selector.specificity
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_id_selector
|
71
|
+
@sac.parse('#x34y {}')
|
72
|
+
selector = @sac.document_handler.selectors.first
|
73
|
+
assert_not_nil selector
|
74
|
+
assert_equal 100, selector.specificity
|
75
|
+
end
|
76
|
+
end
|
data/test/test_xpath.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helper"
|
2
|
+
|
3
|
+
# Thanks, Joe!
|
4
|
+
# http://www.joehewitt.com/blog/files/getElementsBySelector.js
|
5
|
+
|
6
|
+
class XPathTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@parser = CSS::SAC::Parser.new()
|
9
|
+
class << @parser.document_handler
|
10
|
+
attr_accessor :selectors
|
11
|
+
def start_selector(selectors)
|
12
|
+
@selectors = selectors
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# TODO: looks like attribute value quoting
|
18
|
+
# might be broken on the css side?
|
19
|
+
# this: input[type="text"] should be valid CSS
|
20
|
+
# and probably not return the quotes in the node
|
21
|
+
|
22
|
+
def test_any
|
23
|
+
assert_xpath("//*", "*")
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_element
|
27
|
+
assert_xpath("//h1", "h1")
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_id
|
31
|
+
assert_xpath("//*[@id='foo']", "#foo")
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_class
|
35
|
+
assert_xpath("//*[contains(@class, 'foo')]", ".foo")
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_attribute_with_no_value
|
39
|
+
assert_xpath("//*[@checked]", "[checked]")
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_attribute_with_value
|
43
|
+
assert_xpath("//*[@type='text']", "[type=text]")
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_hyphen_separated_attribute
|
47
|
+
# the contains behavior is probably fine here
|
48
|
+
assert_xpath("//*[contains(@type, 'text')]", "[type~=text]")
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_space_separated_attribute
|
52
|
+
# the contains behavior is probably fine here
|
53
|
+
assert_xpath("//*[contains(@type, 'text')]", "[type|=text]")
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_element_with_id
|
57
|
+
assert_xpath("//h1[@id='monkey']", "h1#monkey")
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_element_with_class
|
61
|
+
assert_xpath("//h1[contains(@class, 'foo')]", "h1.foo")
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_element_with_id_and_class
|
65
|
+
assert_xpath("//h1[@id='monkey'][contains(@class, 'foo')]", "h1#monkey.foo")
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_element_with_multiple_classes
|
69
|
+
assert_xpath("//h1[contains(@class, 'foo')][contains(@class, 'bar')]", "h1.foo.bar")
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_descendant
|
73
|
+
assert_xpath("//div//p", "div p")
|
74
|
+
assert_xpath("//div//*[contains(@class, 'angry')]", "div .angry")
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_direct_descendant
|
78
|
+
assert_xpath("//div/p", "div > p")
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_sibling
|
82
|
+
assert_xpath("//div/following-sibling::p", "div + p")
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_safely_ignores_pseudoclasses
|
86
|
+
assert_xpath("//a", "a:hover")
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def assert_xpath(xpath, css)
|
92
|
+
assert_equal(xpath, selector_for(css).to_xpath)
|
93
|
+
end
|
94
|
+
|
95
|
+
def selector_for(string)
|
96
|
+
selectors = selectors_for(string)
|
97
|
+
assert_equal(1, selectors.length)
|
98
|
+
selectors.first
|
99
|
+
end
|
100
|
+
|
101
|
+
def selectors_for(string)
|
102
|
+
@parser.parse("#{string} {}")
|
103
|
+
@parser.document_handler.selectors
|
104
|
+
end
|
105
|
+
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: csspool
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date: 2007-11-
|
6
|
+
version: 0.1.1
|
7
|
+
date: 2007-11-17 00:00:00 -08:00
|
8
8
|
summary: Parses CSS
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -29,13 +29,21 @@ post_install_message:
|
|
29
29
|
authors:
|
30
30
|
- Aaron Patterson
|
31
31
|
files:
|
32
|
+
- .DS_Store
|
32
33
|
- CHANGELOG.txt
|
33
34
|
- Manifest.txt
|
34
35
|
- README.txt
|
35
36
|
- Rakefile
|
36
37
|
- lib/css/sac.rb
|
37
|
-
- lib/css/sac/
|
38
|
-
- lib/css/sac/
|
38
|
+
- lib/css/sac/conditions.rb
|
39
|
+
- lib/css/sac/conditions/attribute_condition.rb
|
40
|
+
- lib/css/sac/conditions/begin_hyphen_condition.rb
|
41
|
+
- lib/css/sac/conditions/class_condition.rb
|
42
|
+
- lib/css/sac/conditions/combinator_condition.rb
|
43
|
+
- lib/css/sac/conditions/condition.rb
|
44
|
+
- lib/css/sac/conditions/id_condition.rb
|
45
|
+
- lib/css/sac/conditions/one_of_condition.rb
|
46
|
+
- lib/css/sac/conditions/pseudo_class_condition.rb
|
39
47
|
- lib/css/sac/document_handler.rb
|
40
48
|
- lib/css/sac/error_handler.rb
|
41
49
|
- lib/css/sac/generated_property_parser.rb
|
@@ -45,22 +53,48 @@ files:
|
|
45
53
|
- lib/css/sac/parser.rb
|
46
54
|
- lib/css/sac/property_parser.rb
|
47
55
|
- lib/css/sac/selectors.rb
|
56
|
+
- lib/css/sac/selectors/child_selector.rb
|
57
|
+
- lib/css/sac/selectors/conditional_selector.rb
|
58
|
+
- lib/css/sac/selectors/descendant_selector.rb
|
59
|
+
- lib/css/sac/selectors/element_selector.rb
|
60
|
+
- lib/css/sac/selectors/selector.rb
|
61
|
+
- lib/css/sac/selectors/sibling_selector.rb
|
62
|
+
- lib/css/sac/selectors/simple_selector.rb
|
48
63
|
- lib/css/sac/token.rb
|
49
64
|
- lib/css/sac/tokenizer.rb
|
65
|
+
- lib/css/sac/visitable.rb
|
50
66
|
- lib/parser.y
|
51
67
|
- lib/property_parser.y
|
52
68
|
- lib/property_parser.y.erb
|
69
|
+
- test/condition_test_case.rb
|
53
70
|
- test/helper.rb
|
71
|
+
- test/selector_test_case.rb
|
54
72
|
- test/test_all.rb
|
73
|
+
- test/test_attribute_condition.rb
|
74
|
+
- test/test_begin_hyphen_condition.rb
|
75
|
+
- test/test_child_selector.rb
|
76
|
+
- test/test_class_condition.rb
|
77
|
+
- test/test_combinator_condition.rb
|
78
|
+
- test/test_condition.rb
|
79
|
+
- test/test_conditional_selector.rb
|
80
|
+
- test/test_descendant_selector.rb
|
81
|
+
- test/test_element_selector.rb
|
82
|
+
- test/test_id_condition.rb
|
55
83
|
- test/test_lexeme.rb
|
56
84
|
- test/test_lexical_unit.rb
|
85
|
+
- test/test_one_of_condition.rb
|
57
86
|
- test/test_parse_error.rb
|
58
87
|
- test/test_parser.rb
|
59
88
|
- test/test_property_parser.rb
|
89
|
+
- test/test_selector.rb
|
60
90
|
- test/test_selector_as_string.rb
|
61
91
|
- test/test_selector_parser.rb
|
92
|
+
- test/test_sibling_selector.rb
|
93
|
+
- test/test_simple_selector.rb
|
94
|
+
- test/test_specificity.rb
|
62
95
|
- test/test_token.rb
|
63
96
|
- test/test_tokenizer.rb
|
97
|
+
- test/test_xpath.rb
|
64
98
|
test_files:
|
65
99
|
- test/test_all.rb
|
66
100
|
rdoc_options:
|
@@ -1,78 +0,0 @@
|
|
1
|
-
module CSS
|
2
|
-
module SAC
|
3
|
-
class AttributeCondition < Condition
|
4
|
-
attr_accessor :local_name, :value, :specified
|
5
|
-
alias :specified? :specified
|
6
|
-
|
7
|
-
class << self
|
8
|
-
def pseudo_class_condition(pseudo_class)
|
9
|
-
self.new do |condition|
|
10
|
-
condition.condition_type = :SAC_PSEUDO_CLASS_CONDITION
|
11
|
-
condition.value = pseudo_class
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def attribute_id(id_value)
|
16
|
-
self.new do |condition|
|
17
|
-
condition.condition_type = :SAC_ID_CONDITION
|
18
|
-
condition.specified = true
|
19
|
-
condition.value = id_value
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def class_condition(class_name)
|
24
|
-
self.new do |condition|
|
25
|
-
condition.condition_type = :SAC_CLASS_CONDITION
|
26
|
-
condition.specified = true
|
27
|
-
condition.value = class_name
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def attribute_condition(attribute, conditions)
|
32
|
-
self.new do |condition|
|
33
|
-
if attribute
|
34
|
-
condition.condition_type = :SAC_ATTRIBUTE_CONDITION
|
35
|
-
condition.local_name = attribute
|
36
|
-
end
|
37
|
-
|
38
|
-
if conditions
|
39
|
-
condition.condition_type =
|
40
|
-
case conditions.first
|
41
|
-
when '~='
|
42
|
-
:SAC_ONE_OF_ATTRIBUTE_CONDITION
|
43
|
-
when '|='
|
44
|
-
:SAC_BEGIN_HYPHEN_ATTRIBUTE_CONDITION
|
45
|
-
when '='
|
46
|
-
:SAC_ATTRIBUTE_CONDITION
|
47
|
-
end
|
48
|
-
condition.value = conditions.last
|
49
|
-
condition.specified = true
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def initialize(attribute = nil, conditions = nil)
|
56
|
-
@specified = false
|
57
|
-
@local_name = nil
|
58
|
-
@value = nil
|
59
|
-
yield self if block_given?
|
60
|
-
end
|
61
|
-
|
62
|
-
def to_css
|
63
|
-
case condition_type
|
64
|
-
when :SAC_ONE_OF_ATTRIBUTE_CONDITION
|
65
|
-
"[#{local_name}~=#{value}]"
|
66
|
-
when :SAC_BEGIN_HYPHEN_ATTRIBUTE_CONDITION
|
67
|
-
"[#{local_name}|=#{value}]"
|
68
|
-
when :SAC_ATTRIBUTE_CONDITION
|
69
|
-
"[#{local_name}=#{value}]"
|
70
|
-
when :SAC_CLASS_CONDITION
|
71
|
-
".#{value}"
|
72
|
-
when :SAC_ID_CONDITION
|
73
|
-
"#{value}"
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
data/lib/css/sac/condition.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module CSS
|
2
|
-
module SAC
|
3
|
-
class Condition
|
4
|
-
attr_accessor :condition_type
|
5
|
-
end
|
6
|
-
|
7
|
-
class CombinatorCondition < Condition
|
8
|
-
attr_accessor :first_condition, :second_condition
|
9
|
-
|
10
|
-
def initialize(first, second, type = :SAC_AND_CONDITION)
|
11
|
-
@first_condition = first
|
12
|
-
@second_condition = second
|
13
|
-
@condition_type = type
|
14
|
-
end
|
15
|
-
|
16
|
-
def to_css
|
17
|
-
"#{first_condition.to_css}#{second_condition.to_css}"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|