Skip to content

Commit

Permalink
Added license and readme along with ability to parse file, file name …
Browse files Browse the repository at this point in the history
…or style string
  • Loading branch information
andrewtimberlake committed Jan 6, 2011
1 parent 6620549 commit c378445
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 50 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
tags
*.gem
19 changes: 19 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (C) 2010 by Andrew Timberlake

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
11 changes: 11 additions & 0 deletions README.rdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
=CSS

A Ruby gem that allows the parsing and creation of css files.

==Quick Start

style = "body { background: #FFF url('image.png') no-repeat; }"
css = CSS::Parser.new.parse(style)
puts css['body'].background.color.to_s #=> #FFF
css['body'].background.position = 'top center'
puts css['body'].to_s #=> 'background: #FFF url('image.png') top center no-repeat'
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require 'rake/rdoctask'
require 'rake/testtask'

$LOAD_PATH.unshift('lib')
require 'css-parser'
require 'css'

desc 'Run code coverage'
task :coverage do |t|
Expand Down
1 change: 0 additions & 1 deletion css.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ Gem::Specification.new do |s|
]
s.files = [
"LICENSE",
"VERSION",
] + Dir['lib/**/*.rb']
s.homepage = %q{http://github.com/andrewtimberlake/css}
s.rdoc_options = ["--charset=UTF-8"]
Expand Down
123 changes: 76 additions & 47 deletions lib/css/parser.rb
Original file line number Diff line number Diff line change
@@ -1,59 +1,88 @@
module CSS
class Parser
def parse(file_name)
ruleset = RuleSet.new
# Parse a css style by string, file or file name
#
# ==Examples
# parser = CSS::Parser.new
# css = parser.parse("body { background: #FFF }")
#
# css = parser.parse("/home/andrew/style.css")
#
# File.open("style.css") do |file|
# css = parser.parse(file)
# end
def parse(file_file_name_or_style_string)
css_style = file_file_name_or_style_string
reset
lineno = 1
if css_style.respond_to?(:size) && css_style.size < 255 && File.exists?(css_style)
File.open(css_style) do |file|
file.each_line do |line|
parse_line(line, lineno)
lineno += 1
end
end
elsif css_style.respond_to?(:each_line)
css_style.each_line do |line|
parse_line(line, lineno)
lineno += 1
end
end

state = :selector
previous_state = nil
previous_char = nil
buffer = []
selector = nil
@ruleset
end

File.open(file_name) do |file|
file.each do |line|
char_count = 1
line.each_char do |char|
buffer << char unless state == :comment
private
def reset
@ruleset = RuleSet.new

case char
when '{'
if state == :selector
buffer.pop
selector = buffer.join.strip
buffer.clear
state = :ruleset
else
unless state == :comment
raise CSSError.new(file.lineno, char_count, "Unexpected '{'")
end
end
when '}'
unless state == :comment
buffer.pop
ruleset << Rule.new(selector, buffer.join.strip)
state = :selector
buffer.clear
end
when '/'
if previous_char == '*'
buffer.pop
state = previous_state
end
when '*'
if previous_char == '/'
buffer.pop
previous_state = state
state = :comment
@state = :selector
@previous_state = nil
@previous_char = nil
@buffer = []
@selector = nil
end

def parse_line(line, lineno)
char_count = 1
line.each_char do |char|
@buffer << char unless @state == :comment

case char
when '{'
if @state == :selector
@buffer.pop
@selector = @buffer.join.strip
@buffer.clear
@state = :ruleset
else
unless @state == :comment
raise CSSError.new(lineno, char_count, "Unexpected '{'")
end
end

previous_char = char unless char == ' '
char_count += 1
when '}'
unless @state == :comment
@buffer.pop
@ruleset << Rule.new(@selector, @buffer.join.strip)
@state = :selector
@buffer.clear
end
when '/'
if @previous_char == '*'
@buffer.pop
@state = @previous_state
end
when '*'
if @previous_char == '/'
@buffer.pop
@previous_state = @state
@state = :comment
end
end

@previous_char = char unless char == ' '
char_count += 1
end
end

ruleset
end
end
end
4 changes: 3 additions & 1 deletion lib/css/rule.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Shorthand conversions based on guide by Dustin Diaz - http://www.dustindiaz.com/css-shorthand/
require 'set'

module CSS
class Rule
include Colors
Expand All @@ -8,7 +10,7 @@ class Rule

def initialize(selector, rule_text)
@selector = selector
@properties = Set.new
@properties = ::Set.new
@rules = {}

parse_rules(@properties, @rules, rule_text)
Expand Down
35 changes: 35 additions & 0 deletions spec/lib/css/parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,41 @@ module CSS
end
end

context "parsing a CSS string" do
let(:style) { "body { background: #FFF url('image.png') no-repeat; color: #333 }" }
let(:css) { Parser.new.parse(style) }

it "should return the body background color" do
css['body'].backgroundColor.should == '#FFF'
end
end

context "parsing an open file" do
let(:css) do
css = nil
parser = Parser.new
File.open(fixture('style.css')) do |file|
css = parser.parse(file)
end
css
end

it "should return the body background color" do
css['body'].color.should == '#333333'
end
end

context "parsing two styles one after each other" do
it "should be able to parse both successfully" do
parser = Parser.new
css1 = parser.parse("body { color: #333 }")
css2 = parser.parse("body { color: #FFF }")

css1['body'].color.should == '#333'
css2['body'].color.should == '#FFF'
end
end

context "A failing parse" do
let(:error) do
error = nil
Expand Down

0 comments on commit c378445

Please sign in to comment.