csspress 0.0.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.
- 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
|