flatrack 1.0.0.alpha5 → 1.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -1
  3. data/.rubocop.yml +6 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +5 -0
  6. data/Gemfile +1 -3
  7. data/Guardfile +11 -0
  8. data/README.md +41 -10
  9. data/Rakefile +8 -1
  10. data/bin/flatrack +1 -1
  11. data/flatrack.gemspec +30 -20
  12. data/lib/flatrack.rb +50 -7
  13. data/lib/flatrack/asset_extensions.rb +2 -4
  14. data/lib/flatrack/cli.rb +71 -20
  15. data/lib/flatrack/renderer.rb +18 -7
  16. data/lib/flatrack/renderer/base.rb +2 -4
  17. data/lib/flatrack/request.rb +6 -14
  18. data/lib/flatrack/response.rb +19 -32
  19. data/lib/flatrack/response/view_context.rb +27 -40
  20. data/lib/flatrack/site.rb +27 -9
  21. data/lib/flatrack/version.rb +2 -2
  22. data/lib/rake/asset_tasks.rb +12 -12
  23. data/logo.png +0 -0
  24. data/public/assets/manifest-6d7e78baa6d2c0670a82be957315fcbc.json +1 -0
  25. data/renderers/erb.rb +1 -3
  26. data/renderers/html.rb +1 -3
  27. data/renderers/rb.rb +11 -9
  28. data/spec/fixtures/assets/application.js.coffee +2 -0
  29. data/spec/lib/flatrack/asset_extensions_spec.rb +13 -0
  30. data/spec/lib/flatrack/cli_spec.rb +58 -0
  31. data/spec/lib/flatrack/renderer/base_spec.rb +4 -0
  32. data/spec/lib/flatrack/renderer_spec.rb +4 -0
  33. data/spec/lib/flatrack/request_spec.rb +22 -0
  34. data/spec/lib/flatrack/response/view_context_spec.rb +76 -0
  35. data/spec/lib/flatrack/response_spec.rb +22 -0
  36. data/spec/lib/flatrack/site_spec.rb +39 -0
  37. data/spec/lib/flatrack_spec.rb +28 -0
  38. data/spec/lib/rake/asset_tasks_spec.rb +55 -0
  39. data/spec/renderers/erb_spec.rb +21 -0
  40. data/spec/renderers/html_spec.rb +21 -0
  41. data/spec/renderers/rb_spec.rb +21 -0
  42. data/spec/spec_helper.rb +14 -2
  43. data/spec/support/site_helper.rb +52 -0
  44. data/templates/.gitignore +2 -1
  45. data/{spec/rake/asset_tasks_spec.rb → templates/.keep} +0 -0
  46. data/templates/404.html +1 -0
  47. data/templates/500.html +1 -0
  48. data/templates/Rakefile +1 -1
  49. data/templates/boot.rb +3 -1
  50. data/templates/javascript.js.coffee +2 -0
  51. data/templates/layout.html.erb +5 -3
  52. data/templates/stylesheet.css.scss +2 -0
  53. metadata +163 -54
@@ -1,24 +1,16 @@
1
- module Flatrack
1
+ class Flatrack
2
2
  class Request
3
-
4
3
  DEFAULT_FORMAT = 'html'
5
4
 
6
5
  attr_reader :env, :rack_request
7
6
 
8
7
  def initialize(env)
9
8
  @rack_request = Rack::Request.new(env)
10
- @env = env
9
+ @env = env
11
10
  end
12
11
 
13
12
  def path
14
- env['REQUEST_PATH']
15
- end
16
-
17
- def headers
18
- env.reduce({}) do |hash, (key, value)|
19
- next hash unless /^HTTP_(?<name>.+)/ =~ key
20
- hash.merge name.downcase.to_sym => value
21
- end
13
+ env['PATH_INFO']
22
14
  end
23
15
 
24
16
  def params
@@ -42,8 +34,8 @@ module Flatrack
42
34
  def respond_with_error(code)
43
35
  Response.new(self).render(file: "#{code}.html", status: code)
44
36
  rescue FileNotFound
45
- Response.new(self).render(text: code, status: code)
37
+ file = File.join Flatrack.gem_root, '../templates', "#{code}.html"
38
+ Response.new(self).render(file: file, status: code)
46
39
  end
47
-
48
40
  end
49
- end
41
+ end
@@ -1,9 +1,8 @@
1
- module Flatrack
1
+ class Flatrack
2
2
  class Response
3
-
4
3
  autoload :ViewContext, 'flatrack/response/view_context'
5
4
 
6
- DEFAULT_FILE = 'index'
5
+ DEFAULT_FILE = 'index'
7
6
  CONTENT_TYPES = {
8
7
  html: 'text/html',
9
8
  rb: 'text/html'
@@ -15,17 +14,6 @@ module Flatrack
15
14
  @request = request
16
15
  end
17
16
 
18
- def render(options={})
19
- file, text, status, layout = options.values_at(:file, :text, :status, :layout)
20
- set_content_type
21
- status ||= 200
22
- if text
23
- render_text text, status: status
24
- else
25
- render_file file, status: status, layout: layout
26
- end
27
- end
28
-
29
17
  def headers
30
18
  @headers ||= {}
31
19
  end
@@ -34,29 +22,29 @@ module Flatrack
34
22
  @body ||= []
35
23
  end
36
24
 
25
+ def render(file: file_for(request.path), status: 200, layout: :layout)
26
+ page_content = proc { renderer_for(file).render(view_context) }
27
+ set_content_type
28
+ body << begin
29
+ layout_for(layout).render(view_context, &page_content)
30
+ rescue Flatrack::FileNotFound
31
+ page_content.call
32
+ end
33
+ [status, headers, body]
34
+ end
35
+
37
36
  def set_content_type
38
37
  headers['Content-Type'] = CONTENT_TYPES[request.format.to_sym]
39
38
  end
40
39
 
41
40
  private
42
41
 
43
- def render_file(file = nil, options={})
44
- status, layout = options.values_at(:status, :layout)
45
- layout ||= :layout
46
- file ||= file_for(request.path)
47
- contents = renderer_for(file).render(view_context)
48
- contents = layout_for(layout).render(view_context){ contents } if layout
49
- self.body << contents
50
- [status, headers, body]
51
- end
52
-
53
- def render_text(text = '', options={})
54
- status = options[:status]
55
- [status, headers, [text.to_s]]
56
- end
57
-
58
42
  def file_for(path)
59
- File.directory?(File.join 'pages', path) ? File.join(path, DEFAULT_FILE) : path
43
+ if File.directory?(File.join 'pages', path)
44
+ File.join(path, DEFAULT_FILE)
45
+ else
46
+ path
47
+ end
60
48
  end
61
49
 
62
50
  def renderer_for(file)
@@ -70,6 +58,5 @@ module Flatrack
70
58
  def view_context
71
59
  @view_context ||= ViewContext.new(self)
72
60
  end
73
-
74
61
  end
75
- end
62
+ end
@@ -1,4 +1,4 @@
1
- module Flatrack
1
+ class Flatrack
2
2
  class Response
3
3
  class ViewContext
4
4
  include AssetExtensions
@@ -11,64 +11,51 @@ module Flatrack
11
11
  binding(&block)
12
12
  end
13
13
 
14
- def path
15
- @response.request.path
16
- end
17
-
18
- def params
19
- @response.request.params
20
- end
21
-
22
- def files
23
- Dir.glob(File.join 'pages', path, '*').map do |file|
24
- File.basename File.basename(file, '.*'), '.*'
25
- end - [DEFAULT_FILE]
14
+ def html_tag(tag, options = {}, &block)
15
+ meta = options.map { |k, v| "#{k}=\"#{v}\"" }
16
+ prefix = [tag, *meta].join(' ')
17
+ "<#{prefix}" + (block_given? ? ">#{yield}</#{tag}>" : '/>')
26
18
  end
27
19
 
28
20
  def image_tag(uri, options = {})
29
- uri = File.join('/assets', uri.to_s) + '.js' if uri.is_a? Symbol
21
+ uri = asset_path(uri)
30
22
  html_tag(:img, { src: uri }.merge(options))
31
23
  end
32
24
 
33
25
  def javascript_tag(uri)
34
- uri = File.join('/assets', uri.to_s) + '.js' if uri.is_a? Symbol
35
- html_tag(:script, src: uri){ nil }
26
+ uri = asset_path(uri) + '.js' if uri.is_a? Symbol
27
+ html_tag(:script, src: uri) { nil }
36
28
  end
37
29
 
38
- def stylesheet_tag(uri)
39
- uri = File.join('/assets', uri.to_s) + '.css' if uri.is_a? Symbol
40
- html_tag(:link, rel: 'stylesheet', type: 'text/css', href: uri)
30
+ def link_to(link_or_name, link_or_options=nil, options={})
31
+ name = link_or_name
32
+ link, options = if link_or_options.is_a?(Hash)
33
+ [name, link_or_options]
34
+ else
35
+ [link_or_options, options]
36
+ end
37
+
38
+ html_tag(:a, link_to_options(link, options)) { name }
41
39
  end
42
40
 
43
- def page_stylesheet_tag
44
- file = @response.send(:file_for, path.to_s)
45
- base_path = File.join File.dirname(file), File.basename(file, '.*')
46
- stylesheet_tag base_path if stylesheet_exists?(base_path)
41
+ def params
42
+ @response.request.params
47
43
  end
48
44
 
49
- def link_to(name, link, options={})
50
- link = [link, options.delete(:params).to_param].join('?') if options[:params].is_a?(Hash) && options[:params].present?
51
- html_tag(:a, { href: link }.merge(options) ){ name }
45
+ def path
46
+ @response.request.path
52
47
  end
53
48
 
54
- def html_tag(tag, options={}, &block)
55
- [].tap do |lines|
56
- lines << "<#{tag} " + options.map{ |k, v| "#{k}=\"#{v}\"" }.join(' ') + (block_given? ? ">" : "/>")
57
- if block_given?
58
- lines << yield
59
- lines << "</#{tag}>"
60
- end
61
- end.compact.join("\n")
49
+ def stylesheet_tag(uri)
50
+ uri = asset_path(uri) + '.css' if uri.is_a? Symbol
51
+ html_tag(:link, rel: 'stylesheet', type: 'text/css', href: uri)
62
52
  end
63
53
 
64
54
  private
65
55
 
66
- def stylesheet_exists?(name)
67
- Flatrack.assets[name]
68
- end
69
-
70
- def javascript_exists?(name)
71
- Flatrack.assets[name]
56
+ def link_to_options(link, opts={})
57
+ link << '?' + opts.delete(:params).to_param if opts[:params].present?
58
+ { href: link }.merge(opts)
72
59
  end
73
60
 
74
61
  end
@@ -1,15 +1,33 @@
1
- module Flatrack
1
+ require 'rack/server'
2
2
 
3
- register_format :html, 'text/html'
3
+ class Flatrack
4
+ module Site
4
5
 
5
- Site = Rack::Builder.app do
6
- map '/assets' do
7
- run Flatrack.assets
6
+ def self.call(env)
7
+ builder.call(env)
8
8
  end
9
9
 
10
- map '/' do
11
- use Rack::Static, urls: ["/favicon.ico", "assets"], root: "public"
12
- run ->(env){ Request.new(env).response }
10
+ private
11
+
12
+ def self.builder
13
+ mapping = self.mapping
14
+ Rack::Builder.app do
15
+ use Rack::Static, urls: ['/favicon.ico', 'assets'], root: 'public'
16
+ Flatrack.middleware.each { |mw| use(*mw) }
17
+ mapping.each { |path, app| map(path) { run app } }
18
+ end
19
+ end
20
+
21
+ def self.site
22
+ ->(env) { Request.new(env).response }
13
23
  end
24
+
25
+ def self.mapping
26
+ {
27
+ '/assets' => Flatrack.assets,
28
+ '/' => site
29
+ }
30
+ end
31
+
14
32
  end
15
- end
33
+ end
@@ -1,3 +1,3 @@
1
- module Flatrack
2
- VERSION = "1.0.0.alpha5"
1
+ class Flatrack
2
+ VERSION = '1.0.0'
3
3
  end
@@ -9,11 +9,10 @@ module Rake
9
9
  # Rake::AssetTasks.new
10
10
  #
11
11
  class AssetTasks < Rake::TaskLib
12
-
13
- attr_reader :environment
12
+ attr_accessor :output
13
+ attr_accessor :environment
14
14
  attr_reader :index
15
15
  attr_reader :manifest
16
- attr_reader :output
17
16
  attr_reader :keep
18
17
 
19
18
  # Number of old assets to keep.
@@ -46,8 +45,9 @@ module Rake
46
45
  @environment = Flatrack.assets
47
46
  @logger = Logger.new($stderr)
48
47
  @logger.level = Logger::INFO
48
+ @output = './public/assets'
49
+ yield self
49
50
  @index = environment.index
50
- @output = "./public/assets"
51
51
  @manifest = Sprockets::Manifest.new(index, output)
52
52
  @keep = 2
53
53
  define
@@ -56,8 +56,9 @@ module Rake
56
56
  def assets
57
57
  Dir['assets/**/*.*'].map do |file|
58
58
  file_basename = File.basename file
59
- file = file.split('.').tap(&:pop).join('.') if file_basename.split('.').size > 2
60
- File.expand_path(file).sub(/(#{environment.paths.join('|')})\//,'')
59
+ parts = file_basename.split('.').size
60
+ file = file.split('.').tap(&:pop).join('.') if parts > 2
61
+ File.expand_path(file).sub(/(#{environment.paths.join('|')})\//, '')
61
62
  end
62
63
  end
63
64
 
@@ -71,20 +72,19 @@ module Rake
71
72
  end
72
73
  end
73
74
 
74
- desc "Remove all assets"
75
+ desc 'Remove all assets'
75
76
  task :clobber do
76
77
  with_logger do
77
78
  manifest.clobber
78
79
  end
79
80
  end
80
81
 
81
- desc "Clean old assets"
82
+ desc 'Clean old assets'
82
83
  task :clean do
83
84
  with_logger do
84
85
  manifest.clean(keep)
85
86
  end
86
87
  end
87
-
88
88
  end
89
89
  end
90
90
 
@@ -93,7 +93,8 @@ module Rake
93
93
  # Sub out environment logger with our rake task logger that
94
94
  # writes to stderr.
95
95
  def with_logger
96
- if env = manifest.environment
96
+ env = manifest.environment
97
+ if env
97
98
  old_logger = env.logger
98
99
  env.logger = @logger
99
100
  end
@@ -101,6 +102,5 @@ module Rake
101
102
  ensure
102
103
  env.logger = old_logger if env
103
104
  end
104
-
105
105
  end
106
- end
106
+ end
Binary file
@@ -1,11 +1,9 @@
1
1
  require 'flatrack/renderer/base'
2
2
 
3
3
  class Flatrack::Renderer::ERB < Flatrack::Renderer::Base
4
-
5
4
  renders :erb
6
5
 
7
6
  def render(context = binding, &block)
8
7
  ::ERB.new(contents).result context.get_binding(&block)
9
8
  end
10
-
11
- end
9
+ end
@@ -1,11 +1,9 @@
1
1
  require 'flatrack/renderer/base'
2
2
 
3
3
  class Flatrack::Renderer::Html < Flatrack::Renderer::Base
4
-
5
4
  renders :html
6
5
 
7
6
  def render(*args)
8
7
  contents
9
8
  end
10
-
11
- end
9
+ end
@@ -1,17 +1,19 @@
1
1
  require 'flatrack/renderer/base'
2
2
 
3
3
  class Flatrack::Renderer::Rb < Flatrack::Renderer::Base
4
-
5
4
  renders :rb
6
5
 
7
6
  def render(context)
8
- result = nil
9
- evaluator = Thread.start do
10
- $SAFE = 3
11
- result = eval contents, context
12
- end
13
- nil while evaluator.alive?
14
- result
7
+ eval <<-RUBY, context.get_binding
8
+ r = nil
9
+ evaluator = Thread.start do
10
+ $SAFE = 3
11
+ r = begin
12
+ #{contents}
13
+ end
14
+ end
15
+ nil while evaluator.alive?
16
+ r
17
+ RUBY
15
18
  end
16
-
17
19
  end
@@ -0,0 +1,2 @@
1
+ #= require_self
2
+ #= require_tree
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Flatrack::AssetExtensions do
4
+
5
+ subject(:instance){ double.extend described_class }
6
+
7
+ describe '#asset_path' do
8
+ it 'should be a path to the asset' do
9
+ expect(instance.asset_path :foo).to eq '/assets/foo'
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe Flatrack::CLI do
4
+ extend FileUtils
5
+ include SiteHelper
6
+
7
+ describe '#new' do
8
+ it 'should create a new site' do
9
+ in_temp_sites do
10
+ sha = SecureRandom.hex
11
+ Flatrack::CLI.start(['new', sha, '--verbose', 'false'])
12
+ expect(File.directory? sha).to be true
13
+ cleanup(sha)
14
+ end
15
+ end
16
+ end
17
+
18
+ describe '#start' do
19
+ it 'should start the rack server' do
20
+ expect do
21
+ site do
22
+ thread = Thread.new do
23
+ Flatrack::CLI.start(['start', '--verbose', 'false'])
24
+ end
25
+ retries = 0
26
+ begin
27
+ Net::HTTP.get URI.parse 'http://localhost:5959'
28
+ thread.kill
29
+ rescue Errno::ECONNREFUSED => error
30
+ retries += 1
31
+ sleep 0.1 and retry unless retries > 100
32
+ raise error
33
+ end
34
+ end
35
+ end.to_not raise_error
36
+ end
37
+
38
+ it 'should start a server on a custom port' do
39
+ expect do
40
+ site do
41
+ thread = Thread.new do
42
+ Flatrack::CLI.start(['start', '--port', '8282', '--verbose', 'false'])
43
+ end
44
+ retries = 0
45
+ begin
46
+ Net::HTTP.get URI.parse 'http://localhost:8282'
47
+ thread.kill
48
+ rescue Errno::ECONNREFUSED => error
49
+ retries += 1
50
+ sleep 0.1 and retry unless retries > 100
51
+ raise error
52
+ end
53
+ end
54
+ end.to_not raise_error
55
+ end
56
+ end
57
+
58
+ end