middleman-extensionless-helper 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/Gemfile +18 -0
  4. data/LICENSE.md +21 -0
  5. data/README.md +193 -0
  6. data/Rakefile +14 -0
  7. data/features/another_build_dir.feature +27 -0
  8. data/features/avoid-layout.feature +25 -0
  9. data/features/erb-path.feature +24 -0
  10. data/features/erb.feature +57 -0
  11. data/features/html_erb.feature +20 -0
  12. data/features/no_erb.feature +28 -0
  13. data/features/no_file.feature +18 -0
  14. data/features/no_target.feature +19 -0
  15. data/features/ruby_file.feature +21 -0
  16. data/features/support/env.rb +4 -0
  17. data/fixtures/another-build-dir-app/_BUILD_DIR_REQUIED_ +0 -0
  18. data/fixtures/another-build-dir-app/config.rb +1 -0
  19. data/fixtures/another-build-dir-app/source/target.erb +1 -0
  20. data/fixtures/another-build-dir-app/source/target.txt.erb +1 -0
  21. data/fixtures/avoid-layout-app/config.rb +1 -0
  22. data/fixtures/avoid-layout-app/source/layouts/layout.erb +3 -0
  23. data/fixtures/avoid-layout-app/source/target.erb +1 -0
  24. data/fixtures/avoid-layout-app/source/target.txt.erb +1 -0
  25. data/fixtures/erb-app/config.rb +1 -0
  26. data/fixtures/erb-app/source/.htaccess.erb +1 -0
  27. data/fixtures/erb-app/source/.target.erb +1 -0
  28. data/fixtures/erb-app/source/target.erb +1 -0
  29. data/fixtures/erb-app/source/target.txt.erb +1 -0
  30. data/fixtures/erb-app/source/target_cap.ERB +1 -0
  31. data/fixtures/erb-app/source/target_inner_.erb_.erb +1 -0
  32. data/fixtures/erb-app/source/target_no_tag.erb +1 -0
  33. data/fixtures/erb-app/source/target_no_tag.txt.erb +1 -0
  34. data/fixtures/erb-path-app/config.rb +1 -0
  35. data/fixtures/erb-path-app/source/sub/target.erb +1 -0
  36. data/fixtures/erb-path-app/source/sub/target.txt.erb +1 -0
  37. data/fixtures/html-erb-app/config.rb +1 -0
  38. data/fixtures/html-erb-app/source/target.html.erb +1 -0
  39. data/fixtures/no-erb-app/config.rb +1 -0
  40. data/fixtures/no-erb-app/source/target +1 -0
  41. data/fixtures/no-erb-app/source/target.erb.txt +1 -0
  42. data/fixtures/no-erb-app/source/target.txt +1 -0
  43. data/fixtures/no-file-app/config.rb +1 -0
  44. data/fixtures/no-file-app/source/target.erb +1 -0
  45. data/fixtures/no-target-app/config.rb +1 -0
  46. data/fixtures/no-target-app/source/target.erb +1 -0
  47. data/fixtures/no-target-app/source/target.txt.erb +1 -0
  48. data/fixtures/ruby-file-app/config.rb +1 -0
  49. data/fixtures/ruby-file-app/source/target.rb +4 -0
  50. data/fixtures/ruby-file-app/source/target.txt +4 -0
  51. data/lib/middleman-extensionless-helper.rb +6 -0
  52. data/lib/middleman-extensionless-helper/extension.rb +169 -0
  53. data/lib/middleman-extensionless-helper/version.rb +5 -0
  54. data/lib/middleman_extension.rb +1 -0
  55. data/middleman-extensionless-helper.gemspec +24 -0
  56. 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
@@ -0,0 +1,9 @@
1
+ # Ignore bundler lock file
2
+ Gemfile.lock
3
+
4
+ # Ignore pkg folder
5
+ pkg
6
+
7
+ .bundle
8
+ tmp
9
+ vendor
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
+
@@ -0,0 +1,4 @@
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-extensionless-helper')
@@ -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,3 @@
1
+ <html>
2
+ <%= yield %>
3
+ </html>
@@ -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,4 @@
1
+ # coding: utf-8
2
+
3
+ puts 'Hello, Ruby!'
4
+
@@ -0,0 +1,4 @@
1
+ # coding: utf-8
2
+
3
+ puts 'Hello, Ruby!'
4
+
@@ -0,0 +1,6 @@
1
+ require 'middleman-core'
2
+
3
+ ::Middleman::Extensions.register(:extensionless_helper) do
4
+ require 'middleman-extensionless-helper/extension'
5
+ ::Middleman::ExtensionLessHelper
6
+ end
@@ -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,5 @@
1
+ module Middleman
2
+ class ExtensionlessHelper
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -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: