sass4 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +13 -0
- data/AGENTS.md +534 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/CONTRIBUTING.md +148 -0
- data/MIT-LICENSE +20 -0
- data/README.md +242 -0
- data/VERSION +1 -0
- data/VERSION_NAME +1 -0
- data/bin/sass +13 -0
- data/bin/sass-convert +12 -0
- data/bin/scss +13 -0
- data/extra/sass-spec-ref.sh +40 -0
- data/extra/update_watch.rb +13 -0
- data/init.rb +18 -0
- data/lib/sass/cache_stores/base.rb +88 -0
- data/lib/sass/cache_stores/chain.rb +34 -0
- data/lib/sass/cache_stores/filesystem.rb +60 -0
- data/lib/sass/cache_stores/memory.rb +46 -0
- data/lib/sass/cache_stores/null.rb +25 -0
- data/lib/sass/cache_stores.rb +15 -0
- data/lib/sass/callbacks.rb +67 -0
- data/lib/sass/css.rb +407 -0
- data/lib/sass/deprecation.rb +55 -0
- data/lib/sass/engine.rb +1236 -0
- data/lib/sass/environment.rb +236 -0
- data/lib/sass/error.rb +198 -0
- data/lib/sass/exec/base.rb +188 -0
- data/lib/sass/exec/sass_convert.rb +283 -0
- data/lib/sass/exec/sass_scss.rb +436 -0
- data/lib/sass/exec.rb +9 -0
- data/lib/sass/features.rb +48 -0
- data/lib/sass/importers/base.rb +182 -0
- data/lib/sass/importers/deprecated_path.rb +51 -0
- data/lib/sass/importers/filesystem.rb +221 -0
- data/lib/sass/importers.rb +23 -0
- data/lib/sass/logger/base.rb +47 -0
- data/lib/sass/logger/delayed.rb +50 -0
- data/lib/sass/logger/log_level.rb +45 -0
- data/lib/sass/logger.rb +17 -0
- data/lib/sass/media.rb +210 -0
- data/lib/sass/plugin/compiler.rb +552 -0
- data/lib/sass/plugin/configuration.rb +134 -0
- data/lib/sass/plugin/generic.rb +15 -0
- data/lib/sass/plugin/merb.rb +48 -0
- data/lib/sass/plugin/rack.rb +60 -0
- data/lib/sass/plugin/rails.rb +47 -0
- data/lib/sass/plugin/staleness_checker.rb +199 -0
- data/lib/sass/plugin.rb +134 -0
- data/lib/sass/railtie.rb +10 -0
- data/lib/sass/repl.rb +57 -0
- data/lib/sass/root.rb +7 -0
- data/lib/sass/script/css_lexer.rb +33 -0
- data/lib/sass/script/css_parser.rb +36 -0
- data/lib/sass/script/functions.rb +3103 -0
- data/lib/sass/script/lexer.rb +518 -0
- data/lib/sass/script/parser.rb +1164 -0
- data/lib/sass/script/tree/funcall.rb +314 -0
- data/lib/sass/script/tree/interpolation.rb +220 -0
- data/lib/sass/script/tree/list_literal.rb +119 -0
- data/lib/sass/script/tree/literal.rb +49 -0
- data/lib/sass/script/tree/map_literal.rb +64 -0
- data/lib/sass/script/tree/node.rb +119 -0
- data/lib/sass/script/tree/operation.rb +149 -0
- data/lib/sass/script/tree/selector.rb +26 -0
- data/lib/sass/script/tree/string_interpolation.rb +125 -0
- data/lib/sass/script/tree/unary_operation.rb +69 -0
- data/lib/sass/script/tree/variable.rb +57 -0
- data/lib/sass/script/tree.rb +16 -0
- data/lib/sass/script/value/arg_list.rb +36 -0
- data/lib/sass/script/value/base.rb +258 -0
- data/lib/sass/script/value/bool.rb +35 -0
- data/lib/sass/script/value/callable.rb +25 -0
- data/lib/sass/script/value/color.rb +704 -0
- data/lib/sass/script/value/function.rb +19 -0
- data/lib/sass/script/value/helpers.rb +298 -0
- data/lib/sass/script/value/list.rb +135 -0
- data/lib/sass/script/value/map.rb +70 -0
- data/lib/sass/script/value/null.rb +44 -0
- data/lib/sass/script/value/number.rb +564 -0
- data/lib/sass/script/value/string.rb +138 -0
- data/lib/sass/script/value.rb +13 -0
- data/lib/sass/script.rb +66 -0
- data/lib/sass/scss/css_parser.rb +61 -0
- data/lib/sass/scss/parser.rb +1343 -0
- data/lib/sass/scss/rx.rb +134 -0
- data/lib/sass/scss/static_parser.rb +351 -0
- data/lib/sass/scss.rb +14 -0
- data/lib/sass/selector/abstract_sequence.rb +112 -0
- data/lib/sass/selector/comma_sequence.rb +195 -0
- data/lib/sass/selector/pseudo.rb +291 -0
- data/lib/sass/selector/sequence.rb +661 -0
- data/lib/sass/selector/simple.rb +124 -0
- data/lib/sass/selector/simple_sequence.rb +348 -0
- data/lib/sass/selector.rb +327 -0
- data/lib/sass/shared.rb +76 -0
- data/lib/sass/source/map.rb +209 -0
- data/lib/sass/source/position.rb +39 -0
- data/lib/sass/source/range.rb +41 -0
- data/lib/sass/stack.rb +140 -0
- data/lib/sass/supports.rb +225 -0
- data/lib/sass/tree/at_root_node.rb +83 -0
- data/lib/sass/tree/charset_node.rb +22 -0
- data/lib/sass/tree/comment_node.rb +82 -0
- data/lib/sass/tree/content_node.rb +9 -0
- data/lib/sass/tree/css_import_node.rb +68 -0
- data/lib/sass/tree/debug_node.rb +18 -0
- data/lib/sass/tree/directive_node.rb +59 -0
- data/lib/sass/tree/each_node.rb +24 -0
- data/lib/sass/tree/error_node.rb +18 -0
- data/lib/sass/tree/extend_node.rb +43 -0
- data/lib/sass/tree/for_node.rb +36 -0
- data/lib/sass/tree/function_node.rb +44 -0
- data/lib/sass/tree/if_node.rb +52 -0
- data/lib/sass/tree/import_node.rb +75 -0
- data/lib/sass/tree/keyframe_rule_node.rb +15 -0
- data/lib/sass/tree/media_node.rb +48 -0
- data/lib/sass/tree/mixin_def_node.rb +38 -0
- data/lib/sass/tree/mixin_node.rb +52 -0
- data/lib/sass/tree/node.rb +240 -0
- data/lib/sass/tree/prop_node.rb +162 -0
- data/lib/sass/tree/return_node.rb +19 -0
- data/lib/sass/tree/root_node.rb +44 -0
- data/lib/sass/tree/rule_node.rb +153 -0
- data/lib/sass/tree/supports_node.rb +38 -0
- data/lib/sass/tree/trace_node.rb +33 -0
- data/lib/sass/tree/variable_node.rb +36 -0
- data/lib/sass/tree/visitors/base.rb +72 -0
- data/lib/sass/tree/visitors/check_nesting.rb +173 -0
- data/lib/sass/tree/visitors/convert.rb +350 -0
- data/lib/sass/tree/visitors/cssize.rb +362 -0
- data/lib/sass/tree/visitors/deep_copy.rb +107 -0
- data/lib/sass/tree/visitors/extend.rb +64 -0
- data/lib/sass/tree/visitors/perform.rb +572 -0
- data/lib/sass/tree/visitors/set_options.rb +139 -0
- data/lib/sass/tree/visitors/to_css.rb +440 -0
- data/lib/sass/tree/warn_node.rb +18 -0
- data/lib/sass/tree/while_node.rb +18 -0
- data/lib/sass/util/multibyte_string_scanner.rb +151 -0
- data/lib/sass/util/normalized_map.rb +122 -0
- data/lib/sass/util/subset_map.rb +109 -0
- data/lib/sass/util/test.rb +9 -0
- data/lib/sass/util.rb +1137 -0
- data/lib/sass/version.rb +120 -0
- data/lib/sass.rb +102 -0
- data/rails/init.rb +1 -0
- metadata +283 -0
@@ -0,0 +1,48 @@
|
|
1
|
+
unless defined?(Sass::MERB_LOADED)
|
2
|
+
Sass::MERB_LOADED = true
|
3
|
+
|
4
|
+
module Sass::Plugin::Configuration
|
5
|
+
# Different default options in a m environment.
|
6
|
+
def default_options
|
7
|
+
@default_options ||= begin
|
8
|
+
version = Merb::VERSION.split('.').map {|n| n.to_i}
|
9
|
+
if version[0] <= 0 && version[1] < 5
|
10
|
+
root = MERB_ROOT
|
11
|
+
env = MERB_ENV
|
12
|
+
else
|
13
|
+
root = Merb.root.to_s
|
14
|
+
env = Merb.environment
|
15
|
+
end
|
16
|
+
|
17
|
+
{
|
18
|
+
:always_update => false,
|
19
|
+
:template_location => root + '/public/stylesheets/sass',
|
20
|
+
:css_location => root + '/public/stylesheets',
|
21
|
+
:cache_location => root + '/tmp/sass-cache',
|
22
|
+
:always_check => env != "production",
|
23
|
+
:quiet => env != "production",
|
24
|
+
:full_exception => env != "production"
|
25
|
+
}.freeze
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
config = Merb::Plugins.config[:sass] || Merb::Plugins.config["sass"] || {}
|
31
|
+
|
32
|
+
if defined? config.symbolize_keys!
|
33
|
+
config.symbolize_keys!
|
34
|
+
end
|
35
|
+
|
36
|
+
Sass::Plugin.options.merge!(config)
|
37
|
+
|
38
|
+
require 'sass/plugin/rack'
|
39
|
+
class Sass::Plugin::MerbBootLoader < Merb::BootLoader
|
40
|
+
after Merb::BootLoader::RackUpApplication
|
41
|
+
|
42
|
+
def self.run
|
43
|
+
# Apparently there's no better way than this to add Sass
|
44
|
+
# to Merb's Rack stack.
|
45
|
+
Merb::Config[:app] = Sass::Plugin::Rack.new(Merb::Config[:app])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Sass
|
2
|
+
module Plugin
|
3
|
+
# Rack middleware for compiling Sass code.
|
4
|
+
#
|
5
|
+
# ## Activate
|
6
|
+
#
|
7
|
+
# require 'sass/plugin/rack'
|
8
|
+
# use Sass::Plugin::Rack
|
9
|
+
#
|
10
|
+
# ## Customize
|
11
|
+
#
|
12
|
+
# Sass::Plugin.options.merge!(
|
13
|
+
# :cache_location => './tmp/sass-cache',
|
14
|
+
# :never_update => environment != :production,
|
15
|
+
# :full_exception => environment != :production)
|
16
|
+
#
|
17
|
+
# {file:SASS_REFERENCE.md#Options See the Reference for more options}.
|
18
|
+
#
|
19
|
+
# ## Use
|
20
|
+
#
|
21
|
+
# Put your Sass files in `public/stylesheets/sass`.
|
22
|
+
# Your CSS will be generated in `public/stylesheets`,
|
23
|
+
# and regenerated every request if necessary.
|
24
|
+
# The locations and frequency {file:SASS_REFERENCE.md#Options can be customized}.
|
25
|
+
# That's all there is to it!
|
26
|
+
class Rack
|
27
|
+
# The delay, in seconds, between update checks.
|
28
|
+
# Useful when many resources are requested for a single page.
|
29
|
+
# `nil` means no delay at all.
|
30
|
+
#
|
31
|
+
# @return [Float]
|
32
|
+
attr_accessor :dwell
|
33
|
+
|
34
|
+
# Initialize the middleware.
|
35
|
+
#
|
36
|
+
# @param app [#call] The Rack application
|
37
|
+
# @param dwell [Float] See \{#dwell}
|
38
|
+
def initialize(app, dwell = 1.0)
|
39
|
+
@app = app
|
40
|
+
@dwell = dwell
|
41
|
+
@check_after = Time.now.to_f
|
42
|
+
end
|
43
|
+
|
44
|
+
# Process a request, checking the Sass stylesheets for changes
|
45
|
+
# and updating them if necessary.
|
46
|
+
#
|
47
|
+
# @param env The Rack request environment
|
48
|
+
# @return [(#to_i, {String => String}, Object)] The Rack response
|
49
|
+
def call(env)
|
50
|
+
if @dwell.nil? || Time.now.to_f > @check_after
|
51
|
+
Sass::Plugin.check_for_updates
|
52
|
+
@check_after = Time.now.to_f + @dwell if @dwell
|
53
|
+
end
|
54
|
+
@app.call(env)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
require 'sass/plugin'
|
@@ -0,0 +1,47 @@
|
|
1
|
+
unless defined?(Sass::RAILS_LOADED)
|
2
|
+
Sass::RAILS_LOADED = true
|
3
|
+
|
4
|
+
module Sass::Plugin::Configuration
|
5
|
+
# Different default options in a rails environment.
|
6
|
+
def default_options
|
7
|
+
return @default_options if @default_options
|
8
|
+
opts = {
|
9
|
+
:quiet => Sass::Util.rails_env != "production",
|
10
|
+
:full_exception => Sass::Util.rails_env != "production",
|
11
|
+
:cache_location => Sass::Util.rails_root + '/tmp/sass-cache'
|
12
|
+
}
|
13
|
+
|
14
|
+
opts.merge!(
|
15
|
+
:always_update => false,
|
16
|
+
:template_location => Sass::Util.rails_root + '/public/stylesheets/sass',
|
17
|
+
:css_location => Sass::Util.rails_root + '/public/stylesheets',
|
18
|
+
:always_check => Sass::Util.rails_env == "development")
|
19
|
+
|
20
|
+
@default_options = opts.freeze
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Sass::Plugin.options.reverse_merge!(Sass::Plugin.default_options)
|
25
|
+
|
26
|
+
# Rails 3.1 loads and handles Sass all on its own
|
27
|
+
if defined?(ActionController::Metal)
|
28
|
+
# 3.1 > Rails >= 3.0
|
29
|
+
require 'sass/plugin/rack'
|
30
|
+
Rails.configuration.middleware.use(Sass::Plugin::Rack)
|
31
|
+
elsif defined?(ActionController::Dispatcher) &&
|
32
|
+
defined?(ActionController::Dispatcher.middleware)
|
33
|
+
# Rails >= 2.3
|
34
|
+
require 'sass/plugin/rack'
|
35
|
+
ActionController::Dispatcher.middleware.use(Sass::Plugin::Rack)
|
36
|
+
else
|
37
|
+
module ActionController
|
38
|
+
class Base
|
39
|
+
alias_method :sass_old_process, :process
|
40
|
+
def process(*args)
|
41
|
+
Sass::Plugin.check_for_updates
|
42
|
+
sass_old_process(*args)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
module Plugin
|
5
|
+
# The class handles `.s[ca]ss` file staleness checks via their mtime timestamps.
|
6
|
+
#
|
7
|
+
# To speed things up two level of caches are employed:
|
8
|
+
#
|
9
|
+
# * A class-level dependency cache which stores @import paths for each file.
|
10
|
+
# This is a long-lived cache that is reused by every StalenessChecker instance.
|
11
|
+
# * Three short-lived instance-level caches, one for file mtimes,
|
12
|
+
# one for whether a file is stale during this particular run.
|
13
|
+
# and one for the parse tree for a file.
|
14
|
+
# These are only used by a single StalenessChecker instance.
|
15
|
+
#
|
16
|
+
# Usage:
|
17
|
+
#
|
18
|
+
# * For a one-off staleness check of a single `.s[ca]ss` file,
|
19
|
+
# the class-level {stylesheet_needs_update?} method
|
20
|
+
# should be used.
|
21
|
+
# * For a series of staleness checks (e.g. checking all files for staleness)
|
22
|
+
# a StalenessChecker instance should be created,
|
23
|
+
# and the instance-level \{#stylesheet\_needs\_update?} method should be used.
|
24
|
+
# the caches should make the whole process significantly faster.
|
25
|
+
# *WARNING*: It is important not to retain the instance for too long,
|
26
|
+
# as its instance-level caches are never explicitly expired.
|
27
|
+
class StalenessChecker
|
28
|
+
@dependencies_cache = {}
|
29
|
+
@dependency_cache_mutex = Mutex.new
|
30
|
+
|
31
|
+
class << self
|
32
|
+
# TODO: attach this to a compiler instance.
|
33
|
+
# @private
|
34
|
+
attr_accessor :dependencies_cache
|
35
|
+
attr_reader :dependency_cache_mutex
|
36
|
+
end
|
37
|
+
|
38
|
+
# Creates a new StalenessChecker
|
39
|
+
# for checking the staleness of several stylesheets at once.
|
40
|
+
#
|
41
|
+
# @param options [{Symbol => Object}]
|
42
|
+
# See {file:SASS_REFERENCE.md#Options the Sass options documentation}.
|
43
|
+
def initialize(options)
|
44
|
+
# URIs that are being actively checked for staleness. Protects against
|
45
|
+
# import loops.
|
46
|
+
@actively_checking = Set.new
|
47
|
+
|
48
|
+
# Entries in the following instance-level caches are never explicitly expired.
|
49
|
+
# Instead they are supposed to automatically go out of scope when a series of staleness
|
50
|
+
# checks (this instance of StalenessChecker was created for) is finished.
|
51
|
+
@mtimes, @dependencies_stale, @parse_trees = {}, {}, {}
|
52
|
+
@options = Sass::Engine.normalize_options(options)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns whether or not a given CSS file is out of date
|
56
|
+
# and needs to be regenerated.
|
57
|
+
#
|
58
|
+
# @param css_file [String] The location of the CSS file to check.
|
59
|
+
# @param template_file [String] The location of the Sass or SCSS template
|
60
|
+
# that is compiled to `css_file`.
|
61
|
+
# @return [Boolean] Whether the stylesheet needs to be updated.
|
62
|
+
def stylesheet_needs_update?(css_file, template_file, importer = nil)
|
63
|
+
template_file = File.expand_path(template_file)
|
64
|
+
begin
|
65
|
+
css_mtime = File.mtime(css_file)
|
66
|
+
rescue Errno::ENOENT
|
67
|
+
return true
|
68
|
+
end
|
69
|
+
stylesheet_modified_since?(template_file, css_mtime, importer)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns whether a Sass or SCSS stylesheet has been modified since a given time.
|
73
|
+
#
|
74
|
+
# @param template_file [String] The location of the Sass or SCSS template.
|
75
|
+
# @param mtime [Time] The modification time to check against.
|
76
|
+
# @param importer [Sass::Importers::Base] The importer used to locate the stylesheet.
|
77
|
+
# Defaults to the filesystem importer.
|
78
|
+
# @return [Boolean] Whether the stylesheet has been modified.
|
79
|
+
def stylesheet_modified_since?(template_file, mtime, importer = nil)
|
80
|
+
importer ||= @options[:filesystem_importer].new(".")
|
81
|
+
dependency_updated?(mtime).call(template_file, importer)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns whether or not a given CSS file is out of date
|
85
|
+
# and needs to be regenerated.
|
86
|
+
#
|
87
|
+
# The distinction between this method and the instance-level \{#stylesheet\_needs\_update?}
|
88
|
+
# is that the instance method preserves mtime and stale-dependency caches,
|
89
|
+
# so it's better to use when checking multiple stylesheets at once.
|
90
|
+
#
|
91
|
+
# @param css_file [String] The location of the CSS file to check.
|
92
|
+
# @param template_file [String] The location of the Sass or SCSS template
|
93
|
+
# that is compiled to `css_file`.
|
94
|
+
# @return [Boolean] Whether the stylesheet needs to be updated.
|
95
|
+
def self.stylesheet_needs_update?(css_file, template_file, importer = nil)
|
96
|
+
new(Plugin.engine_options).stylesheet_needs_update?(css_file, template_file, importer)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns whether a Sass or SCSS stylesheet has been modified since a given time.
|
100
|
+
#
|
101
|
+
# The distinction between this method and the instance-level \{#stylesheet\_modified\_since?}
|
102
|
+
# is that the instance method preserves mtime and stale-dependency caches,
|
103
|
+
# so it's better to use when checking multiple stylesheets at once.
|
104
|
+
#
|
105
|
+
# @param template_file [String] The location of the Sass or SCSS template.
|
106
|
+
# @param mtime [Time] The modification time to check against.
|
107
|
+
# @param importer [Sass::Importers::Base] The importer used to locate the stylesheet.
|
108
|
+
# Defaults to the filesystem importer.
|
109
|
+
# @return [Boolean] Whether the stylesheet has been modified.
|
110
|
+
def self.stylesheet_modified_since?(template_file, mtime, importer = nil)
|
111
|
+
new(Plugin.engine_options).stylesheet_modified_since?(template_file, mtime, importer)
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def dependencies_stale?(uri, importer, css_mtime)
|
117
|
+
timestamps = @dependencies_stale[[uri, importer]] ||= {}
|
118
|
+
timestamps.each_pair do |checked_css_mtime, is_stale|
|
119
|
+
if checked_css_mtime <= css_mtime && !is_stale
|
120
|
+
return false
|
121
|
+
elsif checked_css_mtime > css_mtime && is_stale
|
122
|
+
return true
|
123
|
+
end
|
124
|
+
end
|
125
|
+
timestamps[css_mtime] = dependencies(uri, importer).any?(&dependency_updated?(css_mtime))
|
126
|
+
rescue Sass::SyntaxError
|
127
|
+
# If there's an error finding dependencies, default to recompiling.
|
128
|
+
true
|
129
|
+
end
|
130
|
+
|
131
|
+
def mtime(uri, importer)
|
132
|
+
@mtimes[[uri, importer]] ||=
|
133
|
+
begin
|
134
|
+
mtime = importer.mtime(uri, @options)
|
135
|
+
if mtime.nil?
|
136
|
+
with_dependency_cache {|cache| cache.delete([uri, importer])}
|
137
|
+
nil
|
138
|
+
else
|
139
|
+
mtime
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def dependencies(uri, importer)
|
145
|
+
stored_mtime, dependencies =
|
146
|
+
with_dependency_cache {|cache| Sass::Util.destructure(cache[[uri, importer]])}
|
147
|
+
|
148
|
+
if !stored_mtime || stored_mtime < mtime(uri, importer)
|
149
|
+
dependencies = compute_dependencies(uri, importer)
|
150
|
+
with_dependency_cache do |cache|
|
151
|
+
cache[[uri, importer]] = [mtime(uri, importer), dependencies]
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
dependencies
|
156
|
+
end
|
157
|
+
|
158
|
+
def dependency_updated?(css_mtime)
|
159
|
+
proc do |uri, importer|
|
160
|
+
next true if @actively_checking.include?(uri)
|
161
|
+
begin
|
162
|
+
@actively_checking << uri
|
163
|
+
sass_mtime = mtime(uri, importer)
|
164
|
+
!sass_mtime ||
|
165
|
+
sass_mtime > css_mtime ||
|
166
|
+
dependencies_stale?(uri, importer, css_mtime)
|
167
|
+
ensure
|
168
|
+
@actively_checking.delete uri
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def compute_dependencies(uri, importer)
|
174
|
+
tree(uri, importer).grep(Tree::ImportNode) do |n|
|
175
|
+
next if n.css_import?
|
176
|
+
file = n.imported_file
|
177
|
+
key = [file.options[:filename], file.options[:importer]]
|
178
|
+
@parse_trees[key] = file.to_tree
|
179
|
+
key
|
180
|
+
end.compact
|
181
|
+
end
|
182
|
+
|
183
|
+
def tree(uri, importer)
|
184
|
+
@parse_trees[[uri, importer]] ||= importer.find(uri, @options).to_tree
|
185
|
+
end
|
186
|
+
|
187
|
+
# Get access to the global dependency cache in a threadsafe manner.
|
188
|
+
# Inside the block, no other thread can access the dependency cache.
|
189
|
+
#
|
190
|
+
# @yieldparam cache [Hash] The hash that is the global dependency cache
|
191
|
+
# @return The value returned by the block to which this method yields
|
192
|
+
def with_dependency_cache
|
193
|
+
StalenessChecker.dependency_cache_mutex.synchronize do
|
194
|
+
yield StalenessChecker.dependencies_cache
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
data/lib/sass/plugin.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
require 'sass'
|
4
|
+
require 'sass/plugin/compiler'
|
5
|
+
|
6
|
+
module Sass
|
7
|
+
# This module provides a single interface to the compilation of Sass/SCSS files
|
8
|
+
# for an application. It provides global options and checks whether CSS files
|
9
|
+
# need to be updated.
|
10
|
+
#
|
11
|
+
# This module is used as the primary interface with Sass
|
12
|
+
# when it's used as a plugin for various frameworks.
|
13
|
+
# All Rack-enabled frameworks are supported out of the box.
|
14
|
+
# The plugin is
|
15
|
+
# {file:SASS_REFERENCE.md#Rack_Rails_Merb_Plugin automatically activated for Rails and Merb}.
|
16
|
+
# Other frameworks must enable it explicitly; see {Sass::Plugin::Rack}.
|
17
|
+
#
|
18
|
+
# This module has a large set of callbacks available
|
19
|
+
# to allow users to run code (such as logging) when certain things happen.
|
20
|
+
# All callback methods are of the form `on_#{name}`,
|
21
|
+
# and they all take a block that's called when the given action occurs.
|
22
|
+
#
|
23
|
+
# Note that this class proxies almost all methods to its {Sass::Plugin::Compiler} instance.
|
24
|
+
# See \{#compiler}.
|
25
|
+
#
|
26
|
+
# @example Using a callback
|
27
|
+
# Sass::Plugin.on_updating_stylesheet do |template, css|
|
28
|
+
# puts "Compiling #{template} to #{css}"
|
29
|
+
# end
|
30
|
+
# Sass::Plugin.update_stylesheets
|
31
|
+
# #=> Compiling app/sass/screen.scss to public/stylesheets/screen.css
|
32
|
+
# #=> Compiling app/sass/print.scss to public/stylesheets/print.css
|
33
|
+
# #=> Compiling app/sass/ie.scss to public/stylesheets/ie.css
|
34
|
+
# @see Sass::Plugin::Compiler
|
35
|
+
module Plugin
|
36
|
+
extend self
|
37
|
+
|
38
|
+
@checked_for_updates = false
|
39
|
+
|
40
|
+
# Whether or not Sass has **ever** checked if the stylesheets need to be updated
|
41
|
+
# (in this Ruby instance).
|
42
|
+
#
|
43
|
+
# @return [Boolean]
|
44
|
+
attr_accessor :checked_for_updates
|
45
|
+
|
46
|
+
# Same as \{#update\_stylesheets}, but respects \{#checked\_for\_updates}
|
47
|
+
# and the {file:SASS_REFERENCE.md#always_update-option `:always_update`}
|
48
|
+
# and {file:SASS_REFERENCE.md#always_check-option `:always_check`} options.
|
49
|
+
#
|
50
|
+
# @see #update_stylesheets
|
51
|
+
def check_for_updates
|
52
|
+
return unless !Sass::Plugin.checked_for_updates ||
|
53
|
+
Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
|
54
|
+
update_stylesheets
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns the singleton compiler instance.
|
58
|
+
# This compiler has been pre-configured according
|
59
|
+
# to the plugin configuration.
|
60
|
+
#
|
61
|
+
# @return [Sass::Plugin::Compiler]
|
62
|
+
def compiler
|
63
|
+
@compiler ||= Compiler.new
|
64
|
+
end
|
65
|
+
|
66
|
+
# Updates out-of-date stylesheets.
|
67
|
+
#
|
68
|
+
# Checks each Sass/SCSS file in
|
69
|
+
# {file:SASS_REFERENCE.md#template_location-option `:template_location`}
|
70
|
+
# to see if it's been modified more recently than the corresponding CSS file
|
71
|
+
# in {file:SASS_REFERENCE.md#css_location-option `:css_location`}.
|
72
|
+
# If it has, it updates the CSS file.
|
73
|
+
#
|
74
|
+
# @param individual_files [Array<(String, String)>]
|
75
|
+
# A list of files to check for updates
|
76
|
+
# **in addition to those specified by the
|
77
|
+
# {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
|
78
|
+
# The first string in each pair is the location of the Sass/SCSS file,
|
79
|
+
# the second is the location of the CSS file that it should be compiled to.
|
80
|
+
def update_stylesheets(individual_files = [])
|
81
|
+
return if options[:never_update]
|
82
|
+
compiler.update_stylesheets(individual_files)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Updates all stylesheets, even those that aren't out-of-date.
|
86
|
+
# Ignores the cache.
|
87
|
+
#
|
88
|
+
# @param individual_files [Array<(String, String)>]
|
89
|
+
# A list of files to check for updates
|
90
|
+
# **in addition to those specified by the
|
91
|
+
# {file:SASS_REFERENCE.md#template_location-option `:template_location` option}.**
|
92
|
+
# The first string in each pair is the location of the Sass/SCSS file,
|
93
|
+
# the second is the location of the CSS file that it should be compiled to.
|
94
|
+
# @see #update_stylesheets
|
95
|
+
def force_update_stylesheets(individual_files = [])
|
96
|
+
Compiler.new(
|
97
|
+
options.dup.merge(
|
98
|
+
:never_update => false,
|
99
|
+
:always_update => true,
|
100
|
+
:cache => false)).update_stylesheets(individual_files)
|
101
|
+
end
|
102
|
+
|
103
|
+
# All other method invocations are proxied to the \{#compiler}.
|
104
|
+
#
|
105
|
+
# @see #compiler
|
106
|
+
# @see Sass::Plugin::Compiler
|
107
|
+
def method_missing(method, *args, &block)
|
108
|
+
if compiler.respond_to?(method)
|
109
|
+
compiler.send(method, *args, &block)
|
110
|
+
else
|
111
|
+
super
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# For parity with method_missing
|
116
|
+
def respond_to?(method)
|
117
|
+
super || compiler.respond_to?(method)
|
118
|
+
end
|
119
|
+
|
120
|
+
# There's a small speedup by not using method missing for frequently delegated methods.
|
121
|
+
def options
|
122
|
+
compiler.options
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
if defined?(ActionController)
|
128
|
+
# On Rails 3+ the rails plugin is loaded at the right time in railtie.rb
|
129
|
+
require 'sass/plugin/rails' unless Sass::Util.ap_geq_3?
|
130
|
+
elsif defined?(Merb::Plugins)
|
131
|
+
require 'sass/plugin/merb'
|
132
|
+
else
|
133
|
+
require 'sass/plugin/generic'
|
134
|
+
end
|
data/lib/sass/railtie.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Rails 3.0.0.beta.2+, < 3.1
|
2
|
+
if defined?(ActiveSupport) && ActiveSupport.public_methods.include?(:on_load) &&
|
3
|
+
!Sass::Util.ap_geq?('3.1.0.beta')
|
4
|
+
require 'sass/plugin/configuration'
|
5
|
+
ActiveSupport.on_load(:before_configuration) do
|
6
|
+
require 'sass'
|
7
|
+
require 'sass/plugin'
|
8
|
+
require 'sass/plugin/rails'
|
9
|
+
end
|
10
|
+
end
|
data/lib/sass/repl.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'readline'
|
2
|
+
|
3
|
+
module Sass
|
4
|
+
# Runs a SassScript read-eval-print loop.
|
5
|
+
# It presents a prompt on the terminal,
|
6
|
+
# reads in SassScript expressions,
|
7
|
+
# evaluates them,
|
8
|
+
# and prints the result.
|
9
|
+
class Repl
|
10
|
+
# @param options [{Symbol => Object}] An options hash.
|
11
|
+
def initialize(options = {})
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
# Starts the read-eval-print loop.
|
16
|
+
def run
|
17
|
+
environment = Environment.new
|
18
|
+
@line = 0
|
19
|
+
loop do
|
20
|
+
@line += 1
|
21
|
+
unless (text = Readline.readline('>> '))
|
22
|
+
puts
|
23
|
+
return
|
24
|
+
end
|
25
|
+
|
26
|
+
Readline::HISTORY << text
|
27
|
+
parse_input(environment, text)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def parse_input(environment, text)
|
34
|
+
case text
|
35
|
+
when Script::MATCH
|
36
|
+
name = $1
|
37
|
+
guarded = !!$3
|
38
|
+
val = Script::Parser.parse($2, @line, text.size - ($3 || '').size - $2.size)
|
39
|
+
|
40
|
+
unless guarded && environment.var(name)
|
41
|
+
environment.set_var(name, val.perform(environment))
|
42
|
+
end
|
43
|
+
|
44
|
+
p environment.var(name)
|
45
|
+
else
|
46
|
+
p Script::Parser.parse(text, @line, 0).perform(environment)
|
47
|
+
end
|
48
|
+
rescue Sass::SyntaxError => e
|
49
|
+
puts "SyntaxError: #{e.message}"
|
50
|
+
if @options[:trace]
|
51
|
+
e.backtrace.each do |line|
|
52
|
+
puts "\tfrom #{line}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/sass/root.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Sass
|
2
|
+
module Script
|
3
|
+
# This is a subclass of {Lexer} for use in parsing plain CSS properties.
|
4
|
+
#
|
5
|
+
# @see Sass::SCSS::CssParser
|
6
|
+
class CssLexer < Lexer
|
7
|
+
private
|
8
|
+
|
9
|
+
def token
|
10
|
+
important || super
|
11
|
+
end
|
12
|
+
|
13
|
+
def string(re, *args)
|
14
|
+
if re == :uri
|
15
|
+
uri = scan(URI)
|
16
|
+
return unless uri
|
17
|
+
return [:string, Script::Value::String.new(uri)]
|
18
|
+
end
|
19
|
+
|
20
|
+
return unless scan(STRING)
|
21
|
+
string_value = Sass::Script::Value::String.value(@scanner[1] || @scanner[2])
|
22
|
+
value = Script::Value::String.new(string_value, :string)
|
23
|
+
[:string, value]
|
24
|
+
end
|
25
|
+
|
26
|
+
def important
|
27
|
+
s = scan(IMPORTANT)
|
28
|
+
return unless s
|
29
|
+
[:raw, s]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'sass/script'
|
2
|
+
require 'sass/script/css_lexer'
|
3
|
+
|
4
|
+
module Sass
|
5
|
+
module Script
|
6
|
+
# This is a subclass of {Parser} for use in parsing plain CSS properties.
|
7
|
+
#
|
8
|
+
# @see Sass::SCSS::CssParser
|
9
|
+
class CssParser < Parser
|
10
|
+
private
|
11
|
+
|
12
|
+
# @private
|
13
|
+
def lexer_class; CssLexer; end
|
14
|
+
|
15
|
+
# We need a production that only does /,
|
16
|
+
# since * and % aren't allowed in plain CSS
|
17
|
+
production :div, :unary_plus, :div
|
18
|
+
|
19
|
+
def string
|
20
|
+
tok = try_tok(:string)
|
21
|
+
return number unless tok
|
22
|
+
return if @lexer.peek && @lexer.peek.type == :begin_interpolation
|
23
|
+
literal_node(tok.value, tok.source_range)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Short-circuit all the SassScript-only productions
|
27
|
+
def interpolation(first: nil, inner: :space)
|
28
|
+
first || send(inner)
|
29
|
+
end
|
30
|
+
|
31
|
+
alias_method :or_expr, :div
|
32
|
+
alias_method :unary_div, :ident
|
33
|
+
alias_method :paren, :string
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|