csspool 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|