flatrack 1.0.0.alpha5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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