mirror of
https://github.com/haml/haml.git
synced 2022-11-09 12:33:31 -05:00
Merge branch 'master' into sassc
Conflicts: lib/sass/plugin.rb
This commit is contained in:
commit
f4e2c536d2
3 changed files with 157 additions and 168 deletions
|
@ -1,20 +1,11 @@
|
|||
require 'haml/engine'
|
||||
|
||||
module Haml
|
||||
class Template
|
||||
class << self
|
||||
@@options = {}
|
||||
module Template
|
||||
extend self
|
||||
|
||||
# Gets various options for Haml. See README.rdoc for details.
|
||||
def options
|
||||
@@options
|
||||
end
|
||||
|
||||
# Sets various options for Haml. See README.rdoc for details.
|
||||
def options=(value)
|
||||
@@options = value
|
||||
end
|
||||
end
|
||||
@options = {}
|
||||
attr_accessor :options
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ require 'enumerator'
|
|||
|
||||
module Haml
|
||||
module Util
|
||||
class << self; include Haml::Util; end
|
||||
extend self
|
||||
|
||||
RUBY_VERSION = ::RUBY_VERSION.split(".").map {|s| s.to_i}
|
||||
|
||||
|
|
|
@ -5,141 +5,142 @@ module 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 = {
|
||||
:css_location => './public/stylesheets',
|
||||
:always_update => false,
|
||||
:always_check => true,
|
||||
:full_exception => true
|
||||
}
|
||||
@@checked_for_updates = false
|
||||
extend self
|
||||
|
||||
# Whether or not Sass has *ever* checked if the stylesheets need updates
|
||||
# (in this Ruby instance).
|
||||
def checked_for_updates
|
||||
@@checked_for_updates
|
||||
end
|
||||
@options = {
|
||||
:css_location => './public/stylesheets',
|
||||
:always_update => false,
|
||||
:always_check => true,
|
||||
:full_exception => true
|
||||
}
|
||||
@checked_for_updates = false
|
||||
|
||||
# Gets various options for Sass. See README.rdoc for details.
|
||||
#--
|
||||
# TODO: *DOCUMENT OPTIONS*
|
||||
#++
|
||||
def options
|
||||
@@options
|
||||
end
|
||||
# Whether or not Sass has *ever* checked if the stylesheets need updates
|
||||
# (in this Ruby instance).
|
||||
def checked_for_updates
|
||||
@checked_for_updates
|
||||
end
|
||||
|
||||
# Sets various options for Sass.
|
||||
def options=(value)
|
||||
@@options.merge!(value)
|
||||
end
|
||||
# Gets various options for Sass. See README.rdoc for details.
|
||||
#--
|
||||
# TODO: *DOCUMENT OPTIONS*
|
||||
#++
|
||||
def options
|
||||
@options
|
||||
end
|
||||
|
||||
# Get the options ready to be passed to the Sass::Engine
|
||||
def engine_options(additional_options = {})
|
||||
opts = options.dup.merge(additional_options)
|
||||
opts[:load_paths] = load_paths(opts)
|
||||
opts
|
||||
end
|
||||
# Sets various options for Sass.
|
||||
def options=(value)
|
||||
@options.merge!(value)
|
||||
end
|
||||
|
||||
# Checks each stylesheet in <tt>options[:css_location]</tt>
|
||||
# to see if it needs updating,
|
||||
# and updates it using the corresponding template
|
||||
# from <tt>options[:templates]</tt>
|
||||
# if it does.
|
||||
def update_stylesheets
|
||||
return if options[:never_update]
|
||||
# Get the options ready to be passed to the Sass::Engine
|
||||
def engine_options(additional_options = {})
|
||||
opts = options.dup.merge(additional_options)
|
||||
opts[:load_paths] = load_paths(opts)
|
||||
opts
|
||||
end
|
||||
|
||||
@@checked_for_updates = true
|
||||
template_locations.zip(css_locations).each do |template_location, css_location|
|
||||
# Checks each stylesheet in <tt>options[:css_location]</tt>
|
||||
# to see if it needs updating,
|
||||
# and updates it using the corresponding template
|
||||
# from <tt>options[:templates]</tt>
|
||||
# if it does.
|
||||
def update_stylesheets
|
||||
return if options[:never_update]
|
||||
|
||||
Dir.glob(File.join(template_location, "**", "*.sass")).each do |file|
|
||||
# Get the relative path to the file with no extension
|
||||
name = file.sub(template_location + "/", "")[0...-5]
|
||||
@checked_for_updates = true
|
||||
template_locations.zip(css_locations).each do |template_location, css_location|
|
||||
|
||||
if !forbid_update?(name) && (options[:always_update] || stylesheet_needs_update?(name, template_location, css_location))
|
||||
update_stylesheet(name, template_location, css_location)
|
||||
end
|
||||
Dir.glob(File.join(template_location, "**", "*.sass")).each do |file|
|
||||
# Get the relative path to the file with no extension
|
||||
name = file.sub(template_location + "/", "")[0...-5]
|
||||
|
||||
if !forbid_update?(name) && (options[:always_update] || stylesheet_needs_update?(name, template_location, css_location))
|
||||
update_stylesheet(name, template_location, css_location)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
def update_stylesheet(name, template_location, css_location)
|
||||
css = css_filename(name, css_location)
|
||||
File.delete(css) if File.exists?(css)
|
||||
def update_stylesheet(name, template_location, css_location)
|
||||
css = css_filename(name, css_location)
|
||||
File.delete(css) if File.exists?(css)
|
||||
|
||||
filename = template_filename(name, template_location)
|
||||
result = begin
|
||||
Sass::Files.tree_for(filename, engine_options(:css_filename => css, :filename => filename)).
|
||||
perform(Environment.new).to_s
|
||||
rescue Exception => e
|
||||
exception_string(e)
|
||||
end
|
||||
filename = template_filename(name, template_location)
|
||||
result = begin
|
||||
Sass::Files.tree_for(filename, engine_options(:css_filename => css, :filename => filename)).
|
||||
perform(Environment.new).to_s
|
||||
rescue Exception => e
|
||||
exception_string(e)
|
||||
end
|
||||
|
||||
# Create any directories that might be necessary
|
||||
mkpath(css_location, name)
|
||||
# Create any directories that might be necessary
|
||||
mkpath(css_location, name)
|
||||
|
||||
# Finally, write the file
|
||||
File.open(css, 'w') do |file|
|
||||
file.print(result)
|
||||
end
|
||||
# Finally, write the file
|
||||
File.open(css, 'w') do |file|
|
||||
file.print(result)
|
||||
end
|
||||
|
||||
# Create any successive directories required to be able to write a file to: File.join(base,name)
|
||||
def mkpath(base, name)
|
||||
dirs = [base]
|
||||
name.split(File::SEPARATOR)[0...-1].each { |dir| dirs << File.join(dirs[-1],dir) }
|
||||
dirs.each { |dir| Dir.mkdir(dir) unless File.exist?(dir) }
|
||||
end
|
||||
|
||||
# Create any successive directories required to be able to write a file to: File.join(base,name)
|
||||
def mkpath(base, name)
|
||||
dirs = [base]
|
||||
name.split(File::SEPARATOR)[0...-1].each { |dir| dirs << File.join(dirs[-1],dir) }
|
||||
dirs.each { |dir| Dir.mkdir(dir) unless File.exist?(dir) }
|
||||
end
|
||||
|
||||
def load_paths(opts = options)
|
||||
(opts[:load_paths] || []) + template_locations
|
||||
end
|
||||
|
||||
def template_locations
|
||||
location = (options[:template_location] || File.join(options[:css_location],'sass'))
|
||||
if location.is_a?(String)
|
||||
[location]
|
||||
else
|
||||
location.to_a.map { |l| l.first }
|
||||
end
|
||||
|
||||
def load_paths(opts = options)
|
||||
(opts[:load_paths] || []) + template_locations
|
||||
end
|
||||
|
||||
def template_locations
|
||||
location = (options[:template_location] || File.join(options[:css_location],'sass'))
|
||||
if location.is_a?(String)
|
||||
[location]
|
||||
else
|
||||
location.to_a.map { |l| l.first }
|
||||
end
|
||||
end
|
||||
|
||||
def css_locations
|
||||
if options[:template_location] && !options[:template_location].is_a?(String)
|
||||
options[:template_location].to_a.map { |l| l.last }
|
||||
else
|
||||
[options[:css_location]]
|
||||
end
|
||||
end
|
||||
|
||||
def css_locations
|
||||
if options[:template_location] && !options[:template_location].is_a?(String)
|
||||
options[:template_location].to_a.map { |l| l.last }
|
||||
else
|
||||
[options[:css_location]]
|
||||
end
|
||||
end
|
||||
|
||||
def exception_string(e)
|
||||
if options[:full_exception]
|
||||
e_string = "#{e.class}: #{e.message}"
|
||||
def exception_string(e)
|
||||
if options[:full_exception]
|
||||
e_string = "#{e.class}: #{e.message}"
|
||||
|
||||
if e.is_a? Sass::SyntaxError
|
||||
e_string << "\non line #{e.sass_line}"
|
||||
if e.is_a? Sass::SyntaxError
|
||||
e_string << "\non line #{e.sass_line}"
|
||||
|
||||
if e.sass_filename
|
||||
e_string << " of #{e.sass_filename}"
|
||||
if e.sass_filename
|
||||
e_string << " of #{e.sass_filename}"
|
||||
|
||||
if File.exists?(e.sass_filename)
|
||||
e_string << "\n\n"
|
||||
if File.exists?(e.sass_filename)
|
||||
e_string << "\n\n"
|
||||
|
||||
min = [e.sass_line - 5, 0].max
|
||||
begin
|
||||
File.read(e.sass_filename).rstrip.split("\n")[
|
||||
min .. e.sass_line + 5
|
||||
].each_with_index do |line, i|
|
||||
e_string << "#{min + i + 1}: #{line}\n"
|
||||
end
|
||||
rescue
|
||||
e_string << "Couldn't read sass file: #{e.sass_filename}"
|
||||
min = [e.sass_line - 5, 0].max
|
||||
begin
|
||||
File.read(e.sass_filename).rstrip.split("\n")[
|
||||
min .. e.sass_line + 5
|
||||
].each_with_index do |line, i|
|
||||
e_string << "#{min + i + 1}: #{line}\n"
|
||||
end
|
||||
rescue
|
||||
e_string << "Couldn't read sass file: #{e.sass_filename}"
|
||||
end
|
||||
end
|
||||
end
|
||||
<<END
|
||||
end
|
||||
<<END
|
||||
/*
|
||||
#{e_string}
|
||||
|
||||
|
@ -150,54 +151,51 @@ body:before {
|
|||
font-family: monospace;
|
||||
content: "#{e_string.gsub('"', '\"').gsub("\n", '\\A ')}"; }
|
||||
END
|
||||
# Fix an emacs syntax-highlighting hiccup: '
|
||||
else
|
||||
"/* Internal stylesheet error */"
|
||||
# Fix an emacs syntax-highlighting hiccup: '
|
||||
else
|
||||
"/* Internal stylesheet error */"
|
||||
end
|
||||
end
|
||||
|
||||
def template_filename(name, path)
|
||||
"#{path}/#{name}.sass"
|
||||
end
|
||||
|
||||
def css_filename(name, path)
|
||||
"#{path}/#{name}.css"
|
||||
end
|
||||
|
||||
def forbid_update?(name)
|
||||
name.sub(/^.*\//, '')[0] == ?_
|
||||
end
|
||||
|
||||
def stylesheet_needs_update?(name, template_path, css_path)
|
||||
css_file = css_filename(name, css_path)
|
||||
template_file = template_filename(name, template_path)
|
||||
exact_stylesheet_needs_update?(css_file, template_file)
|
||||
end
|
||||
|
||||
def exact_stylesheet_needs_update?(css_file, template_file)
|
||||
return true unless File.exists?(css_file)
|
||||
|
||||
css_mtime = File.mtime(css_file)
|
||||
File.mtime(template_file) > css_mtime ||
|
||||
dependencies(template_file).any?(&dependency_updated?(css_mtime))
|
||||
end
|
||||
|
||||
def dependency_updated?(css_mtime)
|
||||
lambda do |dep|
|
||||
File.mtime(dep) > css_mtime ||
|
||||
dependencies(dep).any?(&dependency_updated?(css_mtime))
|
||||
end
|
||||
end
|
||||
|
||||
def dependencies(filename)
|
||||
File.readlines(filename).grep(/^@import /).map do |line|
|
||||
line[8..-1].split(',').map do |inc|
|
||||
Sass::Files.find_file_to_import(inc.strip, [File.dirname(filename)] + load_paths)
|
||||
end
|
||||
end
|
||||
|
||||
def template_filename(name, path)
|
||||
"#{path}/#{name}.sass"
|
||||
end
|
||||
|
||||
def css_filename(name, path)
|
||||
"#{path}/#{name}.css"
|
||||
end
|
||||
|
||||
def forbid_update?(name)
|
||||
name.sub(/^.*\//, '')[0] == ?_
|
||||
end
|
||||
|
||||
def stylesheet_needs_update?(name, template_path, css_path)
|
||||
css_file = css_filename(name, css_path)
|
||||
template_file = template_filename(name, template_path)
|
||||
exact_stylesheet_needs_update?(css_file, template_file)
|
||||
end
|
||||
|
||||
def exact_stylesheet_needs_update?(css_file, template_file)
|
||||
if !File.exists?(css_file)
|
||||
return true
|
||||
else
|
||||
css_mtime = File.mtime(css_file)
|
||||
File.mtime(template_file) > css_mtime ||
|
||||
dependencies(template_file).any?(&dependency_updated?(css_mtime))
|
||||
end
|
||||
end
|
||||
|
||||
def dependency_updated?(css_mtime)
|
||||
lambda do |dep|
|
||||
File.mtime(dep) > css_mtime ||
|
||||
dependencies(dep).any?(&dependency_updated?(css_mtime))
|
||||
end
|
||||
end
|
||||
|
||||
def dependencies(filename)
|
||||
File.readlines(filename).grep(/^@import /).map do |line|
|
||||
line[8..-1].split(',').map do |inc|
|
||||
Sass::Files.find_file_to_import(inc.strip, [File.dirname(filename)] + load_paths)
|
||||
end
|
||||
end.flatten.grep(/\.sass$/)
|
||||
end
|
||||
end.flatten.grep(/\.sass$/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue