csspress 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +32 -0
- data/PostInstall.txt +8 -0
- data/README.txt +63 -0
- data/Rakefile +4 -0
- data/bin/css +198 -0
- data/config/hoe.rb +72 -0
- data/config/requirements.rb +15 -0
- data/lib/csspress.rb +21 -0
- data/lib/csspress/declaration.rb +144 -0
- data/lib/csspress/rule.rb +123 -0
- data/lib/csspress/style_sheet.rb +243 -0
- data/lib/csspress/template_builder.rb +73 -0
- data/lib/csspress/version.rb +20 -0
- data/lib/templates/default.csst +1 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/spec/csspress_spec.rb +11 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- data/website/index.html +15 -0
- data/website/index.txt +3 -0
- data/website/stylesheets/screen.css +18 -0
- data/website/template.html.erb +14 -0
- metadata +99 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# declaration.rb
|
4
|
+
#
|
5
|
+
# Created by David Madden on 2008-05-14.
|
6
|
+
# Copyright 2008 David Madden. All rights reserved.
|
7
|
+
#
|
8
|
+
# This is Free Software. See LICENSE for details.
|
9
|
+
|
10
|
+
# Declaration represents a declaration in a style sheet rule.
|
11
|
+
# It is composed of a property and a value. The property must be
|
12
|
+
# valid.
|
13
|
+
#
|
14
|
+
# Declaration takes a string and populates itself.
|
15
|
+
#
|
16
|
+
# Example:
|
17
|
+
# d = declaration.new ( "border-color : blue" )
|
18
|
+
# puts d.property #=> "border-color"
|
19
|
+
# puts d.value #=> "blue"
|
20
|
+
#
|
21
|
+
class Declaration
|
22
|
+
|
23
|
+
# Declaration property
|
24
|
+
attr_reader :property
|
25
|
+
# Declaration value
|
26
|
+
attr_reader :value
|
27
|
+
|
28
|
+
# internal error for invalid property types
|
29
|
+
#
|
30
|
+
class PropertyError < StandardError
|
31
|
+
# do nothing - just creating a specific error
|
32
|
+
end
|
33
|
+
|
34
|
+
# Properties for CSS1 to CSS3
|
35
|
+
VALID_PROPERTIES = %w(
|
36
|
+
alignment-adjust alignment-baseline appearance azimuth background background-attachment background-break
|
37
|
+
background-clip background-color background-image background-origin background-position background-repeat
|
38
|
+
background-size baseline-shift binding bookmark-label bookmark-level bookmark-target border border-bottom
|
39
|
+
border-bottom-color border-bottom-left-radius border-bottom-right-radius border-bottom-style border-bottom-width
|
40
|
+
border-break border-collapse border-color border-image border-left border-left-color border-left-style
|
41
|
+
border-left-width border-length border-radius border-right border-right-color border-right-style border-right-width
|
42
|
+
border-spacing border-style border-top border-top-color border-top-left-radius border-top-right-radius border-top-style
|
43
|
+
border-top-width border-width bottom box-align box-direction box-flex box-flex-group box-lines box-orient box-pack
|
44
|
+
box-shadow box-sizing caption-side clear clip color color-profile column-break-after column-break-before column-count
|
45
|
+
column-fill column-gap column-rule column-rule-color column-rule-style column-rule-width column-span column-width columns
|
46
|
+
content counter-increment counter-reset crop cue cue-after cue-before cursor direction display dominant-baseline
|
47
|
+
drop-initial-after-adjust drop-initial-after-align drop-initial-before-adjust drop-initial-before-align
|
48
|
+
drop-initial-size drop-initial-value elevation empty-cells fit fit-position float float-offset font
|
49
|
+
font-effect font-emphasize font-emphasize-position font-emphasize-style font-family font-size font-size-adjust
|
50
|
+
font-smooth font-stretch font-style font-variant font-weight grid-columns grid-rows hanging-punctuation height
|
51
|
+
hyphenate-after hyphenate-before hyphenate-character hyphenate-lines hyphenate-resource hyphens icon image-orientation
|
52
|
+
image-resolution inline-box-align left letter-spacing line-height line-stacking line-stacking-ruby line-stacking-shift
|
53
|
+
line-stacking-strategy list-style list-style-image list-style-position list-style-type margin margin-bottom margin-left
|
54
|
+
margin-right margin-top mark mark-after mark-before marker-offset marks marquee-direction marquee-loop marquee-speed
|
55
|
+
marquee-style max-height max-width min-height min-width move-to nav-down nav-index nav-left nav-right nav-up opacity orphans
|
56
|
+
outline outline-color outline-offset outline-style outline-width overflow overflow-style overflow-x overflow-y padding
|
57
|
+
padding-bottom padding-left padding-right padding-top page page-break-after page-break-before page-break-inside page-policy
|
58
|
+
pause pause-after pause-before phonemes pitch pitch-range play-during position presentation-level punctuation-trim quotes
|
59
|
+
rendering-intent resize rest rest-after rest-before richness right rotation rotation-point ruby-align ruby-overhang ruby-position
|
60
|
+
ruby-span size speak speak-header speak-numeral speak-punctuation speech-rate stress string-set tab-side table-layout target
|
61
|
+
target-name target-new target-position text-align text-align-last text-decoration text-emphasis text-height text-indent
|
62
|
+
text-justify text-outline text-replace text-shadow text-transform text-wrap top unicode-bidi vertical-align visibility
|
63
|
+
voice-balance voice-duration voice-family voice-pitch voice-pitch-range voice-rate voice-stress voice-volume volume
|
64
|
+
white-space white-space-collapse widows width word-break word-spacing word-wrap z-index
|
65
|
+
)
|
66
|
+
|
67
|
+
## Create a new Declaration from a string
|
68
|
+
# (The string should be valid CSS!)
|
69
|
+
#
|
70
|
+
def initialize(text)
|
71
|
+
dp = DeclarationParser.new(text)
|
72
|
+
@property = dp.property
|
73
|
+
@value = dp.value
|
74
|
+
end
|
75
|
+
|
76
|
+
# Print out the rule neatly
|
77
|
+
#
|
78
|
+
def to_s
|
79
|
+
"#{@property}:#{@value}"
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
# This class parses the text entered and makes the
|
85
|
+
# property and value available to the Declaration that
|
86
|
+
# initialised it.
|
87
|
+
#
|
88
|
+
class DeclarationParser #:nodoc:
|
89
|
+
attr_reader :property, :value
|
90
|
+
|
91
|
+
def initialize(raw_data)
|
92
|
+
@raw_data = raw_data
|
93
|
+
@property = ""
|
94
|
+
@value = ""
|
95
|
+
parse
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
# Call methods to parse @raw_data and
|
101
|
+
# extract the property and name.
|
102
|
+
#
|
103
|
+
# Raise an error if the property found
|
104
|
+
# is invalid.
|
105
|
+
#
|
106
|
+
def parse
|
107
|
+
@property = get_property
|
108
|
+
raise PropertyError, "Invalid property type found: #{@property}" unless VALID_PROPERTIES.include? @property
|
109
|
+
@value = get_value
|
110
|
+
end
|
111
|
+
|
112
|
+
# Get the property from @raw_data
|
113
|
+
#---
|
114
|
+
# The property is the part of @raw_data
|
115
|
+
# before the ':' character.
|
116
|
+
#+++
|
117
|
+
#
|
118
|
+
def get_property
|
119
|
+
@raw_data.slice(0, @raw_data.index(":")).strip
|
120
|
+
end
|
121
|
+
|
122
|
+
# Get the value from @raw_data
|
123
|
+
#---
|
124
|
+
# The value is the part of @raw_data
|
125
|
+
# after the ':' character.
|
126
|
+
#+++
|
127
|
+
#
|
128
|
+
def get_value
|
129
|
+
@raw_data.slice(@raw_data.index(":")+1..@raw_data.size-1).strip
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
|
136
|
+
if __FILE__ == $0
|
137
|
+
begin
|
138
|
+
d = Declaration.new("backgrond-color: sdfds")
|
139
|
+
puts d.property
|
140
|
+
puts d.value
|
141
|
+
rescue PropertyError => e
|
142
|
+
puts e.message
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# rule.rb
|
4
|
+
#
|
5
|
+
# Created by David Madden on 2008-05-14.
|
6
|
+
# Copyright 2008 David Madden. All rights reserved.
|
7
|
+
#
|
8
|
+
# This is Free Software. See LICENSE for details.
|
9
|
+
|
10
|
+
# Rule represents a rule in a style sheet.
|
11
|
+
# An example of a rule would be:
|
12
|
+
# body { margin : 0; padding : 0 }
|
13
|
+
#
|
14
|
+
# The components of a rule are:
|
15
|
+
# name { declarations }
|
16
|
+
#
|
17
|
+
# All declarations of Rule can be accessed using the
|
18
|
+
# .each_declaration(){} method where each declaration
|
19
|
+
# is passed to the block as a Declaration object.
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
# r = Rule.new ( "foo { margin: 0; padding: 0 }" )
|
23
|
+
# r.each_declaration do |dec|
|
24
|
+
# puts dec
|
25
|
+
# end
|
26
|
+
# puts r.name
|
27
|
+
#
|
28
|
+
class Rule
|
29
|
+
|
30
|
+
# name of the Rule
|
31
|
+
attr_reader :name
|
32
|
+
# declarations contained within Rule
|
33
|
+
attr_reader :declarations
|
34
|
+
|
35
|
+
# Create a new Rule from a string
|
36
|
+
# (The string should be a valid CSS rule!)
|
37
|
+
#
|
38
|
+
def initialize( string )
|
39
|
+
rp = RuleParser.new( string )
|
40
|
+
@name = rp.name
|
41
|
+
@declarations = rp.declarations
|
42
|
+
end
|
43
|
+
|
44
|
+
# Yeild all declarations for self
|
45
|
+
#
|
46
|
+
def each_declaration
|
47
|
+
@declarations.each do |declaration|
|
48
|
+
yield declaration
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Print out the rule neatly
|
53
|
+
#
|
54
|
+
def to_s
|
55
|
+
"#{@name}{#{@declarations.join(";")}}"
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# This class parses the text entered and makes the
|
61
|
+
# name and declarations available to the Rule that
|
62
|
+
# initialised it.
|
63
|
+
#
|
64
|
+
class RuleParser #:nodoc:
|
65
|
+
|
66
|
+
attr_reader :name, :declarations
|
67
|
+
|
68
|
+
# Create a new RuleParser and parse raw_data
|
69
|
+
#
|
70
|
+
def initialize( raw_data )
|
71
|
+
@raw_data = raw_data
|
72
|
+
@name = ""
|
73
|
+
@declarations = []
|
74
|
+
parse
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
# Calls the methods needed to retrieve the
|
80
|
+
# information from @raw_data
|
81
|
+
#
|
82
|
+
def parse
|
83
|
+
@name = get_rule_name
|
84
|
+
@declarations = get_declarations
|
85
|
+
end
|
86
|
+
|
87
|
+
# Get the name of the rule from @raw_data
|
88
|
+
#---
|
89
|
+
# Simply a case of cutting the front off the
|
90
|
+
# @raw data string up to the first '{' and
|
91
|
+
# remove any white space
|
92
|
+
# +++
|
93
|
+
#
|
94
|
+
def get_rule_name
|
95
|
+
@raw_data.slice(0, @raw_data.index("{")).strip
|
96
|
+
end
|
97
|
+
|
98
|
+
# Get an array of declartaions for the Rule.
|
99
|
+
#---
|
100
|
+
# Get the part of @raw_data between '{'..'}'
|
101
|
+
# This is all of the declaration text.
|
102
|
+
# Declarations are delimeted by ';' so
|
103
|
+
# the string is split on the semi-colon and
|
104
|
+
# a new Declaration object is created for each
|
105
|
+
# one.
|
106
|
+
#+++
|
107
|
+
#
|
108
|
+
def get_declarations
|
109
|
+
tmp = []
|
110
|
+
raw = @raw_data.slice(@raw_data.index("{")+1..@raw_data.index("}")-1).strip
|
111
|
+
raw.split(";").each do |line|
|
112
|
+
tmp << Declaration.new(line.strip)
|
113
|
+
end
|
114
|
+
tmp
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
if __FILE__ == $0
|
120
|
+
r = Rule.new("this is a test { background-color: sdfds; color:adlkasdj}")
|
121
|
+
puts r.name
|
122
|
+
puts r.declarations
|
123
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# style_sheet.rb
|
4
|
+
#
|
5
|
+
# Created by David Madden on 2008-05-14.
|
6
|
+
# Copyright 2008 David Madden. All rights reserved.
|
7
|
+
#
|
8
|
+
# This is Free Software. See LICENSE for details.
|
9
|
+
|
10
|
+
# StyleSheet is a container class for Rule objects which can be added
|
11
|
+
# individually using the .add() method. The Rule objects that StyleSheet
|
12
|
+
# contains can be accessed using the .each_rule(){} method which yields
|
13
|
+
# each Rule to the block.
|
14
|
+
#
|
15
|
+
# StyleSheet can also accept a CSS file as a paramiter to .new or using the
|
16
|
+
# .load() method. This file is then converted into Rule objects and they are
|
17
|
+
# added to StyleSheet. A compressed version of StyleSheet can be output using
|
18
|
+
# a TemplateBuilder object and passing it StyleSheet as a parameter.
|
19
|
+
#
|
20
|
+
# Example:
|
21
|
+
# ss = StyleSheet.new ( "foo.css" )
|
22
|
+
# tb = TemplateBuilder.new ( ss )
|
23
|
+
# puts tb.publish # output compressed version of ss
|
24
|
+
#
|
25
|
+
class StyleSheet
|
26
|
+
|
27
|
+
# rule objects
|
28
|
+
#---
|
29
|
+
# TODO: remove this and only allow access through each_rule.
|
30
|
+
# +++
|
31
|
+
attr_reader :rules
|
32
|
+
|
33
|
+
# Creates a new StyleSheet object. Can also accept a file name
|
34
|
+
# and parse the contents to initalize the StyleSheet with the file's
|
35
|
+
# contents.
|
36
|
+
#
|
37
|
+
def initialize(file=nil)
|
38
|
+
@rules = []
|
39
|
+
load file unless file.nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
# Yeild each style rule in self
|
43
|
+
#
|
44
|
+
def each_rule
|
45
|
+
@rules.each do |rule|
|
46
|
+
yield rule
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Output a compressed version of self
|
51
|
+
#
|
52
|
+
#def compress
|
53
|
+
# out = ""
|
54
|
+
# self.each_style do |rule|
|
55
|
+
# out << rule.compress
|
56
|
+
# end
|
57
|
+
# out
|
58
|
+
#end
|
59
|
+
|
60
|
+
# Load a CSS file into self
|
61
|
+
#
|
62
|
+
def load(file)
|
63
|
+
ssp = StyleSheetParser.new(file)
|
64
|
+
ssp.each { |rule| add(rule) }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Add a rule to self
|
68
|
+
#
|
69
|
+
def add(rule)
|
70
|
+
@rules << Rule.new(rule)
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
# Output self as String
|
75
|
+
#
|
76
|
+
def to_s
|
77
|
+
out = ""
|
78
|
+
self.each_rule do |rule|
|
79
|
+
out << "#{rule}\n"
|
80
|
+
end
|
81
|
+
out
|
82
|
+
end
|
83
|
+
|
84
|
+
# Number of Rules in Self
|
85
|
+
#
|
86
|
+
def size
|
87
|
+
@rules.size
|
88
|
+
end
|
89
|
+
|
90
|
+
# Alias of size
|
91
|
+
#
|
92
|
+
def length
|
93
|
+
size
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
# This class is responsible for processing a CSS file
|
99
|
+
# and allows iteration over the rules contained within
|
100
|
+
# the file to add to a StyleSheet object.
|
101
|
+
#--
|
102
|
+
# Due to the flexible nature of CSS syntax most of the
|
103
|
+
# work performed by the parser is envolved in normalizing
|
104
|
+
# the text into an array of style rules with the
|
105
|
+
# comments striped out.
|
106
|
+
#
|
107
|
+
# This parser uses patern matching and string manupulation
|
108
|
+
# rather than analysing the file byte, by byte. This may or
|
109
|
+
# may not be proved to be a good thing.
|
110
|
+
#
|
111
|
+
# At present all '@import' statements with in the CSS file are
|
112
|
+
# ignored!
|
113
|
+
#
|
114
|
+
# A file is processed as follows:
|
115
|
+
# 1. The file is read into an array (@raw_data)
|
116
|
+
# 2. White space is removed from the beginnig and end of each field in the @raw_data
|
117
|
+
# 3. Comments are sepatated into there own array fields as they could be mixed into style code
|
118
|
+
# 4. All fields with comments and empty fields are removed from @raw_data
|
119
|
+
# 5. All style rules are put in their own array field
|
120
|
+
# 6. Each field has any white space removed
|
121
|
+
# Data clean!
|
122
|
+
#
|
123
|
+
# Only the file in gerneral is parsed. Parsing of Rules and Declarations
|
124
|
+
# is handled by them internaly.
|
125
|
+
#++
|
126
|
+
#
|
127
|
+
class StyleSheetParser #:nodoc:
|
128
|
+
attr_reader :lines
|
129
|
+
|
130
|
+
# Creates new StyleSheetParser to parse the file
|
131
|
+
# file_name
|
132
|
+
#
|
133
|
+
def initialize( file_name )
|
134
|
+
@file = file_name
|
135
|
+
@raw_data = []
|
136
|
+
parse
|
137
|
+
end
|
138
|
+
|
139
|
+
# Yield each rule in the parsed file
|
140
|
+
#
|
141
|
+
def each
|
142
|
+
@raw_data.each do |rule|
|
143
|
+
yield rule
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
# Controls the processing of the data by calling
|
150
|
+
# a number of private functions.
|
151
|
+
#
|
152
|
+
# The order of the method calls is important and
|
153
|
+
# the successful removal of comments depends
|
154
|
+
# upon it!
|
155
|
+
#
|
156
|
+
def parse
|
157
|
+
get_lines
|
158
|
+
remove_white_space
|
159
|
+
separate_comments
|
160
|
+
delete_comments_and_blank_lines
|
161
|
+
separate_rules
|
162
|
+
remove_white_space
|
163
|
+
end
|
164
|
+
|
165
|
+
# Read in all lines of @file to @raw_data.
|
166
|
+
# Will raise an error if there is any problem with
|
167
|
+
# accessing the file.
|
168
|
+
#
|
169
|
+
def get_lines
|
170
|
+
begin
|
171
|
+
f = File.open( @file, 'r' )
|
172
|
+
@raw_data = f.readlines
|
173
|
+
rescue
|
174
|
+
raise IOError, "Could not process file: #{@file}"
|
175
|
+
ensure
|
176
|
+
f.close unless f.nil?
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# This removes white space from the beginning
|
181
|
+
# and end of every field in the @raw_data array,
|
182
|
+
# as well as removing runs of space characters.
|
183
|
+
#
|
184
|
+
def remove_white_space
|
185
|
+
@raw_data.each do |line|
|
186
|
+
line.strip! # remove white space from line beginnig and end
|
187
|
+
line.squeeze!( " " ) # remove runs of spaces
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Put a linebreak before and after every comment
|
192
|
+
# in @raw_data
|
193
|
+
#
|
194
|
+
def separate_comments
|
195
|
+
tmp = @raw_data.join(" ") # convert to string
|
196
|
+
tmp.gsub!( '/*', "\n/*" ) # add new line before comment
|
197
|
+
tmp.gsub!( '*/', "*/\n" ) # add new line after comment
|
198
|
+
@raw_data = tmp.split( "\n" ) # convert to array
|
199
|
+
end
|
200
|
+
|
201
|
+
# Remove comments and blank lines from @raw_data.
|
202
|
+
#
|
203
|
+
# This method currently also removes import stetments.
|
204
|
+
# TODO: move import handleing to separate method.
|
205
|
+
#
|
206
|
+
def delete_comments_and_blank_lines
|
207
|
+
tmp = []
|
208
|
+
@raw_data.each do |line|
|
209
|
+
line.strip! # remove any white space
|
210
|
+
next if line.length < 1 # ignore blank line
|
211
|
+
next if line =~ /\/\*/ # ignore comments
|
212
|
+
next if line =~ /import/ # ignore imports specially
|
213
|
+
tmp << line
|
214
|
+
end
|
215
|
+
@raw_data = tmp
|
216
|
+
end
|
217
|
+
|
218
|
+
# Add a new line character after every style rule
|
219
|
+
# in @raw_data
|
220
|
+
#
|
221
|
+
def separate_rules
|
222
|
+
tmp = @raw_data.join( " " ) # convert to string
|
223
|
+
tmp.gsub!( '}', "}\n" ) # add a new line after every style rule
|
224
|
+
@raw_data = tmp.split( "\n" ) # convert to array
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
if __FILE__ == $0
|
231
|
+
begin
|
232
|
+
ss = StyleSheet.new( "../test_data/style.css" )
|
233
|
+
#ss.load( "../test_data/style.css" )
|
234
|
+
tb = TemplateBuilder.new(ss)
|
235
|
+
puts tb.publish
|
236
|
+
rescue Declaration::PropertyError => e
|
237
|
+
puts e
|
238
|
+
rescue IOError => e
|
239
|
+
puts e
|
240
|
+
rescue Error => e
|
241
|
+
puts e
|
242
|
+
end
|
243
|
+
end
|