flatrack 1.3.3 → 1.4.1

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.
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
@@ -13,6 +13,10 @@ class Flatrack
13
13
 
14
14
  # the path of the incoming request
15
15
  def path
16
+ env['ORIGINAL_PATH_INFO'] || env['PATH_INFO']
17
+ end
18
+
19
+ def page
16
20
  env['PATH_INFO']
17
21
  end
18
22
 
@@ -33,12 +37,22 @@ class Flatrack
33
37
  # the processed response for an inbound request
34
38
  def response
35
39
  Response.new(self).render
36
- rescue TemplateNotFound
40
+ rescue TemplateNotFound => e
41
+ raise e if config.raise_errors
37
42
  respond_with_error(500)
38
- rescue FileNotFound
43
+ rescue FileNotFound => e
44
+ raise e if config.raise_errors
39
45
  respond_with_error(404)
40
46
  end
41
47
 
48
+ def config
49
+ env['flatrack.config']
50
+ end
51
+
52
+ def mount_path
53
+ env['SCRIPT_NAME'].present? ? env['SCRIPT_NAME'] : '/'
54
+ end
55
+
42
56
  private
43
57
 
44
58
  def respond_with_error(code)
@@ -6,7 +6,7 @@ class Flatrack
6
6
 
7
7
  attr_accessor :layout
8
8
  attr_reader :request
9
- delegate :format, to: :request
9
+ delegate :mount_path, :config, :format, to: :request
10
10
 
11
11
  # Initializes a response
12
12
  # @param request [Flatrack::Request]
@@ -20,7 +20,7 @@ class Flatrack
20
20
  # @option opts [Fixnum] :status
21
21
  # @option opts [Symbol] :layout
22
22
  # @return [Array] the rack response
23
- def render(file: file_for(request.path), status: 200, layout: :layout)
23
+ def render(file: file_for(request.page), status: 200, layout: :layout)
24
24
  @file, @status, @layout = file, status, layout
25
25
  page_content = pre_render_page
26
26
  body << begin
@@ -57,19 +57,18 @@ class Flatrack
57
57
  end
58
58
 
59
59
  def file_for(path)
60
- if File.directory?(File.join 'pages', path)
61
- File.join(path, DEFAULT_FILE)
62
- else
63
- path
60
+ if File.directory?(File.join config.site_root, 'pages', path)
61
+ path = File.join(path, DEFAULT_FILE)
64
62
  end
63
+ path
65
64
  end
66
65
 
67
66
  def renderer_for_page(file)
68
- Template.find :page, format, file
67
+ Template.find config.site_root, :page, format, file
69
68
  end
70
69
 
71
70
  def renderer_for_layout(file)
72
- Template.find :layout, format, file
71
+ Template.find config.site_root, :layout, format, file
73
72
  end
74
73
 
75
74
  def view
@@ -0,0 +1,32 @@
1
+ class Flatrack
2
+ def Rewriter(source, opts={})
3
+ to = opts.delete(:to)
4
+ klass = Class.new(Rewriter)
5
+ klass.send(:define_method, :initialize) do |app, mw_opts|
6
+ mapping = { source => to }
7
+ super app, mapping, mw_opts
8
+ end
9
+ klass
10
+ end
11
+
12
+ class Rewriter
13
+
14
+ def initialize(app, mapping = {}, opts = {})
15
+ @if = opts[:if] || Proc.new { true }
16
+ @unless = opts[:unless] || Proc.new { false }
17
+ @app = app
18
+ @mapping =
19
+ Hash[mapping.map { |paths| paths.map { |p| File.join '', p } }]
20
+ end
21
+
22
+ def call(env)
23
+ allow = @if.call(env) && !@unless.call(env)
24
+ if allow && @mapping.keys.include?(env['PATH_INFO'])
25
+ env['ORIGINAL_PATH_INFO'] = env['PATH_INFO']
26
+ env['PATH_INFO'] = @mapping[env['PATH_INFO']]
27
+ end
28
+ @app.call env
29
+ end
30
+
31
+ end
32
+ end
@@ -148,16 +148,16 @@ module Sass::Script::Functions
148
148
  defined?(@signatures) && @signatures.delete(method)
149
149
  end
150
150
 
151
- declare :asset_path, [:source], :var_kwargs => true
151
+ declare :asset_path, [:source], var_kwargs: true
152
152
  declare :asset_path, [:source, :kind]
153
- declare :asset_url, [:source], :var_kwargs => true
153
+ declare :asset_url, [:source], var_kwargs: true
154
154
  declare :asset_url, [:source, :kind]
155
- declare :image_path, [:source], :var_kwargs => true
156
- declare :image_url, [:source], :var_kwargs => true
155
+ declare :image_path, [:source], var_kwargs: true
156
+ declare :image_url, [:source], var_kwargs: true
157
157
  declare :image_url, [:source, :only_path]
158
158
  declare :image_url, [:source, :only_path, :cache_buster]
159
- declare :font_path, [:source], :var_kwargs => true
160
- declare :font_url, [:source], :var_kwargs => true
159
+ declare :font_path, [:source], var_kwargs: true
160
+ declare :font_url, [:source], var_kwargs: true
161
161
  declare :font_url, [:source, :only_path]
162
162
  declare :asset_data_uri, [:source]
163
163
  end
@@ -48,9 +48,9 @@ class Flatrack
48
48
  pathname = resolve(context, path, base_path) or return nil
49
49
  context.depend_on pathname
50
50
  ::Sass::Engine.new evaluate(context, pathname), options.merge(
51
- :filename => pathname.to_s,
52
- :syntax => syntax(pathname),
53
- :importer => self
51
+ filename: pathname.to_s,
52
+ syntax: syntax(pathname),
53
+ importer: self
54
54
  )
55
55
  end
56
56
 
@@ -65,9 +65,9 @@ class Flatrack
65
65
  end
66
66
  return nil if imports.empty?
67
67
  ::Sass::Engine.new imports, options.merge(
68
- :filename => base_path.to_s,
69
- :syntax => :scss,
70
- :importer => self
68
+ filename: base_path.to_s,
69
+ syntax: :scss,
70
+ importer: self
71
71
  )
72
72
  end
73
73
 
@@ -135,7 +135,7 @@ class Flatrack
135
135
  attributes = context.environment.attributes_for(path)
136
136
  processors = context.environment.preprocessors(attributes.content_type) + attributes.engines.reverse
137
137
  processors.delete_if { |processor| processor < Tilt::SassTemplate }
138
- context.evaluate(path, :processors => processors)
138
+ context.evaluate(path, processors: processors)
139
139
  end
140
140
  end
141
141
  end
@@ -66,12 +66,12 @@ class Flatrack
66
66
  # Assemble the options for the `Sass::Engine`
67
67
  def sass_options
68
68
  merge_sass_options(default_sass_options, options).merge(
69
- :filename => eval_file,
70
- :line => line,
71
- :syntax => syntax,
72
- :cache_store => cache_store,
73
- :importer => Importer.new,
74
- :custom => { :sprockets_context => context }
69
+ filename: eval_file,
70
+ line: line,
71
+ syntax: syntax,
72
+ cache_store: cache_store,
73
+ importer: Importer.new,
74
+ custom: { sprockets_context: context }
75
75
  )
76
76
  end
77
77
 
@@ -3,32 +3,7 @@ require 'rack/server'
3
3
  class Flatrack
4
4
  # Provides a rake wrapper for encapsulating a flatrack site
5
5
  module Site
6
- # Call the site with a rack env
7
- # @param env [Hash] the rack env
8
- def self.call(env)
9
- builder.call(env)
10
- end
11
-
12
- private
13
-
14
- def self.builder
15
- mapping = self.mapping
16
- Rack::Builder.app do
17
- use Rack::Static, urls: ['/favicon.ico', 'assets'], root: 'public'
18
- Flatrack.middleware.each { |mw| use(*mw) }
19
- mapping.each { |path, app| map(path) { run app } }
20
- end
21
- end
22
-
23
- def self.site
24
- ->(env) { Request.new(env).response }
25
- end
26
-
27
- def self.mapping
28
- {
29
- '/assets' => Flatrack.assets,
30
- '/' => site
31
- }
32
- end
6
+ extend self
7
+ delegate :call, to: Flatrack
33
8
  end
34
9
  end
@@ -9,32 +9,47 @@ class Flatrack
9
9
  # @private
10
10
  DEFAULT_FORMAT = 'html'
11
11
 
12
- attr_reader :type, :file, :format
12
+ attr_reader :base_path, :type, :file, :format
13
13
  delegate :render, to: :@renderer
14
14
 
15
+ def self.register_path(path)
16
+ classes.each do |klass|
17
+ files = Dir.glob File.join path, '**', "*.#{klass::RENDERS}"
18
+ Tilt.register klass, *files
19
+ end
20
+ end
21
+
15
22
  # Creates a new template instance and invokes find
16
23
  # @param type [Symbol] the type of template
17
24
  # @param format [String] the format e.g. html
18
25
  # @param file [String] the location of the file
19
- def self.find(type, format, file)
20
- new(type, format, file)
26
+ def self.find(base_path, type, format, file)
27
+ new(base_path, type, format, file)
21
28
  end
22
29
 
23
30
  # Creates a new template instance
24
31
  # @param type [Symbol] the type of template
25
32
  # @param format [String] the format e.g. html
26
33
  # @param file [String] the location of the file
27
- def initialize(type, format, file)
34
+ def initialize(base_path, type, format, file)
35
+ @base_path = base_path
28
36
  @format = format || DEFAULT_FORMAT
29
37
  @type, @file = type, file.to_s
30
- @renderer = find
38
+ @renderer = find
31
39
  end
32
40
 
33
41
  private
34
42
 
43
+ def self.classes
44
+ constants.map { |k| const_get k }.select do |klass|
45
+ klass.is_a?(Class) && klass < Tilt::Template
46
+ end
47
+ end
48
+
35
49
  def find
36
50
  template = find_by_type
37
51
  fail FileNotFound, "could not find #{file}" unless template
52
+ template = File.expand_path template
38
53
  Tilt.new template, options
39
54
  rescue RuntimeError
40
55
  raise TemplateNotFound, "could not find a renderer for #{file}"
@@ -48,11 +63,15 @@ class Flatrack
48
63
  end
49
64
 
50
65
  def find_by_type
51
- if File.exist?(file)
66
+ paths = [base_path, Flatrack.gem_root]
67
+
68
+ # To support direct html files
69
+ if paths.any? { |path| file.start_with? path } && File.exist?(file)
52
70
  file
53
71
  else
54
- file_with_format = [file, format].compact.join('.')
55
- Dir[File.join type.to_s.pluralize, "#{file_with_format}*"].first
72
+ file_without_format = File.join(File.dirname(file), File.basename(file, ".#{format}"))
73
+ file_with_format = [file_without_format, format].compact.join('.')
74
+ Dir[File.join base_path, type.to_s.pluralize, "#{file_with_format}*"].first
56
75
  end
57
76
  end
58
77
  end
@@ -2,6 +2,8 @@ class Flatrack
2
2
  class Template
3
3
  # The tilt template for rendering ERB in flatrack
4
4
  class Erubis < Tilt::ErubisTemplate
5
+ RENDERS = 'erb'
6
+
5
7
  extend ActiveSupport::Autoload
6
8
  autoload :Handler
7
9
 
@@ -19,5 +21,3 @@ class Flatrack
19
21
  end
20
22
  end
21
23
  end
22
-
23
- Tilt.prefer Flatrack::Template::Erubis, 'erb'
@@ -2,6 +2,8 @@ class Flatrack
2
2
  class Template
3
3
  # The tilt template for rendering HTML in flatrack
4
4
  class Html < Tilt::PlainTemplate
5
+ RENDERS = 'html'
6
+
5
7
  private
6
8
 
7
9
  def evaluate(scope, locals, &block)
@@ -10,5 +12,3 @@ class Flatrack
10
12
  end
11
13
  end
12
14
  end
13
-
14
- Tilt.prefer Flatrack::Template::Html, 'html'
@@ -4,6 +4,8 @@ class Flatrack
4
4
  class Template
5
5
  # The tilt template for rendering Ruby in flatrack
6
6
  class Rb < Tilt::ErubisTemplate
7
+ RENDERS = 'rb'
8
+
7
9
  private
8
10
 
9
11
  def data
@@ -12,5 +14,3 @@ class Flatrack
12
14
  end
13
15
  end
14
16
  end
15
-
16
- Tilt.prefer Flatrack::Template::Rb, 'rb'
@@ -1,5 +1,5 @@
1
1
  # Version
2
2
  class Flatrack
3
3
  # @private
4
- VERSION = '1.3.3'
4
+ VERSION = '1.4.1'
5
5
  end
@@ -19,7 +19,7 @@ class Flatrack
19
19
  include ERB::Util
20
20
 
21
21
  attr_accessor :output_buffer
22
- delegate :use_layout, to: :@response
22
+ delegate :mount_path, :config, :use_layout, to: :@response
23
23
 
24
24
  # initializes a flatrack view
25
25
  # @param response [Flatrack::Response]
@@ -9,8 +9,7 @@ class Flatrack
9
9
  def capture(*args)
10
10
  value = nil
11
11
  buffer = with_output_buffer { value = yield(*args) }
12
- string = buffer.presence || value
13
- html_escape string if string.is_a?(String)
12
+ buffer.presence || value
14
13
  end
15
14
 
16
15
  # Use an alternate output buffer for the duration of the block.
@@ -32,7 +32,14 @@ class Flatrack
32
32
  # @return [String]
33
33
  def link_to(*args, &block)
34
34
  href, options, block = link_to_options(*args, &block)
35
- html_tag :a, link_to_tag_options(href, options || {}), &block
35
+ if href.start_with?('/') && !href.start_with?('//') && mount_path != '/'
36
+ href = File.join '', mount_path, href
37
+ end
38
+ tag_opts = link_to_tag_options(href, options || {})
39
+ if current_path == tag_opts[:href]
40
+ ((tag_opts[:class] ||= '') << ' active').strip!
41
+ end
42
+ html_tag(:a, tag_opts, false, &block)
36
43
  end
37
44
 
38
45
  private
@@ -6,7 +6,7 @@ class Flatrack
6
6
  # @param file [Symbol, String]
7
7
  # @return [String]
8
8
  def render(file, *args)
9
- Template.find(:partial, nil, file.to_s).render(self, *args)
9
+ Template.find(config.site_root, :partial, nil, file.to_s).render(self, *args)
10
10
  end
11
11
  end
12
12
  end
@@ -8,11 +8,32 @@ class Flatrack
8
8
  @response.request.params
9
9
  end
10
10
 
11
- # Returns the path
11
+ # Returns the path before rewrites
12
12
  # @return [String]
13
- def path
13
+ def current_path
14
14
  @response.request.path
15
15
  end
16
+ alias path current_path
17
+
18
+ # Returns the page being displayed
19
+ # @return [String]
20
+ def current_page
21
+ @response.request.page
22
+ end
23
+ alias page current_page
24
+
25
+ # Returns the IP address for the request
26
+ # @return [String]
27
+ def request_ip
28
+ @response.request.env['REMOTE_ADDR']
29
+ end
30
+
31
+ # Returns the cookies
32
+ # @return [Hash]
33
+ def cookies
34
+ @response.request.env['rack.cookies']
35
+ end
36
+
16
37
  end
17
38
  end
18
39
  end
@@ -7,11 +7,11 @@ class Flatrack
7
7
 
8
8
  # @private
9
9
  PRE_CONTENT_STRINGS = {
10
- textarea: "\n"
10
+ textarea: "\n"
11
11
  }
12
12
 
13
13
  # @private
14
- BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked autobuffer
14
+ BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple checked autobuffer
15
15
  autoplay controls loop selected hidden scoped
16
16
  async defer reversed ismap seamless muted
17
17
  required autofocus novalidate formnovalidate open
@@ -37,16 +37,17 @@ class Flatrack
37
37
  # @param options [Hash] the html options for the tag
38
38
  # @yield the tag content
39
39
  # @return [String]
40
- def html_tag(name, content_or_options_with_block = nil, options = nil,
41
- escape = true, &block)
40
+ def html_tag(name, *args, &block)
41
+ content, options, escape = args
42
42
  if block_given?
43
- if content_or_options_with_block.is_a?(Hash)
44
- options = content_or_options_with_block
45
- end
46
- html_tag_string(name, capture(&block), options, escape)
43
+ check_arguments [name, *args], 1..3
44
+ options, escape = content, options
45
+ content = capture(&block)
47
46
  else
48
- html_tag_string(name, content_or_options_with_block, options, escape)
47
+ check_arguments [name, *args], 2..4
49
48
  end
49
+ escape = true if escape.nil?
50
+ html_tag_string(name, content, options, escape)
50
51
  end
51
52
 
52
53
  # Returns an HTML image tag
@@ -77,6 +78,13 @@ class Flatrack
77
78
 
78
79
  private
79
80
 
81
+ def check_arguments(args, number_or_range)
82
+ range = number_or_range.is_a?(Fixnum) ? [number_or_range] : number_or_range
83
+ unless range.include? args.size
84
+ raise ArgumentError, "wrong number of arguments (#{args.count} for #{number_or_range.inspect})"
85
+ end
86
+ end
87
+
80
88
  def html_tag_string(name, content, options, escape = true)
81
89
  tag_options = tag_options(options, escape) if options
82
90
  content = h(content) if escape && !content.nil?
@@ -115,8 +123,8 @@ class Flatrack
115
123
  def data_tag_option(key, value, escape)
116
124
  key = "data-#{key.to_s.dasherize}"
117
125
  value = value.to_json unless value.is_a?(String) ||
118
- value.is_a?(Symbol) ||
119
- value.is_a?(BigDecimal)
126
+ value.is_a?(Symbol) ||
127
+ value.is_a?(BigDecimal)
120
128
  tag_option(key, value, escape)
121
129
  end
122
130