csspool 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,170 @@
1
+ require File.dirname(__FILE__) + "/helper"
2
+
3
+ class SelectorParserTest < Test::Unit::TestCase
4
+ def setup
5
+ @sac = CSS::SAC::Parser.new()
6
+ class << @sac.document_handler
7
+ attr_reader :selectors
8
+ def start_selector(selectors)
9
+ @selectors = selectors
10
+ end
11
+ end
12
+ end
13
+
14
+ def test_multiple_selectors
15
+ @sac.parse('h1, h2 { }')
16
+ selectors = @sac.document_handler.selectors
17
+ assert_equal(2, selectors.length)
18
+ end
19
+
20
+ def test_adjacent
21
+ @sac.parse('h1 + h2 { }')
22
+ selectors = @sac.document_handler.selectors
23
+ assert_equal(1, selectors.length)
24
+
25
+ sel = selectors.first
26
+ assert_equal(:SAC_DIRECT_ADJACENT_SELECTOR, sel.selector_type)
27
+
28
+ sibling = sel.sibling_selector
29
+ assert sibling
30
+ assert_equal('h2', sibling.local_name)
31
+
32
+ first = sel.selector
33
+ assert first
34
+ assert_equal('h1', first.local_name)
35
+ end
36
+
37
+ def test_descendant_non_direct
38
+ @sac.parse('h1 h2 { }')
39
+ selectors = @sac.document_handler.selectors
40
+ assert_equal(1, selectors.length)
41
+
42
+ sel = selectors.first
43
+ assert_equal(:SAC_DESCENDANT_SELECTOR, sel.selector_type)
44
+
45
+ ancestor = sel.ancestor_selector
46
+ assert ancestor
47
+ assert_equal('h1', ancestor.local_name)
48
+
49
+ me = sel.selector
50
+ assert me
51
+ assert_equal('h2', me.local_name)
52
+ end
53
+
54
+ def test_descendant_direct
55
+ @sac.parse('h1 > h2 { }')
56
+ selectors = @sac.document_handler.selectors
57
+ assert_equal(1, selectors.length)
58
+
59
+ sel = selectors.first
60
+ assert_equal(:SAC_CHILD_SELECTOR, sel.selector_type)
61
+
62
+ ancestor = sel.ancestor_selector
63
+ assert ancestor
64
+ assert_equal('h1', ancestor.local_name)
65
+
66
+ me = sel.selector
67
+ assert me
68
+ assert_equal('h2', me.local_name)
69
+ end
70
+
71
+ @@single_selector_tests = {
72
+ :id => {
73
+ :css => '#foo { }',
74
+ :value => '#foo',
75
+ :type => :SAC_ID_CONDITION,
76
+ },
77
+ :class => {
78
+ :css => '.foo { }',
79
+ :value => 'foo',
80
+ :type => :SAC_CLASS_CONDITION,
81
+ },
82
+ :attribute => {
83
+ :css => '[foo=bar] { }',
84
+ :value => 'bar',
85
+ :type => :SAC_ATTRIBUTE_CONDITION,
86
+ },
87
+ :pseudo => {
88
+ :css => ':clicked { }',
89
+ :value => 'clicked',
90
+ :type => :SAC_PSEUDO_CLASS_CONDITION,
91
+ }
92
+ }
93
+
94
+ @@multiple_selector_tests = {
95
+ :ids => {
96
+ :css => '#foo#bar#baz { }',
97
+ :values => %w{ #foo #bar #baz },
98
+ :types => [:SAC_ID_CONDITION] * 3,
99
+ },
100
+ :classes => {
101
+ :css => '.foo.bar.baz { }',
102
+ :values => %w{ foo bar baz },
103
+ :types => [:SAC_CLASS_CONDITION] * 3,
104
+ },
105
+ :attributes => {
106
+ :css => '[foo=bar][bar=baz] { }',
107
+ :values => %w{ bar baz },
108
+ :types => [:SAC_ATTRIBUTE_CONDITION] * 2,
109
+ },
110
+ :pseudo => {
111
+ :css => ':clicked:hover { }',
112
+ :values => %w{ clicked hover },
113
+ :types => [:SAC_PSEUDO_CLASS_CONDITION] * 2,
114
+ }
115
+ }
116
+
117
+ @@single_selector_tests.each do |name,tests|
118
+ define_method :"test_single_#{name}" do
119
+ @sac.parse(tests[:css])
120
+ selectors = @sac.document_handler.selectors
121
+ assert_equal(1, selectors.length)
122
+
123
+ selector = selectors.first
124
+ assert_nil selector.simple_selector
125
+ assert selector.condition
126
+ assert_equal(:SAC_CONDITIONAL_SELECTOR, selector.selector_type)
127
+
128
+ condition = selector.condition
129
+ assert_equal(tests[:type], condition.condition_type)
130
+ assert_equal(tests[:value], condition.value)
131
+ end
132
+ end
133
+
134
+ @@multiple_selector_tests.each do |name,tests|
135
+ define_method :"test_multiple_#{name}" do
136
+ @sac.parse(tests[:css])
137
+ selectors = @sac.document_handler.selectors
138
+ assert_equal(1, selectors.length)
139
+
140
+ selector = selectors.first
141
+ assert_nil selector.simple_selector
142
+ assert selector.condition
143
+ assert_equal(:SAC_CONDITIONAL_SELECTOR, selector.selector_type)
144
+
145
+ combined = reduce_combinator_condition(selector.condition)
146
+ assert_equal(tests[:values].length, combined.length)
147
+ assert_equal(tests[:values], combined.map { |x| x.value })
148
+ assert_equal(tests[:types], combined.map { |x| x.condition_type })
149
+ end
150
+ end
151
+
152
+ def reduce_combinator_condition(condition)
153
+ conditions = []
154
+ assert_equal(:SAC_AND_CONDITION, condition.condition_type)
155
+ first = condition.first_condition
156
+ second = condition.second_condition
157
+
158
+ assert first
159
+ assert second
160
+ assert_not_equal(:SAC_AND_CONDITION, first.condition_type)
161
+ conditions << first
162
+
163
+ if second.condition_type == :SAC_AND_CONDITION
164
+ conditions += reduce_combinator_condition(second)
165
+ else
166
+ conditions << second
167
+ end
168
+ conditions
169
+ end
170
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + "/helper"
2
+
3
+ class TokenTest < Test::Unit::TestCase
4
+ include CSS
5
+
6
+ def test_tokens_have_a_name_value_and_position
7
+ token = SAC::Token.new(:foo, "bar", 14)
8
+ assert_equal(:foo, token.name)
9
+ assert_equal("bar", token.value)
10
+ assert_equal(14, token.position)
11
+ end
12
+
13
+ def test_to_racc_token_returns_a_name_value_array
14
+ assert_equal([:foo, "bar"], SAC::Token.new(:foo, "bar", 99).to_racc_token)
15
+ end
16
+
17
+ def test_delimiter_token_is_always_delim
18
+ assert_equal(:delim, SAC::DelimiterToken.new(";", 99).name)
19
+ end
20
+
21
+ def test_delimiter_token_just_returns_values_for_racc
22
+ assert_equal(%w(; ;), SAC::DelimiterToken.new(";", 99).to_racc_token)
23
+ end
24
+ end
@@ -0,0 +1,117 @@
1
+ require File.dirname(__FILE__) + "/helper"
2
+
3
+ class TokenizerTest < Test::Unit::TestCase
4
+ include CSS::SAC
5
+
6
+ def setup
7
+ @tokenizer = Tokenizer.new
8
+ end
9
+
10
+ def test_tokenize
11
+ assert_equal([], @tokenizer.tokenize(""))
12
+ end
13
+
14
+ def test_parse_simple
15
+ text = '
16
+ @import "subs.css";
17
+ * { margin: 0px; }
18
+ body {
19
+ margin: 0px;
20
+ padding: 0px;
21
+ }'
22
+
23
+ assert_tokens(text,
24
+ [:IMPORT_SYM, "@import"],
25
+ [:STRING, "\"subs.css\""],
26
+ [:delim, ";"],
27
+ [:delim, "*"],
28
+ [:LBRACE, " {"],
29
+ [:IDENT, "margin"],
30
+ [:delim, ":"],
31
+ [:LENGTH, "0px"],
32
+ [:delim, ";"],
33
+ [:delim, "}"],
34
+ [:IDENT, "body"],
35
+ [:LBRACE, " {"],
36
+ [:IDENT, "margin"],
37
+ [:delim, ":"],
38
+ [:LENGTH, "0px"],
39
+ [:delim, ";"],
40
+ [:IDENT, "padding"],
41
+ [:delim, ":"],
42
+ [:LENGTH, "0px"],
43
+ [:delim, ";"],
44
+ [:delim, "}"])
45
+ end
46
+
47
+ def test_at_import
48
+ tokens = @tokenizer.tokenize('@import "subs.css" print;')
49
+ assert_equal(6, tokens.length)
50
+ end
51
+
52
+ def test_at_media
53
+ assert_tokens('@media print { h1 { color: black; } }',
54
+ [:MEDIA_SYM, "@media"],
55
+ [:IDENT, "print"],
56
+ [:LBRACE, " {"],
57
+ [:IDENT, "h1"],
58
+ [:LBRACE, " {"],
59
+ [:IDENT, "color"],
60
+ [:delim, ":"],
61
+ [:IDENT, "black"],
62
+ [:delim, ";"],
63
+ [:delim, "}"],
64
+ [:delim, "}"])
65
+ end
66
+
67
+ def test_at_page
68
+ tokens = @tokenizer.tokenize('@page print { color: black; }')
69
+ assert_equal(12, tokens.length)
70
+
71
+ tokens = @tokenizer.tokenize('@page :left { color: black; }')
72
+ assert_equal(13, tokens.length)
73
+
74
+ tokens = @tokenizer.tokenize('@page print :left { color: black; }')
75
+ assert_equal(15, tokens.length)
76
+ end
77
+
78
+ def test_two_strings
79
+ tokens = @tokenizer.tokenize('"one" "two"')
80
+ assert_equal(3, tokens.length)
81
+ end
82
+
83
+ def test_at_font_face
84
+ tokens = @tokenizer.tokenize('@font-face { color: black; }')
85
+ assert_equal(11, tokens.length)
86
+ end
87
+
88
+ def test_ignorable_at
89
+ tokens = @tokenizer.tokenize('@aaron { color: black; }')
90
+ assert_equal(11, tokens.length)
91
+ end
92
+
93
+ def test_function_token
94
+ assert_tokens("foo(aaron)", :FUNCTION, :IDENT, :delim)
95
+ end
96
+
97
+ def test_an_example_of_assert_tokens
98
+ assert_tokens("body { color: pink; }",
99
+ :IDENT, :LBRACE, :IDENT, :delim, [:IDENT, "pink"], :delim, :delim)
100
+ end
101
+
102
+ def assert_tokens(text, *expected)
103
+ tokens = @tokenizer.tokenize(text).reject { |t| t.name == :S }
104
+ # puts tokens.collect { |t| [t.name, t.value].inspect }.join(",\n")
105
+
106
+ assert_equal(expected.size, tokens.size)
107
+
108
+ count = 1
109
+
110
+ tokens.zip(expected).each do |sets|
111
+ token, expected_name, expected_value = sets.flatten
112
+ assert_equal(expected_name, token.name, "token #{count} name")
113
+ assert_equal(expected_value, token.value, "token #{count} value") if expected_value
114
+ count += 1
115
+ end
116
+ end
117
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.4
3
+ specification_version: 1
4
+ name: csspool
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2007-11-02 00:00:00 -07:00
8
+ summary: Parses CSS
9
+ require_paths:
10
+ - lib
11
+ email: aaronp@rubyforge.org
12
+ homepage: http://csspool.rubyforge.org/
13
+ rubyforge_project: csspool
14
+ description: CSSpool (pronounced "cesspool") is a validating SAC parser for CSS. The parser calls methods on a document handler depending on what it has found. CSSPool currently only supports CSS 2.1. CSSPool will not yield invalid properties or selectors.
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Aaron Patterson
31
+ files:
32
+ - CHANGELOG.txt
33
+ - Manifest.txt
34
+ - README.txt
35
+ - Rakefile
36
+ - lib/css/sac.rb
37
+ - lib/css/sac/attribute_condition.rb
38
+ - lib/css/sac/condition.rb
39
+ - lib/css/sac/document_handler.rb
40
+ - lib/css/sac/error_handler.rb
41
+ - lib/css/sac/generated_property_parser.rb
42
+ - lib/css/sac/lexeme.rb
43
+ - lib/css/sac/lexical_unit.rb
44
+ - lib/css/sac/parse_exception.rb
45
+ - lib/css/sac/parser.rb
46
+ - lib/css/sac/property_parser.rb
47
+ - lib/css/sac/selectors.rb
48
+ - lib/css/sac/token.rb
49
+ - lib/css/sac/tokenizer.rb
50
+ - lib/parser.y
51
+ - lib/property_parser.y
52
+ - lib/property_parser.y.erb
53
+ - test/helper.rb
54
+ - test/test_all.rb
55
+ - test/test_lexeme.rb
56
+ - test/test_lexical_unit.rb
57
+ - test/test_parse_error.rb
58
+ - test/test_parser.rb
59
+ - test/test_property_parser.rb
60
+ - test/test_selector_as_string.rb
61
+ - test/test_selector_parser.rb
62
+ - test/test_token.rb
63
+ - test/test_tokenizer.rb
64
+ test_files:
65
+ - test/test_all.rb
66
+ rdoc_options:
67
+ - --main
68
+ - README.txt
69
+ extra_rdoc_files:
70
+ - CHANGELOG.txt
71
+ - Manifest.txt
72
+ - README.txt
73
+ executables: []
74
+
75
+ extensions: []
76
+
77
+ requirements: []
78
+
79
+ dependencies:
80
+ - !ruby/object:Gem::Dependency
81
+ name: hoe
82
+ version_requirement:
83
+ version_requirements: !ruby/object:Gem::Version::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: 1.3.0
88
+ version: