csspool 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
data/.DS_Store ADDED
Binary file
data/CHANGELOG.txt CHANGED
@@ -1,3 +1,13 @@
1
+ == 0.1.1
2
+
3
+ * Added specificity to selectors.
4
+ * Added == to selector ASTs.
5
+ * Added =~ to selector ASTs. The object passed in to =~ must quack like an
6
+ hpricot node. It must implement the following methods: name, parent, child,
7
+ next_sibling, attributes.
8
+ * Added .to_xpath to the selector AST.
9
+ * Fixed a bug where functions as pseudo classes didn't parse.
10
+
1
11
  == 0.1.0
2
12
 
3
13
  * Birthday!
data/Manifest.txt CHANGED
@@ -1,10 +1,18 @@
1
+ .DS_Store
1
2
  CHANGELOG.txt
2
3
  Manifest.txt
3
4
  README.txt
4
5
  Rakefile
5
6
  lib/css/sac.rb
6
- lib/css/sac/attribute_condition.rb
7
- lib/css/sac/condition.rb
7
+ lib/css/sac/conditions.rb
8
+ lib/css/sac/conditions/attribute_condition.rb
9
+ lib/css/sac/conditions/begin_hyphen_condition.rb
10
+ lib/css/sac/conditions/class_condition.rb
11
+ lib/css/sac/conditions/combinator_condition.rb
12
+ lib/css/sac/conditions/condition.rb
13
+ lib/css/sac/conditions/id_condition.rb
14
+ lib/css/sac/conditions/one_of_condition.rb
15
+ lib/css/sac/conditions/pseudo_class_condition.rb
8
16
  lib/css/sac/document_handler.rb
9
17
  lib/css/sac/error_handler.rb
10
18
  lib/css/sac/generated_property_parser.rb
@@ -14,19 +22,45 @@ lib/css/sac/parse_exception.rb
14
22
  lib/css/sac/parser.rb
15
23
  lib/css/sac/property_parser.rb
16
24
  lib/css/sac/selectors.rb
25
+ lib/css/sac/selectors/child_selector.rb
26
+ lib/css/sac/selectors/conditional_selector.rb
27
+ lib/css/sac/selectors/descendant_selector.rb
28
+ lib/css/sac/selectors/element_selector.rb
29
+ lib/css/sac/selectors/selector.rb
30
+ lib/css/sac/selectors/sibling_selector.rb
31
+ lib/css/sac/selectors/simple_selector.rb
17
32
  lib/css/sac/token.rb
18
33
  lib/css/sac/tokenizer.rb
34
+ lib/css/sac/visitable.rb
19
35
  lib/parser.y
20
36
  lib/property_parser.y
21
37
  lib/property_parser.y.erb
38
+ test/condition_test_case.rb
22
39
  test/helper.rb
40
+ test/selector_test_case.rb
23
41
  test/test_all.rb
42
+ test/test_attribute_condition.rb
43
+ test/test_begin_hyphen_condition.rb
44
+ test/test_child_selector.rb
45
+ test/test_class_condition.rb
46
+ test/test_combinator_condition.rb
47
+ test/test_condition.rb
48
+ test/test_conditional_selector.rb
49
+ test/test_descendant_selector.rb
50
+ test/test_element_selector.rb
51
+ test/test_id_condition.rb
24
52
  test/test_lexeme.rb
25
53
  test/test_lexical_unit.rb
54
+ test/test_one_of_condition.rb
26
55
  test/test_parse_error.rb
27
56
  test/test_parser.rb
28
57
  test/test_property_parser.rb
58
+ test/test_selector.rb
29
59
  test/test_selector_as_string.rb
30
60
  test/test_selector_parser.rb
61
+ test/test_sibling_selector.rb
62
+ test/test_simple_selector.rb
63
+ test/test_specificity.rb
31
64
  test/test_token.rb
32
65
  test/test_tokenizer.rb
66
+ test/test_xpath.rb
data/README.txt CHANGED
@@ -32,8 +32,8 @@ This example prints out all properties from a particular CSS file.
32
32
  end
33
33
  end
34
34
 
35
- token = CSS::SAC::Parser.new(DH.new)
36
- token.parse(File.read(ARGV[0]))
35
+ parser = CSS::SAC::Parser.new(DH.new)
36
+ parser.parse(File.read(ARGV[0]))
37
37
 
38
38
  See CSS::SAC::DocumentHandler for callbacks to implement.
39
39
 
@@ -41,8 +41,8 @@ See SAC[http://www.w3.org/Style/CSS/SAC/] for more information on SAC.
41
41
 
42
42
  == Authors
43
43
 
44
- * Aaron Patterson[http://tenderlovemaking.com/] <aaronp@rubyforge.com>
45
- * John Barnette
44
+ * {Aaron Patterson}[http://tenderlovemaking.com] <aaronp@rubyforge.com>
45
+ * {John Barnette}[http://geeksomnia.com] <jbarnette@rubyforge.com>
46
46
 
47
47
  == LICENSE
48
48
 
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), "lib")
7
7
  GENERATED_PARSER = "lib/css/sac/generated_parser.rb"
8
8
  GENERATED_PROPERTY_PARSER = "lib/css/sac/generated_property_parser.rb"
9
9
 
10
- Hoe.new('csspool', '0.1.0') do |p|
10
+ Hoe.new('csspool', '0.1.1') do |p|
11
11
  p.rubyforge_name = 'csspool'
12
12
  p.author = 'Aaron Patterson'
13
13
  p.email = 'aaronp@rubyforge.org'
@@ -0,0 +1,52 @@
1
+ require "css/sac/conditions"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Conditions
6
+ class AttributeCondition < Condition
7
+ attr_accessor :local_name, :value, :specified
8
+ alias :specified? :specified
9
+
10
+ class << self
11
+ def build(name, raw)
12
+ condition, value = raw
13
+
14
+ case condition
15
+ when "~="
16
+ OneOfCondition.new(name, value)
17
+ when "|="
18
+ BeginHyphenCondition.new(name, value)
19
+ else
20
+ AttributeCondition.new(name, value, true)
21
+ end
22
+ end
23
+ end
24
+
25
+ def initialize(local_name, value, specified, condition_type=:SAC_ATTRIBUTE_CONDITION)
26
+ super(condition_type)
27
+
28
+ @local_name = local_name
29
+ @value = value
30
+ @specified = specified
31
+ end
32
+
33
+ def to_css
34
+ "[#{local_name}#{value && "=#{value}"}]"
35
+ end
36
+
37
+ def to_xpath
38
+ "[@#{local_name}#{value && "='#{value}'"}]"
39
+ end
40
+
41
+ def specificity
42
+ 10
43
+ end
44
+
45
+ def ==(other)
46
+ super && local_name == other.local_name && value == other.value &&
47
+ specified == other.specified
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,22 @@
1
+ require "css/sac/conditions"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Conditions
6
+ class BeginHyphenCondition < AttributeCondition
7
+
8
+ def initialize(local_name, value)
9
+ super(local_name, value, true, :SAC_BEGIN_HYPHEN_ATTRIBUTE_CONDITION)
10
+ end
11
+
12
+ def to_css
13
+ "[#{local_name}|=#{value}]"
14
+ end
15
+
16
+ def to_xpath
17
+ "[contains(@#{local_name}, '#{value}')]"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require "css/sac/conditions"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Conditions
6
+ class ClassCondition < AttributeCondition
7
+
8
+ def initialize(klass)
9
+ super("class", klass, true, :SAC_CLASS_CONDITION)
10
+ end
11
+
12
+ def to_css
13
+ ".#{value}"
14
+ end
15
+
16
+ def to_xpath
17
+ "[contains(@#{local_name}, '#{value}')]"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,36 @@
1
+ require "css/sac/conditions"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Conditions
6
+ class CombinatorCondition < Condition
7
+ attr_accessor :first_condition, :second_condition
8
+ alias :first :first_condition
9
+ alias :second :second_condition
10
+
11
+ def initialize(first, second)
12
+ super(:SAC_AND_CONDITION)
13
+
14
+ @first_condition = first
15
+ @second_condition = second
16
+ end
17
+
18
+ def to_css
19
+ "#{first.to_css}#{second.to_css}"
20
+ end
21
+
22
+ def to_xpath
23
+ "#{first.to_xpath}#{second.to_xpath}"
24
+ end
25
+
26
+ def specificity
27
+ first.specificity + second.specificity
28
+ end
29
+
30
+ def ==(other)
31
+ super && first == other.first && second == other.second
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ module CSS
2
+ module SAC
3
+ module Conditions
4
+ class Condition
5
+ include CSS::SAC::Visitable
6
+
7
+ attr_accessor :condition_type
8
+
9
+ def initialize(condition_type)
10
+ @condition_type = condition_type
11
+ end
12
+
13
+ def ==(other)
14
+ self.class === other && condition_type == other.condition_type
15
+ end
16
+
17
+ def to_css
18
+ nil
19
+ end
20
+
21
+ def =~(node)
22
+ MatchesVisitor.new(node).accept(self)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ require "css/sac/conditions"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Conditions
6
+ class IDCondition < AttributeCondition
7
+
8
+ def initialize(id)
9
+ id = id[1..id.size] if id[0] == ?#
10
+ super("id", id, true, :SAC_ID_CONDITION)
11
+ end
12
+
13
+ def to_css
14
+ "##{value}"
15
+ end
16
+
17
+ def to_xpath
18
+ "[@id='#{value}']"
19
+ end
20
+
21
+ def specificity
22
+ 100
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ require "css/sac/conditions"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Conditions
6
+ class OneOfCondition < AttributeCondition
7
+
8
+ def initialize(local_name, value)
9
+ super(local_name, value, true, :SAC_ONE_OF_ATTRIBUTE_CONDITION)
10
+ end
11
+
12
+ def to_css
13
+ "[#{local_name}~=#{value}]"
14
+ end
15
+
16
+ def to_xpath
17
+ "[contains(@#{local_name}, '#{value}')]"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ require "css/sac/conditions"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Conditions
6
+ class PseudoClassCondition < AttributeCondition
7
+ def initialize(pseudo_class)
8
+ super(nil, pseudo_class, false, :SAC_PSEUDO_CLASS_CONDITION)
9
+ end
10
+
11
+ def to_css
12
+ ":#{value}"
13
+ end
14
+
15
+ def to_xpath
16
+ end
17
+
18
+ def specificity
19
+ 0
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,5 @@
1
+ require "css/sac/conditions/condition"
2
+
3
+ %w(attribute begin_hyphen class combinator id one_of pseudo_class).each do |type|
4
+ require "css/sac/conditions/#{type}_condition"
5
+ end
@@ -1,6 +1,6 @@
1
1
  module CSS
2
2
  module SAC
3
- class CSS::SAC::DocumentHandler
3
+ class DocumentHandler
4
4
  def initialize
5
5
  end
6
6
 
@@ -1,3 +1,4 @@
1
+ require "css/sac/visitable"
1
2
  require "css/sac/document_handler"
2
3
  require "css/sac/error_handler"
3
4
  require "css/sac/generated_parser"
@@ -5,15 +6,15 @@ require "css/sac/lexical_unit"
5
6
  require "css/sac/parse_exception"
6
7
  require "css/sac/tokenizer"
7
8
  require "css/sac/property_parser"
8
- require "css/sac/condition"
9
- require "css/sac/attribute_condition"
9
+
10
+ require "css/sac/conditions"
10
11
  require "css/sac/selectors"
11
12
 
12
13
  module CSS
13
14
  module SAC
14
15
  class Parser < CSS::SAC::GeneratedParser
15
16
  # The version of CSSPool you're using
16
- VERSION = '0.1.0'
17
+ VERSION = '0.1.1'
17
18
 
18
19
  TOKENIZER = Tokenizer.new
19
20
 
@@ -35,6 +36,7 @@ module CSS
35
36
  self.document_handler.start_document(string)
36
37
  do_parse
37
38
  self.document_handler.end_document(string)
39
+ self.document_handler
38
40
  end
39
41
 
40
42
  alias :parse :parse_style_sheet
@@ -0,0 +1,36 @@
1
+ require "css/sac/selectors"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Selectors
6
+ class ChildSelector < SimpleSelector
7
+ attr_accessor :ancestor_selector, :simple_selector
8
+ alias :parent :ancestor_selector
9
+ alias :selector :simple_selector
10
+
11
+ def initialize(parent, selector)
12
+ super(:SAC_CHILD_SELECTOR)
13
+
14
+ @ancestor_selector = parent
15
+ @simple_selector = selector
16
+ end
17
+
18
+ def to_css
19
+ "#{parent.to_css} > #{selector.to_css}"
20
+ end
21
+
22
+ def to_xpath(prefix=true)
23
+ "#{parent.to_xpath(prefix)}/#{selector.to_xpath(false)}"
24
+ end
25
+
26
+ def specificity
27
+ parent.specificity + selector.specificity
28
+ end
29
+
30
+ def ==(other)
31
+ super && parent == other.parent && selector == other.selector
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,43 @@
1
+ require "css/sac/selectors"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Selectors
6
+ class ConditionalSelector < SimpleSelector
7
+ attr_accessor :condition, :simple_selector
8
+ alias :selector :simple_selector
9
+
10
+ def initialize(selector, condition)
11
+ super(:SAC_CONDITIONAL_SELECTOR)
12
+
13
+ @condition = condition
14
+ @simple_selector = selector
15
+ end
16
+
17
+ def to_css
18
+ [selector, condition].map { |x|
19
+ x ? x.to_css : ''
20
+ }.join('')
21
+ end
22
+
23
+ def to_xpath(prefix=true)
24
+ atoms = []
25
+ atoms << "//" if prefix
26
+ atoms << (selector ? selector.to_xpath(false) : "*")
27
+ atoms << condition.to_xpath
28
+
29
+ atoms.join("")
30
+ end
31
+
32
+ def specificity
33
+ (selector ? selector.specificity : 0) +
34
+ (condition ? condition.specificity : 0)
35
+ end
36
+
37
+ def ==(other)
38
+ super && condition == other.condition && selector == other.selector
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,36 @@
1
+ require "css/sac/selectors"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Selectors
6
+ class DescendantSelector < SimpleSelector
7
+ attr_accessor :ancestor_selector, :simple_selector
8
+ alias :ancestor :ancestor_selector
9
+ alias :selector :simple_selector
10
+
11
+ def initialize(ancestor, selector)
12
+ super(:SAC_DESCENDANT_SELECTOR)
13
+
14
+ @ancestor_selector = ancestor
15
+ @simple_selector = selector
16
+ end
17
+
18
+ def to_css
19
+ "#{ancestor.to_css} #{selector.to_css}"
20
+ end
21
+
22
+ def to_xpath(prefix=true)
23
+ "#{ancestor.to_xpath(prefix)}//#{selector.to_xpath(false)}"
24
+ end
25
+
26
+ def specificity
27
+ ancestor.specificity + selector.specificity
28
+ end
29
+
30
+ def ==(other)
31
+ super && selector == other.selector && ancestor == other.ancestor
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ require "css/sac/selectors"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Selectors
6
+ class ElementSelector < SimpleSelector
7
+ attr_reader :local_name
8
+ alias :name :local_name
9
+
10
+ def initialize(name)
11
+ super(:SAC_ELEMENT_NODE_SELECTOR)
12
+ @local_name = name
13
+ end
14
+
15
+ def to_css
16
+ local_name
17
+ end
18
+
19
+ def to_xpath(prefix=true)
20
+ atoms = [local_name]
21
+ atoms.unshift("//") if prefix
22
+ atoms.join
23
+ end
24
+
25
+ def specificity
26
+ 1
27
+ end
28
+
29
+ def ==(other)
30
+ super && name == other.name
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ module CSS
2
+ module SAC
3
+ module Selectors
4
+ class Selector
5
+ include CSS::SAC::Visitable
6
+
7
+ attr_reader :selector_type
8
+
9
+ def initialize(selector_type)
10
+ @selector_type = selector_type
11
+ end
12
+
13
+ def ==(other)
14
+ self.class === other && selector_type == other.selector_type
15
+ end
16
+
17
+ def =~(node)
18
+ MatchesVisitor.new(node).accept(self)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,35 @@
1
+ require "css/sac/selectors"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Selectors
6
+ class SiblingSelector < SimpleSelector
7
+ attr_accessor :selector, :sibling_selector
8
+ alias :sibling :sibling_selector
9
+
10
+ def initialize(selector, sibling)
11
+ super(:SAC_DIRECT_ADJACENT_SELECTOR)
12
+
13
+ @selector = selector
14
+ @sibling_selector = sibling
15
+ end
16
+
17
+ def to_css
18
+ "#{selector.to_css} + #{sibling.to_css}"
19
+ end
20
+
21
+ def to_xpath(prefix=true)
22
+ "#{selector.to_xpath(prefix)}/following-sibling::#{sibling.to_xpath(false)}"
23
+ end
24
+
25
+ def specificity
26
+ selector.specificity + sibling.specificity
27
+ end
28
+
29
+ def ==(other)
30
+ super && selector == other.selector && sibling == other.sibling
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,25 @@
1
+ require "css/sac/selectors"
2
+
3
+ module CSS
4
+ module SAC
5
+ module Selectors
6
+ class SimpleSelector < Selector
7
+ def initialize(selector_type=:SAC_ANY_NODE_SELECTOR)
8
+ super(selector_type)
9
+ end
10
+
11
+ def to_css
12
+ '*'
13
+ end
14
+
15
+ def to_xpath
16
+ "//*"
17
+ end
18
+
19
+ def specificity
20
+ 0
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end