mirror of
https://github.com/haml/haml.git
synced 2022-11-09 12:33:31 -05:00
Added new "foo: bar" Sass syntax. Patch by Jonah Fox (aka Weepy) - thanks!
git-svn-id: svn://hamptoncatlin.com/haml/trunk@499 7063305b-7217-0410-af8c-cdc13e5119b9
This commit is contained in:
parent
d30629a966
commit
cc654e0890
10 changed files with 89 additions and 47 deletions
1
TODO
1
TODO
|
@ -1,6 +1,5 @@
|
|||
Bugs:
|
||||
Get rid of alias_method_chain dependency
|
||||
Move new is_haml? to stable
|
||||
|
||||
Testing:
|
||||
Test html2haml
|
||||
|
|
21
lib/sass.rb
21
lib/sass.rb
|
@ -77,12 +77,27 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
|
|||
#
|
||||
# === Attributes
|
||||
#
|
||||
# The syntax for attributes is also slightly different.
|
||||
# There are two different ways to write CSS attrbibutes.
|
||||
# The first is very similar to the how you're used to writing them:
|
||||
# with a colon between the name and the value.
|
||||
# However, Sass attributes don't have semicolons at the end;
|
||||
# each attribute is on its own line, so they aren't necessary.
|
||||
# For example:
|
||||
#
|
||||
# #main p
|
||||
# color: #00ff00
|
||||
# width: 97%
|
||||
#
|
||||
# is compiled to:
|
||||
#
|
||||
# #main p {
|
||||
# color: #00ff00;
|
||||
# width: 97% }
|
||||
#
|
||||
# The second syntax for attributes is slightly different.
|
||||
# The colon is at the beginning of the attribute,
|
||||
# rather than between the name and the value,
|
||||
# so it's easier to tell what elements are attributes just by glancing at them.
|
||||
# Attributes also don't have semicolons at the end;
|
||||
# each attribute is on its own line, so they aren't necessary.
|
||||
# For example:
|
||||
#
|
||||
# #main p
|
||||
|
|
|
@ -19,7 +19,7 @@ module Sass
|
|||
class Engine
|
||||
# The character that begins a CSS attribute.
|
||||
ATTRIBUTE_CHAR = ?:
|
||||
|
||||
|
||||
# The character that designates that
|
||||
# an attribute should be assigned to the result of constant arithmetic.
|
||||
SCRIPT_CHAR = ?=
|
||||
|
@ -38,10 +38,16 @@ module Sass
|
|||
|
||||
# The character used to denote a compiler directive.
|
||||
DIRECTIVE_CHAR = ?@
|
||||
|
||||
# The regex that matches attributes.
|
||||
ATTRIBUTE = /:([^\s=]+)\s*(=?)\s*(.*)/
|
||||
|
||||
|
||||
# The regex that matches attributes of the form <tt>:name attr</tt>.
|
||||
ATTRIBUTE = /:([^\s=:]+)\s*(=?)(?:\s|$)+(.*)/
|
||||
|
||||
# The regex that matches attributes of the form <tt>name: attr</tt>.
|
||||
ALTERNATE_ATTRIBUTE_SELECTOR = /^[^\s:]+:(\s+|$)/
|
||||
|
||||
# The regex that extracts data from attributes of the form <tt>name: attr</tt>.
|
||||
ATTRIBUTE_ALTERNATE = /([^\s=]+):\s*(=?)\s*(.*)/
|
||||
|
||||
# Creates a new instace of Sass::Engine that will compile the given
|
||||
# template string when <tt>render</tt> is called.
|
||||
# See README for available options.
|
||||
|
@ -63,7 +69,7 @@ module Sass
|
|||
@lines = []
|
||||
@constants = {}
|
||||
end
|
||||
|
||||
|
||||
# Processes the template and returns the result as a string.
|
||||
def render
|
||||
begin
|
||||
|
@ -86,14 +92,14 @@ module Sass
|
|||
|
||||
def render_to_tree
|
||||
split_lines
|
||||
|
||||
|
||||
root = Tree::Node.new(@options[:style])
|
||||
index = 0
|
||||
while @lines[index]
|
||||
child, index = build_tree(index)
|
||||
|
||||
|
||||
if child.is_a? Tree::Node
|
||||
child.line = index
|
||||
child.line = index
|
||||
root << child
|
||||
elsif child.is_a? Array
|
||||
child.each do |c|
|
||||
|
@ -105,9 +111,9 @@ module Sass
|
|||
|
||||
root
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
# Readies each line in the template for parsing,
|
||||
# and computes the tabulation of the line.
|
||||
def split_lines
|
||||
|
@ -117,17 +123,17 @@ module Sass
|
|||
@line += 1
|
||||
|
||||
tabs = count_tabs(line)
|
||||
|
||||
|
||||
if line[0] == COMMENT_CHAR && line[1] == SASS_COMMENT_CHAR && tabs == 0
|
||||
tabs = old_tabs
|
||||
end
|
||||
|
||||
if tabs # if line isn't blank
|
||||
if tabs - old_tabs > 1
|
||||
raise SyntaxError.new("Illegal Indentation: Only two space characters are allowed as tabulation.", @line)
|
||||
raise SyntaxError.new("Illegal Indentation: Only two space characters are allowed as tabulation.", @line)
|
||||
end
|
||||
@lines << [line.strip, tabs]
|
||||
|
||||
|
||||
old_tabs = tabs
|
||||
else
|
||||
@lines << ['//', old_tabs]
|
||||
|
@ -136,7 +142,7 @@ module Sass
|
|||
|
||||
@line = nil
|
||||
end
|
||||
|
||||
|
||||
# Counts the tabulation of a line.
|
||||
def count_tabs(line)
|
||||
spaces = line.index(/[^ ]/)
|
||||
|
@ -145,14 +151,14 @@ module Sass
|
|||
# Make sure a line with just tabs isn't an error
|
||||
return nil if line.strip.empty?
|
||||
|
||||
raise SyntaxError.new("Illegal Indentation: Only two space characters are allowed as tabulation.", @line)
|
||||
raise SyntaxError.new("Illegal Indentation: Only two space characters are allowed as tabulation.", @line)
|
||||
end
|
||||
spaces / 2
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def build_tree(index)
|
||||
line, tabs = @lines[index]
|
||||
index += 1
|
||||
|
@ -184,7 +190,7 @@ module Sass
|
|||
else
|
||||
while has_children
|
||||
child, index = build_tree(index)
|
||||
|
||||
|
||||
if child == :constant
|
||||
raise SyntaxError.new("Constants may only be declared at the root of a document.", @line)
|
||||
elsif child.is_a? Array
|
||||
|
@ -197,10 +203,10 @@ module Sass
|
|||
has_children = has_children?(index, tabs)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return node, index
|
||||
end
|
||||
|
||||
|
||||
def has_children?(index, tabs)
|
||||
next_line = @lines[index]
|
||||
next_line && next_line[1] > tabs
|
||||
|
@ -209,36 +215,40 @@ module Sass
|
|||
def raw_next_line(index)
|
||||
[@lines[index][0], index + 1]
|
||||
end
|
||||
|
||||
|
||||
def parse_line(line)
|
||||
case line[0]
|
||||
when ATTRIBUTE_CHAR
|
||||
parse_attribute(line)
|
||||
when Constant::CONSTANT_CHAR
|
||||
parse_constant(line)
|
||||
when COMMENT_CHAR
|
||||
parse_comment(line)
|
||||
when DIRECTIVE_CHAR
|
||||
parse_directive(line)
|
||||
if line[0] == ATTRIBUTE_CHAR
|
||||
parse_attribute(line, ATTRIBUTE)
|
||||
elsif line.match(ALTERNATE_ATTRIBUTE_SELECTOR)
|
||||
parse_attribute(line, ATTRIBUTE_ALTERNATE)
|
||||
else
|
||||
Tree::RuleNode.new(line, @options[:style])
|
||||
case line[0]
|
||||
when Constant::CONSTANT_CHAR
|
||||
parse_constant(line)
|
||||
when COMMENT_CHAR
|
||||
parse_comment(line)
|
||||
when DIRECTIVE_CHAR
|
||||
parse_directive(line)
|
||||
else
|
||||
Tree::RuleNode.new(line, @options[:style])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def parse_attribute(line)
|
||||
name, eq, value = line.scan(ATTRIBUTE)[0]
|
||||
|
||||
def parse_attribute(line, attribute_regx)
|
||||
name, eq, value = line.scan(attribute_regx)[0]
|
||||
|
||||
if name.nil? || value.nil?
|
||||
raise SyntaxError.new("Invalid attribute: \"#{line}\"", @line)
|
||||
end
|
||||
|
||||
|
||||
if eq[0] == SCRIPT_CHAR
|
||||
value = Sass::Constant.parse(value, @constants, @line).to_s
|
||||
end
|
||||
|
||||
|
||||
Tree::AttrNode.new(name, value, @options[:style])
|
||||
end
|
||||
|
||||
|
||||
def parse_constant(line)
|
||||
name, value = line.scan(Sass::Constant::MATCH)[0]
|
||||
unless name && value
|
||||
|
@ -317,7 +327,7 @@ module Sass
|
|||
|
||||
@options[:load_paths].each do |path|
|
||||
full_path = File.join(path, filename) + '.sass'
|
||||
|
||||
|
||||
if File.readable?(full_path)
|
||||
new_filename = full_path
|
||||
break
|
||||
|
|
|
@ -10,7 +10,7 @@ module Sass::Tree
|
|||
end
|
||||
|
||||
def to_s(parent_name = nil)
|
||||
if name[-1] == ?: || value[-1] == ?;
|
||||
if value[-1] == ?;
|
||||
raise Sass::SyntaxError.new("Invalid attribute: #{declaration.dump} (This isn't CSS!)", @line)
|
||||
end
|
||||
real_name = name
|
||||
|
|
|
@ -21,7 +21,7 @@ class SassEngineTest < Test::Unit::TestCase
|
|||
": a" => 'Invalid attribute: ": a"',
|
||||
":= a" => 'Invalid attribute: ":= a"',
|
||||
"a\n :b" => 'Invalid attribute: ":b "',
|
||||
"a\n :b: c" => 'Invalid attribute: ":b: c" (This isn\'t CSS!)',
|
||||
"a\n :b: c" => 'Invalid attribute: ":b: c"',
|
||||
"a\n :b c;" => 'Invalid attribute: ":b c;" (This isn\'t CSS!)',
|
||||
":a" => 'Attributes aren\'t allowed at the root of a document.',
|
||||
"!" => 'Invalid constant: "!"',
|
||||
|
|
|
@ -8,7 +8,7 @@ RAILS_ENV = 'testing'
|
|||
require 'sass/plugin'
|
||||
|
||||
class SassPluginTest < Test::Unit::TestCase
|
||||
@@templates = %w{ complex constants parent_ref import }
|
||||
@@templates = %w{ complex constants parent_ref import alt }
|
||||
|
||||
def setup
|
||||
Sass::Plugin.options = {
|
||||
|
|
3
test/sass/results/alt.css
Normal file
3
test/sass/results/alt.css
Normal file
|
@ -0,0 +1,3 @@
|
|||
h1 { float: left; width: 274px; height: 75px; margin: 0; background-repeat: no-repeat; background-image: none; }
|
||||
h1 a:hover, h1 a:visited { color: green; }
|
||||
h1 b:hover { color: red; background-color: green; }
|
|
@ -63,7 +63,7 @@ body { margin: 0; font: 0.85em "Lucida Grande", "Trebuchet MS", Verdana, sans-se
|
|||
#content .container.comments .column.left .box li { list-style-type: none; padding: 10px; margin: 0 0 1em 0; background: #6e000d; border-top: 5px solid #a20013; }
|
||||
#content .container.comments .column.left .box li div { margin-bottom: 1em; }
|
||||
#content .container.comments .column.left .box li ul { text-align: right; }
|
||||
#content .container.comments .column.left .box li ul li { display: inline; border: none; padding: 0; }; }
|
||||
#content .container.comments .column.left .box li ul li { display: inline; border: none; padding: 0; }
|
||||
#content .container.comments .column.right { width: 290px; padding-left: 10px; }
|
||||
#content .container.comments .column.right h2 { margin: 0; padding: 0.5em; background: #6e000d url(/images/hdr_addcomment.gif) 2px 2px no-repeat; text-indent: -9999px; border-top: 5px solid #a20013; }
|
||||
#content .container.comments .column.right .box textarea { width: 290px; height: 100px; border: none; }
|
||||
|
|
13
test/sass/templates/alt.sass
Normal file
13
test/sass/templates/alt.sass
Normal file
|
@ -0,0 +1,13 @@
|
|||
h1
|
||||
:float left
|
||||
:width 274px
|
||||
height: 75px
|
||||
margin: 0
|
||||
background:
|
||||
repeat: no-repeat
|
||||
:image none
|
||||
a:hover, a:visited
|
||||
color: green
|
||||
b:hover
|
||||
color: red
|
||||
:background-color green
|
|
@ -247,7 +247,9 @@ body
|
|||
ul
|
||||
:text-align right
|
||||
li
|
||||
:display inline; border: none; padding: 0; }
|
||||
:display inline
|
||||
:border none
|
||||
:padding 0
|
||||
.column.right
|
||||
:width 290px
|
||||
:padding-left 10px
|
||||
|
|
Loading…
Reference in a new issue