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
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