rack-less 0.1.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.
- data/README.rdoc +90 -0
- data/Rakefile +61 -0
- data/lib/rack/less.rb +34 -0
- data/lib/rack/less/base.rb +69 -0
- data/lib/rack/less/options.rb +128 -0
- data/lib/rack/less/request.rb +72 -0
- data/lib/rack/less/response.rb +45 -0
- data/lib/rack/less/source.rb +98 -0
- data/lib/rack/less/version.rb +13 -0
- metadata +123 -0
data/README.rdoc
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
= Rack::Less
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
A better way to use LESS CSS in Ruby web apps.
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
|
9
|
+
$ gem install rack-less
|
10
|
+
|
11
|
+
== Basic Usage
|
12
|
+
|
13
|
+
Rack::Less is implemented as a piece of Rack middleware and can be used with
|
14
|
+
any Rack-based application. If your application includes a rackup (`.ru`) file
|
15
|
+
or uses Rack::Builder to construct the application pipeline, simply require
|
16
|
+
and use as follows:
|
17
|
+
|
18
|
+
require 'rack/less'
|
19
|
+
use Rack::Less do
|
20
|
+
set :source, 'app/less'
|
21
|
+
set :hosted_at, '/'
|
22
|
+
set :compress, true
|
23
|
+
end
|
24
|
+
run app
|
25
|
+
|
26
|
+
== Using with Rails
|
27
|
+
|
28
|
+
Add this to your `config/environment.rb`:
|
29
|
+
|
30
|
+
config.middleware.use Rack::Less, :compress => true
|
31
|
+
|
32
|
+
You should now see `Rack::Less` listed in the middleware pipeline:
|
33
|
+
|
34
|
+
rake middleware
|
35
|
+
|
36
|
+
== Available Options
|
37
|
+
|
38
|
+
* *root*["."]:
|
39
|
+
the app root. the reference point for the source and public options. #TODO: default appropriately for Rails/Sinatra.
|
40
|
+
|
41
|
+
* *source*['app/stylesheets']:
|
42
|
+
the path (relative to the root) where LESS files are located
|
43
|
+
|
44
|
+
* *public*['public']:
|
45
|
+
the path (relative to the root) where LESS files are located
|
46
|
+
|
47
|
+
* *hosted_at*['/stylesheets']:
|
48
|
+
the public HTTP root path for stylesheets
|
49
|
+
|
50
|
+
* *cache*[false]:
|
51
|
+
whether to cache the compilation output to a corresponding file in the hosted_root
|
52
|
+
|
53
|
+
* *compress*[false]:
|
54
|
+
whether to remove extraneous whitespace from compilation output
|
55
|
+
|
56
|
+
* *combinations*[{}]:
|
57
|
+
directives for combining the ouput of one or more LESS compilations, for example:
|
58
|
+
set :combine, { 'app' => ['one', 'two', 'three'] }
|
59
|
+
will direct Rack::Less to respond to a request for app.css with the concatenated output of compiling one.less, two.less, and three.less
|
60
|
+
|
61
|
+
== Links
|
62
|
+
|
63
|
+
GitHub: http://github.com/kelredd/rack-less
|
64
|
+
|
65
|
+
Less: http://lesscss.org
|
66
|
+
|
67
|
+
== License
|
68
|
+
|
69
|
+
Copyright (c) 2010 Kelly Redding (mailto:kelly@kelredd.com)
|
70
|
+
|
71
|
+
Permission is hereby granted, free of charge, to any person
|
72
|
+
obtaining a copy of this software and associated documentation
|
73
|
+
files (the "Software"), to deal in the Software without
|
74
|
+
restriction, including without limitation the rights to use,
|
75
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
76
|
+
copies of the Software, and to permit persons to whom the
|
77
|
+
Software is furnished to do so, subject to the following
|
78
|
+
conditions:
|
79
|
+
|
80
|
+
The above copyright notice and this permission notice shall be
|
81
|
+
included in all copies or substantial portions of the Software.
|
82
|
+
|
83
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
84
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
85
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
86
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
87
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
88
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
89
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
90
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
require 'lib/rack/less/version'
|
6
|
+
|
7
|
+
spec = Gem::Specification.new do |s|
|
8
|
+
s.name = 'rack-less'
|
9
|
+
s.version = RackLess::Version.to_s
|
10
|
+
s.has_rdoc = true
|
11
|
+
s.extra_rdoc_files = %w(README.rdoc)
|
12
|
+
s.rdoc_options = %w(--main README.rdoc)
|
13
|
+
s.summary = "A better way to use LESS CSS in Ruby web apps."
|
14
|
+
s.author = 'Kelly Redding'
|
15
|
+
s.email = 'kelly@kelredd.com'
|
16
|
+
s.homepage = 'http://github.com/kelredd/rack-less'
|
17
|
+
s.files = %w(README.rdoc Rakefile) + Dir.glob("{lib}/**/*")
|
18
|
+
# s.executables = ['rack-less']
|
19
|
+
|
20
|
+
s.add_dependency("rack", [">= 0.4"])
|
21
|
+
s.add_dependency("less", [">= 1.2.21"])
|
22
|
+
|
23
|
+
s.add_development_dependency("shoulda", [">= 2.10.2"])
|
24
|
+
s.add_development_dependency("sinatra", [">= 0.9.4"])
|
25
|
+
s.add_development_dependency("rack-test", [">= 0.5.3"])
|
26
|
+
s.add_development_dependency("webrat", [">= 0.6.0"])
|
27
|
+
end
|
28
|
+
|
29
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
30
|
+
pkg.gem_spec = spec
|
31
|
+
end
|
32
|
+
|
33
|
+
Rake::TestTask.new do |t|
|
34
|
+
t.libs << 'test'
|
35
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
36
|
+
t.verbose = true
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
require 'rcov/rcovtask'
|
41
|
+
|
42
|
+
Rcov::RcovTask.new(:coverage) do |t|
|
43
|
+
t.libs = ['test']
|
44
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
45
|
+
t.verbose = true
|
46
|
+
t.rcov_opts = ['--text-report', "-x #{Gem.path}", '-x /Library/Ruby', '-x /usr/lib/ruby']
|
47
|
+
end
|
48
|
+
|
49
|
+
task :default => :coverage
|
50
|
+
|
51
|
+
rescue LoadError
|
52
|
+
warn "\n**** Install rcov (sudo gem install relevance-rcov) to get coverage stats ****\n"
|
53
|
+
task :default => :test
|
54
|
+
end
|
55
|
+
|
56
|
+
desc 'Generate the gemspec to serve this gem'
|
57
|
+
task :gemspec do
|
58
|
+
file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
|
59
|
+
File.open(file, 'w') {|f| f << spec.to_ruby }
|
60
|
+
puts "Created gemspec: #{file}"
|
61
|
+
end
|
data/lib/rack/less.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'rack/less/base'
|
3
|
+
require 'rack/less/options'
|
4
|
+
require 'rack/less/request'
|
5
|
+
require 'rack/less/response'
|
6
|
+
require 'rack/less/source'
|
7
|
+
|
8
|
+
# === Usage
|
9
|
+
#
|
10
|
+
# Create with default configs:
|
11
|
+
# require 'rack/less'
|
12
|
+
# Rack::Less.new(app, :compress => true)
|
13
|
+
#
|
14
|
+
# Within a rackup file (or with Rack::Builder):
|
15
|
+
# require 'rack/less'
|
16
|
+
# use Rack::Less do
|
17
|
+
# set :root, "."
|
18
|
+
# set :source, 'app/less'
|
19
|
+
# set :compress, true
|
20
|
+
# end
|
21
|
+
# run app
|
22
|
+
|
23
|
+
module Rack::Less
|
24
|
+
MEDIA_TYPE = "text/css"
|
25
|
+
|
26
|
+
# Create a new Rack::Less middleware component
|
27
|
+
# => the +options+ Hash can be used to specify default configuration values
|
28
|
+
# => a block can given as an alternate method for setting option values (see example above)
|
29
|
+
# => (see Rack::Less::Options for possible key/values)
|
30
|
+
def self.new(app, options={}, &block)
|
31
|
+
Base.new(app, options, &block)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'rack/less/options'
|
2
|
+
require 'rack/less/request'
|
3
|
+
require 'rack/less/response'
|
4
|
+
|
5
|
+
module Rack::Less
|
6
|
+
class Base
|
7
|
+
include Rack::Less::Options
|
8
|
+
|
9
|
+
def initialize(app, options={})
|
10
|
+
@app = app
|
11
|
+
initialize_options options
|
12
|
+
yield self if block_given?
|
13
|
+
validate_options
|
14
|
+
end
|
15
|
+
|
16
|
+
# The Rack call interface. The receiver acts as a prototype and runs
|
17
|
+
# each request in a clone object unless the +rack.run_once+ variable is
|
18
|
+
# set in the environment.
|
19
|
+
# ripped from: http://github.com/rtomayko/rack-cache/blob/master/lib/rack/cache/context.rb
|
20
|
+
def call(env)
|
21
|
+
if env['rack.run_once']
|
22
|
+
call! env
|
23
|
+
else
|
24
|
+
clone.call! env
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# The real Rack call interface.
|
29
|
+
# if LESS CSS is being requested, this is an endpoint:
|
30
|
+
# => generate the compiled css
|
31
|
+
# => respond appropriately
|
32
|
+
# Otherwise, call on up to the app as normal
|
33
|
+
def call!(env)
|
34
|
+
@default_options.each { |k,v| env[k] ||= v }
|
35
|
+
@env = env
|
36
|
+
# TODO: get this going
|
37
|
+
|
38
|
+
if (@request = Request.new(@env.dup.freeze)).for_less?
|
39
|
+
Response.new(@env.dup.freeze, @request.source.to_css).to_rack
|
40
|
+
else
|
41
|
+
@app.call(env)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def validate_options
|
48
|
+
# ensure a root path is specified and does exists
|
49
|
+
unless options.has_key?(option_name(:root)) and !options(:root).nil?
|
50
|
+
raise(ArgumentError, "no :root option set")
|
51
|
+
end
|
52
|
+
unless File.exists?(options(:root))
|
53
|
+
raise(ArgumentError, "the :root path ('#{options(:root)}') does not exist")
|
54
|
+
end
|
55
|
+
|
56
|
+
set :root, File.expand_path(options(:root))
|
57
|
+
|
58
|
+
# ensure a source path is specified and does exists
|
59
|
+
unless options.has_key?(option_name(:source)) and !options(:source).nil?
|
60
|
+
raise(ArgumentError, "no :source option set")
|
61
|
+
end
|
62
|
+
source_path = File.join(options(:root), options(:source))
|
63
|
+
unless File.exists?(source_path)
|
64
|
+
raise(ArgumentError, "the :source path ('#{source_path}') does not exist")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Rack::Less
|
2
|
+
module Options
|
3
|
+
|
4
|
+
# Handles options and configuration for Rack::Less
|
5
|
+
# Available options:
|
6
|
+
# => root
|
7
|
+
# the app root. the reference point for the
|
8
|
+
# source and public options
|
9
|
+
# => source
|
10
|
+
# the path (relative to the root) where
|
11
|
+
# LESS files are located
|
12
|
+
# => public
|
13
|
+
# the path (relative to the root) where
|
14
|
+
# static files are served
|
15
|
+
# => hosted_at
|
16
|
+
# the public HTTP root path for stylesheets
|
17
|
+
# => cache
|
18
|
+
# whether to cache the compilation output to a
|
19
|
+
# corresponding file in the hosted_root
|
20
|
+
# => compress
|
21
|
+
# whether to remove extraneous whitespace from
|
22
|
+
# compilation output
|
23
|
+
# => combine
|
24
|
+
# expects a hash containing directives for combining
|
25
|
+
# the ouput of one or more LESS compilations, for example:
|
26
|
+
# { 'app' => ['one', 'two', 'three']}
|
27
|
+
# will respond to a request for app.css with the concatenated
|
28
|
+
# output of compiling one.less, two.less, and three.less
|
29
|
+
|
30
|
+
# Note: the following code is more or less a rip from:
|
31
|
+
# => http://github.com/rtomayko/rack-cache/blob/master/lib/rack/cache/options.rb
|
32
|
+
# => thanks to rtomayko, I thought this approach was really smart and the credit is his.
|
33
|
+
|
34
|
+
RACK_ENV_NS = "rack-less"
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
|
38
|
+
def defaults
|
39
|
+
{
|
40
|
+
option_name(:root) => ".",
|
41
|
+
option_name(:source) => 'app/stylesheets',
|
42
|
+
option_name(:public) => 'public',
|
43
|
+
option_name(:hosted_at) => '/stylesheets',
|
44
|
+
option_name(:cache) => false,
|
45
|
+
option_name(:compress) => false,
|
46
|
+
option_name(:combine) => {}
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
# Rack::Less uses the Rack Environment to store option values. All options
|
51
|
+
# are stored in the Rack Environment as "<RACK_ENV_PREFIX>.<option>", where
|
52
|
+
# <option> is the option name.
|
53
|
+
def option_name(key)
|
54
|
+
case key
|
55
|
+
when Symbol ; "#{RACK_ENV_NS}.#{key}"
|
56
|
+
when String ; key
|
57
|
+
else raise ArgumentError
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
module InstanceMethods
|
64
|
+
|
65
|
+
# Rack::Less uses the Rack Environment to store option values. All options
|
66
|
+
# are stored in the Rack Environment as "<RACK_ENV_PREFIX>.<option>", where
|
67
|
+
# <option> is the option name.
|
68
|
+
def option_name(key)
|
69
|
+
self.class.option_name(key)
|
70
|
+
end
|
71
|
+
|
72
|
+
# The underlying options Hash. During initialization (or outside of a
|
73
|
+
# request), this is a default values Hash. During a request, this is the
|
74
|
+
# Rack environment Hash. The default values Hash is merged in underneath
|
75
|
+
# the Rack environment before each request is processed.
|
76
|
+
# => if a key is passed, the option value for the key is returned
|
77
|
+
def options(key=nil)
|
78
|
+
if key
|
79
|
+
(@env || @default_options)[option_name(key)]
|
80
|
+
else
|
81
|
+
@env || @default_options
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Set multiple options at once.
|
86
|
+
def options=(hash={})
|
87
|
+
hash.each { |key,value| write_option(key, value) }
|
88
|
+
end
|
89
|
+
|
90
|
+
# Set an option. When +option+ is a Symbol, it is set in the Rack
|
91
|
+
# Environment as "rack-cache.option". When +option+ is a String, it
|
92
|
+
# exactly as specified. The +option+ argument may also be a Hash in
|
93
|
+
# which case each key/value pair is merged into the environment as if
|
94
|
+
# the #set method were called on each.
|
95
|
+
def set(option, value=nil, &block)
|
96
|
+
if block_given?
|
97
|
+
write_option option, block
|
98
|
+
elsif value.nil?
|
99
|
+
self.options = option.to_hash
|
100
|
+
else
|
101
|
+
write_option option, value
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def initialize_options(options={})
|
108
|
+
@default_options = self.class.defaults
|
109
|
+
self.options = options
|
110
|
+
end
|
111
|
+
|
112
|
+
def read_option(key)
|
113
|
+
options[option_name(key)]
|
114
|
+
end
|
115
|
+
|
116
|
+
def write_option(key, value)
|
117
|
+
options[option_name(key)] = value
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.included(receiver)
|
123
|
+
receiver.extend ClassMethods
|
124
|
+
receiver.send :include, InstanceMethods
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'rack/request'
|
2
|
+
require 'rack/less'
|
3
|
+
require 'rack/less/options'
|
4
|
+
require 'rack/less/source'
|
5
|
+
|
6
|
+
module Rack::Less
|
7
|
+
|
8
|
+
# Provides access to the HTTP request.
|
9
|
+
# Request objects respond to everything defined by Rack::Request
|
10
|
+
# as well as some additional convenience methods defined here
|
11
|
+
# => from: http://github.com/rtomayko/rack-cache/blob/master/lib/rack/cache/request.rb
|
12
|
+
|
13
|
+
class Request < Rack::Request
|
14
|
+
include Rack::Less::Options
|
15
|
+
|
16
|
+
CSS_PATH_REGEX = /\A.*\/(\w+)\.(\w+)\Z/
|
17
|
+
CSS_PATH_FORMATS = ['css']
|
18
|
+
|
19
|
+
# The HTTP request method. This is the standard implementation of this
|
20
|
+
# method but is respecified here due to libraries that attempt to modify
|
21
|
+
# the behavior to respect POST tunnel method specifiers. We always want
|
22
|
+
# the real request method.
|
23
|
+
def request_method
|
24
|
+
@env['REQUEST_METHOD']
|
25
|
+
end
|
26
|
+
|
27
|
+
def path_info
|
28
|
+
@env['PATH_INFO']
|
29
|
+
end
|
30
|
+
|
31
|
+
# TODO: test these
|
32
|
+
def path_resource_name
|
33
|
+
path_info =~ CSS_PATH_REGEX ? path_info.match(CSS_PATH_REGEX)[1] : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def path_resource_format
|
37
|
+
path_info =~ CSS_PATH_REGEX ? path_info.match(CSS_PATH_REGEX)[2] : nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# The Rack::Less::Source that the request is for
|
41
|
+
def source
|
42
|
+
@source ||= begin
|
43
|
+
cache = if options(:cache)
|
44
|
+
File.join(options(:root), options(:public), options(:hosted_at))
|
45
|
+
else
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
source_opts = {
|
49
|
+
:folder => File.join(options(:root), options(:source)),
|
50
|
+
:cache => cache,
|
51
|
+
:compress => options(:compress),
|
52
|
+
:combine => options(:combine)
|
53
|
+
}
|
54
|
+
Source.new(path_resource_name, source_opts)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def for_css?
|
59
|
+
media_type == Rack::Less::MEDIA_TYPE ||
|
60
|
+
CSS_PATH_FORMATS.include?(path_resource_format)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Determine if the request is for existing LESS CSS file
|
64
|
+
# This will be called on every request so speed is an issue
|
65
|
+
# => first check if the request is a GET on a css resource (fast)
|
66
|
+
# => then check for less source files that match the request (slow)
|
67
|
+
def for_less?
|
68
|
+
get? && for_css? && !source.files.empty?
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rack/response'
|
2
|
+
require 'rack/utils'
|
3
|
+
|
4
|
+
module Rack::Less
|
5
|
+
|
6
|
+
# Given some generated css, mimicks a Rack::Response
|
7
|
+
# => call to_rack to build standard rack response parameters
|
8
|
+
class Response
|
9
|
+
include Rack::Less::Options
|
10
|
+
include Rack::Response::Helpers
|
11
|
+
|
12
|
+
# Rack response tuple accessors.
|
13
|
+
attr_accessor :status, :headers, :body
|
14
|
+
|
15
|
+
class << self
|
16
|
+
|
17
|
+
# Calculate appropriate content_length
|
18
|
+
def content_length(body)
|
19
|
+
if body.respond_to?(:bytesize)
|
20
|
+
body.bytesize
|
21
|
+
else
|
22
|
+
body.size
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
# Create a Response instance given the env
|
29
|
+
# and some generated css.
|
30
|
+
def initialize(env, css)
|
31
|
+
@env = env
|
32
|
+
@body = css
|
33
|
+
@status = 200 # OK
|
34
|
+
@headers = Rack::Utils::HeaderHash.new
|
35
|
+
|
36
|
+
headers["Content-Type"] = Rack::Less::MEDIA_TYPE
|
37
|
+
headers["Content-Length"] = self.class.content_length(body).to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_rack
|
41
|
+
[status, headers.to_hash, body]
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'less'
|
2
|
+
|
3
|
+
module Rack::Less
|
4
|
+
|
5
|
+
# The engine for compiling LESS CSS
|
6
|
+
# Given the name of the less source file you want
|
7
|
+
# to compile and a path to the source files,
|
8
|
+
# will returns corresponding compiled LESS CSS
|
9
|
+
class Source
|
10
|
+
|
11
|
+
# prefer source files with the .less extension
|
12
|
+
# but also accept files with the .css extension
|
13
|
+
PREFERRED_EXTENSIONS = [:less, :css]
|
14
|
+
|
15
|
+
attr_reader :css_name
|
16
|
+
|
17
|
+
def initialize(css_name, options={})
|
18
|
+
@css_name = css_name
|
19
|
+
@compress = options[:compress]
|
20
|
+
@cache = options[:cache]
|
21
|
+
@folder = get_required_path(options, :folder)
|
22
|
+
@combine = options[:combine] || {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def compress?
|
26
|
+
!!@compress
|
27
|
+
end
|
28
|
+
def cache?
|
29
|
+
!@cache.nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
# Use named css sources before using combine directive sources
|
33
|
+
def files
|
34
|
+
@files ||= (css_sources.empty? ? combined_sources : css_sources)
|
35
|
+
end
|
36
|
+
|
37
|
+
def compiled
|
38
|
+
@compiled ||= begin
|
39
|
+
compiled_css = files.collect do |file_path|
|
40
|
+
Less::Engine.new(File.new(file_path)).to_css
|
41
|
+
end.join("\n")
|
42
|
+
|
43
|
+
compiled_css.delete!("\n") if compress?
|
44
|
+
if cache? && !File.exists?(cf = File.join(@cache, "#{@css_name}.css"))
|
45
|
+
FileUtils.mkdir_p(@cache)
|
46
|
+
File.open(cf, "w") do |file|
|
47
|
+
file.write(compiled_css)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
compiled_css
|
52
|
+
end
|
53
|
+
end
|
54
|
+
alias_method :to_css, :compiled
|
55
|
+
alias_method :css, :compiled
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
# Preferred, existing source files matching the css name
|
60
|
+
def css_sources
|
61
|
+
@css_sources ||= preferred_sources([@css_name])
|
62
|
+
end
|
63
|
+
|
64
|
+
# Preferred, existing source files matching a corresponding
|
65
|
+
# combine directive, if any
|
66
|
+
def combined_sources
|
67
|
+
@combined_sources ||= preferred_sources(@combine[@css_name] || [])
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# Given a list of file names, return a list of
|
73
|
+
# existing source files with the corresponding names
|
74
|
+
# honoring the preferred extension list
|
75
|
+
def preferred_sources(file_names)
|
76
|
+
file_names.collect do |name|
|
77
|
+
PREFERRED_EXTENSIONS.inject(nil) do |source_file, extension|
|
78
|
+
source_file || begin
|
79
|
+
path = File.join(@folder, "#{name}.#{extension}")
|
80
|
+
File.exists?(path) ? path : nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end.compact
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_required_path(options, path_key)
|
87
|
+
unless options.has_key?(path_key)
|
88
|
+
raise(ArgumentError, "no :#{path_key} option specified")
|
89
|
+
end
|
90
|
+
unless File.exists?(options[path_key])
|
91
|
+
raise(ArgumentError, "the :#{path_key} ('#{options[path_key]}') does not exist")
|
92
|
+
end
|
93
|
+
options[path_key]
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-less
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kelly Redding
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-08 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rack
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0.4"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: less
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.2.21
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: shoulda
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.10.2
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: sinatra
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.9.4
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rack-test
|
57
|
+
type: :development
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 0.5.3
|
64
|
+
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: webrat
|
67
|
+
type: :development
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 0.6.0
|
74
|
+
version:
|
75
|
+
description:
|
76
|
+
email: kelly@kelredd.com
|
77
|
+
executables: []
|
78
|
+
|
79
|
+
extensions: []
|
80
|
+
|
81
|
+
extra_rdoc_files:
|
82
|
+
- README.rdoc
|
83
|
+
files:
|
84
|
+
- README.rdoc
|
85
|
+
- Rakefile
|
86
|
+
- lib/rack/less/base.rb
|
87
|
+
- lib/rack/less/options.rb
|
88
|
+
- lib/rack/less/request.rb
|
89
|
+
- lib/rack/less/response.rb
|
90
|
+
- lib/rack/less/source.rb
|
91
|
+
- lib/rack/less/version.rb
|
92
|
+
- lib/rack/less.rb
|
93
|
+
has_rdoc: true
|
94
|
+
homepage: http://github.com/kelredd/rack-less
|
95
|
+
licenses: []
|
96
|
+
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options:
|
99
|
+
- --main
|
100
|
+
- README.rdoc
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: "0"
|
108
|
+
version:
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: "0"
|
114
|
+
version:
|
115
|
+
requirements: []
|
116
|
+
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 1.3.5
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: A better way to use LESS CSS in Ruby web apps.
|
122
|
+
test_files: []
|
123
|
+
|