middleman-apps 0.1.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 +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
|