Merge commit 'origin/stable' into stable

This commit is contained in:
Nathan Weizenbaum 2009-09-23 15:58:25 -07:00
commit dd250ff079
14 changed files with 219 additions and 60 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@
/doc
/pkg
/test/rails
/test/haml/spec
/.sass-cache
/.haml
/site

4
CONTRIBUTING Normal file
View File

@ -0,0 +1,4 @@
Contributions are welcomed. Please see the following sites for guidelines:
http://haml-lang.com/development.html#contributing
http://sass-lang.com/development.html#contributing

View File

@ -69,11 +69,10 @@ task :install => [:package] do
sh %{#{sudo} #{gem} install --no-ri pkg/haml-#{File.read('VERSION').strip}}
end
desc "Release a new Haml package to Rubyforge. Requires the NAME and VERSION flags."
task :release => [:package] do
desc "Release a new Haml package to Rubyforge."
task :release => [:check_release, :release_elpa, :package] do
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 +80,87 @@ task :release => [:package] do
sh %{rubyforge add_file haml haml "#{name} (v#{version})" pkg/haml-#{version}.zip}
end
# Releases haml-mode.el and sass-mode.el to ELPA.
task :release_elpa do
require 'tlsmail'
require 'time'
version = File.read("VERSION").strip
haml_unchanged = mode_unchanged?(:haml, version)
sass_unchanged = mode_unchanged?(:sass, version)
next if haml_unchanged && sass_unchanged
raise "haml-mode.el and sass-mode.el are out of sync." if haml_unchanged ^ sass_unchanged
rev = File.read('.git/HEAD').strip
if rev =~ /^ref: (.*)$/
rev = File.read(".git/#{$1}").strip
end
from = `git config user.email`.strip
raise "Don't know how to send emails except via Gmail" unless from =~ /@gmail.com$/
to = "elpa@tromey.com"
Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
Net::SMTP.start('smtp.gmail.com', 587, 'gmail.com', from, read_password("GMail Password"), :login) do |smtp|
smtp.send_message(<<CONTENT, from, to)
From: Nathan Weizenbaum <#{from}>
To: #{to}
Subject: Submitting haml-mode and sass-mode #{version}
Date: #{Time.now.rfc2822}
haml-mode and sass-mode #{version} are packaged and ready to be included in ELPA.
They can be downloaded from:
http://github.com/nex3/haml/raw/#{rev}/extra/haml-mode.el
http://github.com/nex3/haml/raw/#{rev}/extra/sass-mode.el
CONTENT
end
end
# Ensures that the version have been updated for a new release.
task :check_release do
version = File.read("VERSION").strip
raise "There have been changes since current version (#{version})" if changed_since?(version)
raise "VERSION_NAME must not be 'Bleeding Edge'" if File.read("VERSION_NAME") == "Bleeding Edge"
end
# Reads a password from the command line.
#
# @param name [String] The prompt to use to read the password
def read_password(prompt)
require 'readline'
system "stty -echo"
Readline.readline("#{prompt}: ").strip
ensure
system "stty echo"
puts
end
# Returns whether or not the repository, or specific files,
# has/have changed since a given revision.
#
# @param rev [String] The revision to check against
# @param files [Array<String>] The files to check.
# If this is empty, checks the entire repository
def changed_since?(rev, *files)
IO.popen("git diff --exit-code #{rev} #{files.join(' ')}") {}
return !$?.success?
end
# Returns whether or not the given Emacs mode file (haml or sass)
# has changed since the given version.
#
# @param mode [String, Symbol] The name of the mode
# @param version [String] The version number
def mode_unchanged?(mode, version)
mode_version = File.read("extra/#{mode}-mode.el").scan(/^;; Version: (.*)$/).first.first
return false if mode_version == version
return true unless changed_since?(mode_version, "extra/#{mode}-mode.el")
raise "#{mode}-mode.el version is #{haml_mode_version.inspect}, but it has changed as of #{version.inspect}"
return false
end
task :release_edge do
ensure_git_cleanup do
puts "#{'=' * 50} Running rake release_edge"

View File

@ -1 +1 @@
2.2.4
2.2.5

View File

@ -3,6 +3,27 @@
* Table of contents
{:toc}
## 2.2.6 (Unreleased)
* Made the error message when unable to load a dependency for html2haml
respect the `--trace` option.
* Don't crash when the `__FILE__` constant of a Ruby file is a relative path,
as apparently happens sometimes in TextMate
(thanks to [Karl Varga](http://github.com/kjvarga).
* Add "Sass" to the `--version` string for the executables.
## [2.2.5](http://github.com/nex3/haml/commit/2.2.5)
* Got rid of trailing whitespace produced when opening a conditional comment
(thanks to [Norman Clarke](http://blog.njclarke.com/)).
* Fixed CSS id concatenation when a numeric id is given as an attribute.
(thanks to [Norman Clarke](http://blog.njclarke.com/)).
* Fixed a couple bugs with using "-end" in strings.
## [2.2.4](http://github.com/nex3/haml/commit/2.2.4)
* Allow `end` to be used for silent script when it's followed by code.

View File

@ -3,6 +3,18 @@
* Table of contents
{:toc}
## 2.2.6 (Unreleased)
* Don't crash when the `__FILE__` constant of a Ruby file is a relative path,
as apparently happens sometimes in TextMate
(thanks to [Karl Varga](http://github.com/kjvarga).
* Add "Sass" to the `--version` string for the executables.
## [2.2.5](http://github.com/nex3/haml/commit/2.2.5)
There were no changes made to Sass between versions 2.2.4 and 2.2.5.
## [2.2.4](http://github.com/nex3/haml/commit/2.2.4)
* Don't add `require 'rubygems'` to the top of init.rb when installed

View File

@ -4,8 +4,10 @@
;; Author: Nathan Weizenbaum
;; URL: http://github.com/nex3/haml/tree/master
;; Version: 1.0
;; Keywords: markup, language
;; Version: 2.2.5
;; Created: 2007-03-08
;; By: Nathan Weizenbaum
;; Keywords: markup, language, html
;;; Commentary:
@ -41,9 +43,9 @@
:group 'haml)
(defcustom haml-backspace-backdents-nesting t
"Non-nil to have `haml-electric-backspace' re-indent all code
nested beneath the backspaced line be re-indented along with the
line itself."
"Non-nil to have `haml-electric-backspace' re-indent blocks of code.
This means that all code nested beneath the backspaced line is
re-indented along with the line itself."
:type 'boolean
:group 'haml)
@ -55,7 +57,8 @@ line itself."
:group 'haml)
(defvar haml-indent-function 'haml-indent-p
"This function should look at the current line and return t
"A function for checking if nesting is allowed.
This function should look at the current line and return t
if the next line could be nested within this line.
The function can also return a positive integer to indicate
@ -75,12 +78,15 @@ a specific level to which the current line could be indented.")
"^ */\\(\\[.*\\]\\)?[ \t]*$"
"^ *-#"
"^ *:")
"A list of regexps that match lines of Haml that could have
text nested beneath them.")
"A list of regexps that match lines of Haml that open blocks.
That is, a Haml line that can have text nested beneath it should
be matched by a regexp in this list.")
;; Font lock
(defun haml-nested-regexp (re)
"Create a regexp to match a block starting with RE.
The line containing RE is matched, as well as all lines indented beneath it."
(concat "^\\( *\\)" re "\\(\n\\(?:\\(?:\\1 .*\\| *\\)\n\\)*\\(?:\\1 .*\\| *\\)?\\)?"))
(defconst haml-font-lock-keywords
@ -110,12 +116,14 @@ text nested beneath them.")
(font-lock-fontify-region (- beg 1) end)))))
(defun haml-highlight-ruby-script (limit)
"Highlight a Ruby script expression (-, =, or ~)."
"Highlight a Ruby script expression (-, =, or ~).
LIMIT works as it does in `re-search-forward'."
(when (re-search-forward "^ *\\(-\\|[&!]?[=~]\\) \\(.*\\)$" limit t)
(haml-fontify-region-as-ruby (match-beginning 2) (match-end 2))))
(defun haml-highlight-ruby-tag (limit)
"Highlight Ruby code within a Haml tag.
LIMIT works as it does in `re-search-forward'.
This highlights the tag attributes and object refs of the tag,
as well as the script expression (-, =, or ~) following the tag.
@ -189,13 +197,15 @@ For example, this will highlight all of the following:
t))
(defun haml-move (re)
"Try matching and moving to the end of a regular expression."
"Try matching and moving to the end of regular expression RE.
Returns non-nil if the expression was sucessfully matched."
(when (looking-at re)
(goto-char (match-end 0))
t))
(defun haml-highlight-interpolation (limit)
"Highlight Ruby interpolation (#{foo})."
"Highlight Ruby interpolation (#{foo}).
LIMIT works as it does in `re-search-forward'."
(when (re-search-forward "\\(#{\\)" limit t)
(save-match-data
(forward-char -1)
@ -209,8 +219,8 @@ For example, this will highlight all of the following:
t)))
(defun haml-limited-forward-sexp (limit &optional arg)
"Move forward using `forward-sexp' or to limit,
whichever comes first."
"Move forward using `forward-sexp' or to LIMIT, whichever comes first.
With ARG, do it that many times."
(let (forward-sexp-function)
(condition-case err
(save-restriction
@ -278,7 +288,7 @@ whichever comes first."
(modify-syntax-entry ?: "." table)
(modify-syntax-entry ?_ "w" table)
table)
"Syntax table in use in haml-mode buffers.")
"Syntax table in use in `haml-mode' buffers.")
(defvar haml-mode-map
(let ((map (make-sparse-keymap)))
@ -337,7 +347,8 @@ whichever comes first."
(haml-reindent-region-by (- haml-indent-offset))))
(defun haml-replace-region (start end)
"Replaces the current block of Haml code with the HTML equivalent."
"Replace the current block of Haml code with the HTML equivalent.
Called from a program, START and END specify the region to indent."
(interactive "r")
(save-excursion
(goto-char end)
@ -349,9 +360,10 @@ whichever comes first."
(shell-command-on-region start end "haml" "haml-output" t)))
(defun haml-output-region (start end)
"Displays the HTML output for the current block of Haml code."
"Displays the HTML output for the current block of Haml code.
Called from a program, START and END specify the region to indent."
(interactive "r")
(kill-new (buffer-substring start end))
(kill-new (buffer-substring start end))
(with-temp-buffer
(yank)
(haml-indent-region (point-min) (point-max))
@ -365,10 +377,11 @@ whichever comes first."
;; Navigation
(defun haml-forward-through-whitespace (&optional backward)
"Move the point forward at least one line, until it reaches
"Move the point forward through any whitespace.
The point will move forward at least one line, until it reaches
either the end of the buffer or a line with no whitespace.
If `backward' is non-nil, move the point backward instead."
If BACKWARD is non-nil, move the point backward instead."
(let ((arg (if backward -1 1))
(endp (if backward 'bobp 'eobp)))
(loop do (forward-line arg)
@ -376,9 +389,7 @@ If `backward' is non-nil, move the point backward instead."
(looking-at "^[ \t]*$")))))
(defun haml-at-indent-p ()
"Returns whether or not the point is at the first
non-whitespace character in a line or whitespace preceding that
character."
"Return non-nil if the point is before any text on the line."
(let ((opoint (point)))
(save-excursion
(back-to-indentation)
@ -386,7 +397,7 @@ character."
(defun haml-forward-sexp (&optional arg)
"Move forward across one nested expression.
With `arg', do it that many times. Negative arg -N means move
With ARG, do it that many times. Negative arg -N means move
backward across N balanced expressions.
A sexp in Haml is defined as a line of Haml code as well as any
@ -443,14 +454,14 @@ With ARG, do this that many times."
(back-to-indentation))
(defun haml-mark-sexp ()
"Marks the next Haml block."
"Mark the next Haml block."
(let ((forward-sexp-function 'haml-forward-sexp))
(mark-sexp)))
(defun haml-mark-sexp-but-not-next-line ()
"Marks the next Haml block, but puts the mark at the end of the
last line of the sexp rather than the first non-whitespace
character of the next line."
"Mark the next Haml block, but not the next line.
Put the mark at the end of the last line of the sexp rather than
the first non-whitespace character of the next line."
(haml-mark-sexp)
(set-mark
(save-excursion
@ -507,7 +518,7 @@ beginning the hash."
(when (eq (char-before) ?,) (return-from haml-unclosed-attr-hash-p t))
(re-search-backward "(\\|^")
(haml-move "(")
(haml-parse-new-attr-hash)))
(haml-parse-new-attr-hash)))
(defun* haml-parse-new-attr-hash (&optional (fn (lambda (type beg end) ())))
"Parse a new-style attribute hash on this line, and returns
@ -549,7 +560,8 @@ and BEG and END delimit that text in the buffer."
"Indent each nonblank line in the region.
This is done by indenting the first line based on
`haml-compute-indentation' and preserving the relative
indentation of the rest of the region.
indentation of the rest of the region. START and END specify the
region to indent.
If this command is used multiple times in a row, it will cycle
between possible indentations."
@ -610,7 +622,8 @@ lines in the region have indentation >= that of the first line."
"Delete characters or back-dent the current line.
If invoked following only whitespace on a line, will back-dent
the line and all nested lines to the immediately previous
multiple of `haml-indent-offset' spaces.
multiple of `haml-indent-offset' spaces. With ARG, do it that
many times.
Set `haml-backspace-backdents-nesting' to nil to just back-dent
the current line."

View File

@ -4,8 +4,10 @@
;; Author: Nathan Weizenbaum
;; URL: http://github.com/nex3/haml/tree/master
;; Version: 1.0
;; Keywords: markup, language
;; Version: 2.2.5
;; Created: 2007-03-15
;; By: Nathan Weizenbaum
;; Keywords: markup, language, css
;;; Commentary:
@ -42,8 +44,9 @@
(defvar sass-non-block-openers
'("^ *:[^ \t]+[ \t]+[^ \t]"
"^ *[^ \t:]+[ \t]*[=:][ \t]*[^ \t]")
"A list of regexps that match lines of Sass that couldn't have
text nested beneath them.")
"A list of regexps that match lines of Sass that don't open blocks.
That is, a Sass line that can't have text nested beneath it
should be matched by a regexp in this list.")
;; Font lock
@ -93,18 +96,18 @@ text nested beneath them.")
("\\(\\w+\\)\s*=" 1 font-lock-variable-name-face sass-highlight-script-after-match)
("\\(:\\w+\\)\s*=" 1 font-lock-variable-name-face sass-highlight-script-after-match)
(".*" sass-highlight-selector))
"A list of full-line Sass syntax to highlight,
used by `sass-highlight-line'.
"A list of full-line Sass syntax to highlight, used by `sass-highlight-line'.
Each item is either of the form (REGEXP SUBEXP FACE), (REGEXP FN),
or (REGEXP SUBEXP FACE FN). Each REGEXP is run successively on the
or (REGEXP SUBEXP FACE FN). Each REGEXP is run successively on the
beginning of non-whitespace on the current line until one matches.
If it has SUBEXP and FACE, then SUBEXP is highlighted using FACE.
If it has FN, FN is run.")
(defun sass-highlight-line (limit)
"Highlight a single line using some Sass single-line syntax,
taken from `sass-line-keywords'."
"Highlight a single line using some Sass single-line syntax.
This syntax is taken from `sass-line-keywords'.
LIMIT is the limit of the search."
(save-match-data
(when (re-search-forward "^ *\\(.+\\)$" limit t)
(goto-char (match-beginning 1))
@ -121,8 +124,7 @@ taken from `sass-line-keywords'."
(return t)))))))
(defun sass-highlight-selector ()
"Highlight a CSS selector starting at `point'
and ending at `end-of-line'."
"Highlight a CSS selector starting at `point' and ending at `end-of-line'."
(let ((font-lock-keywords sass-selector-font-lock-keywords)
font-lock-multiline)
(font-lock-fontify-region
@ -139,10 +141,12 @@ and ending at `end-of-line'."
(font-lock-fontify-region beg end)))))
(defun sass-highlight-script-after-match ()
"Highlight a section of SassScript after the last match."
(end-of-line)
(sass-highlight-script (match-end 0) (point)))
(defun sass-highlight-directive ()
"Highlight a Sass directive."
(goto-char (match-end 0))
(block nil
(case (intern (match-string 1))
@ -188,7 +192,7 @@ and ending at `end-of-line'."
;; Indentation
(defun sass-indent-p ()
"Returns t if the current line can have lines nested beneath it."
"Return non-nil if the current line can have lines nested beneath it."
(loop for opener in sass-non-block-openers
unless (looking-at opener) return t
return nil))

View File

@ -245,7 +245,7 @@ RUBY
# @return [Hash<String, String>] `to`, after being merged
def self.merge_attrs(to, from)
if to['id'] && from['id']
to['id'] << '_' << from.delete('id')
to['id'] << '_' << from.delete('id').to_s
elsif to['id'] || from['id']
from['id'] ||= to['id']
end

View File

@ -364,7 +364,8 @@ END
require 'haml/html'
rescue LoadError => err
dep = err.message.scan(/^no such file to load -- (.*)/)[0]
puts "Required dependency #{dep} not found!"
raise err if @options[:trace] || dep.nil? || dep.empty?
$stderr.puts "Required dependency #{dep} not found!\n Use --trace for backtrace."
exit 1
end
end

View File

@ -79,7 +79,7 @@ module Haml
#
# The block is ended after <tt>%p no!</tt>, because <tt>else</tt>
# is a member of this array.
MID_BLOCK_KEYWORD_REGEX = /-\s*(#{%w[else elsif rescue ensure when end].join('|')})\b/
MID_BLOCK_KEYWORD_REGEX = /^-\s*(#{%w[else elsif rescue ensure when end].join('|')})\b/
# The Regex that matches a Doctype command.
DOCTYPE_REGEX = /(\d\.\d)?[\s]*([a-z]*)/i
@ -109,8 +109,8 @@ END
names.map do |name|
# Can't use || because someone might explicitly pass in false with a symbol
sym_local = "_haml_locals[#{name.to_sym.inspect}]"
str_local = "_haml_locals[#{name.to_s.inspect}]"
sym_local = "_haml_locals[#{name.to_sym.inspect}]"
str_local = "_haml_locals[#{name.to_s.inspect}]"
"#{name} = #{sym_local}.nil? ? #{str_local} : #{sym_local}"
end.join(';') + ';'
end
@ -228,9 +228,9 @@ END
newline_now
# Handle stuff like - end.join("|")
@to_close_stack.first << false if text =~ /-\s*end\b/ && !block_opened?
@to_close_stack.first << false if text =~ /^-\s*end\b/ && !block_opened?
case_stmt = text =~ /-\s*case\b/
case_stmt = text =~ /^-\s*case\b/
block = block_opened? && !mid_block_keyword?(text)
push_and_tabulate([:script]) if block || case_stmt
push_and_tabulate(:nil) if block && case_stmt
@ -719,7 +719,7 @@ END
else
open_tag << "\n" unless parse || nuke_inner_whitespace || (self_closing && nuke_outer_whitespace)
end
push_merged_text(open_tag, tag_closed || self_closing || nuke_inner_whitespace ? 0 : 1,
!nuke_outer_whitespace)
@ -775,11 +775,11 @@ END
raise SyntaxError.new('Illegal nesting: nesting within a tag that already has content is illegal.', @next_line.index)
end
open = "<!--#{conditional} "
open = "<!--#{conditional}"
# Render it statically if possible
unless line.empty?
return push_text("#{open}#{line} #{conditional ? "<![endif]-->" : "-->"}")
return push_text("#{open} #{line} #{conditional ? "<![endif]-->" : "-->"}")
end
push_text(open, 1)

View File

@ -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.join(File.dirname(File.dirname(File.dirname(__FILE__))), file)
File.join(File.dirname(File.dirname(File.dirname(File.expand_path(__FILE__)))), file)
end
# Converts an array of `[key, value]` pairs to a hash.

View File

@ -107,6 +107,11 @@ class EngineTest < Test::Unit::TestCase
assert_equal("<div class='atlantis' style='ugly'></div>", render(".atlantis{:style => 'ugly'}").chomp)
end
def test_css_id_as_attribute_should_be_appended_with_underscore
assert_equal("<div id='my_id_1'></div>", render("#my_id{:id => '1'}").chomp)
assert_equal("<div id='my_id_1'></div>", render("#my_id{:id => 1}").chomp)
end
def test_ruby_code_should_work_inside_attributes
author = 'hcatlin'
assert_equal("<p class='3'>foo</p>", render("%p{:class => 1+2} foo").chomp)
@ -463,6 +468,24 @@ HTML
HAML
end
def test_silent_script_with_hyphen_case
assert_equal("", render("- 'foo-case-bar-case'"))
end
def test_silent_script_with_hyphen_end
assert_equal("", render("- 'foo-end-bar-end'"))
end
def test_silent_script_with_hyphen_end_and_block
assert_equal(<<HTML, render(<<HAML))
<p>foo-end</p>
<p>bar-end</p>
HTML
- "foo-end-bar-end".gsub(/\\w+-end/) do |s|
%p= s
HAML
end
# HTML escaping tests
def test_ampersand_equals_should_escape

View File

@ -26,7 +26,7 @@ stuff followed by whitespace
yee\ha
</p>
<!-- Short comment -->
<!--
<!--
This is a block comment
cool, huh?
<strong>there can even be sub-tags!</strong>
@ -35,13 +35,13 @@ stuff followed by whitespace
<p class=''>class attribute should appear!</p>
<p>this attribute shouldn't appear</p>
<!--[if lte IE6]> conditional comment! <![endif]-->
<!--[if gte IE7]>
<!--[if gte IE7]>
<p>Block conditional comment</p>
<div>
<h1>Cool, eh?</h1>
</div>
<![endif]-->
<!--[if gte IE5.2]>
<!--[if gte IE5.2]>
Woah a period.
<![endif]-->
testtest