middleman-apps 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.rubocop.yml +14 -0
- data/.travis.yml +4 -0
- data/Gemfile +19 -0
- data/LICENSE.txt +19 -0
- data/README.md +185 -0
- data/Rakefile +14 -0
- data/features/activation.feature +53 -0
- data/features/build.feature +20 -0
- data/features/child_app.feature +18 -0
- data/features/complex_app.feature +66 -0
- data/features/directory_indexes.feature +52 -0
- data/features/not_found_rack.feature +53 -0
- data/features/not_found_server.feature +8 -0
- data/features/step_definitions/rack_app_steps.rb +15 -0
- data/features/support/env.rb +18 -0
- data/features/verbose.feature +23 -0
- data/fixtures/complex-app/apps/awesome_api.rb +11 -0
- data/fixtures/complex-app/apps/child_app.rb +15 -0
- data/fixtures/complex-app/apps/test_app.rb +12 -0
- data/fixtures/complex-app/build/error.html +1 -0
- data/fixtures/complex-app/build/index.html +2 -0
- data/fixtures/complex-app/config.rb +1 -0
- data/fixtures/complex-app/source/index.html.erb +2 -0
- data/fixtures/simple-app/apps/test_app.rb +8 -0
- data/fixtures/simple-app/build/error.html +1 -0
- data/fixtures/simple-app/build/index.html +2 -0
- data/fixtures/simple-app/config.rb +1 -0
- data/fixtures/simple-app/source/index.html.erb +2 -0
- data/lib/middleman.rb +1 -0
- data/lib/middleman/apps.rb +65 -0
- data/lib/middleman/apps/base.rb +36 -0
- data/lib/middleman/apps/extension.rb +231 -0
- data/lib/middleman/apps/rack_contrib.rb +77 -0
- data/lib/middleman/apps/version.rb +5 -0
- data/middleman-apps.gemspec +27 -0
- metadata +145 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 07e504c02695ba4f0387c2d974c49030b12a0655
|
4
|
+
data.tar.gz: 46a2badf1b57e7572d6f71232999ce7783c8f50b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 110ab87281cb3a4109e9c3ef5b73d4db382a8622a7b34534b4b01ef31aaeab30af06e783bde2cccb727c9d043f32004eaf7d3e5227dfeafd00db1c293eff973e
|
7
|
+
data.tar.gz: 5f8a7f7edc8b1785e3ff7da9ace36d4e731c7ec01319256adea95d71cdf4f200e49ee6c7cb0b6a5b8ef84d1798d8d6f01a95cc2e826dacb7483d978efe225a8d
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# If you do not have OpenSSL installed, update
|
2
|
+
# the following line to use "http://" instead
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in middleman-apps.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
group :development do
|
9
|
+
gem 'rake'
|
10
|
+
gem 'rdoc'
|
11
|
+
gem 'yard'
|
12
|
+
end
|
13
|
+
|
14
|
+
group :test do
|
15
|
+
gem 'aruba'
|
16
|
+
gem 'capybara'
|
17
|
+
gem 'cucumber'
|
18
|
+
gem 'rspec'
|
19
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2017 Nikhil Gupta
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
## Middleman Apps
|
2
|
+
|
3
|
+
`middleman-apps` is an extension for the [Middleman] static site
|
4
|
+
generator that allows you to run truly dynamic pages within your static
|
5
|
+
site using Rack-compatible (e.g. Sinatra) based child apps.
|
6
|
+
|
7
|
+
You can create dynamic pages using this extension. Maybe you want to:
|
8
|
+
|
9
|
+
- Create simple APIs that can be consumed by your static app via AJAX
|
10
|
+
- Showcase Code snippets alongside your blog.
|
11
|
+
- Provide simple Demos of a tech writeup, etc.
|
12
|
+
- Display a dynamic Gallery of your most recent timeline from Flickr?
|
13
|
+
- ... suggest one? ...
|
14
|
+
|
15
|
+
The best way to get started with this extension is to have a look at the
|
16
|
+
various `features` in the test suite. There is a test for each feature
|
17
|
+
that exists for extension, such as:
|
18
|
+
|
19
|
+
- Mount Rack apps by, simply, placing them in `MM_ROOT/apps` directory.
|
20
|
+
- Allow running child apps in-tandem with the static (built) MM app, and
|
21
|
+
wrap them both in a single `Rack::App`, which can be run with e.g.
|
22
|
+
`rackup`.
|
23
|
+
- Use a specific `404` error page that is common across your static
|
24
|
+
website, and child apps mounted using this extension.
|
25
|
+
- Discovery of mountable child apps and automatic mounting.
|
26
|
+
- Optionally, specify a URL where a child app should be mounted.
|
27
|
+
- Optionally, specify a Class name or namespace for the child app.
|
28
|
+
- Optionally, inherit from `Middleman::Apps::BaseApp` for helper methods
|
29
|
+
and added goodies for your apps.
|
30
|
+
|
31
|
+
### Example
|
32
|
+
|
33
|
+
You can, e.g. create a simple JSON API endpoint at: `/base64-api/`
|
34
|
+
by creating a file named `apps/base64_api.rb` with:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
# config.rb
|
38
|
+
...
|
39
|
+
activate :apps
|
40
|
+
...
|
41
|
+
|
42
|
+
# apps/base64_api.rb
|
43
|
+
require 'sinatra'
|
44
|
+
class Base64Api < Sinatra::Base
|
45
|
+
get '/decode/:str' do
|
46
|
+
Base64.decode64(params['str'])
|
47
|
+
end
|
48
|
+
get '/encode/:str' do
|
49
|
+
Base64.encode64(params['str'])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
Run/Build your Middleman site now, and visit:
|
55
|
+
`/base64-api/encode/somestring`. Voila! It just works!
|
56
|
+
|
57
|
+
A `config.ru` is, also, generated for you, so that you can keep
|
58
|
+
using these dynamic pages/endpoints using `rackup`. Try running
|
59
|
+
`rackup`, and visiting the above endpoint on that server instance.
|
60
|
+
|
61
|
+
## Installation
|
62
|
+
|
63
|
+
If you're just getting started, install the `middleman` gem and generate
|
64
|
+
a new project:
|
65
|
+
|
66
|
+
```
|
67
|
+
gem install middleman
|
68
|
+
middleman init MY_PROJECT
|
69
|
+
```
|
70
|
+
|
71
|
+
If you already have a Middleman project: Add `gem "middleman-apps"`
|
72
|
+
to your `Gemfile` and run `bundle install`.
|
73
|
+
|
74
|
+
## Configuration
|
75
|
+
|
76
|
+
```
|
77
|
+
activate :apps,
|
78
|
+
map: {}, # Mappings for custom URL and Class for child apps
|
79
|
+
verbose: false, # Display warnings if any when building main app
|
80
|
+
not_found: "404.html", # Render this page for 404 errors, if it exists
|
81
|
+
namespace: nil # By default, use a namespace for finding Class
|
82
|
+
# of a child app
|
83
|
+
```
|
84
|
+
|
85
|
+
A `config.ru` will be generated for you (if one does not exist already),
|
86
|
+
when you preview/build your MM site. Your child apps will be mounted in
|
87
|
+
both development (preview) mode (e.g. via `middleman server`) as well in
|
88
|
+
production (build) mode of MM (e.g. running the built app using `puma`
|
89
|
+
or `rackup`).
|
90
|
+
|
91
|
+
## Options
|
92
|
+
|
93
|
+
### `not_found: '404.html'`
|
94
|
+
|
95
|
+
This option defines a custom HTML page to use for 404 errors. By
|
96
|
+
default, HTML from `404.html` is served if it exists. Otherwise,
|
97
|
+
a default 404 response is sent.
|
98
|
+
|
99
|
+
A warning is generated in `verbose` mode, if this file does not exist!
|
100
|
+
Set this option to `false`, if you prefer not to use a 404 page and
|
101
|
+
would rather stick with default 404 response from Rack.
|
102
|
+
|
103
|
+
### `verbose: false`
|
104
|
+
|
105
|
+
If true, display warnings such as non-existent 404 error page, and any
|
106
|
+
child apps that were ignored when starting server in
|
107
|
+
development/production mode.
|
108
|
+
|
109
|
+
### `namespace: nil`
|
110
|
+
|
111
|
+
Specify a global namespace to find child apps in. Look at `map` option
|
112
|
+
below for better clarification.
|
113
|
+
|
114
|
+
### `map: {}`
|
115
|
+
|
116
|
+
This option can be used to specify a custom URL endpoint for a specific
|
117
|
+
child app, or different class name for your child app if different than
|
118
|
+
what is guessed (`str.classify.constantize`).
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
activate :apps,
|
122
|
+
namespace: 'DynamicPages',
|
123
|
+
map: {
|
124
|
+
test_app: 'test',
|
125
|
+
awesome_api: {
|
126
|
+
url: 'api',
|
127
|
+
class: "Project::AwesomeAPI"
|
128
|
+
}
|
129
|
+
}
|
130
|
+
```
|
131
|
+
|
132
|
+
With the above configuration in place, here is what happens:
|
133
|
+
|
134
|
+
- class `DynamicPages::TestApp` should exist inside
|
135
|
+
`MM_ROOT/apps/test_app.rb` file, and it will be mounted at: `/test`
|
136
|
+
endpoint.
|
137
|
+
|
138
|
+
- class `Project::AwesomeAPI` should exist inside
|
139
|
+
`MM_ROOT/apps/awesome_api.rb` file, and it will be mounted at: `/api`
|
140
|
+
endpoint.
|
141
|
+
|
142
|
+
- If another child app `DynamicPages::OtherMiniProject` exists in:
|
143
|
+
`MM_ROOT/apps/other_mini_project.rb`, it will be mounted at:
|
144
|
+
`/other-mini-project` endpoint.
|
145
|
+
|
146
|
+
## Community
|
147
|
+
|
148
|
+
The official community forum is available at: http://forum.middlemanapp.com
|
149
|
+
|
150
|
+
## Bug Reports
|
151
|
+
|
152
|
+
Github Issues are used for managing bug reports and feature requests. If
|
153
|
+
you run into issues, please search the issues and submit new problems:
|
154
|
+
https://github.com/middleman/middleman-blog/issues
|
155
|
+
|
156
|
+
The best way to get quick responses to your issues and swift fixes to
|
157
|
+
your bugs is to submit detailed bug reports, include test cases and
|
158
|
+
respond to developer questions in a timely manner. Even better, if you
|
159
|
+
know Ruby, you can submit
|
160
|
+
[Pull Requests](https://help.github.com/articles/using-pull-requests)
|
161
|
+
containing Cucumber Features which describe how your feature should work
|
162
|
+
or exploit the bug you are submitting.
|
163
|
+
|
164
|
+
## How to Run Cucumber Tests
|
165
|
+
|
166
|
+
- Checkout Repository:
|
167
|
+
`git clone https://github.com/nikhgupta/middleman-apps.git`
|
168
|
+
|
169
|
+
- Install Bundler: `gem install bundler`
|
170
|
+
|
171
|
+
- Run `bundle install` inside the project root to install the gem
|
172
|
+
dependencies.
|
173
|
+
|
174
|
+
- Run test cases: `bundle exec rake test`
|
175
|
+
|
176
|
+
## Donate
|
177
|
+
|
178
|
+
[Click here to lend your support to Middleman](https://spacebox.io/s/4dXbHBorC3)
|
179
|
+
|
180
|
+
## License
|
181
|
+
|
182
|
+
Copyright (c) 2018 Nikhil Gupta. MIT Licensed, see [LICENSE] for details.
|
183
|
+
|
184
|
+
[middleman]: http://middlemanapp.com
|
185
|
+
[LICENSE]: https://github.com/nikhgupta/middleman-apps/blob/master/LICENSE.txt
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'cucumber/rake/task'
|
5
|
+
|
6
|
+
Cucumber::Rake::Task.new(:cucumber, 'Run features that should pass') do |t|
|
7
|
+
t.cucumber_opts = '--color --tags ~@wip --strict'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rake/clean'
|
11
|
+
|
12
|
+
task test: ['cucumber']
|
13
|
+
|
14
|
+
task default: :test
|
@@ -0,0 +1,53 @@
|
|
1
|
+
Feature: Activating MiddlemanApps
|
2
|
+
|
3
|
+
Scenario: Without `middleman-apps`
|
4
|
+
Given a fixture app "simple-app"
|
5
|
+
And a file named "config.rb" with:
|
6
|
+
"""
|
7
|
+
"""
|
8
|
+
And the Server is running at "simple-app"
|
9
|
+
When I go to "/"
|
10
|
+
Then I should see "<h1>Middleman</h1>"
|
11
|
+
When I go to "/test-app"
|
12
|
+
Then the status code should be "404"
|
13
|
+
And I should see "<h1>File Not Found</h1>"
|
14
|
+
|
15
|
+
Scenario: Without `middleman-apps` with Rack
|
16
|
+
Given a fixture app "simple-app"
|
17
|
+
And a file named "config.rb" with:
|
18
|
+
"""
|
19
|
+
require 'sinatra'
|
20
|
+
require_relative 'apps/test_app'
|
21
|
+
map("/test-app") { run TestApp }
|
22
|
+
"""
|
23
|
+
And the Server is running at "simple-app"
|
24
|
+
When I go to "/"
|
25
|
+
Then I should see "<h1>Middleman</h1>"
|
26
|
+
When I go to "/test-app"
|
27
|
+
Then I should see "fail"
|
28
|
+
When I go to "/test-app/?test=1"
|
29
|
+
Then I should see "pass"
|
30
|
+
|
31
|
+
Scenario: With `middleman-apps`
|
32
|
+
Given a fixture app "simple-app"
|
33
|
+
And a file named "config.rb" with:
|
34
|
+
"""
|
35
|
+
activate :apps
|
36
|
+
"""
|
37
|
+
And the Server is running at "simple-app"
|
38
|
+
When I go to "/"
|
39
|
+
Then I should see "<h1>Middleman</h1>"
|
40
|
+
When I go to "/test-app"
|
41
|
+
Then I should see "fail"
|
42
|
+
When I go to "/test-app/?test=1"
|
43
|
+
Then I should see "pass"
|
44
|
+
|
45
|
+
Scenario: Adds a `config.ru`
|
46
|
+
Given a fixture app "simple-app"
|
47
|
+
Then the file "config.ru" should not exist
|
48
|
+
Given a file named "config.rb" with:
|
49
|
+
"""
|
50
|
+
activate :apps
|
51
|
+
"""
|
52
|
+
And the Server is running at "simple-app"
|
53
|
+
Then the file "config.ru" should exist
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Feature: Built app
|
2
|
+
|
3
|
+
Scenario: Builds successfully
|
4
|
+
Given a successfully built app at "simple-app"
|
5
|
+
Then the file "config.ru" should exist
|
6
|
+
And the file "build/index.html" should exist
|
7
|
+
And the file "build/apps/test_app.rb" should not exist
|
8
|
+
|
9
|
+
Scenario: Running built app
|
10
|
+
Given a fixture app "simple-app"
|
11
|
+
And app is running with config:
|
12
|
+
"""
|
13
|
+
activate :apps
|
14
|
+
"""
|
15
|
+
When I go to "/"
|
16
|
+
Then I should see "<h1>Middleman</h1>"
|
17
|
+
When I go to "/test-app"
|
18
|
+
Then I should see "fail"
|
19
|
+
When I go to "/test-app?test=1"
|
20
|
+
Then I should see "pass"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: 404 error pages for Child apps
|
2
|
+
|
3
|
+
Scenario: Custom 404 response from child app
|
4
|
+
Given a fixture app "complex-app"
|
5
|
+
And a file named "source/custom.html.erb" with:
|
6
|
+
"""
|
7
|
+
<h2><%= 404 %> Custom Not Found!</h2>
|
8
|
+
"""
|
9
|
+
And app is running with config:
|
10
|
+
"""
|
11
|
+
activate :apps, not_found: "custom.html", namespace: :complex_app
|
12
|
+
"""
|
13
|
+
When I go to "/child-app"
|
14
|
+
Then I should see "hello"
|
15
|
+
When I go to "/child-app/unknown"
|
16
|
+
Then the status code should be "404"
|
17
|
+
And I should see "<h2>404 Custom Not Found!</h2>"
|
18
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
Feature: Real world JSON API example
|
2
|
+
|
3
|
+
Scenario: Allows namespacing applications
|
4
|
+
Given a fixture app "complex-app"
|
5
|
+
And app is running with config:
|
6
|
+
"""
|
7
|
+
activate :apps, namespace: "ComplexApp::SomeNamespace"
|
8
|
+
"""
|
9
|
+
When I go to "/test-app?test=1"
|
10
|
+
Then the status code should be "200"
|
11
|
+
And I should see "pass"
|
12
|
+
|
13
|
+
Scenario: Allows namespacing applications via underscored module path
|
14
|
+
Given a fixture app "complex-app"
|
15
|
+
And app is running with config:
|
16
|
+
"""
|
17
|
+
activate :apps, namespace: "complex_app/some_namespace"
|
18
|
+
"""
|
19
|
+
When I go to "/test-app?test=1"
|
20
|
+
Then the status code should be "200"
|
21
|
+
And I should see "pass"
|
22
|
+
|
23
|
+
Scenario: Ignores modular apps that have no direct mapping
|
24
|
+
Given a fixture app "complex-app"
|
25
|
+
And app is running with config:
|
26
|
+
"""
|
27
|
+
activate :apps, namespace: "other_namespacee"
|
28
|
+
"""
|
29
|
+
When I go to "/test-app?test=1"
|
30
|
+
Then the status code should be "404"
|
31
|
+
|
32
|
+
Scenario: Allows specifying Application Name
|
33
|
+
Given a fixture app "complex-app"
|
34
|
+
And app is running with config:
|
35
|
+
"""
|
36
|
+
activate :apps, namespace: :complex_app,
|
37
|
+
map: { child_app: "/some-other-path/abcd" }
|
38
|
+
"""
|
39
|
+
When I go to "/some-other-path/abcd"
|
40
|
+
Then the status code should be "200"
|
41
|
+
And I should see "hello"
|
42
|
+
|
43
|
+
Scenario: Allows specifying URL path for application
|
44
|
+
Given a fixture app "complex-app"
|
45
|
+
And app is running with config:
|
46
|
+
"""
|
47
|
+
activate :apps,
|
48
|
+
namespace: 'complex_app/some_namespace',
|
49
|
+
map: {
|
50
|
+
test_app: 'test',
|
51
|
+
awesome_api: {
|
52
|
+
url: 'api',
|
53
|
+
class: "OtherNamespace::AwesomeAPI"
|
54
|
+
}
|
55
|
+
}
|
56
|
+
"""
|
57
|
+
When I go to "/test-app?test=1"
|
58
|
+
Then the status code should be "404"
|
59
|
+
When I go to "/test?test=1"
|
60
|
+
Then the status code should be "200"
|
61
|
+
And I should see "pass"
|
62
|
+
When I go to "/awesome-api/ping"
|
63
|
+
Then the status code should be "404"
|
64
|
+
When I go to "/api/ping"
|
65
|
+
Then the status code should be "200"
|
66
|
+
And I should see "pong"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
Feature: Compatibility with other Extensions
|
2
|
+
|
3
|
+
# Use custom error page for `middleman-apps`:
|
4
|
+
# with Directory Indexes on - using `find_resource_by_path`
|
5
|
+
Scenario: Custom error page with Directory Indexes
|
6
|
+
Given a fixture app "simple-app"
|
7
|
+
And a file named "source/custom.html.erb" with:
|
8
|
+
"""
|
9
|
+
<h2><%= 404 %> Custom Not Found!</h2>
|
10
|
+
"""
|
11
|
+
And app is running with config:
|
12
|
+
"""
|
13
|
+
activate :directory_indexes
|
14
|
+
activate :apps, not_found: "custom.html"
|
15
|
+
"""
|
16
|
+
When I go to "/unknown-app"
|
17
|
+
Then the status code should be "404"
|
18
|
+
And I should see "<h2>404 Custom Not Found!</h2>"
|
19
|
+
|
20
|
+
# Use custom error page for `middleman-apps`:
|
21
|
+
# with Directory Indexes on - using `find_resource_by_destination_path`
|
22
|
+
Scenario: Custom error page with Directory Indexes
|
23
|
+
Given a fixture app "simple-app"
|
24
|
+
And a file named "source/custom.html.erb" with:
|
25
|
+
"""
|
26
|
+
<h2><%= 404 %> Custom Not Found!</h2>
|
27
|
+
"""
|
28
|
+
And app is running with config:
|
29
|
+
"""
|
30
|
+
activate :directory_indexes
|
31
|
+
activate :apps, not_found: "custom/index.html"
|
32
|
+
"""
|
33
|
+
When I go to "/unknown-app"
|
34
|
+
Then the status code should be "404"
|
35
|
+
And I should see "<h2>404 Custom Not Found!</h2>"
|
36
|
+
|
37
|
+
# Use custom error page for `middleman-apps`:
|
38
|
+
# with Directory Indexes on - using `find_resource_by_page_id`
|
39
|
+
Scenario: Custom error page with Directory Indexes
|
40
|
+
Given a fixture app "simple-app"
|
41
|
+
And a file named "source/custom.html.erb" with:
|
42
|
+
"""
|
43
|
+
<h2><%= 404 %> Custom Not Found!</h2>
|
44
|
+
"""
|
45
|
+
And app is running with config:
|
46
|
+
"""
|
47
|
+
activate :directory_indexes
|
48
|
+
activate :apps, not_found: "custom"
|
49
|
+
"""
|
50
|
+
When I go to "/unknown-app"
|
51
|
+
Then the status code should be "404"
|
52
|
+
And I should see "<h2>404 Custom Not Found!</h2>"
|
@@ -0,0 +1,53 @@
|
|
1
|
+
Feature: 404 error pages using Rack and MiddlemanApps
|
2
|
+
|
3
|
+
# Rack::NotFound's default response
|
4
|
+
Scenario: Default 404 response from Built app
|
5
|
+
Given a fixture app "simple-app"
|
6
|
+
And app is running
|
7
|
+
When I go to "/unknown-app"
|
8
|
+
Then the status code should be "404"
|
9
|
+
And I should see "Not found"
|
10
|
+
|
11
|
+
# Use default 404 error page for `middleman-apps`:
|
12
|
+
# Serve 404 pages from file: build/404.html
|
13
|
+
Scenario: 404 response from Built app when `404.html` exists
|
14
|
+
Given a fixture app "simple-app"
|
15
|
+
And a file named "source/404.html.erb" with:
|
16
|
+
"""
|
17
|
+
<h1><%= (400+4).to_s + ' - Not Found' %></h1>
|
18
|
+
"""
|
19
|
+
And app is running
|
20
|
+
When I go to "/unknown-app"
|
21
|
+
Then the status code should be "404"
|
22
|
+
And I should see "<h1>404 - Not Found</h1>"
|
23
|
+
|
24
|
+
# Use custom error page for `middleman-apps`:
|
25
|
+
Scenario: With a custom error page
|
26
|
+
Given a fixture app "simple-app"
|
27
|
+
And a file named "source/custom.html.erb" with:
|
28
|
+
"""
|
29
|
+
<h2><%= 404 %> Custom Not Found!</h2>
|
30
|
+
"""
|
31
|
+
And app is running with config:
|
32
|
+
"""
|
33
|
+
activate :apps, not_found: "custom.html"
|
34
|
+
"""
|
35
|
+
When I go to "/unknown-app"
|
36
|
+
Then the status code should be "404"
|
37
|
+
And I should see "<h2>404 Custom Not Found!</h2>"
|
38
|
+
|
39
|
+
# Use custom error page for `middleman-apps`:
|
40
|
+
# Ensure that `build/404.html` is not being used for 404 pages now.
|
41
|
+
Scenario: No default 404 with custom error page
|
42
|
+
Given a fixture app "simple-app"
|
43
|
+
And a file named "source/404.html.erb" with:
|
44
|
+
"""
|
45
|
+
<h1>Not Found</h1>
|
46
|
+
"""
|
47
|
+
And app is running with config:
|
48
|
+
"""
|
49
|
+
activate :apps, not_found: "custom.html"
|
50
|
+
"""
|
51
|
+
When I go to "/unknown-app"
|
52
|
+
Then the status code should be "404"
|
53
|
+
And I should see "Not found"
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Feature: 404 error pages with Middleman Preview Server
|
2
|
+
|
3
|
+
Scenario: Fixed 404 response with Server
|
4
|
+
Given a fixture app "simple-app"
|
5
|
+
And the Server is running at "simple-app"
|
6
|
+
When I go to "/unknown-app"
|
7
|
+
Then the status code should be "404"
|
8
|
+
And I should see "<h1>File Not Found</h1>"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Given(/app is running(?: with config:)?/) do |*args|
|
2
|
+
step %(I overwrite the file named "config.rb" with:), args[0] if args.any?
|
3
|
+
step %(I run `middleman build --verbose`)
|
4
|
+
step %(was successfully built)
|
5
|
+
|
6
|
+
app = nil
|
7
|
+
path = File.expand_path(expand_path('.'))
|
8
|
+
ENV['MM_ROOT'] = path
|
9
|
+
|
10
|
+
Dir.chdir(path) do
|
11
|
+
app, = Rack::Builder.parse_file('config.ru')
|
12
|
+
end
|
13
|
+
|
14
|
+
Capybara.app = app.to_app
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
PROJECT_ROOT_PATH = File.dirname(File.dirname(File.dirname(__FILE__)))
|
2
|
+
require 'middleman-core'
|
3
|
+
require 'middleman-core/step_definitions'
|
4
|
+
require File.join(PROJECT_ROOT_PATH, 'lib', 'middleman/apps')
|
5
|
+
|
6
|
+
Before do
|
7
|
+
delete_environment_variable 'MM_ROOT'
|
8
|
+
end
|
9
|
+
|
10
|
+
module Aruba
|
11
|
+
module Platforms
|
12
|
+
# Turn off deprecation warnings from Aruba,
|
13
|
+
# atleast on my current system :)
|
14
|
+
class UnixPlatform
|
15
|
+
def deprecated(*_args); end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Feature: Verbose mode
|
2
|
+
|
3
|
+
Scenario: Display list of child apps which were ignored
|
4
|
+
Given a fixture app "complex-app"
|
5
|
+
And I overwrite the file named "config.rb" with:
|
6
|
+
"""
|
7
|
+
activate :apps, verbose: true
|
8
|
+
"""
|
9
|
+
And I run `middleman build --verbose`
|
10
|
+
And the aruba exit timeout is 2 seconds
|
11
|
+
And I run `rackup -p 17283` in background
|
12
|
+
Then the output should match:
|
13
|
+
"""
|
14
|
+
Ignored child app:.*apps\/awesome_api\.rb
|
15
|
+
"""
|
16
|
+
And the output should match:
|
17
|
+
"""
|
18
|
+
Ignored child app:.*apps\/test_app\.rb
|
19
|
+
"""
|
20
|
+
And the output should match:
|
21
|
+
"""
|
22
|
+
Ignored child app:.*apps\/child_app\.rb
|
23
|
+
"""
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'middleman/apps/base'
|
2
|
+
|
3
|
+
module ComplexApp
|
4
|
+
# Child app that inherits from Middleman::Apps::BaseApp (which in turn
|
5
|
+
# inherits from Sinatra::Base) for additional features, such as:
|
6
|
+
# - error pages will be same as your main middleman static app
|
7
|
+
# - views and public folders set appropriately
|
8
|
+
# - handly helper methods, etc.
|
9
|
+
#
|
10
|
+
class ChildApp < ::Middleman::Apps::Base
|
11
|
+
get '/' do
|
12
|
+
'hello'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1>Error!!</h1>
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :apps # , not_found: 'error.html'
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1>Error!!</h1>
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :apps # , not_found: 'error.html'
|
data/lib/middleman.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'middleman/apps'
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'middleman-core'
|
2
|
+
|
3
|
+
# Load extension nonetheless, as child apps may/will require this file.
|
4
|
+
require 'middleman/apps/extension'
|
5
|
+
|
6
|
+
# Register this extension with the name of `apps`
|
7
|
+
Middleman::Extensions.register :apps, Middleman::Apps::Extension
|
8
|
+
|
9
|
+
module Middleman
|
10
|
+
# Base namespace for `middleman-apps` extension.
|
11
|
+
#
|
12
|
+
module Apps
|
13
|
+
# Environment in which MM should be run
|
14
|
+
ENVIRONMENT = (ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development').to_sym
|
15
|
+
|
16
|
+
# Middleman options that would be passed to create a reference instance.
|
17
|
+
MIDDLEMAN_OPTIONS = {
|
18
|
+
mode: :config,
|
19
|
+
watcher_disable: true,
|
20
|
+
exit_before_ready: true,
|
21
|
+
environment: ENVIRONMENT
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
# Middleman app instance for reference to configuration, etc.
|
25
|
+
#
|
26
|
+
# @return [Middleman::Application] an instance of {Middleman::Application}
|
27
|
+
# using configuration in {MIDDLEMAN_OPTIONS}
|
28
|
+
#
|
29
|
+
def self.middleman_app
|
30
|
+
Middleman.setup_load_paths
|
31
|
+
|
32
|
+
::Middleman::Application.new do
|
33
|
+
MIDDLEMAN_OPTIONS.each do |key, val|
|
34
|
+
config[key] = val
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Evaluate some code within the context of this extension.
|
40
|
+
#
|
41
|
+
# @param [Proc] block block to be executed
|
42
|
+
# @return [Any] - result of execution of the provided block
|
43
|
+
#
|
44
|
+
# @see .rack_app `.rack_app` method which uses this internally
|
45
|
+
#
|
46
|
+
def self.within_extension(&block)
|
47
|
+
app = middleman_app
|
48
|
+
options = app.extensions[:apps].options.to_h
|
49
|
+
Middleman::Apps::Extension.new(app, options).instance_eval(&block)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Rack app comprising of the static (middleman) app with 404 pages, and
|
53
|
+
# child apps properly mounted.
|
54
|
+
#
|
55
|
+
# This method can be used directly to create a Rack app. Refer to the
|
56
|
+
# generated `config.ru` for an example.
|
57
|
+
#
|
58
|
+
# @return [Rack::App] rack application configuration
|
59
|
+
def self.rack_app
|
60
|
+
within_extension do
|
61
|
+
mount_child_apps(middleman_static_app)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
|
3
|
+
module Middleman
|
4
|
+
module Apps
|
5
|
+
# Base application class for creating child applications.
|
6
|
+
#
|
7
|
+
# Inheriting from this class should provide better syncronization with the
|
8
|
+
# static middleman app.
|
9
|
+
#
|
10
|
+
class Base < ::Sinatra::Base
|
11
|
+
# set :static, true
|
12
|
+
|
13
|
+
# set :mm_root, File.dirname(File.dirname(__FILE__))
|
14
|
+
# set :mm_dir, settings.development? ? 'source' : 'build'
|
15
|
+
# set :public_folder, File.join(settings.mm_root, settings.mm_dir)
|
16
|
+
# set :views, settings.public_folder
|
17
|
+
|
18
|
+
not_found do
|
19
|
+
send_file path_for_not_found, status: 404
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def middleman_app
|
25
|
+
Middleman::Apps.middleman_app
|
26
|
+
end
|
27
|
+
|
28
|
+
def path_for_not_found
|
29
|
+
Middleman::Apps.within_extension do
|
30
|
+
path = find_resource(options.not_found)
|
31
|
+
app.root_path.join(app.config.build_dir, path).to_s
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
require 'middleman-core'
|
2
|
+
require 'middleman-core/load_paths'
|
3
|
+
|
4
|
+
module Middleman
|
5
|
+
module Apps
|
6
|
+
# A Middleman extension to serve Rack applications (e.g. created via
|
7
|
+
# Sinatra) or other such apps when previewing using Middleman Preview
|
8
|
+
# server, as well as in the production (build) mode by creating an umbrella
|
9
|
+
# Rack app.
|
10
|
+
#
|
11
|
+
# Usage examples can be seen in README for this extension.
|
12
|
+
#
|
13
|
+
class Extension < ::Middleman::Extension
|
14
|
+
|
15
|
+
# @!group Options for Extension
|
16
|
+
|
17
|
+
# @!macro [attach] option
|
18
|
+
# @!method $1(value)
|
19
|
+
# Extension Option - $3 - Default: $2
|
20
|
+
# @param value value for this option - Default: `$2`
|
21
|
+
option :not_found, '404.html', 'Path to 404 error page'
|
22
|
+
option :namespace, nil, 'Namespace for the child apps'
|
23
|
+
option :map, {}, 'Mappings for differently named child apps'
|
24
|
+
option :verbose, false, 'Displays list of child apps that were ignored'
|
25
|
+
|
26
|
+
# @!endgroup
|
27
|
+
|
28
|
+
def initialize(app, options_hash = {}, &block)
|
29
|
+
super
|
30
|
+
# useful for converting file names to ruby classes
|
31
|
+
require 'active_support/core_ext/string/inflections'
|
32
|
+
end
|
33
|
+
|
34
|
+
# Mount all child apps on a specific Rack app (or current app)
|
35
|
+
#
|
36
|
+
# @param [Rack::App] rack_app app on which to mount child apps
|
37
|
+
# Default: app from MM configuration
|
38
|
+
#
|
39
|
+
# @return [Rack::App] rack_app with child apps mounted on top
|
40
|
+
#
|
41
|
+
def mount_child_apps(rack_app = nil)
|
42
|
+
rack_app ||= app
|
43
|
+
child_apps.each do |url, klass|
|
44
|
+
rack_app.map(url) { run klass }
|
45
|
+
end
|
46
|
+
rack_app
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get a hash of all child applications URLs paths matched to corresponding
|
50
|
+
# Ruby classes.
|
51
|
+
#
|
52
|
+
# Warning is raised (if `verbose` option is `true`) when a child app was
|
53
|
+
# found, but could not be mapped due to the specified config.
|
54
|
+
#
|
55
|
+
# @return [Hash] - child application URL vs Ruby class
|
56
|
+
#
|
57
|
+
def child_apps
|
58
|
+
apps_list.map do |mapp|
|
59
|
+
require mapp
|
60
|
+
klass = get_application_class_for(mapp)
|
61
|
+
warn "Ignored child app: #{mapp}" unless klass
|
62
|
+
[get_application_url_for(mapp), klass] if klass
|
63
|
+
end.compact.to_h
|
64
|
+
end
|
65
|
+
|
66
|
+
# Get a Rack::App that can serve the MM app's build directory.
|
67
|
+
#
|
68
|
+
# Directory paths, and 404 error page are deduced from extensions' options.
|
69
|
+
#
|
70
|
+
# @return [Rack::App] Rack::TryStatic app for MM app's build directory.
|
71
|
+
#
|
72
|
+
def middleman_static_app
|
73
|
+
not_found = options.not_found
|
74
|
+
return create_static_app(root) unless not_found
|
75
|
+
|
76
|
+
not_found_path = File.join(build_dir, find_resource(not_found))
|
77
|
+
create_static_app build_dir, not_found_path
|
78
|
+
end
|
79
|
+
|
80
|
+
# Get a list of all child apps that are found in `MM_ROOT/apps` directory.
|
81
|
+
#
|
82
|
+
def apps_list
|
83
|
+
pattern = File.join(app.root, 'apps', '*.rb')
|
84
|
+
Dir[pattern].map do |file|
|
85
|
+
File.realpath(file) if File.file?(file)
|
86
|
+
end.compact
|
87
|
+
end
|
88
|
+
|
89
|
+
# Run `after_configuration` hook passed on by MM
|
90
|
+
#
|
91
|
+
# After configuration for middleman has been finalized,
|
92
|
+
# create a `config.ru` in the root directory, and mount all child
|
93
|
+
# apps, if we are on a preview server.
|
94
|
+
#
|
95
|
+
# @return [nil]
|
96
|
+
#
|
97
|
+
# @private
|
98
|
+
# @api private
|
99
|
+
#
|
100
|
+
def after_configuration
|
101
|
+
create_config_ru
|
102
|
+
return unless app.server?
|
103
|
+
mount_child_apps(app)
|
104
|
+
end
|
105
|
+
|
106
|
+
# Create a `config.ru` file, if one does not exist, yet.
|
107
|
+
#
|
108
|
+
# This is done whenever `middleman` cli is run for building, or previewing
|
109
|
+
# the static app.
|
110
|
+
#
|
111
|
+
# @return [nil]
|
112
|
+
#
|
113
|
+
# @private
|
114
|
+
# @api private
|
115
|
+
#
|
116
|
+
def create_config_ru
|
117
|
+
path = File.join(app.root, 'config.ru')
|
118
|
+
return if File.exist?(path)
|
119
|
+
|
120
|
+
content = <<-CONTENT.gsub(/^ {6}/, '')
|
121
|
+
ENV['RACK_ENV'] = 'production'
|
122
|
+
require 'middleman/apps'
|
123
|
+
run Middleman::Apps.rack_app
|
124
|
+
CONTENT
|
125
|
+
|
126
|
+
File.open(path, 'wb') { |file| file.puts content }
|
127
|
+
end
|
128
|
+
|
129
|
+
# Create a Rack::TryStatic application for the given directory root.
|
130
|
+
#
|
131
|
+
# @param [String] root - path to directory root
|
132
|
+
# @param [String] path - path to not found error page
|
133
|
+
# If not provided, default 404 response from Rack
|
134
|
+
# is served.
|
135
|
+
#
|
136
|
+
# @return [Rack::App] static app for the `root` directory
|
137
|
+
#
|
138
|
+
# @api private
|
139
|
+
#
|
140
|
+
def create_static_app(root, path = nil)
|
141
|
+
unless File.exist?(path)
|
142
|
+
warn("Could not find: #{path}")
|
143
|
+
path = nil
|
144
|
+
end
|
145
|
+
|
146
|
+
# require 'rack/contrib'
|
147
|
+
require 'middleman/apps/rack_contrib'
|
148
|
+
::Rack::Builder.new do
|
149
|
+
use ::Rack::TryStatic, urls: ['/'], root: root,
|
150
|
+
try: ['.html', 'index.html', '/index.html']
|
151
|
+
run ::Rack::NotFound.new(path)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Find a resource given its path, destination path, or page_id.
|
156
|
+
#
|
157
|
+
# @param [String] name - identifier for this resource
|
158
|
+
# @return [String] relative path to resource
|
159
|
+
#
|
160
|
+
# @api private
|
161
|
+
#
|
162
|
+
def find_resource(name)
|
163
|
+
sitemap = app.sitemap
|
164
|
+
resource = sitemap.find_resource_by_path(name)
|
165
|
+
resource ||= sitemap.find_resource_by_destination_path(name)
|
166
|
+
resource ||= sitemap.find_resource_by_page_id(name)
|
167
|
+
resource ? resource.destination_path : name
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
# Warn user about message if `verbose` option is on.
|
173
|
+
#
|
174
|
+
# @param [String] message - message to display
|
175
|
+
#
|
176
|
+
# @private
|
177
|
+
# @api private
|
178
|
+
#
|
179
|
+
def warn(message)
|
180
|
+
logger.warn(message) if logger && options.verbose
|
181
|
+
end
|
182
|
+
|
183
|
+
# Get path to MM's build dir.
|
184
|
+
#
|
185
|
+
# @return [String] path to build dir
|
186
|
+
#
|
187
|
+
def build_dir
|
188
|
+
File.expand_path(app.config.build_dir.to_s)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Convert options data to a hash for easy searches.
|
192
|
+
#
|
193
|
+
# @api private
|
194
|
+
# @return [Hash] options data
|
195
|
+
#
|
196
|
+
def mappings
|
197
|
+
options.map.map { |key, val| [key.to_s, val] }.to_h
|
198
|
+
end
|
199
|
+
|
200
|
+
# Get URL at which given child app should be mounted.
|
201
|
+
#
|
202
|
+
# @api private
|
203
|
+
# @param [String] file - path to child app
|
204
|
+
# @return [String] url component for the child app
|
205
|
+
#
|
206
|
+
def get_application_url_for(file)
|
207
|
+
name = File.basename(file, '.rb')
|
208
|
+
url = mappings[name]
|
209
|
+
url = url[:url] if url.is_a?(Hash)
|
210
|
+
'/' + (url ? url.to_s.gsub(%r{^\/}, '') : name.titleize.parameterize)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Get Application Class for the child app.
|
214
|
+
#
|
215
|
+
# @api private
|
216
|
+
# @param [String] file - path to child app
|
217
|
+
# @return [Class, nil] Class for the child app, if exists.
|
218
|
+
#
|
219
|
+
def get_application_class_for(file)
|
220
|
+
name = File.basename(file, '.rb')
|
221
|
+
namespace = options.namespace
|
222
|
+
|
223
|
+
klass = mappings[name][:class] if mappings[name].is_a?(Hash)
|
224
|
+
klass ||= namespace ? "#{namespace}/#{name}" : name
|
225
|
+
klass.to_s.classify.constantize
|
226
|
+
rescue NameError
|
227
|
+
return nil
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# `rack-contrib` depends on `rack` v1.4, which is quite outdated now, and also,
|
2
|
+
# limits us to Sinatra v1.4, while Sinatra v2.0 is out.
|
3
|
+
#
|
4
|
+
# Since, `middleman-apps` uses 2 tiny classes from `rack-contrib`, I copied them
|
5
|
+
# here to remove `rack-contrib` from dependency list.
|
6
|
+
#
|
7
|
+
# Once `rack-contrib` supports `rack` v2.0, we can switch back to using it,
|
8
|
+
# instead of this file.
|
9
|
+
#
|
10
|
+
# @todo
|
11
|
+
# [MAYBE] Merge the two Rack apps below into a single concise Rack app?
|
12
|
+
module ::Rack
|
13
|
+
|
14
|
+
# The Rack::TryStatic middleware delegates requests to Rack::Static middleware
|
15
|
+
# trying to match a static file
|
16
|
+
#
|
17
|
+
# Examples
|
18
|
+
#
|
19
|
+
# use Rack::TryStatic,
|
20
|
+
# :root => "public", # static files root dir
|
21
|
+
# :urls => %w[/], # match all requests
|
22
|
+
# :try => ['.html', 'index.html', '/index.html'] # try these postfixes sequentially
|
23
|
+
#
|
24
|
+
# uses same options as Rack::Static with extra :try option which is an array
|
25
|
+
# of postfixes to find desired file
|
26
|
+
|
27
|
+
class TryStatic
|
28
|
+
|
29
|
+
def initialize(app, options)
|
30
|
+
@app = app
|
31
|
+
@try = ['', *options[:try]]
|
32
|
+
@static = ::Rack::Static.new(
|
33
|
+
lambda { |_| [404, {}, []] },
|
34
|
+
options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(env)
|
38
|
+
orig_path = env['PATH_INFO']
|
39
|
+
found = nil
|
40
|
+
@try.each do |path|
|
41
|
+
resp = @static.call(env.merge!({'PATH_INFO' => orig_path + path}))
|
42
|
+
break if !(403..405).include?(resp[0]) && found = resp
|
43
|
+
end
|
44
|
+
found or @app.call(env.merge!('PATH_INFO' => orig_path))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Rack::NotFound is a default endpoint. Optionally initialize with the
|
49
|
+
# path to a custom 404 page, to override the standard response body.
|
50
|
+
#
|
51
|
+
# Examples:
|
52
|
+
#
|
53
|
+
# Serve default 404 response:
|
54
|
+
# run Rack::NotFound.new
|
55
|
+
#
|
56
|
+
# Serve a custom 404 page:
|
57
|
+
# run Rack::NotFound.new('path/to/your/404.html')
|
58
|
+
|
59
|
+
class NotFound
|
60
|
+
F = ::File
|
61
|
+
|
62
|
+
def initialize(path = nil, content_type = 'text/html')
|
63
|
+
if path.nil?
|
64
|
+
@content = "Not found\n"
|
65
|
+
else
|
66
|
+
@content = F.read(path)
|
67
|
+
end
|
68
|
+
@length = @content.size.to_s
|
69
|
+
|
70
|
+
@content_type = content_type
|
71
|
+
end
|
72
|
+
|
73
|
+
def call(env)
|
74
|
+
[404, {'Content-Type' => @content_type, 'Content-Length' => @length}, [@content]]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
2
|
+
require 'middleman/apps/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'middleman-apps'
|
6
|
+
s.version = Middleman::Apps::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ['Nikhil Gupta']
|
9
|
+
s.email = ['me@nikhgupta.com']
|
10
|
+
s.homepage = 'https://github.com/nikhgupta/middleman-apps'
|
11
|
+
s.summary = 'Middleman extension to run dynamic pages using Sinatra'
|
12
|
+
s.description = 'Middleman extension to run dynamic pages using Sinatra'
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.require_paths = ['lib']
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map do |f|
|
18
|
+
File.basename(f)
|
19
|
+
end
|
20
|
+
|
21
|
+
s.add_runtime_dependency('middleman-core', ['~> 4.2'])
|
22
|
+
s.add_runtime_dependency('sinatra', ['~> 2.0'])
|
23
|
+
s.add_runtime_dependency('activesupport', ['>= 4.2'])
|
24
|
+
# s.add_runtime_dependency('rack-contrib', ['>= 1.7.0'])
|
25
|
+
|
26
|
+
s.add_development_dependency('middleman-cli')
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: middleman-apps
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nikhil Gupta
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-10-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: middleman-core
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sinatra
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4.2'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: middleman-cli
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Middleman extension to run dynamic pages using Sinatra
|
70
|
+
email:
|
71
|
+
- me@nikhgupta.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rubocop.yml"
|
78
|
+
- ".travis.yml"
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- features/activation.feature
|
84
|
+
- features/build.feature
|
85
|
+
- features/child_app.feature
|
86
|
+
- features/complex_app.feature
|
87
|
+
- features/directory_indexes.feature
|
88
|
+
- features/not_found_rack.feature
|
89
|
+
- features/not_found_server.feature
|
90
|
+
- features/step_definitions/rack_app_steps.rb
|
91
|
+
- features/support/env.rb
|
92
|
+
- features/verbose.feature
|
93
|
+
- fixtures/complex-app/apps/awesome_api.rb
|
94
|
+
- fixtures/complex-app/apps/child_app.rb
|
95
|
+
- fixtures/complex-app/apps/test_app.rb
|
96
|
+
- fixtures/complex-app/build/error.html
|
97
|
+
- fixtures/complex-app/build/index.html
|
98
|
+
- fixtures/complex-app/config.rb
|
99
|
+
- fixtures/complex-app/source/index.html.erb
|
100
|
+
- fixtures/simple-app/apps/test_app.rb
|
101
|
+
- fixtures/simple-app/build/error.html
|
102
|
+
- fixtures/simple-app/build/index.html
|
103
|
+
- fixtures/simple-app/config.rb
|
104
|
+
- fixtures/simple-app/source/index.html.erb
|
105
|
+
- lib/middleman.rb
|
106
|
+
- lib/middleman/apps.rb
|
107
|
+
- lib/middleman/apps/base.rb
|
108
|
+
- lib/middleman/apps/extension.rb
|
109
|
+
- lib/middleman/apps/rack_contrib.rb
|
110
|
+
- lib/middleman/apps/version.rb
|
111
|
+
- middleman-apps.gemspec
|
112
|
+
homepage: https://github.com/nikhgupta/middleman-apps
|
113
|
+
licenses: []
|
114
|
+
metadata: {}
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.6.10
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: Middleman extension to run dynamic pages using Sinatra
|
135
|
+
test_files:
|
136
|
+
- features/activation.feature
|
137
|
+
- features/build.feature
|
138
|
+
- features/child_app.feature
|
139
|
+
- features/complex_app.feature
|
140
|
+
- features/directory_indexes.feature
|
141
|
+
- features/not_found_rack.feature
|
142
|
+
- features/not_found_server.feature
|
143
|
+
- features/step_definitions/rack_app_steps.rb
|
144
|
+
- features/support/env.rb
|
145
|
+
- features/verbose.feature
|