mirror of
https://github.com/haml/haml.git
synced 2022-11-09 12:33:31 -05:00
Merge branch 'master' into new-attrs
Conflicts: TODO test/haml/engine_test.rb
This commit is contained in:
commit
99f21fb8a2
26 changed files with 356 additions and 108 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@
|
|||
/doc
|
||||
/pkg
|
||||
/test/rails
|
||||
/.sass-cache
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Copyright (c) 2006-2008 Hampton Catlin
|
||||
Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
|
69
README.md
69
README.md
|
@ -11,24 +11,34 @@ and providing elegant, easily understandable, and powerful syntax.
|
|||
|
||||
## Using
|
||||
|
||||
There are several ways to use Haml and Sass.
|
||||
They can be used as a plugin for Rails or Merb,
|
||||
or embedded on their own in other applications.
|
||||
The first step of all of these is to install the Haml gem:
|
||||
Haml and Sass can be used from the command line
|
||||
or as part of a Ruby web framework.
|
||||
The first step is to install the gem:
|
||||
|
||||
gem install haml
|
||||
|
||||
After you convert some HTML to Haml or some CSS to Sass,
|
||||
you can run
|
||||
|
||||
haml document.haml
|
||||
sass style.sass
|
||||
|
||||
to compile them.
|
||||
For more information on these commands, check out
|
||||
|
||||
haml --help
|
||||
sass --help
|
||||
|
||||
To install Haml and Sass as a Rails plugin,
|
||||
just run `haml --rails path/to/rails/app`
|
||||
and both Haml and Sass will be installed.
|
||||
Views with the `.haml` (or `.html.haml` for edge)
|
||||
extension will automatically use Haml.
|
||||
Views with the `.html.haml` extension will automatically use Haml.
|
||||
Sass is a little more complicated;
|
||||
`.sass` files should be placed in public/stylesheets/sass,
|
||||
`.sass` files should be placed in `public/stylesheets/sass`,
|
||||
where they'll be automatically compiled
|
||||
to corresponding CSS files in public/stylesheets when needed
|
||||
to corresponding CSS files in `public/stylesheets` when needed
|
||||
(the Sass template directory is customizable...
|
||||
see the Sass module docs for details).
|
||||
see [the Sass reference](http://sass-lang.com/docs/yardoc/SASS_REFERENCE.md.html#template_location-option) for details).
|
||||
|
||||
For Merb, `.html.haml` views will work without any further modification.
|
||||
To enable Sass, you also need to add a dependency.
|
||||
|
@ -36,11 +46,11 @@ To do so, just add
|
|||
|
||||
dependency "merb-haml"
|
||||
|
||||
to config/dependencies.rb (or config/init.rb in a flat/very flat Merb application).
|
||||
to `config/dependencies.rb` (or `config/init.rb` in a flat/very flat Merb application).
|
||||
Then it'll work just like it does in Rails.
|
||||
|
||||
To use Haml and Sass programatically,
|
||||
check out the RDocs for the Haml and Sass modules.
|
||||
check out the [YARD documentation](http://haml-lang.com/docs/yardoc).
|
||||
|
||||
## Formatting
|
||||
|
||||
|
@ -302,26 +312,27 @@ See `css2sass --help` for further information and options.
|
|||
|
||||
## Authors
|
||||
|
||||
Haml and Sass are designed by Hampton Catlin (hcatlin) and he is the author
|
||||
of the original implementation. However, Hampton doesn't even know his way
|
||||
around the code anymore and mostly just concentrates on the language issues.
|
||||
Hampton lives in Toronto, Ontario (though he's an American by birth) and
|
||||
is a partner at Unspace Interactive.
|
||||
Haml and Sass were created by [Hampton Catlin](http://hamptoncatlin.com)
|
||||
(hcatlin) and he is the author of the original implementation. However, Hampton
|
||||
doesn't even know his way around the code anymore and now occasionally consults
|
||||
on the language issues. Hampton lives in Jacksonville, Florida and is the lead
|
||||
mobile developer for Wikimedia.
|
||||
|
||||
Nathan Weizenbaum is the primary maintainer and architect of the "modern" Ruby
|
||||
implementation of Haml. His hard work has kept the project alive by endlessly
|
||||
answering forum posts, fixing bugs, refactoring, finding speed improvements,
|
||||
writing documentation, implementing new features, and getting Hampton
|
||||
coffee (a fitting task for a boy-genius). Nathan lives in Seattle, Washington and
|
||||
while not being a student at University of Washington he consults for
|
||||
Unspace Interactive and Microsoft.
|
||||
[Nathan Weizenbaum](http://nex-3.com) is the primary developer and architect of
|
||||
the "modern" Ruby implementation of Haml. His hard work has kept the project
|
||||
alive by endlessly answering forum posts, fixing bugs, refactoring, finding
|
||||
speed improvements, writing documentation, implementing new features, and
|
||||
getting Hampton coffee (a fitting task for a boy-genius). Nathan lives in
|
||||
Seattle, Washington and while not being a student at the University of
|
||||
Washington or working at an internship, he consults for Unspace Interactive.
|
||||
|
||||
Chris Eppstein is a core contributor to Sass and the creator of Compass, the first
|
||||
Sass-based framework. Chris focuses on making Sass more powerful, easy to use, and
|
||||
on ways to speed its adoption through the web development community. Chris lives in
|
||||
San Jose, CA with his wife and daughter. He is the Software Architect for Caring.com,
|
||||
a website devoted to the 34 Million caregivers whose parents are sick or elderly,
|
||||
that uses Haml and Sass.
|
||||
[Chris Eppstein](http://acts-as-architect.blogspot.com) is a core contributor to
|
||||
Sass and the creator of Compass, the first Sass-based framework. Chris focuses
|
||||
on making Sass more powerful, easy to use, and on ways to speed its adoption
|
||||
through the web development community. Chris lives in San Jose, California with
|
||||
his wife and daughter. He is the Software Architect for
|
||||
[Caring.com](http://caring.com), a website devoted to the 34 Million caregivers
|
||||
whose parents are sick or elderly, that uses Haml and Sass.
|
||||
|
||||
If you use this software, you must pay Hampton a compliment. And
|
||||
buy Nathan some jelly beans. Maybe pet a kitten. Yeah. Pet that kitty.
|
||||
|
|
21
Rakefile
21
Rakefile
|
@ -71,8 +71,9 @@ end
|
|||
|
||||
desc "Release a new Haml package to Rubyforge. Requires the NAME and VERSION flags."
|
||||
task :release => [:package] do
|
||||
name, version = ENV['NAME'], ENV['VERSION']
|
||||
raise "Must supply NAME and VERSION for release task." unless name && version
|
||||
name = File.read("VERSION_NAME").strip
|
||||
version = File.read("VERSION").strip
|
||||
raise "VERSION_NAME must not be 'Bleeding Edge'" if name == "Bleeding Edge"
|
||||
sh %{rubyforge login}
|
||||
sh %{rubyforge add_release haml haml "#{name} (v#{version})" pkg/haml-#{version}.gem}
|
||||
sh %{rubyforge add_file haml haml "#{name} (v#{version})" pkg/haml-#{version}.tar.gz}
|
||||
|
@ -81,6 +82,8 @@ task :release => [:package] do
|
|||
end
|
||||
|
||||
task :release_edge do
|
||||
puts "#{'=' * 50} Running rake release_edge"
|
||||
|
||||
sh %{git checkout edge-gem}
|
||||
sh %{git reset --hard origin/edge-gem}
|
||||
sh %{git merge origin/master}
|
||||
|
@ -153,11 +156,12 @@ rescue LoadError
|
|||
end
|
||||
|
||||
task :pages do
|
||||
puts "#{'=' * 50} Running rake pages PROJ=#{ENV["PROJ"].inspect}"
|
||||
raise 'No ENV["PROJ"]!' unless proj = ENV["PROJ"]
|
||||
sh %{git checkout #{proj}-pages}
|
||||
sh %{git reset --hard origin/#{proj}-pages}
|
||||
|
||||
sh %{staticmatic build .}
|
||||
sh %{rake build --trace}
|
||||
sh %{rsync -av --delete site/ /var/www/#{proj}-pages}
|
||||
end
|
||||
|
||||
|
@ -246,15 +250,22 @@ end
|
|||
# ----- Handling Updates -----
|
||||
|
||||
task :handle_update do
|
||||
puts
|
||||
puts
|
||||
puts '=' * 150
|
||||
puts "Running rake handle_update REF=#{ENV["REF"].inspect}"
|
||||
|
||||
sh %{git checkout master}
|
||||
sh %{git fetch origin}
|
||||
sh %{git reset --hard origin/master}
|
||||
|
||||
begin
|
||||
if ENV["REF"] == "refs/heads/master"
|
||||
sh %{rake release_edge}
|
||||
sh %{rake release_edge --trace}
|
||||
sh %{rake pages --trace PROJ=haml}
|
||||
sh %{rake pages --trace PROJ=sass}
|
||||
elsif ENV["REF"] =~ %r{^refs/heads/(haml|sass)-pages$}
|
||||
sh %{rake pages PROJ=#{$1}}
|
||||
sh %{rake pages --trace PROJ=#{$1}}
|
||||
end
|
||||
ensure
|
||||
sh %{git reset --hard HEAD}
|
||||
|
|
12
TODO
12
TODO
|
@ -10,7 +10,19 @@
|
|||
form_for needs -, not =
|
||||
|
||||
* Code
|
||||
** Haml
|
||||
Write HAML_CHANGELOG
|
||||
[2.4] Allow "!!! HTML5" to set :format => :html5 ?
|
||||
How do we deal with partials?
|
||||
[2.4] :ugly + :html improvements
|
||||
Ignore closing tags where we can
|
||||
http://code.google.com/speed/articles/optimizing-html.html
|
||||
Requires Haml parsing refactor
|
||||
Don't quote attributes that don't require it
|
||||
http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
|
||||
http://www.w3.org/TR/html5/syntax.html#attributes
|
||||
** Sass
|
||||
Add tests for ae4f319 and 4a901ed
|
||||
[2.4] CSS superset
|
||||
[2.4] Classes are mixins
|
||||
Can refer to specific property values? Syntax?
|
||||
|
|
1
VERSION_NAME
Normal file
1
VERSION_NAME
Normal file
|
@ -0,0 +1 @@
|
|||
Bleeding Edge
|
|
@ -24,27 +24,29 @@ with some code to generate dynamic content.
|
|||
## Using Haml
|
||||
|
||||
Haml can be used in three ways:
|
||||
as a command-line tool,
|
||||
as a plugin for Ruby on Rails,
|
||||
as a standalone Ruby module,
|
||||
and as a command-line tool.
|
||||
and as a standalone Ruby module.
|
||||
The first step for all of these is to install the Haml gem:
|
||||
|
||||
gem install haml
|
||||
|
||||
To enable it as a Rails plugin,
|
||||
then run
|
||||
|
||||
haml --rails path/to/rails/app
|
||||
|
||||
Once it's installed, all view files with the `".html.haml"` extension
|
||||
will be compiled using Haml.
|
||||
|
||||
To run Haml from the command line, just use
|
||||
|
||||
haml input.haml output.html
|
||||
|
||||
Use `haml --help` for full documentation.
|
||||
|
||||
### Rails/Merb Plugin {#plugin}
|
||||
|
||||
To enable Haml as a Rails plugin, run
|
||||
|
||||
haml --rails path/to/rails/app
|
||||
|
||||
Once it's installed, all view files with the `".html.haml"` extension
|
||||
will be compiled using Haml.
|
||||
Haml is enabled by default in Merb.
|
||||
|
||||
You can access instance variables in Haml templates
|
||||
the same way you do in ERB templates.
|
||||
Helper methods are also available in Haml templates.
|
||||
|
@ -153,6 +155,15 @@ Available options are:
|
|||
Defaults to `['textarea', 'pre']`.
|
||||
See also [Whitespace Preservation](#whitespace_preservation).
|
||||
|
||||
{#encoding-option} `:encoding`
|
||||
: The encoding to use for the HTML output.
|
||||
Only available in Ruby 1.9 or higher.
|
||||
This can be a string or an `Encoding` Object.
|
||||
Note that Haml **does not** automatically re-encode Ruby values;
|
||||
any strings coming from outside the application should be converted
|
||||
before being passed into the Haml template.
|
||||
Defaults to `Encoding.default_internal` or, if that's not set, `"utf-8"`.
|
||||
|
||||
## Plain Text
|
||||
|
||||
A substantial portion of any HTML document is its content,
|
||||
|
@ -232,7 +243,7 @@ is compiled to:
|
|||
Any string is a valid element name;
|
||||
Haml will automatically generate opening and closing tags for any element.
|
||||
|
||||
### Attributes: `{}`
|
||||
### Attributes: `{}` {#attributes}
|
||||
|
||||
Brackets represent a Ruby hash
|
||||
that is used for specifying the attributes of an element.
|
||||
|
@ -1011,14 +1022,16 @@ The pipe character designates a multiline string.
|
|||
It's placed at the end of a line (after some whitespace)
|
||||
and means that all following lines that end with `|`
|
||||
will be evaluated as though they were on the same line.
|
||||
**Note that even the last line in the multiline block
|
||||
should end wit `|`.**
|
||||
For example:
|
||||
|
||||
%whoo
|
||||
%hoo I think this might get |
|
||||
pretty long so I should |
|
||||
probably make it |
|
||||
multiline so it doesn't |
|
||||
look awful. |
|
||||
pretty long so I should |
|
||||
probably make it |
|
||||
multiline so it doesn't |
|
||||
look awful. |
|
||||
%p This is short.
|
||||
|
||||
is compiled to:
|
||||
|
@ -1030,6 +1043,17 @@ is compiled to:
|
|||
<p>This is short</p>
|
||||
</whoo>
|
||||
|
||||
Using multiline declarations in Haml is intentionally awkward.
|
||||
This is designed to discourage people from putting lots and lots of Ruby code
|
||||
in their Haml templates.
|
||||
If you find yourself using multiline declarations, stop and think:
|
||||
could I do this better with a helper?
|
||||
|
||||
Note that there is one case where it's useful to allow
|
||||
something to flow over onto multiple lines in a non-awkward manner: attributes.
|
||||
Some elements just have lots of attributes,
|
||||
so you can wrap attributes without using `|` (see [Attributes](#attributes)).
|
||||
|
||||
## Whitespace Preservation
|
||||
|
||||
Sometimes you don't want Haml to indent all your text.
|
||||
|
|
|
@ -114,7 +114,7 @@ Available options are:
|
|||
or `:width = !main_width`.
|
||||
By default, either syntax is valid.
|
||||
|
||||
{#cache-option} `cache`
|
||||
{#cache-option} `:cache`
|
||||
: Whether parsed Sass files should be cached,
|
||||
allowing greater speed. Defaults to true.
|
||||
|
||||
|
@ -150,7 +150,7 @@ Available options are:
|
|||
Defaults to false in production mode, true otherwise.
|
||||
Only has meaning within Ruby on Rails or Merb.
|
||||
|
||||
{#template-location-option} `:template_location`
|
||||
{#template_location-option} `:template_location`
|
||||
: A path to the root sass template directory for you application.
|
||||
If a hash, `:css_location` is ignored and this option designates
|
||||
both a mapping between input and output directories.
|
||||
|
@ -161,7 +161,7 @@ Available options are:
|
|||
This will be derived from the `:css_location` path list if not provided
|
||||
by appending a folder of "sass" to each corresponding css location.
|
||||
|
||||
{#css-location-option} `:css_location`
|
||||
{#css_location-option} `:css_location`
|
||||
: The path where CSS output should be written to.
|
||||
This option is ignored when `:template_location` is a Hash.
|
||||
Defaults to `RAILS_ROOT + "/public/stylesheets"`
|
||||
|
@ -1032,7 +1032,7 @@ Although the default CSS style that Sass outputs is very nice,
|
|||
and reflects the structure of the document in a similar way that Sass does,
|
||||
sometimes it's good to have other formats available.
|
||||
|
||||
Sass allows you to choose between three different output styles
|
||||
Sass allows you to choose between four different output styles
|
||||
by setting the `:style` option.
|
||||
In Rails, this is done by setting `Sass::Plugin.options[:style]`;
|
||||
outside Rails, it's done by passing an options hash with `:style` set.
|
||||
|
|
|
@ -6,5 +6,5 @@ set :environment, :production
|
|||
Dir.chdir(File.dirname(__FILE__) + "/..")
|
||||
|
||||
post "/" do
|
||||
system %{rake handle_update REF=#{JSON.parse(params["payload"])["ref"].inspect}}
|
||||
system %{rake handle_update --trace REF=#{JSON.parse(params["payload"])["ref"].inspect}}
|
||||
end
|
||||
|
|
|
@ -90,12 +90,8 @@ module Haml
|
|||
def initialize(upper = nil, options = {})
|
||||
@active = true
|
||||
@upper = upper
|
||||
@options = {
|
||||
:attr_wrapper => "'",
|
||||
:ugly => false,
|
||||
:format => :xhtml
|
||||
}.merge options
|
||||
@buffer = ""
|
||||
@options = options
|
||||
@buffer = ruby1_8? ? "" : "".encode(Encoding.find(options[:encoding]))
|
||||
@tabulation = 0
|
||||
|
||||
# The number of tabs that Engine thinks we should have
|
||||
|
|
|
@ -23,11 +23,6 @@ module Haml
|
|||
# @return [Hash<Symbol, Object>]
|
||||
attr_accessor :options
|
||||
|
||||
# The source code that is evaluated to produce the Haml document.
|
||||
#
|
||||
# @return [String]
|
||||
attr_accessor :precompiled
|
||||
|
||||
# The indentation used in the Haml document,
|
||||
# or `nil` if the indentation is ambiguous
|
||||
# (for example, for a single-level document).
|
||||
|
@ -55,6 +50,17 @@ module Haml
|
|||
@options[:format] == :html5
|
||||
end
|
||||
|
||||
# The source code that is evaluated to produce the Haml document.
|
||||
#
|
||||
# In Ruby 1.9, this is automatically converted to the correct encoding
|
||||
# (see {file:HAML_REFERENCE.md#encoding-option the `:encoding` option}).
|
||||
#
|
||||
# @return [String]
|
||||
def precompiled
|
||||
return @precompiled if ruby1_8?
|
||||
return @precompiled.encode(Encoding.find(@options[:encoding]))
|
||||
end
|
||||
|
||||
# Precompiles the Haml template.
|
||||
#
|
||||
# @param template [String] The Haml template
|
||||
|
@ -74,8 +80,11 @@ module Haml
|
|||
:line => 1,
|
||||
:ugly => false,
|
||||
:format => :xhtml,
|
||||
:escape_html => false
|
||||
:escape_html => false,
|
||||
}
|
||||
unless ruby1_8?
|
||||
@options[:encoding] = Encoding.default_internal || "utf-8"
|
||||
end
|
||||
@options.merge! options
|
||||
@index = 0
|
||||
|
||||
|
@ -83,6 +92,10 @@ module Haml
|
|||
raise Haml::Error, "Invalid format #{@options[:format].inspect}"
|
||||
end
|
||||
|
||||
if @options[:encoding] && @options[:encoding].is_a?(Encoding)
|
||||
@options[:encoding] = @options[:encoding].name
|
||||
end
|
||||
|
||||
# :eod is a special end-of-document marker
|
||||
@template = (template.rstrip).split(/\r\n|\r|\n/) + [:eod, :eod]
|
||||
@template_index = 0
|
||||
|
@ -169,7 +182,7 @@ END
|
|||
@haml_buffer = buffer
|
||||
end
|
||||
|
||||
eval(@precompiled, scope, @options[:filename], @options[:line])
|
||||
eval(precompiled, scope, @options[:filename], @options[:line])
|
||||
|
||||
# Get rid of the current buffer
|
||||
scope_object.instance_eval do
|
||||
|
@ -276,7 +289,8 @@ END
|
|||
:preserve => @options[:preserve],
|
||||
:attr_wrapper => @options[:attr_wrapper],
|
||||
:ugly => @options[:ugly],
|
||||
:format => @options[:format]
|
||||
:format => @options[:format],
|
||||
:encoding => @options[:encoding],
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -87,10 +87,10 @@ module Haml
|
|||
def process_result
|
||||
input, output = @options[:input], @options[:output]
|
||||
input_file, output_file = if input
|
||||
[nil, open_file(ARGV[0], 'w')]
|
||||
[nil, open_file(@args[0], 'w')]
|
||||
else
|
||||
@options[:filename] = ARGV[0]
|
||||
[open_file(ARGV[0]), open_file(ARGV[1], 'w')]
|
||||
@options[:filename] = @args[0]
|
||||
[open_file(@args[0]), open_file(@args[1], 'w')]
|
||||
end
|
||||
|
||||
input ||= input_file
|
||||
|
|
|
@ -101,7 +101,7 @@ END
|
|||
@haml_buffer = @haml_buffer.upper
|
||||
_erbout
|
||||
END
|
||||
preamble + locals_code(local_names) + @precompiled + postamble
|
||||
preamble + locals_code(local_names) + precompiled + postamble
|
||||
end
|
||||
|
||||
def locals_code(names)
|
||||
|
|
|
@ -15,7 +15,7 @@ module Haml
|
|||
# @param file [String] The filename relative to the Haml root
|
||||
# @return [String] The filename relative to the the working directory
|
||||
def scope(file)
|
||||
File.expand_path File.join(File.dirname(__FILE__), '..', '..', file)
|
||||
File.join(File.dirname(__FILE__), '..', '..', file)
|
||||
end
|
||||
|
||||
# Converts an array of `[key, value]` pairs to a hash.
|
||||
|
|
|
@ -10,27 +10,33 @@ module Haml
|
|||
|
||||
# Returns a hash representing the version of Haml.
|
||||
# The `:major`, `:minor`, and `:teeny` keys have their respective numbers as Fixnums.
|
||||
# The `:name` key has the name of the version.
|
||||
# The `:string` key contains a human-readable string representation of the version.
|
||||
# The `:number` key is the major, minor, and teeny keys separated by periods.
|
||||
# If Haml is checked out from Git, the `:rev` key will have the revision hash.
|
||||
# For example:
|
||||
#
|
||||
# {
|
||||
# :string=>"2.1.0.9616393",
|
||||
# :rev => "9616393b8924ef36639c7e82aa88a51a24d16949",
|
||||
# :major => 2, :minor => 1, :teeny => 0
|
||||
# :string => "2.1.0.9616393",
|
||||
# :rev => "9616393b8924ef36639c7e82aa88a51a24d16949",
|
||||
# :number => "2.1.0",
|
||||
# :major => 2, :minor => 1, :teeny => 0
|
||||
# }
|
||||
#
|
||||
# @return [Hash<Symbol, String/Symbol>] The version hash
|
||||
# @return [Hash<Symbol, String/Fixnum>] The version hash
|
||||
def version
|
||||
return @@version if defined?(@@version)
|
||||
|
||||
numbers = File.read(scope('VERSION')).strip.split('.').map { |n| n.to_i }
|
||||
name = File.read(scope('VERSION_NAME')).strip
|
||||
@@version = {
|
||||
:major => numbers[0],
|
||||
:minor => numbers[1],
|
||||
:teeny => numbers[2]
|
||||
:teeny => numbers[2],
|
||||
:name => name
|
||||
}
|
||||
@@version[:string] = [:major, :minor, :teeny].map { |comp| @@version[comp] }.compact.join('.')
|
||||
@@version[:number] = [:major, :minor, :teeny].map { |comp| @@version[comp] }.compact.join('.')
|
||||
@@version[:string] = @@version[:number].dup
|
||||
|
||||
if File.exists?(scope('REVISION'))
|
||||
rev = File.read(scope('REVISION')).strip
|
||||
|
@ -47,9 +53,9 @@ module Haml
|
|||
if rev
|
||||
@@version[:rev] = rev
|
||||
unless rev[0] == ?(
|
||||
@@version[:string] << "."
|
||||
@@version[:string] << rev[0...7]
|
||||
@@version[:string] << "." << rev[0...7]
|
||||
end
|
||||
@@version[:string] << " (#{name})"
|
||||
end
|
||||
|
||||
@@version
|
||||
|
|
|
@ -118,7 +118,19 @@ module Sass
|
|||
#
|
||||
# @return [Tree::Node] The parsed rule
|
||||
def rule
|
||||
return unless rule = @template.scan(/[^\{\};]+/)
|
||||
rule = ""
|
||||
loop do
|
||||
token = @template.scan(/(?:[^\{\};\/\s]|\/[^*])+/)
|
||||
if token.nil?
|
||||
return if rule.empty?
|
||||
break
|
||||
end
|
||||
rule << token
|
||||
break unless @template.match?(/\s|\/\*/)
|
||||
whitespace
|
||||
rule << " "
|
||||
end
|
||||
|
||||
rule.strip!
|
||||
directive = rule[0] == ?@
|
||||
|
||||
|
|
|
@ -170,7 +170,10 @@ module Sass
|
|||
lines = []
|
||||
string.gsub(/\r|\n|\r\n|\r\n/, "\n").scan(/^.*?$/).each_with_index do |line, index|
|
||||
index += (@options[:line] || 1)
|
||||
next if line.strip.empty?
|
||||
if line.strip.empty?
|
||||
lines.last.text << "\n" if lines.last && lines.last.comment?
|
||||
next
|
||||
end
|
||||
|
||||
line_tab_str = line[/^\s*/]
|
||||
unless line_tab_str.empty?
|
||||
|
@ -310,7 +313,7 @@ END
|
|||
when MIXIN_DEFINITION_CHAR
|
||||
parse_mixin_definition(line)
|
||||
when MIXIN_INCLUDE_CHAR
|
||||
if line.text[1].nil?
|
||||
if line.text[1].nil? || line.text[1] == ?\s
|
||||
Tree::RuleNode.new(line.text)
|
||||
else
|
||||
parse_mixin_include(line, root)
|
||||
|
|
|
@ -61,6 +61,21 @@ module Sass::Script
|
|||
|
||||
instance_methods.each { |m| undef_method m unless m.to_s =~ /^__/ }
|
||||
|
||||
|
||||
# Creates a {Color} object from red, green, and blue values.
|
||||
# @param red
|
||||
# A number between 0 and 255 inclusive
|
||||
# @param green
|
||||
# A number between 0 and 255 inclusive
|
||||
# @param blue
|
||||
# A number between 0 and 255 inclusive
|
||||
def rgb(red, green, blue)
|
||||
[red.value, green.value, blue.value].each do |v|
|
||||
raise ArgumentError.new("rgb color value of #{v} encountered. Must be between 0 and 255 inclusive.") if v <= 0 || v >= 255
|
||||
end
|
||||
Color.new([red.value, green.value, blue.value])
|
||||
end
|
||||
|
||||
# Creates a {Color} object from hue, saturation, and lightness
|
||||
# as per the CSS3 spec (http://www.w3.org/TR/css3-color/#hsl-color).
|
||||
#
|
||||
|
|
|
@ -170,5 +170,8 @@ module Sass::Script
|
|||
def to_i
|
||||
raise Sass::SyntaxError.new("#{self.inspect} is not an integer.")
|
||||
end
|
||||
|
||||
# @raise [Sass::SyntaxError] if this literal isn't an integer
|
||||
def assert_int!; to_i; end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -155,9 +155,20 @@ module Sass::Script
|
|||
# @param other [Literal] The right-hand side of the operator
|
||||
# @return [Boolean] Whether this number is equal to the other object
|
||||
def eq(other)
|
||||
Sass::Script::Bool.new(super.to_bool &&
|
||||
self.numerator_units.sort == other.numerator_units.sort &&
|
||||
self.denominator_units.sort == other.denominator_units.sort)
|
||||
return Sass::Script::Bool.new(false) unless other.is_a?(Sass::Script::Number)
|
||||
this = self
|
||||
begin
|
||||
if unitless?
|
||||
this = this.coerce(other.numerator_units, other.denominator_units)
|
||||
else
|
||||
other = other.coerce(numerator_units, denominator_units)
|
||||
end
|
||||
rescue Sass::SyntaxError => e
|
||||
raise e unless e.message =~ /^Incompatible units: /
|
||||
return Sass::Script::Bool.new(false)
|
||||
end
|
||||
|
||||
Sass::Script::Bool.new(this.value == other.value)
|
||||
end
|
||||
|
||||
# The SassScript `>` operation.
|
||||
|
@ -249,11 +260,36 @@ module Sass::Script
|
|||
(numerator_units.empty? || numerator_units.size == 1) && denominator_units.empty?
|
||||
end
|
||||
|
||||
# Returns this number converted to other units.
|
||||
# The conversion takes into account the relationship between e.g. mm and cm,
|
||||
# as well as between e.g. in and cm.
|
||||
#
|
||||
# If this number has no units, it will simply return itself
|
||||
# with the given units.
|
||||
#
|
||||
# An incompatible coercion, e.g. between px and cm, will raise an error.
|
||||
#
|
||||
# @param num_units [Array<String>] The numerator units to coerce this number into.
|
||||
# See {#numerator\_units}
|
||||
# @param den_units [Array<String>] The denominator units to coerce this number into.
|
||||
# See {#denominator\_units}
|
||||
# @return [Number] The number with the new units
|
||||
# @raise [Sass::SyntaxError] if the given units are incompatible with the number's
|
||||
# current units
|
||||
def coerce(num_units, den_units)
|
||||
Number.new(if unitless?
|
||||
self.value
|
||||
else
|
||||
self.value * coercion_factor(self.numerator_units, num_units) /
|
||||
coercion_factor(self.denominator_units, den_units)
|
||||
end, num_units, den_units)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def operate(other, operation)
|
||||
this = self
|
||||
if [:+, :-].include?(operation)
|
||||
if [:+, :-, :<=, :<, :>, :>=].include?(operation)
|
||||
if unitless?
|
||||
this = this.coerce(other.numerator_units, other.denominator_units)
|
||||
else
|
||||
|
@ -271,15 +307,6 @@ module Sass::Script
|
|||
end
|
||||
end
|
||||
|
||||
def coerce(num_units, den_units)
|
||||
Number.new(if unitless?
|
||||
self.value
|
||||
else
|
||||
self.value * coercion_factor(self.numerator_units, num_units) /
|
||||
coercion_factor(self.denominator_units, den_units)
|
||||
end, num_units, den_units)
|
||||
end
|
||||
|
||||
def coercion_factor(from_units, to_units)
|
||||
# get a list of unmatched units
|
||||
from_units, to_units = sans_common_units(from_units, to_units)
|
||||
|
|
|
@ -50,9 +50,13 @@ module Sass::Tree
|
|||
def to_s(tabs = 0, _ = nil)
|
||||
return if invisible?
|
||||
|
||||
content = (value.split("\n") + lines.map {|l| l.text})
|
||||
content.map! {|l| (l.empty? ? "" : " ") + l}
|
||||
content.first.gsub!(/^ /, '')
|
||||
content.last.gsub!(%r{ ?\*/ *$}, '')
|
||||
|
||||
spaces = ' ' * (tabs - 1)
|
||||
spaces + "/* " + (value.split("\n") + lines.map {|l| l.text}).
|
||||
map{|l| l.sub(%r{ ?\*/ *$},'')}.join(style == :compact ? ' ' : "\n#{spaces} * ") + " */"
|
||||
spaces + "/* " + content.join(style == :compact ? '' : "\n#{spaces} *") + " */"
|
||||
end
|
||||
|
||||
# Returns `true` if this is a silent comment
|
||||
|
|
|
@ -28,14 +28,18 @@ module Sass::Tree
|
|||
# @return [Array<Tree::Node>] The resulting static nodes
|
||||
# @see Sass::Tree
|
||||
def _perform(environment)
|
||||
from = @from.perform(environment).to_i
|
||||
to = @to.perform(environment).to_i
|
||||
range = Range.new(from, to, @exclusive)
|
||||
from = @from.perform(environment)
|
||||
to = @to.perform(environment)
|
||||
from.assert_int!
|
||||
to.assert_int!
|
||||
|
||||
to = to.coerce(from.numerator_units, from.denominator_units)
|
||||
range = Range.new(from.to_i, to.to_i, @exclusive)
|
||||
|
||||
children = []
|
||||
environment = Sass::Environment.new(environment)
|
||||
range.each do |i|
|
||||
environment.set_local_var(@var, Sass::Script::Number.new(i))
|
||||
environment.set_local_var(@var, Sass::Script::Number.new(i, from.numerator_units, from.denominator_units))
|
||||
children += perform_children(environment)
|
||||
end
|
||||
children
|
||||
|
|
|
@ -130,7 +130,9 @@ module Sass
|
|||
result << child_str + (style == :compressed ? '' : "\n")
|
||||
end
|
||||
end
|
||||
style == :compressed ? result+"\n" : result[0...-1]
|
||||
result.rstrip!
|
||||
return "" if result.empty?
|
||||
return result + "\n"
|
||||
rescue Sass::SyntaxError => e; e.add_metadata(filename, line)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env ruby
|
||||
# -*- coding: utf-8 -*-
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
|
||||
class EngineTest < Test::Unit::TestCase
|
||||
|
@ -908,4 +909,55 @@ END
|
|||
assert_equal("<a a='b' b='c' c='d' d='e'>bar</a>\n",
|
||||
render("%a{:a => 'b',\n:b => 'c'}(c='d'\nd='e') bar"))
|
||||
end
|
||||
|
||||
# Encodings
|
||||
|
||||
unless Haml::Util.ruby1_8?
|
||||
def test_default_encoding
|
||||
assert_equal(Encoding.find("utf-8"), render(<<HAML.encode("us-ascii")).encoding)
|
||||
HTML
|
||||
%p bar
|
||||
%p foo
|
||||
HAML
|
||||
end
|
||||
|
||||
def test_convert_template_render
|
||||
assert_equal(<<HTML, render(<<HAML.encode("iso-8859-1"), :encoding => "utf-8"))
|
||||
<p>bâr</p>
|
||||
<p>föö</p>
|
||||
HTML
|
||||
%p bâr
|
||||
%p föö
|
||||
HAML
|
||||
end
|
||||
|
||||
def test_convert_template_render_proc
|
||||
assert_converts_template_properly {|e| e.render_proc.call}
|
||||
end
|
||||
|
||||
def test_convert_template_render
|
||||
assert_converts_template_properly {|e| e.render}
|
||||
end
|
||||
|
||||
def test_convert_template_def_method
|
||||
assert_converts_template_properly do |e|
|
||||
o = Object.new
|
||||
e.def_method(o, :render)
|
||||
o.render
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def assert_converts_template_properly
|
||||
engine = Haml::Engine.new(<<HAML.encode("iso-8859-1"), :encoding => "utf-8")
|
||||
%p bâr
|
||||
%p föö
|
||||
HAML
|
||||
assert_equal(<<HTML, yield(engine))
|
||||
<p>bâr</p>
|
||||
<p>föö</p>
|
||||
HTML
|
||||
end
|
||||
end
|
||||
|
|
|
@ -207,6 +207,29 @@ down_here { yeah: true; }
|
|||
CSS
|
||||
end
|
||||
|
||||
def test_comments_in_selectors
|
||||
assert_equal(<<SASS, css2sass(<<CSS))
|
||||
.js
|
||||
#location-navigation-form .form-submit, #business-listing-form .form-submit, #detailTabs ul, #detailsEnhanced #addTags, #locationSearchList, #moreHoods
|
||||
display: none
|
||||
|
||||
|
||||
#navListLeft
|
||||
display: none
|
||||
SASS
|
||||
.js #location-navigation-form .form-submit,
|
||||
.js #business-listing-form .form-submit,
|
||||
.js #detailTabs ul,
|
||||
/* .js #addReview, */
|
||||
/* .js #addTags, */
|
||||
.js #detailsEnhanced #addTags,
|
||||
.js #locationSearchList,
|
||||
.js #moreHoods,
|
||||
#navListLeft
|
||||
{ display: none; }
|
||||
CSS
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def css2sass(string, opts={})
|
||||
|
|
|
@ -76,8 +76,11 @@ class SassEngineTest < Test::Unit::TestCase
|
|||
"@if false\n@else if " => "Invalid else directive '@else if': expected 'if <expr>'.",
|
||||
"a\n !b = 12\nc\n d = !b" => 'Undefined variable: "!b".',
|
||||
"=foo\n !b = 12\nc\n +foo\n d = !b" => 'Undefined variable: "!b".',
|
||||
'@for !a from "foo" to 1' => '"foo" is not an integer.',
|
||||
'@for !a from 1 to "2"' => '"2" is not an integer.',
|
||||
'@for !a from 1 to "foo"' => '"foo" is not an integer.',
|
||||
'@for !a from 1 to 1.232323' => '1.232 is not an integer.',
|
||||
'@for !a from 1px to 3em' => "Incompatible units: 'em' and 'px'.",
|
||||
'@if' => "Invalid if directive '@if': expected expression.",
|
||||
'@while' => "Invalid while directive '@while': expected expression.",
|
||||
'@debug' => "Invalid debug directive '@debug': expected expression.",
|
||||
|
@ -186,8 +189,8 @@ SASS
|
|||
end
|
||||
|
||||
def test_css_import
|
||||
assert_equal("@import url(./fonts.css) screen;", render("@import url(./fonts.css) screen"))
|
||||
assert_equal("@import \"./fonts.css\" screen;", render("@import \"./fonts.css\" screen"))
|
||||
assert_equal("@import url(./fonts.css) screen;\n", render("@import url(./fonts.css) screen"))
|
||||
assert_equal("@import \"./fonts.css\" screen;\n", render("@import \"./fonts.css\" screen"))
|
||||
end
|
||||
|
||||
def test_sass_import
|
||||
|
@ -273,7 +276,7 @@ SASS
|
|||
end
|
||||
|
||||
def test_directive
|
||||
assert_equal("@a b;", render("@a b"))
|
||||
assert_equal("@a b;\n", render("@a b"))
|
||||
|
||||
assert_equal("@a {\n b: c; }\n", render("@a\n :b c"))
|
||||
assert_equal("@a { b: c; }\n", render("@a\n :b c", :style => :compact))
|
||||
|
@ -759,6 +762,30 @@ CSS
|
|||
SASS
|
||||
end
|
||||
|
||||
def test_plus_with_space
|
||||
assert_equal(<<CSS, render(<<SASS))
|
||||
a + b {
|
||||
color: green; }
|
||||
CSS
|
||||
a
|
||||
+ b
|
||||
color: green
|
||||
SASS
|
||||
end
|
||||
|
||||
def test_empty_line_comment
|
||||
assert_equal(<<CSS, render(<<SASS))
|
||||
/* Foo
|
||||
*
|
||||
* Bar */
|
||||
CSS
|
||||
/*
|
||||
Foo
|
||||
|
||||
Bar
|
||||
SASS
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render(sass, options = {})
|
||||
|
|
Loading…
Reference in a new issue