csspool 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +4 -0
- data/Manifest.txt +32 -0
- data/README.txt +71 -0
- data/Rakefile +56 -0
- data/lib/css/sac/attribute_condition.rb +78 -0
- data/lib/css/sac/condition.rb +21 -0
- data/lib/css/sac/document_handler.rb +67 -0
- data/lib/css/sac/error_handler.rb +14 -0
- data/lib/css/sac/generated_property_parser.rb +9214 -0
- data/lib/css/sac/lexeme.rb +29 -0
- data/lib/css/sac/lexical_unit.rb +111 -0
- data/lib/css/sac/parse_exception.rb +6 -0
- data/lib/css/sac/parser.rb +98 -0
- data/lib/css/sac/property_parser.rb +47 -0
- data/lib/css/sac/selectors.rb +87 -0
- data/lib/css/sac/token.rb +27 -0
- data/lib/css/sac/tokenizer.rb +186 -0
- data/lib/css/sac.rb +13 -0
- data/lib/parser.y +287 -0
- data/lib/property_parser.y +2346 -0
- data/lib/property_parser.y.erb +1321 -0
- data/test/helper.rb +7 -0
- data/test/test_all.rb +4 -0
- data/test/test_lexeme.rb +39 -0
- data/test/test_lexical_unit.rb +96 -0
- data/test/test_parse_error.rb +199 -0
- data/test/test_parser.rb +183 -0
- data/test/test_property_parser.rb +593 -0
- data/test/test_selector_as_string.rb +83 -0
- data/test/test_selector_parser.rb +170 -0
- data/test/test_token.rb +24 -0
- data/test/test_tokenizer.rb +117 -0
- metadata +88 -0
data/CHANGELOG.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
CHANGELOG.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
lib/css/sac.rb
|
6
|
+
lib/css/sac/attribute_condition.rb
|
7
|
+
lib/css/sac/condition.rb
|
8
|
+
lib/css/sac/document_handler.rb
|
9
|
+
lib/css/sac/error_handler.rb
|
10
|
+
lib/css/sac/generated_property_parser.rb
|
11
|
+
lib/css/sac/lexeme.rb
|
12
|
+
lib/css/sac/lexical_unit.rb
|
13
|
+
lib/css/sac/parse_exception.rb
|
14
|
+
lib/css/sac/parser.rb
|
15
|
+
lib/css/sac/property_parser.rb
|
16
|
+
lib/css/sac/selectors.rb
|
17
|
+
lib/css/sac/token.rb
|
18
|
+
lib/css/sac/tokenizer.rb
|
19
|
+
lib/parser.y
|
20
|
+
lib/property_parser.y
|
21
|
+
lib/property_parser.y.erb
|
22
|
+
test/helper.rb
|
23
|
+
test/test_all.rb
|
24
|
+
test/test_lexeme.rb
|
25
|
+
test/test_lexical_unit.rb
|
26
|
+
test/test_parse_error.rb
|
27
|
+
test/test_parser.rb
|
28
|
+
test/test_property_parser.rb
|
29
|
+
test/test_selector_as_string.rb
|
30
|
+
test/test_selector_parser.rb
|
31
|
+
test/test_token.rb
|
32
|
+
test/test_tokenizer.rb
|
data/README.txt
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
= CSSpool
|
2
|
+
|
3
|
+
http://csspool.rubyforge.org/
|
4
|
+
|
5
|
+
== Description
|
6
|
+
|
7
|
+
CSSpool (pronounced "cesspool") is a validating SAC parser for CSS. The parser
|
8
|
+
calls methods on a document handler depending on what it has found. CSSPool
|
9
|
+
currently only supports CSS 2.1. CSSPool will not yield invalid properties or
|
10
|
+
selectors.
|
11
|
+
|
12
|
+
== Dependencies
|
13
|
+
|
14
|
+
Building CSSpool requires:
|
15
|
+
|
16
|
+
- RACC (not just the runtime)
|
17
|
+
(http://i.loveruby.net/en/projects/racc)
|
18
|
+
|
19
|
+
- rubygems, hoe, flexmock
|
20
|
+
|
21
|
+
== Example
|
22
|
+
|
23
|
+
This example prints out all properties from a particular CSS file.
|
24
|
+
|
25
|
+
class DH < CSS::SAC::DocumentHandler
|
26
|
+
def start_selector(selectors)
|
27
|
+
puts selectors.map { |x| x.to_css }.join(', ')
|
28
|
+
end
|
29
|
+
|
30
|
+
def property(name, value, important)
|
31
|
+
puts "#{name} #{value.join(', ')} #{important}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
token = CSS::SAC::Parser.new(DH.new)
|
36
|
+
token.parse(File.read(ARGV[0]))
|
37
|
+
|
38
|
+
See CSS::SAC::DocumentHandler for callbacks to implement.
|
39
|
+
|
40
|
+
See SAC[http://www.w3.org/Style/CSS/SAC/] for more information on SAC.
|
41
|
+
|
42
|
+
== Authors
|
43
|
+
|
44
|
+
* Aaron Patterson[http://tenderlovemaking.com/] <aaronp@rubyforge.com>
|
45
|
+
* John Barnette
|
46
|
+
|
47
|
+
== LICENSE
|
48
|
+
|
49
|
+
(The MIT License)
|
50
|
+
|
51
|
+
Copyright (c) 2007 Aaron Patterson, John Barnette
|
52
|
+
|
53
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
54
|
+
a copy of this software and associated documentation files (the
|
55
|
+
'Software'), to deal in the Software without restriction, including
|
56
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
57
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
58
|
+
permit persons to whom the Software is furnished to do so, subject to
|
59
|
+
the following conditions:
|
60
|
+
|
61
|
+
The above copyright notice and this permission notice shall be
|
62
|
+
included in all copies or substantial portions of the Software.
|
63
|
+
|
64
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
65
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
66
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
67
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
68
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
69
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
70
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
71
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'erb'
|
3
|
+
require 'hoe'
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "lib")
|
6
|
+
|
7
|
+
GENERATED_PARSER = "lib/css/sac/generated_parser.rb"
|
8
|
+
GENERATED_PROPERTY_PARSER = "lib/css/sac/generated_property_parser.rb"
|
9
|
+
|
10
|
+
Hoe.new('csspool', '0.1.0') do |p|
|
11
|
+
p.rubyforge_name = 'csspool'
|
12
|
+
p.author = 'Aaron Patterson'
|
13
|
+
p.email = 'aaronp@rubyforge.org'
|
14
|
+
p.summary = "Parses CSS"
|
15
|
+
p.description = p.paragraphs_of('README.txt', 3).join("\n\n")
|
16
|
+
p.url = p.paragraphs_of('README.txt', 1).first.strip
|
17
|
+
p.changes = p.paragraphs_of('CHANGELOG.txt', 0..2).join("\n\n")
|
18
|
+
p.clean_globs = [GENERATED_PARSER]
|
19
|
+
end
|
20
|
+
|
21
|
+
class Array
|
22
|
+
def permutations
|
23
|
+
return [self] if size < 2
|
24
|
+
perm = []
|
25
|
+
each { |e| (self - [e]).permutations.each { |p| perm << ([e] + p) } }
|
26
|
+
perm
|
27
|
+
end
|
28
|
+
|
29
|
+
def permute_all_combinations
|
30
|
+
list = []
|
31
|
+
permutations.each do |perm|
|
32
|
+
while perm.length > 0
|
33
|
+
list << perm.dup
|
34
|
+
perm.shift
|
35
|
+
end
|
36
|
+
end
|
37
|
+
list.uniq.sort_by { |x| x.length }.reverse
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
file GENERATED_PARSER => "lib/parser.y" do |t|
|
42
|
+
sh "racc -o #{t.name} #{t.prerequisites.first}"
|
43
|
+
end
|
44
|
+
|
45
|
+
file GENERATED_PROPERTY_PARSER => "lib/property_parser.y.erb" do |t|
|
46
|
+
template = ERB.new(File.open(t.prerequisites.first, 'rb') { |x| x.read })
|
47
|
+
File.open("lib/property_parser.y", 'wb') { |f|
|
48
|
+
f.write template.result(binding)
|
49
|
+
}
|
50
|
+
sh "racc -o #{t.name} lib/property_parser.y"
|
51
|
+
end
|
52
|
+
|
53
|
+
task :parser => [GENERATED_PARSER, GENERATED_PROPERTY_PARSER]
|
54
|
+
|
55
|
+
# make sure the parser's up-to-date when we test
|
56
|
+
Rake::Task[:test].prerequisites << :parser
|
@@ -0,0 +1,78 @@
|
|
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
|
@@ -0,0 +1,21 @@
|
|
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
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module CSS
|
2
|
+
module SAC
|
3
|
+
class CSS::SAC::DocumentHandler
|
4
|
+
def initialize
|
5
|
+
end
|
6
|
+
|
7
|
+
# Receive notification of the beginning of a style sheet.
|
8
|
+
def start_document(input_source)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Receive notification of the end of a style sheet.
|
12
|
+
def end_document(input_source)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Receive notification of a comment
|
16
|
+
def comment(text)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Receive notification of an unknown at rule not supported by this parser.
|
20
|
+
def ignorable_at_rule(at_rule)
|
21
|
+
end
|
22
|
+
|
23
|
+
def namespace_declaration(prefix, uri)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Called on an import statement
|
27
|
+
def import_style(uri, media, default_namespace_uri = nil)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Notification of the start of a media statement
|
31
|
+
def start_media(media)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Notification of the end of a media statement
|
35
|
+
def end_media(media)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Notification of the start of a page statement
|
39
|
+
def start_page(name = nil, pseudo_page = nil)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Notification of the end of a page statement
|
43
|
+
def end_page(name = nil, pseudo_page = nil)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Notification of the beginning of a font face statement.
|
47
|
+
def start_font_face
|
48
|
+
end
|
49
|
+
|
50
|
+
# Notification of the end of a font face statement.
|
51
|
+
def end_font_face
|
52
|
+
end
|
53
|
+
|
54
|
+
# Notification of the beginning of a rule statement.
|
55
|
+
def start_selector(selectors)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Notification of the end of a rule statement.
|
59
|
+
def end_selector(selectors)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Notification of a declaration.
|
63
|
+
def property(name, value, important)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|