1
0
Fork 0
mirror of https://github.com/haml/haml.git synced 2022-11-09 12:33:31 -05:00

Merb handler for Sass. This includes a pretty major restructuring of Sass::Plugin to factor out the Rails-specific code.

git-svn-id: svn://hamptoncatlin.com/haml/trunk@616 7063305b-7217-0410-af8c-cdc13e5119b9
This commit is contained in:
nex3 2007-11-17 19:55:26 +00:00
parent 5c09bf1b82
commit c1b21a2d75
8 changed files with 139 additions and 59 deletions

27
README
View file

@ -11,11 +11,18 @@ and providing elegant, easily understandable, and powerful syntax.
== Using
There are two ways to use Haml and Sass.
The easiest is as a Rails plugin:
Simply type <tt>./script/plugin install http://hamptoncatlin.com/haml/stable</tt>
There are several ways to use Haml and Sass.
They can be used as a plugins 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:
gem install haml
To install Haml and Sass as a Rails plugin,
just run <tt>haml --rails path/to/rails/app</tt>
and both Haml and Sass will be installed.
Views with the <tt>.haml</tt> extension will automatically use Haml.
Views with the <tt>.haml</tt> (or <tt>.html.haml</tt> for edge)
extension will automatically use Haml.
Sass is a little more complicated;
<tt>.sass</tt> files should be placed in public/stylesheets/sass,
where they'll be automatically compiled
@ -23,6 +30,18 @@ to corresponding CSS files in public/stylesheets when needed
(the Sass template directory is customizable...
see the Sass module docs for details).
For Merb, <tt>.html.haml</tt> views will work without any further modification.
To enable Sass, you also need to add it add a dependency.
To do so, just add
dependency "haml"
to config/dependencies.rb.
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.
== Formatting
=== Haml

View file

@ -75,6 +75,7 @@ unless ARGV[0] == 'benchmark'
end.to_a
spec.executables = ['haml', 'html2haml', 'sass']
spec.files = FileList['lib/**/*', 'bin/*', 'test/**/*', 'Rakefile', 'init.rb'].to_a + readmes
spec.autorequire = ['haml', 'sass']
spec.homepage = 'http://haml.hamptoncatlin.com/'
spec.has_rdoc = true
spec.extra_rdoc_files = readmes

View file

@ -1,4 +1,5 @@
begin
raise LoadError if defined?(Merb::Plugins)
require 'rubygems'
require 'active_support'
require 'action_controller'

View file

@ -407,7 +407,7 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
# but all constants in that file are made available in the current file.
#
# Sass looks for other Sass files in the working directory,
# and the Sass file directory under Rails.
# and the Sass file directory under Rails or Merb.
# Additional search directories may be specified
# using the :load_paths option (see below).
#
@ -596,42 +596,51 @@ $LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
# [<tt>:never_update</tt>] Whether the CSS files should never be updated,
# even if the template file changes.
# Setting this to true may give small performance gains.
# It's never true by default,
# even in production mode.
# It always defaults to false.
# Only has meaning within Ruby on Rails or Merb.
#
# [<tt>:always_update</tt>] Whether the CSS files should be updated every
# time a controller is accessed,
# as opposed to only when the template has been modified.
# Defaults to false.
# Only has meaning within Ruby on Rails.
# Only has meaning within Ruby on Rails or Merb.
#
# [<tt>:always_check</tt>] Whether a Sass template should be checked for updates every
# time a controller is accessed,
# as opposed to only when the Rails server starts.
# If a Sass template has been updated,
# it will be recompiled and will overwrite the corresponding CSS file.
# Defaults to false if Rails is running in production mode,
# true otherwise.
# Only has meaning within Ruby on Rails.
# Defaults to false in production mode, true otherwise.
# Only has meaning within Ruby on Rails or Merb.
#
# [<tt>:full_exception</tt>] Whether an error in the Sass code
# should cause Sass to provide a detailed description.
# If set to true, the specific error will be displayed
# along with a line number and source snippet.
# Otherwise, a simple uninformative error message will be displayed.
# Defaults to false in production mode, true otherwise.
# Only has meaning within Ruby on Rails or Merb.
#
# [<tt>:template_location</tt>] The directory where Sass templates should be read from.
# Defaults to <tt>RAILS_ROOT + "/public/stylesheets/sass"</tt>.
# Only has meaning within Ruby on Rails.
# Defaults to <tt>RAILS_ROOT + "/public/stylesheets/sass"</tt>
# or <tt>MERB_ROOT + "/public/stylesheets/sass"</tt>.
# Only has meaning within Ruby on Rails or Merb.
#
# [<tt>:css_location</tt>] The directory where CSS output should be written to.
# Defaults to <tt>RAILS_ROOT + "/public/stylesheets"</tt>.
# Only has meaning within Ruby on Rails.
# Defaults to <tt>RAILS_ROOT + "/public/stylesheets"</tt>
# or <tt>MERB_ROOT + "/public/stylesheets"</tt>.
# Only has meaning within Ruby on Rails or Merb.
#
# [<tt>:filename</tt>] The filename of the file being rendered.
# This is used solely for reporting errors,
# and is automatically set when using Rails.
# and is automatically set when using Rails or Merb.
#
# [<tt>:load_paths</tt>] An array of filesystem paths which should be searched
# for Sass templates imported with the "@import" directive.
# This defaults to the working directory and, in Rails,
# whatever <tt>:template_location</tt> is
# (by default <tt>RAILS_ROOT + "/public/stylesheets/sass"</tt>).
# This defaults to the working directory and, in Rails or Merb,
# whatever <tt>:template_location</tt> is.
#
module Sass; end
require 'sass/engine'
require 'sass/plugin' if defined?(Merb::Plugins)

View file

@ -1,21 +1,17 @@
require 'sass/engine'
require 'rubygems'
require 'action_controller'
RAILS_ROOT = '. 'unless self.class.const_defined?('RAILS_ROOT')
RAILS_ENV = 'production' unless self.class.const_defined?('RAILS_ENV')
module Sass
# This module contains methods that ActionController calls
# to automatically update Sass templates that need updating.
# It wasn't designed to be used outside of the context of ActionController.
# This module contains methods to aid in using Sass
# as a stylesheet-rendering plugin for various systems.
# Currently Rails/ActionController and Merb are supported out of the box.
module Plugin
class << self
@@options = {
:template_location => RAILS_ROOT + '/public/stylesheets/sass',
:css_location => RAILS_ROOT + '/public/stylesheets',
:template_location => './public/stylesheets/sass',
:css_location => './public/stylesheets',
:always_update => false,
:always_check => RAILS_ENV != "production"
:always_check => true,
:full_exception => true
}
# Gets various options for Sass. See README for details.
@ -79,7 +75,7 @@ module Sass
end
def exception_string(e)
if RAILS_ENV != "production"
if options[:full_exception]
e_string = "#{e.class}: #{e.message}"
if e.is_a? Sass::SyntaxError
@ -146,17 +142,5 @@ module Sass
end
end
# This module refers to the ActionController module that's part of Ruby on Rails.
# Sass can be used as an alternate templating engine for Rails,
# and includes some modifications to make this more doable.
# The documentation can be found
# here[http://rubyonrails.org/api/classes/ActionController/Base.html].
module ActionController
class Base # :nodoc:
alias_method :sass_old_process, :process
def process(*args)
Sass::Plugin.update_stylesheets if Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
sass_old_process(*args)
end
end
end
require 'sass/plugin/rails' if defined?(ActionController)
require 'sass/plugin/merb' if defined?(Merb::Plugins)

20
lib/sass/plugin/merb.rb Normal file
View file

@ -0,0 +1,20 @@
unless defined?(Sass::MERB_LOADED)
Sass::MERB_LOADED = true
Sass::Plugin.options.merge!(:template_location => MERB_ROOT + '/public/stylesheets/sass',
:css_location => MERB_ROOT + '/public/stylesheets',
:always_check => MERB_ENV != "production",
:full_exception => MERB_ENV != "production")
config = Merb::Plugins.config[:sass] || Merb::Plugins.config["sass"] || {}
config.symbolize_keys!
Sass::Plugin.options.merge!(config)
class MerbHandler # :nodoc:
def process_with_sass(request, response)
Sass::Plugin.update_stylesheets if Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
process_without_sass(request, response)
end
alias_method :process_without_sass, :process
alias_method :process, :process_with_sass
end
end

18
lib/sass/plugin/rails.rb Normal file
View file

@ -0,0 +1,18 @@
unless defined?(Sass::RAILS_LOADED)
Sass::RAILS_LOADED = true
Sass::Plugin.options.merge!(:template_location => RAILS_ROOT + '/public/stylesheets/sass',
:css_location => RAILS_ROOT + '/public/stylesheets',
:always_check => RAILS_ENV != "production",
:full_exception => RAILS_ENV != "production")
module ActionController # :nodoc:
class Base # :nodoc:
alias_method :sass_old_process, :process
def process(*args)
Sass::Plugin.update_stylesheets if Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
sass_old_process(*args)
end
end
end
end

View file

@ -1,9 +1,14 @@
#!/usr/bin/env ruby
RAILS_ENV = 'testing'
MERB_ENV = RAILS_ENV = 'testing'
RAILS_ROOT = '.'
require 'test/unit'
require 'fileutils'
require File.dirname(__FILE__) + '/../../lib/sass'
require 'rubygems'
require 'action_controller'
require 'sass/plugin'
class SassPluginTest < Test::Unit::TestCase
@ -14,14 +19,7 @@ class SassPluginTest < Test::Unit::TestCase
def setup
FileUtils.mkdir File.dirname(__FILE__) + '/tmp'
Sass::Plugin.options = {
:template_location => File.dirname(__FILE__) + '/templates',
:css_location => File.dirname(__FILE__) + '/tmp',
:style => :compact,
:load_paths => [File.dirname(__FILE__) + '/results'],
}
Sass::Plugin.options[:always_update] = true
set_plugin_opts
Sass::Plugin.update_stylesheets
end
@ -56,7 +54,7 @@ class SassPluginTest < Test::Unit::TestCase
assert !Sass::Plugin.stylesheet_needs_update?('import')
end
def test_exception_handling
def test_full_exception_handling
File.delete(tempfile_loc('bork'))
Sass::Plugin.update_stylesheets
File.open(tempfile_loc('bork')) do |file|
@ -65,18 +63,18 @@ class SassPluginTest < Test::Unit::TestCase
File.delete(tempfile_loc('bork'))
end
def test_production_exception_handling
Sass.const_set('RAILS_ENV', 'production')
def test_nonfull_exception_handling
Sass::Plugin.options[:full_exception] = false
File.delete(tempfile_loc('bork'))
Sass::Plugin.update_stylesheets
assert_equal("/* Internal stylesheet error */", File.read(tempfile_loc('bork')))
File.delete(tempfile_loc('bork'))
Sass::Plugin.const_set('RAILS_ENV', 'testing')
Sass::Plugin.options[:full_exception] = true
end
def test_controller_process
def test_rails_update
File.delete(tempfile_loc('basic'))
assert Sass::Plugin.stylesheet_needs_update?('basic')
@ -85,6 +83,26 @@ class SassPluginTest < Test::Unit::TestCase
assert !Sass::Plugin.stylesheet_needs_update?('basic')
end
def test_merb_update
begin
require 'merb'
rescue LoadError
puts "\nmerb couldn't be loaded, skipping a test"
return
end
require 'sass/plugin/merb'
MerbHandler.send(:define_method, :process_without_sass) { |*args| }
set_plugin_opts
File.delete(tempfile_loc('basic'))
assert Sass::Plugin.stylesheet_needs_update?('basic')
MerbHandler.new('.').process nil, nil
assert !Sass::Plugin.stylesheet_needs_update?('basic')
end
def test_doesnt_render_partials
assert !File.exists?(tempfile_loc('_partial'))
end
@ -109,6 +127,16 @@ class SassPluginTest < Test::Unit::TestCase
def result_loc(name)
File.dirname(__FILE__) + "/results/#{name}.css"
end
def set_plugin_opts
Sass::Plugin.options = {
:template_location => File.dirname(__FILE__) + '/templates',
:css_location => File.dirname(__FILE__) + '/tmp',
:style => :compact,
:load_paths => [File.dirname(__FILE__) + '/results'],
:always_update => true,
}
end
end
module Sass::Plugin