racket-mvc 0.3.3 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 63921b5e05aa5980041e8817c71bcd43b015834d
4
- data.tar.gz: 1f98ea84f965aa6c36707dd515c16b9d7ff7ae29
3
+ metadata.gz: 63dc217836153cda7cd00f43dfe894a519c4de5d
4
+ data.tar.gz: 22bca87d176624f95ff10c8007526c0d2b2f4ca0
5
5
  SHA512:
6
- metadata.gz: 306ae0910122403e2adff6a1cab12d01bea39e17d7142e7b07a2ef0aa1a48e1b61c38e1debf2f2ffff3f38bebc1d9d12cd3f2770dd0509ac44e0bdb2e95c92c2
7
- data.tar.gz: 3fdeac0f87e45d5cefda65f18ebc61d831028a09ce75ffe371f2024838e6b5f06087fe655f64fb8d405fc1e0515167d27b42f74c5c8bcf472c0371ebf05bd11a
6
+ metadata.gz: 332598c7ab0f25fceb9a21356d13d96700f3bb1ba592a71a46b048f365ff7066078230348e7a6432430015f7c6293531b75c3ed560c4a1ad02f0c315363a5046
7
+ data.tar.gz: 33a1208769de0e009036df394fea74a5fa6630b035f35bb7f952f0887873514050a6739dcd126446b2bf1ac2cab1f0eff64d83abd62c38a52c019593fc9e613b
@@ -33,6 +33,12 @@ module Racket
33
33
  @application ||= Utils.build_application(self)
34
34
  end
35
35
 
36
+ # Applies settings.
37
+ def self.apply_settings(settings)
38
+ fail 'Application has already been initialized!' if @settings
39
+ @settings = Settings::Application.new(settings)
40
+ end
41
+
36
42
  def self.calculate_url_path(file)
37
43
  url_path = "/#{file.relative_path_from(@settings.controller_dir).dirname}"
38
44
  url_path = '' if url_path == '/.'
@@ -104,8 +110,8 @@ module Racket
104
110
  # @param [Hash] settings
105
111
  # @return [Class]
106
112
  def self.init(settings = {})
107
- fail 'Application has already been initialized!' if @settings
108
- @settings = Settings::Application.new(settings)
113
+ apply_settings(settings)
114
+ application # This will make sure all plugins and helpers are loaded before any controllers
109
115
  setup_static_server
110
116
  reload
111
117
  self
@@ -129,8 +135,9 @@ module Racket
129
135
  def self.load_controller_file(file)
130
136
  ::Kernel.require file
131
137
  klass = @settings.fetch(:last_added_controller).pop
132
- Utils.apply_helpers(klass)
133
- @router.map(calculate_url_path(file), klass) && nil
138
+ # Helpers may do stuff based on route, make sure it is available before applying helpers.
139
+ @router.map(calculate_url_path(file), klass)
140
+ Utils.apply_helpers(klass) && nil
134
141
  end
135
142
 
136
143
  def self.load_controller_files
@@ -156,13 +163,6 @@ module Racket
156
163
  (::Kernel.require Utils.build_path(*args)) && nil
157
164
  end
158
165
 
159
- # Resets Racket::Application, making it possible to run run a new application with new settings.
160
- # This is a workaround for Racket::Application being a singleton, making tests harder to write,
161
- # @todo Remove this when Racket::Application stops beeing a singleton (if ever).
162
- def self.reset!
163
- instance_variables.each { |ivar| instance_variable_set(ivar, nil) }
164
- end
165
-
166
166
  # Serves a static file (if Racket is configured to serve static files).
167
167
  #
168
168
  # @param [Hash] env Rack environment
@@ -0,0 +1,66 @@
1
+ # Racket - The noisy Rack MVC framework
2
+ # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
3
+ #
4
+ # This file is part of Racket.
5
+ #
6
+ # Racket is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Racket is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with Racket. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ module Racket
20
+ # Helpers module
21
+ module Helpers
22
+ # Helper module that allows CSS files to be loaded dynamically using SASS.
23
+ module Sass
24
+ # Get route to CSS, which will use SASS in the background to deliver the CSS.
25
+ #
26
+ # @param [Symbol] sym
27
+ # @return [String]
28
+ def css(sym)
29
+ route = Application.get_route(self.class)
30
+ route = '' if route == '/' # Special case for root controller
31
+ "/css#{route}/#{sym}.css"
32
+ end
33
+
34
+ def self.add_template_location(route)
35
+ root_dir = Application.settings.root_dir
36
+ sass_dir = Utils.build_path(root_dir, 'sass', route).to_s
37
+ css_dir = Utils.build_path(root_dir, 'public', 'css', route).to_s
38
+ ::Sass::Plugin.add_template_location(sass_dir, css_dir)
39
+ sass_dir
40
+ end
41
+
42
+ def self.add_warmup_urls(sass_dir, route)
43
+ Dir.chdir(sass_dir) do
44
+ basedir = route.empty? ? '/css' : "/css/#{route}"
45
+ Dir.glob('*.s[ac]ss').each do |file|
46
+ Application.settings.warmup_urls << "#{basedir}/#{::File.basename(file, '.*')}.css"
47
+ end
48
+ end
49
+ end
50
+
51
+ # Whenever this helper is included in a controller it will setup a link between
52
+ # a SASS directory and a CSS directory.
53
+ #
54
+ # @param [Class] klass
55
+ # @return [nil]
56
+ def self.included(klass)
57
+ route = Application.get_route(klass)[1..-1] # Remove leading slash
58
+ sass_dir = add_template_location(route)
59
+ add_warmup_urls(sass_dir, route)
60
+ nil
61
+ end
62
+
63
+ private_class_method :add_template_location, :add_warmup_urls
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,54 @@
1
+ # Racket - The noisy Rack MVC framework
2
+ # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
3
+ #
4
+ # This file is part of Racket.
5
+ #
6
+ # Racket is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Racket is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with Racket. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ module Racket
20
+ # Namespace for plugins.
21
+ module Plugins
22
+ # Plugin base class. All plugins should inherit from this class.
23
+ class Base
24
+ attr_reader :settings
25
+
26
+ def initialize(settings = {})
27
+ @settings = {}
28
+ @settings.merge!(settings) if settings.is_a?(Hash)
29
+ end
30
+
31
+ # This method should return an array of helpers (symbols) that the plugin wants to load
32
+ # automatically in every controller. If you do not want your controller to load any helpers
33
+ # automatically you do not need to override this method. You can still add your helpers to
34
+ # individual controllers by using Controller#helper.
35
+ #
36
+ # @return [Array] An array of symbols representing helpers that should be loaded automatically
37
+ def default_controller_helpers
38
+ []
39
+ end
40
+
41
+ # This method should return an array of [Module, Hash] arrays where each module represenents
42
+ # a Rack-compatible middleware module and the hash the settings that should be applied to
43
+ # that middleware. Each pair that the plugin provides will be automatically added to the
44
+ # middleware of the application. This is just for conveniance, a user could still add The same
45
+ # middleware using the global settings.
46
+ #
47
+ # @return [Array] An array of [Module, Hash] pairs that represenents middleware that will be
48
+ # loaded automatically by the plugin
49
+ def middleware
50
+ []
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,50 @@
1
+ # Racket - The noisy Rack MVC framework
2
+ # Copyright (C) 2015 Lars Olsson <lasso@lassoweb.se>
3
+ #
4
+ # This file is part of Racket.
5
+ #
6
+ # Racket is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Affero General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # Racket is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Affero General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Affero General Public License
17
+ # along with Racket. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ require_relative 'base'
20
+
21
+ module Racket
22
+ # Namespace for plugins.
23
+ module Plugins
24
+ # Sass plugin.
25
+ class Sass < Base
26
+ # Called on plugin initialization.
27
+ def initialize(settings = nil)
28
+ super
29
+ begin
30
+ require 'sass/plugin/rack'
31
+ rescue LoadError
32
+ raise 'Failed to load sass rack plugin!'
33
+ end
34
+ apply_sass_settings
35
+ end
36
+
37
+ # Middleware that should be automatically added.
38
+ def middleware
39
+ [[::Sass::Plugin::Rack, nil]]
40
+ end
41
+
42
+ private
43
+
44
+ # Apply each setting to the Sass plugin.
45
+ def apply_sass_settings
46
+ settings.each_pair { |key, value| ::Sass::Plugin.options[key] = value }
47
+ end
48
+ end
49
+ end
50
+ end
@@ -32,6 +32,7 @@ module Racket
32
32
  setting(:logger, Logger.new($stdout))
33
33
  setting(:middleware, [])
34
34
  setting(:mode, :live)
35
+ setting(:plugins, [])
35
36
  setting(
36
37
  :session_handler,
37
38
  [
@@ -44,6 +45,7 @@ module Racket
44
45
  ]
45
46
  )
46
47
  setting(:root_dir, nil) # Will be set automatically by constructor.
48
+ setting(:warmup_urls, Set.new)
47
49
 
48
50
  def initialize(defaults = {})
49
51
  defaults[:root_dir] = Dir.pwd unless defaults.key?(:root_dir)
@@ -34,7 +34,8 @@ module Racket
34
34
  #
35
35
  # @return [Proc]
36
36
  def build
37
- expand_middleware_list
37
+ init_plugins
38
+ add_warmup_hook
38
39
  add_middleware
39
40
  @builder.run(application_proc)
40
41
  @builder
@@ -44,6 +45,7 @@ module Racket
44
45
 
45
46
  # Add middleware to the builder.
46
47
  def add_middleware
48
+ expand_middleware_list
47
49
  @middleware.each do |ware|
48
50
  klass, opts = ware
49
51
  @application.inform_dev("Loading middleware #{klass} with settings #{opts.inspect}.")
@@ -51,6 +53,16 @@ module Racket
51
53
  end
52
54
  end
53
55
 
56
+ # Add a list of urls to visit on startup
57
+ def add_warmup_hook
58
+ warmup_urls = Racket::Application.settings.warmup_urls
59
+ return if warmup_urls.empty?
60
+ @builder.warmup do |app|
61
+ client = Rack::MockRequest.new(app)
62
+ visit_warmup_urls(client, warmup_urls)
63
+ end
64
+ end
65
+
54
66
  # Returns a lambda that represenents that application flow.
55
67
  def application_proc
56
68
  application = @application
@@ -69,6 +81,42 @@ module Racket
69
81
  @middleware.unshift([Rack::ContentType, default_content_type]) if default_content_type
70
82
  @middleware.unshift([Rack::ShowExceptions]) if @application.dev_mode?
71
83
  end
84
+
85
+ # Initializes plugins.
86
+ def init_plugins
87
+ @settings.plugins.each do |plugin_info|
88
+ plugin_instance = self.class.get_plugin_instance(*plugin_info)
89
+ run_plugin_hooks(plugin_instance)
90
+ # TODO: Store plugin instance somewhere in application settings
91
+ end
92
+ end
93
+
94
+ # Runs plugin hooks.
95
+ def run_plugin_hooks(plugin_obj)
96
+ @middleware.concat(plugin_obj.middleware)
97
+ @settings.default_controller_helpers.concat(plugin_obj.default_controller_helpers)
98
+ end
99
+
100
+ # Visits a list of warmup URLs.
101
+ def visit_warmup_urls(client, urls)
102
+ urls.each do |url|
103
+ @application.inform_dev("Visiting warmup url #{url}.")
104
+ client.get(url)
105
+ end
106
+ end
107
+
108
+ # Returns an instance of a specific plugin.
109
+ #
110
+ # @param [Symbol] plugin
111
+ # @param [Hash|nil] settings
112
+ # @return [Object] An instance of the requested plugin class
113
+ def self.get_plugin_instance(plugin, settings)
114
+ Utils.safe_require("racket/plugins/#{plugin}.rb")
115
+ # TODO: Allow custom plugins dir as well
116
+ klass =
117
+ Racket::Plugins.const_get(plugin.to_s.split('_').collect(&:capitalize).join.to_sym)
118
+ klass.new(settings)
119
+ end
72
120
  end
73
121
 
74
122
  # Builds and returns a Rack::Builder using the provided Racket::Application
@@ -153,10 +153,16 @@ module Racket
153
153
  # @return [String|Proc|nil]
154
154
  def self.lookup_template_with_default(path, default_template)
155
155
  template = lookup_template(path)
156
- if !template && (default_template.is_a?(String) || default_template.is_a?(Symbol))
157
- template = lookup_template(Utils.fs_path(path.dirname, default_template))
156
+ unless template
157
+ if default_template.is_a?(String) || default_template.is_a?(Symbol)
158
+ # Strings and symbols can be lookup up in the file system...
159
+ template = lookup_template(Utils.fs_path(path.dirname, default_template))
160
+ else
161
+ # ...but not nils/procs!
162
+ template = default_template
163
+ end
158
164
  end
159
- template || default_template
165
+ template
160
166
  end
161
167
  end
162
168
 
@@ -23,9 +23,9 @@ module Racket
23
23
  # Major version
24
24
  MAJOR = 0
25
25
  # Minor version
26
- MINOR = 3
26
+ MINOR = 4
27
27
  # Teeny version
28
- TEENY = 3
28
+ TEENY = 0
29
29
  # Is it a prerelease?
30
30
  PRERELEASE = false
31
31
 
@@ -1,4 +1,4 @@
1
- describe 'A custom Racket test Application' do
1
+ describe 'A custom Racket test application' do
2
2
  extend Rack::Test::Methods
3
3
  def app
4
4
  @app ||= Racket::Application.using(
@@ -15,6 +15,20 @@ describe 'A custom Racket test Application' do
15
15
  app.settings.view_dir.should.equal(Racket::Utils.build_path('templates'))
16
16
  end
17
17
 
18
+ it 'should get the correct middleware' do
19
+ middleware = app.settings.middleware
20
+ middleware.length.should.equal(3)
21
+ middleware[0].class.should.equal(Array)
22
+ middleware[0].length.should.equal(1)
23
+ middleware[0].first.should.equal(Rack::ShowExceptions)
24
+ middleware[1].class.should.equal(Array)
25
+ middleware[1].length.should.equal(2)
26
+ middleware[1].first.should.equal(Rack::ContentType)
27
+ middleware[2].class.should.equal(Array)
28
+ middleware[2].length.should.equal(2)
29
+ middleware[2].first.should.equal(Rack::Session::Cookie)
30
+ end
31
+
18
32
  it 'should be able to get/set settings on controller' do
19
33
  get '/sub3/a_secret_place'
20
34
  last_response.status.should.equal(302)
@@ -1,4 +1,4 @@
1
- describe 'A default Racket test Application' do
1
+ describe 'A default Racket test application' do
2
2
  extend Rack::Test::Methods
3
3
 
4
4
  def app
@@ -47,6 +47,18 @@ describe 'A default Racket test Application' do
47
47
  JSON.parse(last_response.body).should.equal(%w(foo bar baz))
48
48
  end
49
49
 
50
+ it 'should get the correct middleware' do
51
+ middleware = app.settings.middleware
52
+ middleware.length.should.equal(2)
53
+ middleware[0].class.should.equal(Array)
54
+ middleware[0].length.should.equal(2)
55
+ middleware[0].first.should.equal(Rack::ContentType)
56
+ middleware[1].class.should.equal(Array)
57
+ middleware[1].length.should.equal(2)
58
+ middleware[1].first.should.equal(Rack::Session::Cookie)
59
+ true.should.equal(true)
60
+ end
61
+
50
62
  it 'returns the correct respnse when calling index action' do
51
63
  # RootController
52
64
  get '/'
@@ -0,0 +1,44 @@
1
+ describe 'A Racket application with plugins' do
2
+ extend Rack::Test::Methods
3
+ def app
4
+ @app ||= Racket::Application.using(
5
+ logger: nil,
6
+ plugins: [[:sass, { style: :compressed, sourcemap: :none }]]
7
+ )
8
+ end
9
+
10
+ it 'should get correct defaults from base plugin' do
11
+ require 'racket/plugins/base'
12
+ plugin = Racket::Plugins::Base.new
13
+ plugin.default_controller_helpers.should.equal([])
14
+ plugin.middleware.should.equal([])
15
+ end
16
+
17
+ it 'should return correct CSS paths when querying default controller' do
18
+ get '/css_path'
19
+ last_response.status.should.equal(200)
20
+ last_response.body.should.equal('/css/foo.css')
21
+ end
22
+
23
+ it 'should return correct CSS paths when querying a subcontroller' do
24
+ get '/sub/css_path'
25
+ last_response.status.should.equal(200)
26
+ last_response.body.should.equal('/css/sub/bar.css')
27
+ end
28
+
29
+ =begin
30
+ it 'should render a SASS based stylesheet for the default controller' do
31
+ get '/css/test.css'
32
+ last_response.status.should.equal(200)
33
+ last_response.headers['Content-Type'].should.equal('text/css')
34
+ last_response.body.should.equal("body{background-color:snow;color:black}\n")
35
+ end
36
+
37
+ it 'should render a SASS based stylesheet for a subcontroller' do
38
+ get '/css/sub/test.css'
39
+ last_response.status.should.equal(200)
40
+ last_response.headers['Content-Type'].should.equal('text/css')
41
+ last_response.body.should.equal("body{background-color:steelblue;color:gray}\n")
42
+ end
43
+ =end
44
+ end
@@ -14,6 +14,7 @@ end
14
14
  TEST_DIR = File.absolute_path(File.dirname(__FILE__))
15
15
  TEST_DEFAULT_APP_DIR = File.join(TEST_DIR, 'test_default_app')
16
16
  TEST_CUSTOM_APP_DIR = File.join(TEST_DIR, 'test_custom_app')
17
+ TEST_PLUGIN_APP_DIR = File.join(TEST_DIR, 'test_plugin_app')
17
18
 
18
19
  require 'racket'
19
20
 
@@ -29,7 +30,8 @@ require File.join(TEST_DIR, '_request.rb')
29
30
  # Application tests.
30
31
  suites = [
31
32
  -> { Dir.chdir(TEST_DEFAULT_APP_DIR) { require File.join(TEST_DIR, '_default.rb') } },
32
- -> { Dir.chdir(TEST_CUSTOM_APP_DIR) { require File.join(TEST_DIR, '_custom.rb') } }
33
+ -> { Dir.chdir(TEST_CUSTOM_APP_DIR) { require File.join(TEST_DIR, '_custom.rb') } },
34
+ -> { Dir.chdir(TEST_PLUGIN_APP_DIR) { require File.join(TEST_DIR, '_plugin.rb') } }
33
35
  ]
34
36
 
35
37
  # Leave off randomization for now. Sessions does not seem to be reset correctly between suites!
@@ -37,7 +39,14 @@ suites = [
37
39
 
38
40
  # Run application tests.
39
41
  suites.each do |suite|
40
- Racket::Application.reset!
42
+ # Make sure Racket::Application and Racket::Settings::Application is reset between the suites.
43
+ # Racket::Application@application and Racket::Settings::Application must be pristine on each run!
44
+ Racket.class_eval { remove_const(:Application) }
45
+ Racket::Settings.class_eval { remove_const(:Application) }
46
+ load('lib/racket/application.rb')
47
+ load('lib/racket/settings/application.rb')
48
+
49
+ # Run suite
41
50
  suite.call
42
51
  end
43
52
 
@@ -0,0 +1,8 @@
1
+ # Main controller
2
+ class MainController < Racket::Controller
3
+ helper :sass
4
+
5
+ def css_path
6
+ css(:foo)
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # Sub controller
2
+ class SubController < Racket::Controller
3
+ helper :sass
4
+
5
+ def css_path
6
+ css(:bar)
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ body {
2
+ background-color: steelblue;
3
+ color: gray;
4
+ }
@@ -0,0 +1,4 @@
1
+ body {
2
+ background-color: snow;
3
+ color: black;
4
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: racket-mvc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lars Olsson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-29 00:00:00.000000000 Z
11
+ date: 2016-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http_router
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: '10'
111
+ - !ruby/object:Gem::Dependency
112
+ name: sass
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.4'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.4'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: simplecov
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -151,7 +165,10 @@ files:
151
165
  - lib/racket/current.rb
152
166
  - lib/racket/helpers/file.rb
153
167
  - lib/racket/helpers/routing.rb
168
+ - lib/racket/helpers/sass.rb
154
169
  - lib/racket/helpers/view.rb
170
+ - lib/racket/plugins/base.rb
171
+ - lib/racket/plugins/sass.rb
155
172
  - lib/racket/request.rb
156
173
  - lib/racket/response.rb
157
174
  - lib/racket/router.rb
@@ -172,6 +189,7 @@ files:
172
189
  - spec/_custom.rb
173
190
  - spec/_default.rb
174
191
  - spec/_invalid.rb
192
+ - spec/_plugin.rb
175
193
  - spec/_request.rb
176
194
  - spec/racket.rb
177
195
  - spec/test_custom_app/controllers/sub1/custom_sub_controller_1.rb
@@ -195,6 +213,10 @@ files:
195
213
  - spec/test_default_app/controllers/sub3/default_sub_controller_3.rb
196
214
  - spec/test_default_app/controllers/sub3/inherited/default_inherited_controller.rb
197
215
  - spec/test_default_app/public/hello.txt
216
+ - spec/test_plugin_app/controllers/main.rb
217
+ - spec/test_plugin_app/controllers/sub/sub.rb
218
+ - spec/test_plugin_app/sass/sub/test.scss
219
+ - spec/test_plugin_app/sass/test.scss
198
220
  homepage: https://github.com/lasso/racket
199
221
  licenses:
200
222
  - GNU AFFERO GENERAL PUBLIC LICENSE, version 3