rack-less 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.bundle/config +2 -0
  2. data/.gitignore +5 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +53 -0
  5. data/Rakefile +5 -43
  6. data/lib/rack/less.rb +6 -12
  7. data/lib/rack/less/config.rb +13 -25
  8. data/lib/rack/less/request.rb +36 -22
  9. data/lib/rack/less/source.rb +7 -7
  10. data/lib/rack/less/version.rb +3 -11
  11. data/rack-less.gemspec +29 -0
  12. data/test/app_helper.rb +25 -0
  13. data/test/config_test.rb +215 -0
  14. data/test/env.rb +9 -0
  15. data/test/fixtures/mock_options.rb +9 -0
  16. data/test/fixtures/sinatra/app.rb +9 -0
  17. data/test/fixtures/sinatra/app/stylesheets/all_compiled.css +7 -0
  18. data/test/fixtures/sinatra/app/stylesheets/all_one.less +10 -0
  19. data/test/fixtures/sinatra/app/stylesheets/all_two.less +4 -0
  20. data/test/fixtures/sinatra/app/stylesheets/css.css +4 -0
  21. data/test/fixtures/sinatra/app/stylesheets/css_compiled.css +4 -0
  22. data/test/fixtures/sinatra/app/stylesheets/nested/file.css +10 -0
  23. data/test/fixtures/sinatra/app/stylesheets/nested/file_compiled.css +2 -0
  24. data/test/fixtures/sinatra/app/stylesheets/nested/really/really.less +10 -0
  25. data/test/fixtures/sinatra/app/stylesheets/nested/really/really_compiled.css +2 -0
  26. data/test/fixtures/sinatra/app/stylesheets/normal.less +10 -0
  27. data/test/fixtures/sinatra/app/stylesheets/normal_compiled.css +2 -0
  28. data/test/fixtures/sinatra/app/stylesheets/some-styles.less +8 -0
  29. data/test/fixtures/sinatra/app/stylesheets/some_styles.less +8 -0
  30. data/test/fixtures/sinatra/app/stylesheets/styles1.less +8 -0
  31. data/test/helper.rb +77 -0
  32. data/test/options_test.rb +60 -0
  33. data/test/request_test.rb +142 -0
  34. data/test/response_test.rb +41 -0
  35. data/test/sinatra_test.rb +54 -0
  36. data/test/source_test.rb +158 -0
  37. metadata +93 -57
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_DISABLE_SHARED_GEMS: "1"
@@ -0,0 +1,5 @@
1
+ /pkg/
2
+ /doc/
3
+ /coverage/
4
+ *.log
5
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rack-less.gemspec
4
+ gemspec
@@ -0,0 +1,53 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rack-less (2.0.0)
5
+ less (~> 1.2)
6
+ rack (~> 1.0)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ json (1.5.1)
12
+ kelredd-useful (0.4.1)
13
+ json
14
+ leftright (0.9.0)
15
+ less (1.2.21)
16
+ mutter (>= 0.4.2)
17
+ treetop (>= 1.4.2)
18
+ mutter (0.5.3)
19
+ nokogiri (1.4.4)
20
+ polyglot (0.3.1)
21
+ rack (1.2.2)
22
+ rack-test (0.5.7)
23
+ rack (>= 1.0)
24
+ shoulda (2.11.3)
25
+ sinatra (1.2.1)
26
+ rack (~> 1.1)
27
+ tilt (>= 1.2.2, < 2.0)
28
+ test-belt (0.2.1)
29
+ kelredd-useful (~> 0.4.0)
30
+ leftright (~> 0.9.0)
31
+ shoulda (~> 2.11)
32
+ tilt (1.2.2)
33
+ treetop (1.4.9)
34
+ polyglot (>= 0.3.1)
35
+ webrat (0.7.3)
36
+ nokogiri (>= 1.2.0)
37
+ rack (>= 1.0)
38
+ rack-test (>= 0.5.3)
39
+ yui-compressor (0.9.4)
40
+
41
+ PLATFORMS
42
+ ruby
43
+
44
+ DEPENDENCIES
45
+ bundler (~> 1.0)
46
+ less (~> 1.2)
47
+ rack (~> 1.0)
48
+ rack-less!
49
+ rack-test (>= 0.5.3)
50
+ sinatra (>= 0.9.4)
51
+ test-belt (= 0.2.1)
52
+ webrat (>= 0.6.0)
53
+ yui-compressor (>= 0.9.1)
data/Rakefile CHANGED
@@ -1,45 +1,7 @@
1
- require 'rubygems'
2
- require 'rake/gempackagetask'
3
- require 'simple_gem/testtasks'
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
4
3
 
5
- require 'lib/rack/less/version'
4
+ require 'test_belt/rake_tasks'
5
+ TestBelt::RakeTasks.for :test
6
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_development_dependency("shoulda", [">= 2.10.2"])
21
- s.add_development_dependency("leftright", [">= 0.0.6"])
22
- s.add_development_dependency("sinatra", [">= 0.9.4"])
23
- s.add_development_dependency("rack-test", [">= 0.5.3"])
24
- s.add_development_dependency("webrat", [">= 0.6.0"])
25
- s.add_development_dependency("yui-compressor", [">=0.9.1"])
26
- s.add_development_dependency("kelredd-simple-gem", [">= 0.7.0"])
27
-
28
- s.add_dependency("rack", [">= 0.4"])
29
- s.add_dependency("less", [">= 1.2.21"])
30
- end
31
-
32
- Rake::GemPackageTask.new(spec) do |pkg|
33
- pkg.gem_spec = spec
34
- end
35
-
36
- SimpleGem::TestTasks.new
37
-
38
- desc 'Generate the gemspec to serve this gem'
39
- task :gemspec do
40
- file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
41
- File.open(file, 'w') {|f| f << spec.to_ruby }
42
- puts "Created gemspec: #{file}"
43
- end
44
-
45
- task :default => :gem
7
+ task :default => :build
@@ -24,9 +24,9 @@ require 'rack/less/source'
24
24
  module Rack::Less
25
25
  MIME_TYPE = "text/css"
26
26
  @@config = Config.new
27
-
27
+
28
28
  class << self
29
-
29
+
30
30
  # Configuration accessors for Rack::Less
31
31
  # (see config.rb for details)
32
32
  def configure
@@ -38,12 +38,12 @@ module Rack::Less
38
38
  def config=(value)
39
39
  @@config = value
40
40
  end
41
-
41
+
42
42
  # Combinations config convenience method
43
43
  def combinations(key=nil)
44
44
  @@config.combinations(key)
45
45
  end
46
-
46
+
47
47
  # Stylesheet helper, config convenience method
48
48
  def stylesheet(key)
49
49
  @@config.stylesheet(key)
@@ -54,19 +54,13 @@ module Rack::Less
54
54
  @@config.cache_bust
55
55
  end
56
56
 
57
- # <b>DEPRECATED:</b> Please use <tt>cache_bust</tt> instead.
58
- def combination_timestamp
59
- warn "[DEPRECATION] `combination_timestamp` is deprecated. Please use `cache_bust` instead."
60
- cache_bust
61
- end
62
-
63
57
  end
64
58
 
65
- # Create a new Rack::Less middleware component
59
+ # Create a new Rack::Less middleware component
66
60
  # => the +options+ Hash can be used to specify default configuration values
67
61
  # => (see Rack::Less::Options for possible key/values)
68
62
  def self.new(app, options={}, &block)
69
63
  Base.new(app, options, &block)
70
64
  end
71
-
65
+
72
66
  end
@@ -1,5 +1,5 @@
1
1
  module Rack::Less
2
-
2
+
3
3
  # Handles configuration for Rack::Less
4
4
  # Available config settings:
5
5
  # :cache
@@ -24,10 +24,10 @@ module Rack::Less
24
24
  # :cache_bust
25
25
  # whether to append a timestamp to the sheet requests generated by combinations
26
26
  class Config
27
-
27
+
28
28
  ATTRIBUTES = [:cache, :compress, :combinations, :cache_bust]
29
29
  attr_accessor *ATTRIBUTES
30
-
30
+
31
31
  DEFAULTS = {
32
32
  :cache => false,
33
33
  :compress => false,
@@ -37,30 +37,18 @@ module Rack::Less
37
37
  def initialize(settings={})
38
38
  ATTRIBUTES.each do |a|
39
39
  instance_variable_set("@#{a}", settings[a] || DEFAULTS[a])
40
- end
40
+ end
41
41
  @cache_bust = default_cache_bust if @cache_bust.nil?
42
42
  end
43
-
44
- # <b>DEPRECATED:</b> Please use <tt>cache_bust</tt> instead.
45
- def combination_timestamp
46
- warn "[DEPRECATION] `combination_timestamp` is deprecated. Please use `cache_bust` instead."
47
- cache_bust
48
- end
49
-
50
- # <b>DEPRECATED:</b> Please use <tt>cache_bust=</tt> instead.
51
- def combination_timestamp=(value)
52
- warn "[DEPRECATION] `combination_timestamp=` is deprecated. Please use `cache_bust=` instead."
53
- cache_bust = value
54
- end
55
-
43
+
56
44
  def cache?
57
45
  !!@cache
58
46
  end
59
-
47
+
60
48
  def compress?
61
49
  !!@compress
62
50
  end
63
-
51
+
64
52
  def combinations(key=nil)
65
53
  if key.nil?
66
54
  @combinations
@@ -74,7 +62,7 @@ module Rack::Less
74
62
  end
75
63
  end
76
64
  end
77
-
65
+
78
66
  def stylesheet(key)
79
67
  if @combinations[key]
80
68
  combinations(key.to_s)
@@ -84,7 +72,7 @@ module Rack::Less
84
72
  end
85
73
 
86
74
  private
87
-
75
+
88
76
  def stylesheet_filename(key)
89
77
  filename = key.strip
90
78
  filename += ".css" unless filename.include?('.css')
@@ -98,7 +86,7 @@ module Rack::Less
98
86
  end
99
87
  filename
100
88
  end
101
-
89
+
102
90
  def default_cache_bust
103
91
  if defined?(::Sinatra) && defined?(::Sinatra::Application)
104
92
  app_root_cache_bust(::Sinatra::Application)
@@ -106,18 +94,18 @@ module Rack::Less
106
94
  app_root_cache_bust(::Rails)
107
95
  end || false
108
96
  end
109
-
97
+
110
98
  def app_root_cache_bust(app)
111
99
  if app.respond_to?(:root)
112
100
  mtime_cache_bust(app.root.to_s)
113
101
  end
114
102
  end
115
-
103
+
116
104
  def mtime_cache_bust(path)
117
105
  if File.exists?(path)
118
106
  File.mtime(path).to_i
119
107
  end
120
108
  end
121
-
109
+
122
110
  end
123
111
  end
@@ -23,28 +23,42 @@ module Rack::Less
23
23
  @env['REQUEST_METHOD']
24
24
  end
25
25
 
26
- def path_info
27
- @env['PATH_INFO']
28
- end
29
-
30
26
  def http_accept
31
27
  @env['HTTP_ACCEPT']
32
28
  end
33
29
 
34
- def path_resource_format
35
- File.extname(path_info)
30
+ def path_info
31
+ @env['PATH_INFO']
32
+ end
33
+
34
+ def hosted_at_option
35
+ # sanitized :hosted_at option
36
+ # remove any trailing '/'
37
+ # ensure single leading '/'
38
+ @hosted_at_option ||= options(:hosted_at).sub(/\/+$/, '').sub(/^\/*/, '/')
36
39
  end
37
40
 
38
- def path_resource_name
39
- File.basename(path_info, path_resource_format)
41
+ def path_info_resource
42
+ # sanitized path to the resource being requested
43
+ # ensure single leading '/'
44
+ # remove any resource format
45
+ # ex:
46
+ # '/something.css' => '/something'
47
+ # '/nested/something.css' => '/nested/something'
48
+ # '///something.css' => '/something'
49
+ # '/nested///something.css' => '/nested/something'
50
+ @path_info_resource ||= File.join(
51
+ File.dirname(path_info.gsub(/\/+/, '/')).sub(/^#{hosted_at_option}/, ''),
52
+ File.basename(path_info.gsub(/\/+/, '/'), path_info_format)
53
+ ).sub(/^\/*/, '/')
40
54
  end
41
55
 
42
- def path_resource_source
43
- File.join(File.dirname(path_info).gsub(/#{options(:hosted_at)}/, ''), path_resource_name).gsub(/^\//, '')
56
+ def path_info_format
57
+ @path_info_format ||= File.extname(path_info.gsub(/\/+/, '/'))
44
58
  end
45
59
 
46
60
  def cache
47
- File.join(options(:root), options(:public), options(:hosted_at))
61
+ File.join(options(:root), options(:public), hosted_at_option)
48
62
  end
49
63
 
50
64
  # The Rack::Less::Source that the request is for
@@ -55,35 +69,35 @@ module Rack::Less
55
69
  :cache => Rack::Less.config.cache? ? cache : nil,
56
70
  :compress => Rack::Less.config.compress?
57
71
  }
58
- Source.new(path_resource_source, source_opts)
72
+ Source.new(path_info_resource, source_opts)
59
73
  end
60
74
  end
61
75
 
62
76
  def for_css?
63
77
  (http_accept && http_accept.include?(Rack::Less::MIME_TYPE)) ||
64
78
  (media_type && media_type.include?(Rack::Less::MIME_TYPE )) ||
65
- CSS_PATH_FORMATS.include?(path_resource_format)
79
+ CSS_PATH_FORMATS.include?(path_info_format)
66
80
  end
67
81
 
68
82
  def hosted_at?
69
- path_info =~ /^#{options(:hosted_at)}\//
83
+ path_info =~ /^#{hosted_at_option}\//
70
84
  end
71
85
 
72
- def exists?
73
- File.exists?(File.join(cache, "#{path_resource_source}#{path_resource_format}"))
86
+ def cached?
87
+ File.exists?(File.join(cache, "#{path_info_resource}#{path_info_format}"))
74
88
  end
75
89
 
76
- # Determine if the request is for existing LESS CSS file
90
+ # Determine if the request is for a non-cached existing LESS CSS source file
77
91
  # This will be called on every request so speed is an issue
78
- # => first check if the request is a GET on a css resource :hosted_at (fast)
79
- # => don't process if a file already exists in :hosted_at
92
+ # => first check if the request is a GET on a css resource in :hosted_at (fast)
93
+ # => don't process if a file has already been cached
80
94
  # => otherwise, check for less source files that match the request (slow)
81
95
  def for_less?
82
- get? &&
96
+ get? && # GET on css resource in :hosted_at (fast, check first)
83
97
  for_css? &&
84
98
  hosted_at? &&
85
- !exists? &&
86
- !source.files.empty?
99
+ !cached? && # resource not cached (little slower)
100
+ !source.files.empty? # there is source for the resource (slow, check last)
87
101
  end
88
102
 
89
103
  end
@@ -21,10 +21,10 @@ module Rack::Less
21
21
 
22
22
  YUI_OPTS = {}
23
23
 
24
- attr_reader :path
24
+ attr_reader :css_resource
25
25
 
26
- def initialize(path, options={})
27
- @path = path
26
+ def initialize(css_resource, options={})
27
+ @css_resource = css_resource.gsub(/^\/+/, '')
28
28
  @compress = options[:compress]
29
29
  @cache = options[:cache]
30
30
  @folder = get_required_path(options, :folder)
@@ -64,8 +64,8 @@ module Rack::Less
64
64
  compiled_css
65
65
  end
66
66
 
67
- if cache? && !File.exists?(cf = File.join(@cache, "#{@path}.css"))
68
- FileUtils.mkdir_p(@cache)
67
+ if cache? && !File.exists?(cf = File.join(@cache, "#{@css_resource}.css"))
68
+ FileUtils.mkdir_p(File.dirname(cf))
69
69
  File.open(cf, "w") do |file|
70
70
  file.write(compiled_css)
71
71
  end
@@ -81,13 +81,13 @@ module Rack::Less
81
81
 
82
82
  # Preferred, existing source files matching the css name
83
83
  def css_sources
84
- @css_sources ||= preferred_sources([@path])
84
+ @css_sources ||= preferred_sources([*@css_resource])
85
85
  end
86
86
 
87
87
  # Preferred, existing source files matching a corresponding
88
88
  # Rack::Less::Config combination directive, if any
89
89
  def combination_sources
90
- @combination_sources ||= preferred_sources(Rack::Less.config.combinations[@path] || [])
90
+ @combination_sources ||= preferred_sources(Rack::Less.config.combinations[@css_resource] || [])
91
91
  end
92
92
 
93
93
  private
@@ -1,13 +1,5 @@
1
- module RackLess
2
- module Version
3
-
4
- MAJOR = 1
5
- MINOR = 5
6
- TINY = 0
7
-
8
- def self.to_s # :nodoc:
9
- [MAJOR, MINOR, TINY].join('.')
10
- end
11
-
1
+ module Rack
2
+ module Less
3
+ VERSION = '2.0.0'
12
4
  end
13
5
  end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rack/less/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rack-less"
7
+ s.version = Rack::Less::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Kelly Redding"]
10
+ s.email = ["kelly@kelredd.com"]
11
+ s.homepage = "http://github.com/kelredd/rack-less"
12
+ s.summary = %q{LESS CSS preprocessing for Rack apps.}
13
+ s.description = %q{Use rack middleware to handle LESS CSS preprocessing. Processing happens on requests to LESS resources. This allows you to develop, check in, and deploy unprocessed LESS stylesheets and leave the processing to the middleware. Allows for optimizing by environment: never-cache, always-reprocess in development; cache, process-once in production (for example).}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency("bundler", ["~> 1.0"])
21
+ s.add_development_dependency("test-belt", ["= 0.2.1"]) # locked to a specific version for test stability
22
+ s.add_development_dependency("sinatra", [">= 0.9.4"])
23
+ s.add_development_dependency("rack-test", [">= 0.5.3"])
24
+ s.add_development_dependency("webrat", [">= 0.6.0"])
25
+ s.add_development_dependency("yui-compressor", [">=0.9.1"])
26
+
27
+ s.add_dependency("rack", ["~> 1.0"])
28
+ s.add_dependency("less", ["~> 1.2"])
29
+ end