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 == Using
There are two ways to use Haml and Sass. There are several ways to use Haml and Sass.
The easiest is as a Rails plugin: They can be used as a plugins for Rails or Merb,
Simply type <tt>./script/plugin install http://hamptoncatlin.com/haml/stable</tt> 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. 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; Sass is a little more complicated;
<tt>.sass</tt> files should be placed in public/stylesheets/sass, <tt>.sass</tt> files should be placed in public/stylesheets/sass,
where they'll be automatically compiled 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... (the Sass template directory is customizable...
see the Sass module docs for details). 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 == Formatting
=== Haml === Haml

View file

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

View file

@ -1,4 +1,5 @@
begin begin
raise LoadError if defined?(Merb::Plugins)
require 'rubygems' require 'rubygems'
require 'active_support' require 'active_support'
require 'action_controller' 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. # but all constants in that file are made available in the current file.
# #
# Sass looks for other Sass files in the working directory, # 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 # Additional search directories may be specified
# using the :load_paths option (see below). # 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, # [<tt>:never_update</tt>] Whether the CSS files should never be updated,
# even if the template file changes. # even if the template file changes.
# Setting this to true may give small performance gains. # Setting this to true may give small performance gains.
# It's never true by default, # It always defaults to false.
# even in production mode. # Only has meaning within Ruby on Rails or Merb.
# #
# [<tt>:always_update</tt>] Whether the CSS files should be updated every # [<tt>:always_update</tt>] Whether the CSS files should be updated every
# time a controller is accessed, # time a controller is accessed,
# as opposed to only when the template has been modified. # as opposed to only when the template has been modified.
# Defaults to false. # 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 # [<tt>:always_check</tt>] Whether a Sass template should be checked for updates every
# time a controller is accessed, # time a controller is accessed,
# as opposed to only when the Rails server starts. # as opposed to only when the Rails server starts.
# If a Sass template has been updated, # If a Sass template has been updated,
# it will be recompiled and will overwrite the corresponding CSS file. # it will be recompiled and will overwrite the corresponding CSS file.
# Defaults to false if Rails is running in production mode, # Defaults to false in production mode, true otherwise.
# true otherwise. # Only has meaning within Ruby on Rails or Merb.
# Only has meaning within Ruby on Rails. #
# [<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. # [<tt>:template_location</tt>] The directory where Sass templates should be read from.
# Defaults to <tt>RAILS_ROOT + "/public/stylesheets/sass"</tt>. # Defaults to <tt>RAILS_ROOT + "/public/stylesheets/sass"</tt>
# Only has meaning within Ruby on Rails. # 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. # [<tt>:css_location</tt>] The directory where CSS output should be written to.
# Defaults to <tt>RAILS_ROOT + "/public/stylesheets"</tt>. # Defaults to <tt>RAILS_ROOT + "/public/stylesheets"</tt>
# Only has meaning within Ruby on Rails. # 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. # [<tt>:filename</tt>] The filename of the file being rendered.
# This is used solely for reporting errors, # 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 # [<tt>:load_paths</tt>] An array of filesystem paths which should be searched
# for Sass templates imported with the "@import" directive. # for Sass templates imported with the "@import" directive.
# This defaults to the working directory and, in Rails, # This defaults to the working directory and, in Rails or Merb,
# whatever <tt>:template_location</tt> is # whatever <tt>:template_location</tt> is.
# (by default <tt>RAILS_ROOT + "/public/stylesheets/sass"</tt>).
# #
module Sass; end module Sass; end
require 'sass/engine' require 'sass/engine'
require 'sass/plugin' if defined?(Merb::Plugins)

View file

@ -1,21 +1,17 @@
require 'sass/engine' 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 module Sass
# This module contains methods that ActionController calls # This module contains methods to aid in using Sass
# to automatically update Sass templates that need updating. # as a stylesheet-rendering plugin for various systems.
# It wasn't designed to be used outside of the context of ActionController. # Currently Rails/ActionController and Merb are supported out of the box.
module Plugin module Plugin
class << self class << self
@@options = { @@options = {
:template_location => RAILS_ROOT + '/public/stylesheets/sass', :template_location => './public/stylesheets/sass',
:css_location => RAILS_ROOT + '/public/stylesheets', :css_location => './public/stylesheets',
:always_update => false, :always_update => false,
:always_check => RAILS_ENV != "production" :always_check => true,
:full_exception => true
} }
# Gets various options for Sass. See README for details. # Gets various options for Sass. See README for details.
@ -79,7 +75,7 @@ module Sass
end end
def exception_string(e) def exception_string(e)
if RAILS_ENV != "production" if options[:full_exception]
e_string = "#{e.class}: #{e.message}" e_string = "#{e.class}: #{e.message}"
if e.is_a? Sass::SyntaxError if e.is_a? Sass::SyntaxError
@ -146,17 +142,5 @@ module Sass
end end
end end
# This module refers to the ActionController module that's part of Ruby on Rails. require 'sass/plugin/rails' if defined?(ActionController)
# Sass can be used as an alternate templating engine for Rails, require 'sass/plugin/merb' if defined?(Merb::Plugins)
# 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

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 #!/usr/bin/env ruby
RAILS_ENV = 'testing' MERB_ENV = RAILS_ENV = 'testing'
RAILS_ROOT = '.'
require 'test/unit' require 'test/unit'
require 'fileutils' require 'fileutils'
require File.dirname(__FILE__) + '/../../lib/sass' require File.dirname(__FILE__) + '/../../lib/sass'
require 'rubygems'
require 'action_controller'
require 'sass/plugin' require 'sass/plugin'
class SassPluginTest < Test::Unit::TestCase class SassPluginTest < Test::Unit::TestCase
@ -14,14 +19,7 @@ class SassPluginTest < Test::Unit::TestCase
def setup def setup
FileUtils.mkdir File.dirname(__FILE__) + '/tmp' FileUtils.mkdir File.dirname(__FILE__) + '/tmp'
Sass::Plugin.options = { set_plugin_opts
: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
Sass::Plugin.update_stylesheets Sass::Plugin.update_stylesheets
end end
@ -56,7 +54,7 @@ class SassPluginTest < Test::Unit::TestCase
assert !Sass::Plugin.stylesheet_needs_update?('import') assert !Sass::Plugin.stylesheet_needs_update?('import')
end end
def test_exception_handling def test_full_exception_handling
File.delete(tempfile_loc('bork')) File.delete(tempfile_loc('bork'))
Sass::Plugin.update_stylesheets Sass::Plugin.update_stylesheets
File.open(tempfile_loc('bork')) do |file| File.open(tempfile_loc('bork')) do |file|
@ -65,18 +63,18 @@ class SassPluginTest < Test::Unit::TestCase
File.delete(tempfile_loc('bork')) File.delete(tempfile_loc('bork'))
end end
def test_production_exception_handling def test_nonfull_exception_handling
Sass.const_set('RAILS_ENV', 'production') Sass::Plugin.options[:full_exception] = false
File.delete(tempfile_loc('bork')) File.delete(tempfile_loc('bork'))
Sass::Plugin.update_stylesheets Sass::Plugin.update_stylesheets
assert_equal("/* Internal stylesheet error */", File.read(tempfile_loc('bork'))) assert_equal("/* Internal stylesheet error */", File.read(tempfile_loc('bork')))
File.delete(tempfile_loc('bork')) File.delete(tempfile_loc('bork'))
Sass::Plugin.const_set('RAILS_ENV', 'testing') Sass::Plugin.options[:full_exception] = true
end end
def test_controller_process def test_rails_update
File.delete(tempfile_loc('basic')) File.delete(tempfile_loc('basic'))
assert Sass::Plugin.stylesheet_needs_update?('basic') assert Sass::Plugin.stylesheet_needs_update?('basic')
@ -85,6 +83,26 @@ class SassPluginTest < Test::Unit::TestCase
assert !Sass::Plugin.stylesheet_needs_update?('basic') assert !Sass::Plugin.stylesheet_needs_update?('basic')
end 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 def test_doesnt_render_partials
assert !File.exists?(tempfile_loc('_partial')) assert !File.exists?(tempfile_loc('_partial'))
end end
@ -109,6 +127,16 @@ class SassPluginTest < Test::Unit::TestCase
def result_loc(name) def result_loc(name)
File.dirname(__FILE__) + "/results/#{name}.css" File.dirname(__FILE__) + "/results/#{name}.css"
end 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 end
module Sass::Plugin module Sass::Plugin