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.
Files changed (51) hide show
  1. data/.DS_Store +0 -0
  2. data/CHANGELOG.txt +10 -0
  3. data/Manifest.txt +36 -2
  4. data/README.txt +4 -4
  5. data/Rakefile +1 -1
  6. data/lib/css/sac/conditions/attribute_condition.rb +52 -0
  7. data/lib/css/sac/conditions/begin_hyphen_condition.rb +22 -0
  8. data/lib/css/sac/conditions/class_condition.rb +22 -0
  9. data/lib/css/sac/conditions/combinator_condition.rb +36 -0
  10. data/lib/css/sac/conditions/condition.rb +27 -0
  11. data/lib/css/sac/conditions/id_condition.rb +27 -0
  12. data/lib/css/sac/conditions/one_of_condition.rb +22 -0
  13. data/lib/css/sac/conditions/pseudo_class_condition.rb +24 -0
  14. data/lib/css/sac/conditions.rb +5 -0
  15. data/lib/css/sac/document_handler.rb +1 -1
  16. data/lib/css/sac/parser.rb +5 -3
  17. data/lib/css/sac/selectors/child_selector.rb +36 -0
  18. data/lib/css/sac/selectors/conditional_selector.rb +43 -0
  19. data/lib/css/sac/selectors/descendant_selector.rb +36 -0
  20. data/lib/css/sac/selectors/element_selector.rb +35 -0
  21. data/lib/css/sac/selectors/selector.rb +23 -0
  22. data/lib/css/sac/selectors/sibling_selector.rb +35 -0
  23. data/lib/css/sac/selectors/simple_selector.rb +25 -0
  24. data/lib/css/sac/selectors.rb +3 -85
  25. data/lib/css/sac/visitable.rb +104 -0
  26. data/lib/parser.y +24 -15
  27. data/test/condition_test_case.rb +6 -0
  28. data/test/helper.rb +2 -0
  29. data/test/selector_test_case.rb +20 -0
  30. data/test/test_attribute_condition.rb +30 -0
  31. data/test/test_begin_hyphen_condition.rb +15 -0
  32. data/test/test_child_selector.rb +48 -0
  33. data/test/test_class_condition.rb +15 -0
  34. data/test/test_combinator_condition.rb +29 -0
  35. data/test/test_condition.rb +13 -0
  36. data/test/test_conditional_selector.rb +29 -0
  37. data/test/test_descendant_selector.rb +52 -0
  38. data/test/test_element_selector.rb +22 -0
  39. data/test/test_id_condition.rb +16 -0
  40. data/test/test_one_of_condition.rb +15 -0
  41. data/test/test_parser.rb +58 -0
  42. data/test/test_selector.rb +19 -0
  43. data/test/test_selector_as_string.rb +11 -0
  44. data/test/test_selector_parser.rb +2 -2
  45. data/test/test_sibling_selector.rb +33 -0
  46. data/test/test_simple_selector.rb +9 -0
  47. data/test/test_specificity.rb +76 -0
  48. data/test/test_xpath.rb +105 -0
  49. metadata +38 -4
  50. data/lib/css/sac/attribute_condition.rb +0 -78
  51. 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 => '#foo',
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{ #foo #bar #baz },
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,9 @@
1
+ require File.dirname(__FILE__) + "/helper"
2
+
3
+ class SimpleSelectorTest < SelectorTestCase
4
+ def test_equals_tilde
5
+ sel = SimpleSelector.new
6
+ assert(! (sel =~ nil))
7
+ assert(sel =~ Node.new)
8
+ end
9
+ end
@@ -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
@@ -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.0
7
- date: 2007-11-02 00:00:00 -07:00
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/attribute_condition.rb
38
- - lib/css/sac/condition.rb
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
@@ -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