middleman-extensionless-helper 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +18 -0
- data/LICENSE.md +21 -0
- data/README.md +193 -0
- data/Rakefile +14 -0
- data/features/another_build_dir.feature +27 -0
- data/features/avoid-layout.feature +25 -0
- data/features/erb-path.feature +24 -0
- data/features/erb.feature +57 -0
- data/features/html_erb.feature +20 -0
- data/features/no_erb.feature +28 -0
- data/features/no_file.feature +18 -0
- data/features/no_target.feature +19 -0
- data/features/ruby_file.feature +21 -0
- data/features/support/env.rb +4 -0
- data/fixtures/another-build-dir-app/_BUILD_DIR_REQUIED_ +0 -0
- data/fixtures/another-build-dir-app/config.rb +1 -0
- data/fixtures/another-build-dir-app/source/target.erb +1 -0
- data/fixtures/another-build-dir-app/source/target.txt.erb +1 -0
- data/fixtures/avoid-layout-app/config.rb +1 -0
- data/fixtures/avoid-layout-app/source/layouts/layout.erb +3 -0
- data/fixtures/avoid-layout-app/source/target.erb +1 -0
- data/fixtures/avoid-layout-app/source/target.txt.erb +1 -0
- data/fixtures/erb-app/config.rb +1 -0
- data/fixtures/erb-app/source/.htaccess.erb +1 -0
- data/fixtures/erb-app/source/.target.erb +1 -0
- data/fixtures/erb-app/source/target.erb +1 -0
- data/fixtures/erb-app/source/target.txt.erb +1 -0
- data/fixtures/erb-app/source/target_cap.ERB +1 -0
- data/fixtures/erb-app/source/target_inner_.erb_.erb +1 -0
- data/fixtures/erb-app/source/target_no_tag.erb +1 -0
- data/fixtures/erb-app/source/target_no_tag.txt.erb +1 -0
- data/fixtures/erb-path-app/config.rb +1 -0
- data/fixtures/erb-path-app/source/sub/target.erb +1 -0
- data/fixtures/erb-path-app/source/sub/target.txt.erb +1 -0
- data/fixtures/html-erb-app/config.rb +1 -0
- data/fixtures/html-erb-app/source/target.html.erb +1 -0
- data/fixtures/no-erb-app/config.rb +1 -0
- data/fixtures/no-erb-app/source/target +1 -0
- data/fixtures/no-erb-app/source/target.erb.txt +1 -0
- data/fixtures/no-erb-app/source/target.txt +1 -0
- data/fixtures/no-file-app/config.rb +1 -0
- data/fixtures/no-file-app/source/target.erb +1 -0
- data/fixtures/no-target-app/config.rb +1 -0
- data/fixtures/no-target-app/source/target.erb +1 -0
- data/fixtures/no-target-app/source/target.txt.erb +1 -0
- data/fixtures/ruby-file-app/config.rb +1 -0
- data/fixtures/ruby-file-app/source/target.rb +4 -0
- data/fixtures/ruby-file-app/source/target.txt +4 -0
- data/lib/middleman-extensionless-helper.rb +6 -0
- data/lib/middleman-extensionless-helper/extension.rb +169 -0
- data/lib/middleman-extensionless-helper/version.rb +5 -0
- data/lib/middleman_extension.rb +1 -0
- data/middleman-extensionless-helper.gemspec +24 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 51a62b069c13d681ab55c192751795e908b390ec
|
4
|
+
data.tar.gz: 2f52076a6deefec06181a889bfc74abfba942794
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bc1199811b6942ffc9a27146cf91bd2c1335b8e57e523a291acb1fdd526d0c1bd5d672314338442e3c683e4346009db6a86f2edb5351cacd78cb23afe3fa24e0
|
7
|
+
data.tar.gz: 3f058f37d2bbf499d24f33ecfe9cc103fe51234b78e2ce149781aad403eab9aac5aae087ce3576b039d3c78fbdd7d1ebb67f38a04a23b549193b63bb76def6a0
|
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in middleman-extensionless-helper.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :development do
|
7
|
+
gem "nokogiri", '1.6.3'
|
8
|
+
|
9
|
+
gem 'rake'
|
10
|
+
gem 'rdoc'
|
11
|
+
gem 'yard'
|
12
|
+
end
|
13
|
+
|
14
|
+
group :test do
|
15
|
+
gem 'cucumber'
|
16
|
+
gem 'aruba'
|
17
|
+
gem 'rspec'
|
18
|
+
end
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
(c) 2016 AT-AT
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# Middleman-Extensionless-Helper
|
2
|
+
|
3
|
+
middleman-extensionless-helper is a Middleman(only for v3) extension to remove a file extension which is attached to extension-less files by the "automatically adding content extensions" feature in a build process.
|
4
|
+
|
5
|
+
Currently, this extension only works for ERb, and works for files that are specified in the option of this extension.
|
6
|
+
|
7
|
+
### What is the "automatically adding content extensions"?
|
8
|
+
|
9
|
+
Let's say, Middleman builds the following file
|
10
|
+
|
11
|
+
```
|
12
|
+
source/foo.erb
|
13
|
+
```
|
14
|
+
|
15
|
+
to
|
16
|
+
|
17
|
+
```
|
18
|
+
build/foo.html.erb
|
19
|
+
```
|
20
|
+
|
21
|
+
This is the "automatically adding content extensions" feature.
|
22
|
+
But in some cases, we want to avoid this feature.
|
23
|
+
This extension renames it to
|
24
|
+
|
25
|
+
```
|
26
|
+
build/foo
|
27
|
+
```
|
28
|
+
|
29
|
+
However, Middleman builds following files
|
30
|
+
|
31
|
+
```
|
32
|
+
source/
|
33
|
+
.erb
|
34
|
+
.foo.erb
|
35
|
+
bar.txt.erb
|
36
|
+
baz.quux.erb
|
37
|
+
```
|
38
|
+
|
39
|
+
to
|
40
|
+
|
41
|
+
```
|
42
|
+
build/
|
43
|
+
# ".erb" and ".foo.erb" does not be built,
|
44
|
+
# because Middleman only builds ".htaccess" and ".htpasswd" on the dot file.
|
45
|
+
|
46
|
+
# Middleman does not attach extension to a file which has some extension.
|
47
|
+
bar.txt
|
48
|
+
baz.quux
|
49
|
+
```
|
50
|
+
|
51
|
+
So, this extension never handle those files.
|
52
|
+
|
53
|
+
### Why only for v3?
|
54
|
+
|
55
|
+
Because Middleman-v4 does not have the "automatically adding content extensions" feature.
|
56
|
+
See [this issue](https://github.com/middleman/middleman/issues/1211).
|
57
|
+
|
58
|
+
### Why only for ERb?
|
59
|
+
|
60
|
+
Because others are not general-purpose format like as ERb, IMO there is no need to handle them.
|
61
|
+
|
62
|
+
## Installation
|
63
|
+
|
64
|
+
Add the following line to the Gemfile of your Middleman project:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
gem "middleman-extensionless-helper"
|
68
|
+
```
|
69
|
+
|
70
|
+
Then as usual, run:
|
71
|
+
|
72
|
+
```sh
|
73
|
+
bundle install
|
74
|
+
```
|
75
|
+
|
76
|
+
## Usage
|
77
|
+
|
78
|
+
To activate and configure this extension, add the following configuration block to Middleman's config.rb:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
activate :extensionless_helper do |f|
|
82
|
+
# The "target" option has been initialized with a empty Array.
|
83
|
+
f.target << 'foo.erb' # assumed to be placed in "source/foo.erb"
|
84
|
+
# It is possible to change whole the value.
|
85
|
+
f.target = ['foo.erb', 'bar/baz.erb'] # assumed to be placed in "source/foo.erb", "source/bar/baz.erb"
|
86
|
+
end
|
87
|
+
```
|
88
|
+
|
89
|
+
| Option | Description
|
90
|
+
| ---------- | ------------
|
91
|
+
| target | An array with target files placed in a `source` directory.<br>Relative path from the `source` directory is acceptable.
|
92
|
+
|
93
|
+
## Build Messages
|
94
|
+
|
95
|
+
This extension displays some messages in a build process as below.
|
96
|
+
|
97
|
+
Let's say, beginning state is:
|
98
|
+
|
99
|
+
```
|
100
|
+
build/
|
101
|
+
(empty)
|
102
|
+
source/
|
103
|
+
foo.erb
|
104
|
+
```
|
105
|
+
|
106
|
+
Run build, then messages are:
|
107
|
+
|
108
|
+
```
|
109
|
+
create build/foo.html <-- Middleman says
|
110
|
+
EH:rename build/foo.html => build/foo <-- This extension says
|
111
|
+
```
|
112
|
+
|
113
|
+
Then, state is:
|
114
|
+
|
115
|
+
```
|
116
|
+
build/
|
117
|
+
foo
|
118
|
+
source/
|
119
|
+
foo.erb
|
120
|
+
```
|
121
|
+
|
122
|
+
Just build again without any change, then messages are:
|
123
|
+
|
124
|
+
```
|
125
|
+
identical build/foo.html <-- Middleman says
|
126
|
+
EH:rename build/foo.html => build/foo (identical) <-- This extension says
|
127
|
+
```
|
128
|
+
|
129
|
+
Then, state is:
|
130
|
+
|
131
|
+
```
|
132
|
+
build/
|
133
|
+
foo
|
134
|
+
source/
|
135
|
+
foo.erb
|
136
|
+
```
|
137
|
+
|
138
|
+
Change `foo.erb` and build, then messages are:
|
139
|
+
|
140
|
+
```
|
141
|
+
update build/foo.html <-- Middleman says
|
142
|
+
EH:rename build/foo.html => build/foo (update) <-- This extension says
|
143
|
+
```
|
144
|
+
|
145
|
+
Then, state is:
|
146
|
+
|
147
|
+
```
|
148
|
+
build/
|
149
|
+
foo
|
150
|
+
source/
|
151
|
+
foo.erb
|
152
|
+
```
|
153
|
+
|
154
|
+
Remove `foo.erb` and build, then messages are:
|
155
|
+
|
156
|
+
```
|
157
|
+
remove build/foo.html <-- Middleman says
|
158
|
+
EH:remove build/foo <-- This extension says
|
159
|
+
```
|
160
|
+
|
161
|
+
Then, state is:
|
162
|
+
|
163
|
+
```
|
164
|
+
build/
|
165
|
+
(empty)
|
166
|
+
source/
|
167
|
+
(empty)
|
168
|
+
```
|
169
|
+
|
170
|
+
Just build again, then message is:
|
171
|
+
|
172
|
+
```
|
173
|
+
EH:no-target build/foo <-- This extension says
|
174
|
+
```
|
175
|
+
|
176
|
+
## Development
|
177
|
+
|
178
|
+
Personal references:
|
179
|
+
* [Middleman-v3 - Document/custom extensions](https://github.com/middleman/middleman-guides/blob/v3/source/localizable/advanced/custom_extensions.jp.html.markdown)
|
180
|
+
* [Middleman-v3 - steps](https://github.com/middleman/middleman/tree/v3-stable/middleman-core/lib/middleman-core/step_definitions)
|
181
|
+
* [Cucumber-ruby](https://github.com/cucumber/cucumber-ruby)
|
182
|
+
* [Aruba](https://github.com/cucumber/aruba)
|
183
|
+
* [Thor - Actions](http://www.rubydoc.info/github/wycats/thor/Thor/Actions)
|
184
|
+
* [Thor - Shell/Basic](http://www.rubydoc.info/github/wycats/thor/Thor/Shell/Basic)
|
185
|
+
|
186
|
+
## TODO
|
187
|
+
|
188
|
+
* Add unit test.
|
189
|
+
* Consider test for displaying message.
|
190
|
+
|
191
|
+
## License
|
192
|
+
|
193
|
+
(c) 2016 AT-AT. MIT Licensed, see [LICENSE](LICENSE.md) for details.
|
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 = "--format progress --color --tags ~@wip --strict"
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rake/clean'
|
11
|
+
|
12
|
+
task test: ['cucumber']
|
13
|
+
|
14
|
+
task default: :test
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Feature: Handle ERb files placed in the another(not default) build directory.
|
2
|
+
|
3
|
+
Scenario: Build ERb file
|
4
|
+
Given a fixture app "another-build-dir-app"
|
5
|
+
And a file named "config.rb" with:
|
6
|
+
"""
|
7
|
+
activate :extensionless_helper do |f|
|
8
|
+
f.target = [
|
9
|
+
'target.erb',
|
10
|
+
'target.txt.erb',
|
11
|
+
]
|
12
|
+
end
|
13
|
+
set :test_msg, 'CONVERTED'
|
14
|
+
configure :build do
|
15
|
+
set :build_dir, %Q!#{config[:build_dir]}_another!
|
16
|
+
end
|
17
|
+
"""
|
18
|
+
And a successfully built app at "another-build-dir-app"
|
19
|
+
When I cd to "build_another"
|
20
|
+
|
21
|
+
Then a file named "target.html" should not exist
|
22
|
+
Then a file named "target" should exist
|
23
|
+
Then the file "target" should contain "CONVERTED"
|
24
|
+
|
25
|
+
Then a file named "target.txt" should exist
|
26
|
+
Then the file "target.txt" should contain "CONVERTED"
|
27
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Feature: Avoid applying a layout.
|
2
|
+
|
3
|
+
Scenario: There's a layout file
|
4
|
+
Given a fixture app "avoid-layout-app"
|
5
|
+
And a file named "config.rb" with:
|
6
|
+
"""
|
7
|
+
activate :extensionless_helper do |f|
|
8
|
+
f.target = [
|
9
|
+
'target.erb',
|
10
|
+
'target.txt.erb',
|
11
|
+
]
|
12
|
+
end
|
13
|
+
set :test_msg, 'CONVERTED'
|
14
|
+
"""
|
15
|
+
And a successfully built app at "avoid-layout-app"
|
16
|
+
When I cd to "build"
|
17
|
+
|
18
|
+
Then a file named "target" should exist
|
19
|
+
Then the file "target" should contain "CONVERTED"
|
20
|
+
Then the file "target" should not contain "html"
|
21
|
+
|
22
|
+
Then a file named "target.txt" should exist
|
23
|
+
Then the file "target.txt" should contain "CONVERTED"
|
24
|
+
Then the file "target.txt" should not contain "html"
|
25
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Feature: Handle ERb files designated with a relative path.
|
2
|
+
|
3
|
+
Scenario: Build ERb file
|
4
|
+
Given a fixture app "erb-path-app"
|
5
|
+
And a file named "config.rb" with:
|
6
|
+
"""
|
7
|
+
activate :extensionless_helper do |f|
|
8
|
+
f.target = [
|
9
|
+
'sub/target.erb',
|
10
|
+
'sub/target.txt.erb',
|
11
|
+
]
|
12
|
+
end
|
13
|
+
set :test_msg, 'CONVERTED'
|
14
|
+
"""
|
15
|
+
And a successfully built app at "erb-path-app"
|
16
|
+
When I cd to "build"
|
17
|
+
|
18
|
+
Then a file named "sub/target.html" should not exist
|
19
|
+
Then a file named "sub/target" should exist
|
20
|
+
Then the file "sub/target" should contain "CONVERTED"
|
21
|
+
|
22
|
+
Then a file named "sub/target.txt" should exist
|
23
|
+
Then the file "sub/target.txt" should contain "CONVERTED"
|
24
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
Feature: Handle ERb files.
|
2
|
+
|
3
|
+
Scenario: Build ERb file
|
4
|
+
Given a fixture app "erb-app"
|
5
|
+
And a file named "config.rb" with:
|
6
|
+
"""
|
7
|
+
activate :extensionless_helper do |f|
|
8
|
+
f.target = [
|
9
|
+
# Handle in the following cases.
|
10
|
+
'.htaccess.erb',
|
11
|
+
'target.erb',
|
12
|
+
'target_no_tag.erb',
|
13
|
+
|
14
|
+
# Except, because dot file other than ".htaccess" and ".htpasswd" do not be built.
|
15
|
+
'.target.erb',
|
16
|
+
|
17
|
+
# Except, because file has two(src, dest) extensions.
|
18
|
+
'target.txt.erb',
|
19
|
+
'target_inner_.erb_.erb',
|
20
|
+
'target_no_tag.txt.erb',
|
21
|
+
|
22
|
+
# Except, because capitalized extension do NOT produce auto-adding-ext.
|
23
|
+
'target_cap.ERB',
|
24
|
+
]
|
25
|
+
end
|
26
|
+
set :test_msg, 'CONVERTED'
|
27
|
+
"""
|
28
|
+
And a successfully built app at "erb-app"
|
29
|
+
When I cd to "build"
|
30
|
+
|
31
|
+
Then a file named ".htaccess" should exist
|
32
|
+
Then the file ".htaccess" should contain "CONVERTED"
|
33
|
+
|
34
|
+
Then a file named "target.html" should not exist
|
35
|
+
Then a file named "target" should exist
|
36
|
+
Then the file "target" should contain "CONVERTED"
|
37
|
+
|
38
|
+
Then a file named "target_no_tag" should exist
|
39
|
+
Then the file "target_no_tag" should not contain "CONVERTED"
|
40
|
+
|
41
|
+
|
42
|
+
Then a file named ".target" should not exist
|
43
|
+
|
44
|
+
|
45
|
+
Then a file named "target.txt" should exist
|
46
|
+
Then the file "target.txt" should contain "CONVERTED"
|
47
|
+
|
48
|
+
Then a file named "target_inner_.erb_" should exist
|
49
|
+
Then the file "target_inner_.erb_" should contain "CONVERTED"
|
50
|
+
|
51
|
+
Then a file named "target_no_tag.txt" should exist
|
52
|
+
Then the file "target_no_tag.txt" should not contain "CONVERTED"
|
53
|
+
|
54
|
+
|
55
|
+
Then a file named "target_cap" should exist
|
56
|
+
Then the file "target_cap" should contain "CONVERTED"
|
57
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Feature: Handle a ERb file for HTML.
|
2
|
+
In this case, this extension does nothing.
|
3
|
+
|
4
|
+
Scenario: Build HTML from ERb file
|
5
|
+
Given a fixture app "html-erb-app"
|
6
|
+
And a file named "config.rb" with:
|
7
|
+
"""
|
8
|
+
activate :extensionless_helper do |f|
|
9
|
+
f.target = [
|
10
|
+
'target.html.erb',
|
11
|
+
]
|
12
|
+
end
|
13
|
+
set :test_msg, 'CONVERTED'
|
14
|
+
"""
|
15
|
+
And a successfully built app at "html-erb-app"
|
16
|
+
When I cd to "build"
|
17
|
+
|
18
|
+
Then a file named "target.html" should exist
|
19
|
+
Then the file "target.html" should contain "CONVERTED"
|
20
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Feature: Handle no ERb file.
|
2
|
+
In this case, this extension does nothing.
|
3
|
+
|
4
|
+
Scenario: Build no ERb file
|
5
|
+
Given a fixture app "no-erb-app"
|
6
|
+
And a file named "config.rb" with:
|
7
|
+
"""
|
8
|
+
activate :extensionless_helper do |f|
|
9
|
+
f.target = [
|
10
|
+
'target',
|
11
|
+
'target.txt',
|
12
|
+
'target.erb.txt',
|
13
|
+
]
|
14
|
+
end
|
15
|
+
set :test_msg, 'CONVERTED'
|
16
|
+
"""
|
17
|
+
And a successfully built app at "no-erb-app"
|
18
|
+
When I cd to "build"
|
19
|
+
|
20
|
+
Then a file named "target" should exist
|
21
|
+
Then the file "target" should not contain "CONVERTED"
|
22
|
+
|
23
|
+
Then a file named "target.txt" should exist
|
24
|
+
Then the file "target.txt" should not contain "CONVERTED"
|
25
|
+
|
26
|
+
Then a file named "target.erb.txt" should exist
|
27
|
+
Then the file "target.erb.txt" should not contain "CONVERTED"
|
28
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: Handle a non-existent file.
|
2
|
+
In this case, this extension does nothing.
|
3
|
+
|
4
|
+
Scenario: Designated file does not exist
|
5
|
+
Given a fixture app "no-file-app"
|
6
|
+
And a file named "config.rb" with:
|
7
|
+
"""
|
8
|
+
activate :extensionless_helper do |f|
|
9
|
+
f.target = [
|
10
|
+
'this_file_does_not_exist.erb',
|
11
|
+
]
|
12
|
+
end
|
13
|
+
set :test_msg, 'CONVERTED'
|
14
|
+
"""
|
15
|
+
And a successfully built app at "no-file-app"
|
16
|
+
When I cd to "build"
|
17
|
+
Then a file named "this_file_does_not_exist" should not exist
|
18
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Feature: Handle no target.
|
2
|
+
In this case, this extension does nothing.
|
3
|
+
|
4
|
+
Scenario: No target is designated
|
5
|
+
Given a fixture app "no-target-app"
|
6
|
+
And a file named "config.rb" with:
|
7
|
+
"""
|
8
|
+
activate :extensionless_helper
|
9
|
+
set :test_msg, 'CONVERTED'
|
10
|
+
"""
|
11
|
+
And a successfully built app at "no-target-app"
|
12
|
+
When I cd to "build"
|
13
|
+
|
14
|
+
Then a file named "target.html" should exist
|
15
|
+
Then the file "target.html" should contain "CONVERTED"
|
16
|
+
|
17
|
+
Then a file named "target.txt" should exist
|
18
|
+
Then the file "target.txt" should contain "CONVERTED"
|
19
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Change below tag(@wip) to anything else when invoke this test.
|
2
|
+
@wip
|
3
|
+
Feature: Handle a ruby file.
|
4
|
+
This feature(test) is not for the extension, but leave for a examination.
|
5
|
+
The Problem:
|
6
|
+
MM builds a file by rendering with a template engine.
|
7
|
+
If content extension that is acceptable for available template engines is not attached, MM uses ERb.
|
8
|
+
However, ERb removes a magic comment of Ruby in ANY file type, like .rb, .txt, .py(!), etc.
|
9
|
+
This problem prevents to place ruby script that should not be changed in the source directory. 8-(
|
10
|
+
|
11
|
+
Scenario: A Ruby file is placed in the source directory
|
12
|
+
Given a fixture app "ruby-file-app"
|
13
|
+
And a successfully built app at "ruby-file-app"
|
14
|
+
When I cd to "build"
|
15
|
+
|
16
|
+
Then a file named "target.rb" should exist
|
17
|
+
Then the file "target.rb" should contain "# coding: utf-8"
|
18
|
+
|
19
|
+
Then a file named "target.txt" should exist
|
20
|
+
Then the file "target.txt" should contain "# coding: utf-8"
|
21
|
+
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :extensionless_helper
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :extensionless_helper
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :extensionless_helper
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
This file should not be changed.
|
@@ -0,0 +1 @@
|
|
1
|
+
This file should not be changed.
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :extensionless_helper
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :extensionless_helper
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :extensionless_helper
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :extensionless_helper
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :extensionless_helper
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= config[:test_msg] %>
|
@@ -0,0 +1 @@
|
|
1
|
+
activate :extensionless_helper
|
@@ -0,0 +1,169 @@
|
|
1
|
+
module Middleman
|
2
|
+
class ExtensionLessHelper < Extension
|
3
|
+
option :target, [], 'Target files/paths from the source directory'
|
4
|
+
|
5
|
+
EXTENSION_MAP = {
|
6
|
+
'.erb' => '.html'
|
7
|
+
}
|
8
|
+
|
9
|
+
|
10
|
+
def initialize(app, options_hash={}, &block)
|
11
|
+
super
|
12
|
+
|
13
|
+
require 'digest/sha2'
|
14
|
+
require 'fileutils'
|
15
|
+
require 'ostruct'
|
16
|
+
|
17
|
+
@target = create_target(options.target)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
#
|
22
|
+
# Hooks
|
23
|
+
#
|
24
|
+
|
25
|
+
public
|
26
|
+
|
27
|
+
def after_configuration
|
28
|
+
|
29
|
+
# Avoid applying a layout to target files.
|
30
|
+
# #page requires a URL having a absolute path from the root that is not the source directory
|
31
|
+
# but the web site. Besides, because of it's the URL, a file name in it must be the same as MM
|
32
|
+
# names in a build process. Hence the URL looks like "/foo.html"(the original file is "foo").
|
33
|
+
@target.each do |target|
|
34
|
+
app.page File.join('', target.build), :layout => false
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
def before_build(builder)
|
40
|
+
|
41
|
+
# Rename target files in the build directory for avoiding a "create" message by MM.
|
42
|
+
# e.g. build/foo -> build/foo.html
|
43
|
+
# Because target files are renamed by this extension in a previous build process, MM cannot
|
44
|
+
# find them and assumes that they are newly created and displays a "create" message.
|
45
|
+
# So, restore a name of target files to one which MM names in a build process.
|
46
|
+
@target.each do |target|
|
47
|
+
rename_build_file(target.expect, target.build)
|
48
|
+
end
|
49
|
+
|
50
|
+
# SHOULD do after above the process, because a build path in a target object is referred.
|
51
|
+
inject_target_state
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
def after_build(builder)
|
56
|
+
|
57
|
+
# Rename target files in the build directory as we expect.
|
58
|
+
# e.g. build/foo.html -> build/foo
|
59
|
+
@target.each do |target|
|
60
|
+
rename_build_file(target.build, target.expect)
|
61
|
+
|
62
|
+
# SHOULD do after above the process, because a build path in a target object is referred.
|
63
|
+
present_status(builder, target)
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
#
|
71
|
+
# Internals
|
72
|
+
#
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def convert_source_path(source)
|
77
|
+
# This isn't a smart way, but shouldn't use #split|Regexp because there are some "edge" cases.
|
78
|
+
|
79
|
+
template_exts = EXTENSION_MAP.keys
|
80
|
+
|
81
|
+
first_ext = File.extname(source).downcase
|
82
|
+
return {} unless template_exts.include?(first_ext)
|
83
|
+
|
84
|
+
expected_path = source.sub(/#{Regexp.quote(first_ext)}$/i, '')
|
85
|
+
return {} if File.extname(expected_path) != ''
|
86
|
+
|
87
|
+
base_name = File.basename expected_path
|
88
|
+
return {} if base_name.start_with?('.') && !base_name.match(/^\.ht(?:access|passwd)$/)
|
89
|
+
|
90
|
+
build_ext = EXTENSION_MAP[first_ext]
|
91
|
+
{build: (expected_path + build_ext), expect: expected_path}
|
92
|
+
end
|
93
|
+
|
94
|
+
def create_target(target)
|
95
|
+
|
96
|
+
# SHOULD NOT check an existence of file in here, because files in a source directory are
|
97
|
+
# changed, created and removed until starting a build process.
|
98
|
+
[target].flatten.inject([]) do |stack, path|
|
99
|
+
paths = convert_source_path(path)
|
100
|
+
(stack << OpenStruct.new(paths.merge(original: path))) if !paths.empty?
|
101
|
+
stack
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
def digest_of(path)
|
107
|
+
Digest::SHA256.file(path).hexdigest
|
108
|
+
end
|
109
|
+
|
110
|
+
def inject_target_state
|
111
|
+
state_skel = {created: false, removed: false, active: true, digest: ''}
|
112
|
+
|
113
|
+
@target.each do |target|
|
114
|
+
path_in_source = path_of target.original, :source
|
115
|
+
path_in_build = path_of target.build, :build
|
116
|
+
in_source = File.file? path_in_source
|
117
|
+
in_build = File.file? path_in_build
|
118
|
+
state = OpenStruct.new state_skel.dup
|
119
|
+
|
120
|
+
case true
|
121
|
+
when in_source && in_build then # no-op # File is updated or identical.
|
122
|
+
when in_source && !in_build then state.created = true # File is created.
|
123
|
+
when !in_source && in_build then state.removed = true # File is removed.
|
124
|
+
else state.active = false # No file.
|
125
|
+
end
|
126
|
+
|
127
|
+
state.digest = digest_of(path_in_build) if in_build
|
128
|
+
target.state = state
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def path_of(path_crumb, type, absolute = true)
|
133
|
+
|
134
|
+
# SHOULD get path to the build|source directory at any time of need, because the configuration
|
135
|
+
# value of :build_dir|:source can be updated anytime.
|
136
|
+
id = type.to_sym == :build ? :build_dir : :source
|
137
|
+
path = File.join(app.config[id], path_crumb)
|
138
|
+
absolute ? File.expand_path(path) : path
|
139
|
+
end
|
140
|
+
|
141
|
+
def present_status(builder, target)
|
142
|
+
build_path = ->(path){ path_of path, :build, false }
|
143
|
+
message = "#{build_path.call target.build} => #{build_path.call target.expect}"
|
144
|
+
|
145
|
+
status, message, color = \
|
146
|
+
case true
|
147
|
+
when target.state.created
|
148
|
+
['rename', "#{message} (create)", :green]
|
149
|
+
when target.state.removed
|
150
|
+
['remove', "#{build_path.call target.expect}", :red]
|
151
|
+
when target.state.active
|
152
|
+
digest_of(path_of(target.expect, :build)) == target.state.digest \
|
153
|
+
? ['rename', "#{message} (identical)", :blue] \
|
154
|
+
: ['rename', "#{message} (update)", :yellow]
|
155
|
+
else
|
156
|
+
['no-target', path_of(target.original, :source, false), :magenta]
|
157
|
+
end
|
158
|
+
|
159
|
+
builder.say_status "EH:#{status}", message, color
|
160
|
+
end
|
161
|
+
|
162
|
+
def rename_build_file(from, to)
|
163
|
+
src, dest = [path_of(from, :build), path_of(to, :build)]
|
164
|
+
FileUtils.mv(src, dest) if File.file?(src) && !File.exist?(dest)
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'middleman-extensionless-helper'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "middleman-extensionless-helper/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "middleman-extensionless-helper"
|
7
|
+
s.version = Middleman::ExtensionlessHelper::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["AT-AT"]
|
10
|
+
s.email = ["dec.alpha21264@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/AT-AT/middleman-extensionless-helper"
|
12
|
+
s.summary = %q{A Middleman extension to remove an automatically added content extension}
|
13
|
+
s.description = %q{A Middleman extension to remove an automatically added content extension}
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features,fixtures}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
|
19
|
+
# The version of middleman-core your extension depends on
|
20
|
+
s.add_runtime_dependency("middleman-core", ["~> 3.4.1"])
|
21
|
+
|
22
|
+
# Additional dependencies
|
23
|
+
# None.
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: middleman-extensionless-helper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- AT-AT
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-07 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: 3.4.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.4.1
|
27
|
+
description: A Middleman extension to remove an automatically added content extension
|
28
|
+
email:
|
29
|
+
- dec.alpha21264@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- ".gitignore"
|
35
|
+
- Gemfile
|
36
|
+
- LICENSE.md
|
37
|
+
- README.md
|
38
|
+
- Rakefile
|
39
|
+
- features/another_build_dir.feature
|
40
|
+
- features/avoid-layout.feature
|
41
|
+
- features/erb-path.feature
|
42
|
+
- features/erb.feature
|
43
|
+
- features/html_erb.feature
|
44
|
+
- features/no_erb.feature
|
45
|
+
- features/no_file.feature
|
46
|
+
- features/no_target.feature
|
47
|
+
- features/ruby_file.feature
|
48
|
+
- features/support/env.rb
|
49
|
+
- fixtures/another-build-dir-app/_BUILD_DIR_REQUIED_
|
50
|
+
- fixtures/another-build-dir-app/config.rb
|
51
|
+
- fixtures/another-build-dir-app/source/target.erb
|
52
|
+
- fixtures/another-build-dir-app/source/target.txt.erb
|
53
|
+
- fixtures/avoid-layout-app/config.rb
|
54
|
+
- fixtures/avoid-layout-app/source/layouts/layout.erb
|
55
|
+
- fixtures/avoid-layout-app/source/target.erb
|
56
|
+
- fixtures/avoid-layout-app/source/target.txt.erb
|
57
|
+
- fixtures/erb-app/config.rb
|
58
|
+
- fixtures/erb-app/source/.htaccess.erb
|
59
|
+
- fixtures/erb-app/source/.target.erb
|
60
|
+
- fixtures/erb-app/source/target.erb
|
61
|
+
- fixtures/erb-app/source/target.txt.erb
|
62
|
+
- fixtures/erb-app/source/target_cap.ERB
|
63
|
+
- fixtures/erb-app/source/target_inner_.erb_.erb
|
64
|
+
- fixtures/erb-app/source/target_no_tag.erb
|
65
|
+
- fixtures/erb-app/source/target_no_tag.txt.erb
|
66
|
+
- fixtures/erb-path-app/config.rb
|
67
|
+
- fixtures/erb-path-app/source/sub/target.erb
|
68
|
+
- fixtures/erb-path-app/source/sub/target.txt.erb
|
69
|
+
- fixtures/html-erb-app/config.rb
|
70
|
+
- fixtures/html-erb-app/source/target.html.erb
|
71
|
+
- fixtures/no-erb-app/config.rb
|
72
|
+
- fixtures/no-erb-app/source/target
|
73
|
+
- fixtures/no-erb-app/source/target.erb.txt
|
74
|
+
- fixtures/no-erb-app/source/target.txt
|
75
|
+
- fixtures/no-file-app/config.rb
|
76
|
+
- fixtures/no-file-app/source/target.erb
|
77
|
+
- fixtures/no-target-app/config.rb
|
78
|
+
- fixtures/no-target-app/source/target.erb
|
79
|
+
- fixtures/no-target-app/source/target.txt.erb
|
80
|
+
- fixtures/ruby-file-app/config.rb
|
81
|
+
- fixtures/ruby-file-app/source/target.rb
|
82
|
+
- fixtures/ruby-file-app/source/target.txt
|
83
|
+
- lib/middleman-extensionless-helper.rb
|
84
|
+
- lib/middleman-extensionless-helper/extension.rb
|
85
|
+
- lib/middleman-extensionless-helper/version.rb
|
86
|
+
- lib/middleman_extension.rb
|
87
|
+
- middleman-extensionless-helper.gemspec
|
88
|
+
homepage: https://github.com/AT-AT/middleman-extensionless-helper
|
89
|
+
licenses: []
|
90
|
+
metadata: {}
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 2.5.1
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: A Middleman extension to remove an automatically added content extension
|
111
|
+
test_files:
|
112
|
+
- features/another_build_dir.feature
|
113
|
+
- features/avoid-layout.feature
|
114
|
+
- features/erb-path.feature
|
115
|
+
- features/erb.feature
|
116
|
+
- features/html_erb.feature
|
117
|
+
- features/no_erb.feature
|
118
|
+
- features/no_file.feature
|
119
|
+
- features/no_target.feature
|
120
|
+
- features/ruby_file.feature
|
121
|
+
- features/support/env.rb
|
122
|
+
- fixtures/another-build-dir-app/_BUILD_DIR_REQUIED_
|
123
|
+
- fixtures/another-build-dir-app/config.rb
|
124
|
+
- fixtures/another-build-dir-app/source/target.erb
|
125
|
+
- fixtures/another-build-dir-app/source/target.txt.erb
|
126
|
+
- fixtures/avoid-layout-app/config.rb
|
127
|
+
- fixtures/avoid-layout-app/source/layouts/layout.erb
|
128
|
+
- fixtures/avoid-layout-app/source/target.erb
|
129
|
+
- fixtures/avoid-layout-app/source/target.txt.erb
|
130
|
+
- fixtures/erb-app/config.rb
|
131
|
+
- fixtures/erb-app/source/.htaccess.erb
|
132
|
+
- fixtures/erb-app/source/.target.erb
|
133
|
+
- fixtures/erb-app/source/target.erb
|
134
|
+
- fixtures/erb-app/source/target.txt.erb
|
135
|
+
- fixtures/erb-app/source/target_cap.ERB
|
136
|
+
- fixtures/erb-app/source/target_inner_.erb_.erb
|
137
|
+
- fixtures/erb-app/source/target_no_tag.erb
|
138
|
+
- fixtures/erb-app/source/target_no_tag.txt.erb
|
139
|
+
- fixtures/erb-path-app/config.rb
|
140
|
+
- fixtures/erb-path-app/source/sub/target.erb
|
141
|
+
- fixtures/erb-path-app/source/sub/target.txt.erb
|
142
|
+
- fixtures/html-erb-app/config.rb
|
143
|
+
- fixtures/html-erb-app/source/target.html.erb
|
144
|
+
- fixtures/no-erb-app/config.rb
|
145
|
+
- fixtures/no-erb-app/source/target
|
146
|
+
- fixtures/no-erb-app/source/target.erb.txt
|
147
|
+
- fixtures/no-erb-app/source/target.txt
|
148
|
+
- fixtures/no-file-app/config.rb
|
149
|
+
- fixtures/no-file-app/source/target.erb
|
150
|
+
- fixtures/no-target-app/config.rb
|
151
|
+
- fixtures/no-target-app/source/target.erb
|
152
|
+
- fixtures/no-target-app/source/target.txt.erb
|
153
|
+
- fixtures/ruby-file-app/config.rb
|
154
|
+
- fixtures/ruby-file-app/source/target.rb
|
155
|
+
- fixtures/ruby-file-app/source/target.txt
|
156
|
+
has_rdoc:
|