flatrack 1.3.3 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +3 -6
  5. data/flatrack.gemspec +4 -3
  6. data/lib/custom-extensions/sprockets-sass.rb +32 -0
  7. data/lib/flatrack.rb +123 -11
  8. data/lib/flatrack/asset_extensions.rb +7 -1
  9. data/lib/flatrack/cli.rb +9 -1
  10. data/lib/flatrack/domain_parser.rb +13 -0
  11. data/lib/flatrack/middleware.rb +32 -0
  12. data/lib/flatrack/redirector.rb +63 -0
  13. data/lib/flatrack/request.rb +16 -2
  14. data/lib/flatrack/response.rb +7 -8
  15. data/lib/flatrack/rewriter.rb +32 -0
  16. data/lib/flatrack/sass/functions.rb +6 -6
  17. data/lib/flatrack/sass/importer.rb +7 -7
  18. data/lib/flatrack/sass/sass_template.rb +6 -6
  19. data/lib/flatrack/site.rb +2 -27
  20. data/lib/flatrack/template.rb +27 -8
  21. data/lib/flatrack/template/erubis.rb +2 -2
  22. data/lib/flatrack/template/html.rb +2 -2
  23. data/lib/flatrack/template/rb.rb +2 -2
  24. data/lib/flatrack/version.rb +1 -1
  25. data/lib/flatrack/view.rb +1 -1
  26. data/lib/flatrack/view/capture_helper.rb +1 -2
  27. data/lib/flatrack/view/link_helper.rb +8 -1
  28. data/lib/flatrack/view/render_helper.rb +1 -1
  29. data/lib/flatrack/view/request_helper.rb +23 -2
  30. data/lib/flatrack/view/tag_helper.rb +19 -11
  31. data/spec/lib/flatrack/cli_spec.rb +28 -2
  32. data/spec/lib/flatrack/middleware_spec.rb +55 -0
  33. data/spec/lib/flatrack/site_spec.rb +3 -5
  34. data/spec/lib/flatrack/view/render_helper_spec.rb +4 -0
  35. data/spec/lib/flatrack/view/set_layout_spec.rb +1 -1
  36. data/spec/lib/flatrack/view/tag_helper_spec.rb +9 -0
  37. data/spec/lib/flatrack/view_spec.rb +1 -1
  38. data/spec/lib/flatrack_spec.rb +73 -0
  39. data/spec/lib/rake/asset_tasks_spec.rb +2 -2
  40. data/spec/spec_helper.rb +1 -0
  41. data/spec/support/fixture_helper.rb +1 -1
  42. data/spec/support/site_helper.rb +3 -1
  43. metadata +32 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4712856b901f1113021c85dcd49feb181318fbc5
4
- data.tar.gz: 9234ce5891267c17e254b3953bb2219a4e4a2dfe
3
+ metadata.gz: 2d13c4d84da9f6348b2d63a2b12ba6e76f422a1a
4
+ data.tar.gz: c3d9bfc0ec684c2922edfe260e92fbfbb994a793
5
5
  SHA512:
6
- metadata.gz: 39da8a5e1fce769e1d847d74cbdeb8642d484650ffd5a533872ef56a442799ad7ffd1a7f8c24375487541967108ee5b0b7c13567664c59e7e8b3fac8c4d472af
7
- data.tar.gz: ab7fcf8c901f5613006707a6c23432f8c6723e6ed7010300c55cf503bce952cb14554d3a7442e80e694b5ce5d8936ebd6630cf350fb942ffea7dba60ea3a642b
6
+ metadata.gz: 73606292ae76a830287a1b6426df26f31fb6695eccdd4ec43ab01adb322bfe210e33a08c38b23f7afc8e9301e27d10bed724a82e6d62f5d82e43ae2548082db6
7
+ data.tar.gz: f96358443ba28a52c4d8736818b7c7b9d8f26cd0d8bb6b189799438da3246568bdac01874376e3249be0914ed53dc2eb830acd733a0f822bf8a74e80b05dd6ad
data/.gitignore CHANGED
@@ -4,6 +4,7 @@ pkg/*
4
4
  tmp
5
5
  coverage
6
6
  /.sass-cache/
7
+ .bundle
7
8
 
8
9
  /.yardoc/
9
10
 
@@ -1 +1 @@
1
- 2.1.3
1
+ 2.2.0
@@ -1,10 +1,9 @@
1
1
  language: ruby
2
+ sudo: false
2
3
  rvm:
3
4
  - 2.0.0
4
- - 2.1.1
5
- - 2.1.2
6
- - 2.1.2
7
- - 2.2.0-preview1
5
+ - 2.1.5
6
+ - 2.2.0
8
7
  cache: bundler
9
8
  after_success:
10
9
  - bundle exec inch
@@ -12,5 +11,3 @@ after_success:
12
11
 
13
12
  matrix:
14
13
  fast_finish: true
15
- allow_failures:
16
- - rvm: 2.2.0-preview1
@@ -30,14 +30,15 @@ based routing.
30
30
 
31
31
  # Dependencies
32
32
  spec.add_runtime_dependency 'rack', '~> 1.4'
33
+ spec.add_runtime_dependency 'rack-contrib', '~> 1.2'
33
34
  spec.add_runtime_dependency 'erubis', '~> 2.7'
34
35
  spec.add_runtime_dependency 'tilt', '~> 1.1'
35
- spec.add_runtime_dependency 'activesupport', ['> 3.2', '< 4.2']
36
- spec.add_runtime_dependency 'sass', '~> 3.2.0'
36
+ spec.add_runtime_dependency 'activesupport', ['> 3.2', '< 5.0']
37
+ spec.add_runtime_dependency 'sass', '~> 3.2'
37
38
  spec.add_runtime_dependency 'sprockets-sass', '~> 1.2'
38
39
  spec.add_runtime_dependency 'thor', '~> 0.18'
39
40
  spec.add_runtime_dependency 'coffee-script', '~> 2.2'
40
- spec.add_runtime_dependency 'rake', ['> 0.8.7', '< 10.2']
41
+ spec.add_runtime_dependency 'rake', ['> 0.8.7', '< 10.4']
41
42
 
42
43
  # Dev Dependencies
43
44
  spec.add_development_dependency 'bundler', '~> 1.5'
@@ -0,0 +1,32 @@
1
+ require 'sprockets'
2
+ require 'sprockets/sass/version'
3
+ require 'sprockets/sass/sass_template'
4
+ require 'sprockets/sass/scss_template'
5
+ require 'sprockets/engines'
6
+
7
+ module Sprockets
8
+ module Sass
9
+ autoload :CacheStore, 'sprockets/sass/cache_store'
10
+ autoload :Compressor, 'sprockets/sass/compressor'
11
+ autoload :Importer, 'sprockets/sass/importer'
12
+
13
+ class << self
14
+ # Global configuration for `Sass::Engine` instances.
15
+ attr_accessor :options
16
+
17
+ # When false, the asset path helpers provided by
18
+ # sprockets-helpers will not be added as Sass functions.
19
+ # `true` by default.
20
+ attr_accessor :add_sass_functions
21
+ end
22
+
23
+ @options = {}
24
+ @add_sass_functions = true
25
+
26
+ # Allow to fallback to real sass
27
+ def self.const_missing(const)
28
+ ::Sass.const_get const
29
+ end
30
+
31
+ end
32
+ end
@@ -1,10 +1,10 @@
1
1
  require 'flatrack/version'
2
2
  require 'active_support/all'
3
- require 'sprockets'
4
- require 'sprockets-sass'
3
+ require 'custom-extensions/sprockets-sass'
5
4
  require 'coffee-script'
6
5
  require 'sass'
7
6
  require 'rack'
7
+ require 'rack/contrib'
8
8
 
9
9
  # A static site generator with a little sprinkle of ruby magic
10
10
  class Flatrack
@@ -17,15 +17,26 @@ class Flatrack
17
17
  autoload :Site
18
18
  autoload :AssetExtensions
19
19
  autoload :CLI
20
+ autoload :Middleware
21
+ autoload :Rewriter
22
+ autoload :Redirector
23
+ autoload :DomainParser
24
+
25
+ Redirector
26
+ Rewriter
20
27
 
21
28
  # @private
22
29
  TemplateNotFound = Class.new StandardError
23
30
  # @private
24
31
  FileNotFound = Class.new StandardError
25
32
  # @private
26
- FORMATS = {}
33
+ FORMATS = {}
34
+ # @private
35
+ MAPPING = { '/assets' => :assets, '/' => :site }
27
36
 
28
- delegate :gem_root, :site_root, to: self
37
+ delegate :gem_root, to: self
38
+ delegate :call, to: :builder
39
+ attr_accessor :raise_errors
29
40
 
30
41
  class << self
31
42
  # The root of the flatrack gem
@@ -39,14 +50,20 @@ class Flatrack
39
50
  # @!attribute [r] site_root
40
51
  # @return [String]
41
52
  def site_root
42
- File.expand_path Dir.pwd
53
+ Dir.pwd
43
54
  end
44
55
 
45
56
  # Reset the state of flatrack and its configuration
57
+ # For testing
58
+ # @private
46
59
  def reset!
47
60
  @delegate_instance = nil
48
61
  end
49
62
 
63
+ def site=(instance)
64
+ @delegate_instance = instance
65
+ end
66
+
50
67
  private
51
68
 
52
69
  def delegate_instance
@@ -61,9 +78,12 @@ class Flatrack
61
78
  # Configure the flatrack instance
62
79
  # @yield [Flatrack] configuration for the flatrack instance
63
80
  # @return [Flatrack]
64
- def config(&block)
65
- yield self
66
- self
81
+ def config
82
+ yield self if block_given?
83
+ OpenStruct.new(
84
+ site_root: site_root,
85
+ raise_errors: raise_errors
86
+ ).freeze
67
87
  end
68
88
 
69
89
  # The flatrack sprockets environment
@@ -71,10 +91,13 @@ class Flatrack
71
91
  # @return [Sprockets::Environment]
72
92
  def assets
73
93
  @assets ||= begin
94
+ Sass.load_paths << File.join(site_root, 'assets/stylesheets')
74
95
  Sprockets::Environment.new.tap do |environment|
75
- environment.append_path 'assets/images'
76
- environment.append_path 'assets/javascripts'
77
- environment.append_path 'assets/stylesheets'
96
+ environment.register_engine '.sass', Sprockets::Sass::SassTemplate
97
+ environment.register_engine '.scss', Sprockets::Sass::ScssTemplate
98
+ environment.append_path File.join site_root, 'assets/images'
99
+ environment.append_path File.join site_root, 'assets/javascripts'
100
+ environment.append_path File.join site_root, 'assets/stylesheets'
78
101
  environment.context_class.class_eval { include AssetExtensions }
79
102
  end
80
103
  end
@@ -88,10 +111,54 @@ class Flatrack
88
111
  end
89
112
 
90
113
  # The middleware stack for flatrack
114
+ # @!attribute [r] middleware
115
+ # @return [Hash]
91
116
  def middleware
92
117
  @middleware ||= []
93
118
  end
94
119
 
120
+ # This is for testing
121
+ # @private
122
+ def mock_env_for(url, opts={})
123
+ env = Rack::MockRequest.env_for url, opts
124
+ env.merge! env_extensions
125
+ end
126
+
127
+ # Rewrite a path
128
+ # @param source [String]
129
+ # @param to [String]
130
+ def rewrite(source, to: nil)
131
+ unless [source, to].all? { |path| path.is_a? String }
132
+ raise ArgumentError, 'mappings must be strings'
133
+ end
134
+ rewrites.merge! source => to
135
+ end
136
+
137
+ # redirect a path
138
+ # @param source [String]
139
+ # @param to [String]
140
+ # @param type [Symbol]
141
+ def redirect(source, to: nil, type: :permanent)
142
+ unless [source, to].all? { |path| path.is_a? String }
143
+ raise ArgumentError, 'mappings must be strings'
144
+ end
145
+ redirects.merge! source => Redirector::Redirect.new(to, type)
146
+ end
147
+
148
+ # The rewrites
149
+ # @!attribute [r] rewrites
150
+ # @return [Hash]
151
+ def rewrites
152
+ @rewrites ||= {}
153
+ end
154
+
155
+ # The redirects
156
+ # @!attribute [r] redirects
157
+ # @return [Hash]
158
+ def redirects
159
+ @redirects ||= {}
160
+ end
161
+
95
162
  # Insert a rack middleware at the end of the stack
96
163
  # @param middleware [Class] the middleware class
97
164
  # @param options [Hash] the options for the middleware
@@ -99,6 +166,51 @@ class Flatrack
99
166
  self.middleware << [middleware, options].compact
100
167
  end
101
168
 
169
+ def site_root=(path)
170
+ path = File.expand_path path
171
+ Template.register_path path
172
+ @site_root = path
173
+ end
174
+
175
+ # The site root
176
+ # @!attribute [r] site_root
177
+ # @return [String]
178
+ def site_root
179
+ @site_root || (self.site_root = self.class.site_root)
180
+ end
181
+
182
+ # Returns the site lambda
183
+ # @return [Proc]
184
+ def site
185
+ lambda { |env|
186
+ env.merge! env_extensions
187
+ Request.new(env).response
188
+ }
189
+ end
190
+
191
+ private
192
+
193
+ def builder
194
+ @builder ||= begin
195
+ this = self
196
+ Rack::Builder.app do
197
+ use Rack::Cookies
198
+ use DomainParser
199
+ use Flatrack::Rewriter, this.rewrites if this.rewrites.present?
200
+ use Flatrack::Redirector, this.redirects if this.redirects.present?
201
+ use Rack::Static,
202
+ urls: ['/favicon.ico', 'assets'],
203
+ root: File.join(this.site_root, 'public')
204
+ this.middleware.each { |mw| use *mw }
205
+ MAPPING.each { |path, app| map(path) { run this.send(app) } }
206
+ end
207
+ end
208
+ end
209
+
210
+ def env_extensions
211
+ { 'flatrack.config' => self.config }
212
+ end
213
+
102
214
  # By default we know how to render 'text/html'
103
215
  register_format :html, 'text/html'
104
216
 
@@ -5,7 +5,13 @@ class Flatrack
5
5
  # @param path [String] the asset name or path
6
6
  # @return [String]
7
7
  def asset_path(path, _ = {})
8
- File.join('/assets', path.to_s)
8
+ File.join('/', mount_path, 'assets', path.to_s)
9
+ end
10
+
11
+ def mount_path
12
+ a = singleton_class.ancestors
13
+ has_super = a[a.index(AssetExtensions) + 1].method_defined? __method__
14
+ has_super ? super : '/'
9
15
  end
10
16
  end
11
17
  end
@@ -58,11 +58,19 @@ class Flatrack
58
58
 
59
59
  method_option :verbose, type: :boolean, default: true, aliases: :v
60
60
  method_option :port, type: :numeric, default: 5959, aliases: :p
61
+ method_option :root, default: Dir.pwd, type: :string, aliases: :r
61
62
 
62
63
  desc 'start --port PORT', 'run the site on the given port'
63
64
  # Start the app
64
65
  def start
65
- require './boot'
66
+ Flatrack.config do |config|
67
+ config.site_root = options[:root]
68
+ end
69
+ begin
70
+ require File.join Dir.pwd, 'boot'
71
+ rescue LoadError
72
+ nil
73
+ end
66
74
  run_opts = {}
67
75
  run_opts[:app] = Flatrack::Site
68
76
  run_opts[:Port] = options[:port]
@@ -0,0 +1,13 @@
1
+ class Flatrack
2
+ class DomainParser < Struct.new :app
3
+
4
+ def call(env)
5
+ *subdomains, host, tld = env['SERVER_NAME'].split '.'
6
+ env['domain.sub'] = subdomains.join '.'
7
+ env['domain.host'] = host
8
+ env['domain.tld'] = tld
9
+ app.call(env)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ class Flatrack
2
+ class Middleware
3
+
4
+ def initialize(app, opts = {})
5
+ @if = opts[:if] || Proc.new { true }
6
+ @unless = opts[:unless] || Proc.new { false }
7
+ @app = app
8
+ @flatrack_app = opts[:flatrack_app] || Flatrack::Site
9
+ end
10
+
11
+ def call(env)
12
+ Flatrack::DomainParser.new(null_app).call(env)
13
+ allow = @if.call(env) && !@unless.call(env)
14
+ return call_app env unless allow
15
+ response = @flatrack_app.call env
16
+ status, _, _ = response
17
+ response = call_app(env) if status == 404
18
+ response
19
+ rescue Flatrack::FileNotFound
20
+ call_app env
21
+ end
22
+
23
+ def call_app(env)
24
+ @app.call env
25
+ end
26
+
27
+ def null_app
28
+ ->(_){}
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,63 @@
1
+ class Flatrack
2
+ def Redirector(source, opts={})
3
+ to = opts.delete(:to)
4
+ type = opts.delete(:type) || :permanent
5
+ klass = Class.new(Redirector)
6
+ klass.send(:define_method, :initialize) do |app, mw_opts|
7
+ mapping = { source => Redirector::Redirect.new(to, type) }
8
+ super app, mapping, mw_opts
9
+ end
10
+ klass
11
+ end
12
+
13
+ class Redirector
14
+
15
+ def initialize(app, mapping = {}, opts = {})
16
+ @if = opts[:if] || Proc.new { true }
17
+ @unless = opts[:unless] || Proc.new { false }
18
+ @app = app
19
+ @mapping =
20
+ Hash[mapping.map { |k, v| [File.join('', k), v] }]
21
+ end
22
+
23
+ def call(env)
24
+ allow = @if.call(env) && !@unless.call(env)
25
+ if allow && @mapping.keys.include?(env['PATH_INFO'])
26
+ @mapping[env['PATH_INFO']].response
27
+ else
28
+ @app.call env
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ class Redirect
35
+
36
+ attr_reader :url, :type
37
+
38
+ def initialize(url, type = :permanent)
39
+ @url, @type = url, type
40
+ code # just to check args
41
+ end
42
+
43
+ # Returns the code for the specified type
44
+ # @returns [Fixnum]
45
+ def code
46
+ case type.to_sym
47
+ when :permanent
48
+ 301
49
+ when :temporary
50
+ 302
51
+ else
52
+ raise ArgumentError, 'type must be :temporary or :permanent'
53
+ end
54
+ end
55
+
56
+ def response
57
+ [code, { 'location' => url }, ["you are being redirected to: `#{url}`"]]
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end