middleman-extensionless-helper 1.0.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 +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:
|