middleman-diff 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +18 -0
  5. data/LICENSE.md +20 -0
  6. data/README.md +64 -0
  7. data/Rakefile +27 -0
  8. data/cucumber.yml +2 -0
  9. data/features/diff.feature +38 -0
  10. data/features/extension.feature +11 -0
  11. data/features/hooks.feature +34 -0
  12. data/features/keep.feature +47 -0
  13. data/features/step_definitions/diff_steps.rb +18 -0
  14. data/features/step_definitions/filesystem_steps.rb +25 -0
  15. data/features/step_definitions/output_steps.rb +7 -0
  16. data/features/storage.feature +25 -0
  17. data/features/support/env.rb +4 -0
  18. data/fixtures/inactive/.gitkeep +0 -0
  19. data/fixtures/typical-modified/build/index.html +10 -0
  20. data/fixtures/typical-modified/build/javascripts/main.js +4 -0
  21. data/fixtures/typical-modified/build/stylesheets/main.css +2 -0
  22. data/fixtures/typical-modified/config.rb +16 -0
  23. data/fixtures/typical-modified/source/index.html.haml +1 -0
  24. data/fixtures/typical-modified/source/javascripts/main.js.coffee +1 -0
  25. data/fixtures/typical-modified/source/layouts/layout.haml +7 -0
  26. data/fixtures/typical-modified/source/stylesheets/main.css.sass +2 -0
  27. data/fixtures/typical/build/index.html +10 -0
  28. data/fixtures/typical/build/javascripts/main.js +4 -0
  29. data/fixtures/typical/build/stylesheets/main.css +2 -0
  30. data/fixtures/typical/config.rb +16 -0
  31. data/fixtures/typical/source/index.html.haml +1 -0
  32. data/fixtures/typical/source/javascripts/main.js.coffee +1 -0
  33. data/fixtures/typical/source/layouts/layout.haml +7 -0
  34. data/fixtures/typical/source/stylesheets/main.css.sass +2 -0
  35. data/lib/middleman-diff.rb +4 -0
  36. data/lib/middleman-diff/cli.rb +71 -0
  37. data/lib/middleman-diff/extension.rb +43 -0
  38. data/lib/middleman-diff/preview.rb +116 -0
  39. data/lib/middleman_extension.rb +1 -0
  40. data/middleman-diff.gemspec +19 -0
  41. metadata +124 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 61d953d17238b483e2833b03800c49920a23c2fd
4
+ data.tar.gz: 0981c88714d42bd0ecfda876ad22ddee10929253
5
+ SHA512:
6
+ metadata.gz: a3573b71ed9f1b1e64b4319f96d64c637320a7bf4f53b84b4feb308349fd00601f980c522f806a23e1676f2bb96542c0941609e5b1c036f7ae76458f28c2e23d
7
+ data.tar.gz: c9072661426000a2b3e15205cca45db482dd3ecc08a46fb245ad592790fa32beff14529f0297d9fc6ff72bd72412ca3b576a2ae4842c01552635dde2afed98f9
@@ -0,0 +1,7 @@
1
+ # Aruba, Middleman
2
+ /tmp
3
+
4
+ # Bundler
5
+ /bin
6
+ /Gemfile.lock
7
+ /pkg
@@ -0,0 +1,6 @@
1
+ bundler_args: --without development
2
+ language: ruby
3
+ rvm:
4
+ - 2.1
5
+ - 2.0.0
6
+ script: bundle exec rake test
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake', group: [:development, :test]
6
+
7
+ group :development do
8
+ gem 'rdoc'
9
+ gem 'yard'
10
+ end
11
+
12
+ group :test do
13
+ gem 'aruba'
14
+ gem 'cucumber'
15
+ gem 'fivemat'
16
+ gem 'middleman'
17
+ gem 'rspec'
18
+ end
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Andrew Kvalheim
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ 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, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ # middleman-diff
2
+
3
+ [![Gem Version][gem-version-badge]][gem-version]
4
+ [![Build Status][build-status-badge]][build-status]
5
+
6
+ Preview what's changed in your [Middleman][middleman] build.
7
+
8
+ ## Installation
9
+
10
+ Add the extension to your `Gemfile`,
11
+
12
+ ```ruby
13
+ gem 'middleman-diff'
14
+ ```
15
+
16
+ run `bundle install`, and activate it in `config.rb`:
17
+
18
+ ```ruby
19
+ activate :diff
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ Preview what's changed since the last build, and optionally use it as the
25
+ current build:
26
+
27
+ ```console
28
+ $ middleman diff
29
+ create tmp/preview/index.html
30
+ {build => tmp/preview}/index.html | 2 +-
31
+ 1 file changed, 1 insertion(+), 1 deletion(-)
32
+
33
+ diff --git a/build/index.html b/tmp/preview/index.html
34
+ index 68c37b9..218e4ff 100644
35
+ --- a/build/index.html
36
+ +++ b/tmp/preview/index.html
37
+ @@ -5,6 +5,6 @@
38
+ </head>
39
+ <body>
40
+ <h1>Hello there!</h1>
41
+ - <p>This site is kind of alright.</p>
42
+ + <p>This site is awesome.</p>
43
+ </body>
44
+ </html>
45
+ Would you like to apply these changes to the build? [y/N] y
46
+ Build has been updated.
47
+ ```
48
+
49
+ ## Configuration
50
+
51
+ The following configuration options are available:
52
+
53
+ Name | Default | Description
54
+ ------------- | --------- | ---------------------------------------------------
55
+ `build_hooks` | `true` | Whether to run build hooks when previewing the build
56
+ `keep` | `:prompt` | Whether to `:always`, `:never`, or `:prompt` to keep the preview as the build
57
+ `temp_dir` | `'tmp'` | Directory in which to build when previewing
58
+
59
+
60
+ [build-status]: https://travis-ci.org/AndrewKvalheim/middleman-diff
61
+ [build-status-badge]: https://travis-ci.org/AndrewKvalheim/middleman-diff.png?branch=master
62
+ [gem-version]: https://badge.fury.io/rb/middleman-diff
63
+ [gem-version-badge]: https://badge.fury.io/rb/middleman-diff.png
64
+ [middleman]: http://middlemanapp.com/
@@ -0,0 +1,27 @@
1
+ require 'bundler'
2
+ require 'rake/clean'
3
+
4
+ # Gem helpers
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ # Feature tests
8
+ begin
9
+ require 'cucumber'
10
+ require 'cucumber/rake/task'
11
+
12
+ Cucumber::Rake::Task.new(:features) do |cucumber|
13
+ cucumber.cucumber_opts = '--profile ci' if ENV['CI'] == 'true'
14
+ end
15
+ rescue
16
+ desc 'Cucumber is not available.'
17
+ task :features do
18
+ abort 'Cucumber is not available.'
19
+ end
20
+ end
21
+
22
+ # All tests
23
+ desc 'Run all tests.'
24
+ task test: %w(features)
25
+
26
+ # Default
27
+ task default: :test
@@ -0,0 +1,2 @@
1
+ ci: --format pretty
2
+ default: --format Fivemat
@@ -0,0 +1,38 @@
1
+ Feature: Diff
2
+
3
+ Scenario: There is no last build.
4
+ Given a fixture app "typical" without "build"
5
+ When I attempt to diff
6
+ Then it should fail with "There's no existing build to compare against."
7
+
8
+ Scenario: No changes have been made since the last build.
9
+ Given a fixture app "typical"
10
+ When I diff
11
+ Then the output should not match /^[+-]/
12
+
13
+ Scenario: A file has been created since the last build.
14
+ Given a fixture app "typical"
15
+ And a file named "source/created.html.haml" with:
16
+ """
17
+ This is the created document.
18
+ """
19
+ When I diff
20
+ Then the output should match /^\+\s+This is the created document/
21
+ And the output should not match /^-\s+/
22
+
23
+ Scenario: A file has been modified since the last build.
24
+ Given a fixture app "typical"
25
+ And a file named "source/index.html.haml" with:
26
+ """
27
+ This is the modified document.
28
+ """
29
+ When I diff
30
+ Then the output should match /^-\s+This is the original document/
31
+ And the output should match /^\+\s+This is the modified document/
32
+
33
+ Scenario: A file has been deleted since the last build.
34
+ Given a fixture app "typical"
35
+ And I remove the file "source/index.html.haml"
36
+ When I diff
37
+ Then the output should match /^-\s+This is the original document/
38
+ And the output should not match /^\+\s+/
@@ -0,0 +1,11 @@
1
+ Feature: Extension
2
+
3
+ Scenario: Activation is required.
4
+ Given a fixture app "inactive"
5
+ When I attempt to diff
6
+ Then it should fail with "You must activate this extension."
7
+
8
+ Scenario: The build command is unaffected.
9
+ Given a fixture app "typical"
10
+ When I successfully run `middleman build`
11
+ Then a directory named "build" should exist
@@ -0,0 +1,34 @@
1
+ Feature: Hooks
2
+
3
+ Scenario: Build hooks are not modified.
4
+ Given a fixture app "typical"
5
+ When I successfully run `middleman build`
6
+ Then the output should contain "The before_build hook has been run."
7
+ And the output should contain "The after_build hook has been run."
8
+
9
+ Scenario: Build hooks are run.
10
+ Given a fixture app "typical"
11
+ When I diff
12
+ Then the output should contain "The before_build hook has been run."
13
+ And the output should contain "The after_build hook has been run."
14
+
15
+ Scenario: Build hooks have been disabled.
16
+ Given a fixture app "typical"
17
+ And the text "activate :diff" in the file "config.rb" is replaced with:
18
+ """
19
+ activate :diff, build_hooks: false
20
+ """
21
+ When I diff and type "n"
22
+ Then the output should not match /The \w+_build hook has been run./
23
+
24
+ Scenario: Files from a build hook are previewed.
25
+ Given a fixture app "typical"
26
+ And I append to "config.rb" with "activate :gzip"
27
+ When I diff
28
+ Then a file named "build/index.html.gz" should not exist
29
+
30
+ Scenario: Files from a build hook are kept.
31
+ Given a fixture app "typical"
32
+ And I append to "config.rb" with "activate :gzip"
33
+ When I diff and type "y"
34
+ Then a file named "build/index.html.gz" should exist
@@ -0,0 +1,47 @@
1
+ Feature: Keep
2
+
3
+ Scenario: A prompt is displayed.
4
+ Given a fixture app "typical-modified"
5
+ When I diff
6
+ Then the output should contain:
7
+ """
8
+ Would you like to apply these changes to the build? [y/N]
9
+ """
10
+
11
+ Scenario: Changes are discarded by default.
12
+ Given a fixture app "typical-modified"
13
+ When I diff
14
+ Then the output should contain "Preview has been discarded."
15
+ And the file "build/index.html" should contain "original document"
16
+
17
+ Scenario: Changes are discarded.
18
+ Given a fixture app "typical-modified"
19
+ When I diff and type "n"
20
+ Then it should pass with "Preview has been discarded."
21
+ And the file "build/index.html" should contain "original document"
22
+
23
+ Scenario: Changes are kept.
24
+ Given a fixture app "typical-modified"
25
+ When I diff and type "y"
26
+ Then it should pass with "Build has been updated."
27
+ And the file "build/index.html" should contain "modified document"
28
+
29
+ Scenario: Changes are always discarded.
30
+ Given a fixture app "typical-modified"
31
+ And the text "activate :diff" in the file "config.rb" is replaced with:
32
+ """
33
+ activate :diff, keep: :never
34
+ """
35
+ When I diff noninteractively
36
+ Then the output should contain "Preview has been discarded."
37
+ And the file "build/index.html" should contain "original document"
38
+
39
+ Scenario: Changes are always kept.
40
+ Given a fixture app "typical-modified"
41
+ And the text "activate :diff" in the file "config.rb" is replaced with:
42
+ """
43
+ activate :diff, keep: :always
44
+ """
45
+ When I diff noninteractively
46
+ Then the output should contain "Build has been updated."
47
+ And the file "build/index.html" should contain "modified document"
@@ -0,0 +1,18 @@
1
+ When(/^I attempt to diff$/) do
2
+ step 'I run `middleman diff`'
3
+ end
4
+
5
+ When(/^I diff noninteractively$/) do
6
+ step 'I attempt to diff'
7
+ step 'the exit status should be 0'
8
+ end
9
+
10
+ When(/^I diff$/) do
11
+ step 'I diff and type ""'
12
+ end
13
+
14
+ When(/^I diff and type "(.*?)"$/) do |text|
15
+ step 'I run `middleman diff` interactively'
16
+ step "I type \"#{ text }\""
17
+ step 'the exit status should be 0'
18
+ end
@@ -0,0 +1,25 @@
1
+ require 'fileutils'
2
+ require 'pathname'
3
+
4
+ Then(/^a directory named "(.*?)" should be empty$/) do |path|
5
+ in_current_dir do
6
+ Pathname.new(path).children.empty?
7
+ end
8
+ end
9
+
10
+ Given(/^a fixture app "(.*?)" without "(.*?)"$/) do |name, path|
11
+ step "a fixture app \"#{ name }\""
12
+ in_current_dir do
13
+ FileUtils.rmtree path
14
+ end
15
+ end
16
+
17
+ Given(/^the text "(.*?)" in the file "(.*?)" is replaced with:$/) do |text, path, replacement|
18
+ in_current_dir do
19
+ content = open(path) { |file| file.read }
20
+
21
+ open(path, 'w') do |file|
22
+ file.write content.gsub(text, replacement)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ When(/^it should fail with "(.*?)"$/) do |output|
2
+ step 'it should fail with:', output
3
+ end
4
+
5
+ When(/^it should pass with "(.*?)"$/) do |output|
6
+ step 'it should pass with:', output
7
+ end
@@ -0,0 +1,25 @@
1
+ Feature: Storage
2
+
3
+ Scenario: The temporary directory is created if necessary.
4
+ Given a fixture app "typical"
5
+ When I diff
6
+ Then a directory named "tmp" should exist
7
+
8
+ Scenario: The preview directory is cleaned when unused.
9
+ Given a fixture app "typical" without "build"
10
+ When I attempt to diff
11
+ Then a directory named "tmp" should be empty
12
+
13
+ Scenario: The preview directory is cleaned.
14
+ Given a fixture app "typical"
15
+ When I diff
16
+ Then a directory named "tmp" should be empty
17
+
18
+ Scenario: A non-default temporary directory is configured and created.
19
+ Given a fixture app "typical"
20
+ And the text "activate :diff" in the file "config.rb" is replaced with:
21
+ """
22
+ activate :diff, temp_dir: 'some/other/location'
23
+ """
24
+ When I diff
25
+ Then a directory named "some/other/location" should exist
@@ -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-diff')
File without changes
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <link href="/stylesheets/main.css" rel="stylesheet" type="text/css" />
5
+ </head>
6
+ <body>
7
+ This is the original document.
8
+ <script src="/javascripts/main.js" type="text/javascript"></script>
9
+ </body>
10
+ </html>
@@ -0,0 +1,4 @@
1
+ (function() {
2
+ document.write('This is the original script.');
3
+
4
+ }).call(this);
@@ -0,0 +1,2 @@
1
+ body:before {
2
+ content: "This is the original stylesheet."; }
@@ -0,0 +1,16 @@
1
+ activate :diff
2
+
3
+ before_build do
4
+ puts 'The before_build hook has been run.'
5
+ end
6
+
7
+ after_build do
8
+ puts 'The after_build hook has been run.'
9
+ end
10
+
11
+ # Workaround for middleman/middleman#706
12
+ configure :build do
13
+ compass_config do |config|
14
+ config.sass_options = { line_comments: false }
15
+ end
16
+ end
@@ -0,0 +1 @@
1
+ This is the modified document.
@@ -0,0 +1 @@
1
+ document.write 'This is the original script.'
@@ -0,0 +1,7 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ = stylesheet_link_tag 'main'
5
+ %body
6
+ = yield
7
+ = javascript_include_tag 'main'
@@ -0,0 +1,2 @@
1
+ body:before
2
+ content: "This is the original stylesheet."
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <link href="/stylesheets/main.css" rel="stylesheet" type="text/css" />
5
+ </head>
6
+ <body>
7
+ This is the original document.
8
+ <script src="/javascripts/main.js" type="text/javascript"></script>
9
+ </body>
10
+ </html>
@@ -0,0 +1,4 @@
1
+ (function() {
2
+ document.write('This is the original script.');
3
+
4
+ }).call(this);
@@ -0,0 +1,2 @@
1
+ body:before {
2
+ content: "This is the original stylesheet."; }
@@ -0,0 +1,16 @@
1
+ activate :diff
2
+
3
+ before_build do
4
+ puts 'The before_build hook has been run.'
5
+ end
6
+
7
+ after_build do
8
+ puts 'The after_build hook has been run.'
9
+ end
10
+
11
+ # Workaround for middleman/middleman#706
12
+ configure :build do
13
+ compass_config do |config|
14
+ config.sass_options = { line_comments: false }
15
+ end
16
+ end
@@ -0,0 +1 @@
1
+ This is the original document.
@@ -0,0 +1 @@
1
+ document.write 'This is the original script.'
@@ -0,0 +1,7 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ = stylesheet_link_tag 'main'
5
+ %body
6
+ = yield
7
+ = javascript_include_tag 'main'
@@ -0,0 +1,2 @@
1
+ body:before
2
+ content: "This is the original stylesheet."
@@ -0,0 +1,4 @@
1
+ require 'middleman-diff/cli'
2
+ require 'middleman-diff/extension'
3
+
4
+ Middleman::Diff::Extension.register(:diff)
@@ -0,0 +1,71 @@
1
+ require 'middleman-core/cli'
2
+
3
+ module Middleman
4
+ module Cli
5
+ # Extension to the Middleman CLI
6
+ class Diff < Thor
7
+ include Thor::Actions
8
+
9
+ namespace :diff
10
+
11
+ # Whether to exit with status 1 when a failure happens
12
+ #
13
+ # @return [Boolean]
14
+ def self.exit_on_failure?
15
+ true
16
+ end
17
+
18
+ # Interactively diff a preview with the build, optionally replacing the
19
+ # existing build with it.
20
+ #
21
+ # @return [void]
22
+ desc 'diff', "Preview what's changed in the build."
23
+ def diff
24
+ extension.with_preview do |preview|
25
+ preview.show_diff
26
+
27
+ if keep?
28
+ preview.replace_build
29
+ say 'Build has been updated.'
30
+ else
31
+ say 'Preview has been discarded.'
32
+ end
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ # Middleman application instance
39
+ #
40
+ # @return [Middleman::Application]
41
+ def app
42
+ @_app ||= ::Middleman::Application.server.inst
43
+ end
44
+
45
+ # Activated extension instance
46
+ #
47
+ # @return [Middleman::Extensions::Diff]
48
+ def extension
49
+ @_extension ||= begin
50
+ extension = app.extensions.find { |e| e.first == :diff }.try(:last)
51
+
52
+ fail Thor::Error, 'You must activate this extension.' unless extension
53
+
54
+ extension
55
+ end
56
+ end
57
+
58
+ # Whether to replace the existing build with the preview
59
+ #
60
+ # @return [Boolean]
61
+ def keep?
62
+ case extension.options.keep
63
+ when :always then true
64
+ when :never then false
65
+ when :prompt
66
+ yes?('Would you like to apply these changes to the build? [y/N]')
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,43 @@
1
+ require 'middleman-core'
2
+
3
+ module Middleman
4
+ module Diff
5
+ # Middleman extension
6
+ class Extension < ::Middleman::Extension
7
+ option :build_hooks, true,
8
+ 'Whether to run build hooks when previewing the build'
9
+ option :keep, :prompt,
10
+ 'Whether to :always, :never, or :prompt to keep the preview'
11
+ option :temp_dir, 'tmp',
12
+ 'Path in which to build when previewing'
13
+
14
+ # Runs when the extension is activated
15
+ #
16
+ # @param app [Middleman::Application] Middleman application instance
17
+ # @param options_hash [Hash] options
18
+ # @param block [Block] configuration block
19
+ # @return [void]
20
+ def initialize(app, **options_hash, &block)
21
+ # Build options from options_hash
22
+ super
23
+
24
+ require 'middleman-diff/preview'
25
+ require 'pathname'
26
+ end
27
+
28
+ # Yield a preview of the build.
29
+ #
30
+ # @yield [Middleman::Diff::Preview]
31
+ # @yieldreturn [void]
32
+ # @return [void]
33
+ def with_preview
34
+ preview = Preview.new(app, build_hooks: options.build_hooks,
35
+ temp_dir: options.temp_dir)
36
+
37
+ yield preview
38
+
39
+ preview.dispose
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,116 @@
1
+ require 'fileutils'
2
+ require 'pathname'
3
+ require 'rack/test' # Required by Middleman::Cli::Build
4
+ require 'tmpdir'
5
+
6
+ module Middleman
7
+ module Diff
8
+ # Preview of the build
9
+ class Preview
10
+ # Generate a preview of the build.
11
+ #
12
+ # @param app [Middleman::Appliation] Middleman application instance
13
+ # @param build_hooks [Boolean]
14
+ # @param temp_dir [String] path to temporary directory
15
+ # @return [void]
16
+ def initialize(app, build_hooks: true, temp_dir: 'tmp')
17
+ @app = app
18
+ @build_hooks = build_hooks
19
+ @temp_dir = Pathname.new(temp_dir)
20
+
21
+ build_preview
22
+ end
23
+
24
+ # Clean up any temporary files from the preview.
25
+ #
26
+ # @return [void]
27
+ def dispose
28
+ preview_dir.rmtree if preview_dir.exist?
29
+ end
30
+
31
+ # Replace the existing build with the preview.
32
+ #
33
+ # @return [void]
34
+ def replace_build
35
+ build_dir.rmtree
36
+ FileUtils.move preview_dir, build_dir
37
+ end
38
+
39
+ # Output a diff of the existing build and preview.
40
+ #
41
+ # @return [void]
42
+ def show_diff
43
+ prefix = %w(git diff --no-index --patch-with-stat --)
44
+ system(*(prefix + [build_dir.to_s, preview_dir.to_s]))
45
+ end
46
+
47
+ private
48
+
49
+ # Instance of the CLI used for building
50
+ #
51
+ # @return [thor_with_preview_dir]
52
+ def build_cli
53
+ @_build_cli ||= build_cli_with_preview_dir.new
54
+ end
55
+
56
+ # A modified Middleman::Cli::Build that builds to the preview directory
57
+ #
58
+ # @return [Class]
59
+ def build_cli_with_preview_dir
60
+ current_preview_dir = preview_dir
61
+
62
+ Class.new(::Middleman::Cli::Build).tap do |klass|
63
+ klass.define_singleton_method(:shared_instance) do
64
+ @_shared_instance ||= ::Middleman::Application.server.inst do
65
+ set :build_dir, current_preview_dir
66
+ config[:environment] = :build
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ # Build into the preview directory.
73
+ #
74
+ # @return [void]
75
+ def build_preview
76
+ trigger_build_hook :before_build
77
+ build_cli.action Middleman::Cli::BuildAction.new(build_cli, {})
78
+ trigger_build_hook :after_build
79
+ end
80
+
81
+ # Directory of the existing build
82
+ #
83
+ # @return [Pathname]
84
+ def build_dir
85
+ @_build_dir ||= begin
86
+ dir = Pathname.new(@app.build_dir)
87
+
88
+ unless dir.exist?
89
+ fail Thor::Error, "There's no existing build to compare against."
90
+ end
91
+
92
+ dir
93
+ end
94
+ end
95
+
96
+ # Directory in which to build the preview
97
+ #
98
+ # @return [Pathname]
99
+ def preview_dir
100
+ @_preview_dir ||= begin
101
+ Pathname.new(Dir.mktmpdir('preview_', @temp_dir.tap(&:mkpath)))
102
+ end
103
+ end
104
+
105
+ # Run a build hook.
106
+ #
107
+ # @param name [Symbol]
108
+ # @return [void]
109
+ def trigger_build_hook(name)
110
+ return unless @build_hooks
111
+
112
+ build_cli.class.shared_instance.run_hook name, build_cli
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1 @@
1
+ require 'middleman-diff'
@@ -0,0 +1,19 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'middleman-diff'
5
+ gem.version = '0.0.1'
6
+ gem.platform = Gem::Platform::RUBY
7
+ gem.required_ruby_version = '~> 2.1'
8
+ gem.license = 'MIT'
9
+ gem.authors = ['Andrew Kvalheim']
10
+ gem.email = ['Andrew@Kvalhe.im']
11
+ gem.homepage = 'https://github.com/AndrewKvalheim/middleman-diff'
12
+ gem.summary = "Preview what's changed in your Middleman build."
13
+
14
+ gem.files = `git ls-files -z`.split("\0")
15
+ gem.test_files = gem.files.grep(/^(features|fixtures)\//)
16
+ gem.require_paths = ['lib']
17
+
18
+ gem.add_runtime_dependency 'middleman-core', '~> 3.3'
19
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: middleman-diff
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Kvalheim
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-12 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.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.3'
27
+ description:
28
+ email:
29
+ - Andrew@Kvalhe.im
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".gitignore"
35
+ - ".travis.yml"
36
+ - Gemfile
37
+ - LICENSE.md
38
+ - README.md
39
+ - Rakefile
40
+ - cucumber.yml
41
+ - features/diff.feature
42
+ - features/extension.feature
43
+ - features/hooks.feature
44
+ - features/keep.feature
45
+ - features/step_definitions/diff_steps.rb
46
+ - features/step_definitions/filesystem_steps.rb
47
+ - features/step_definitions/output_steps.rb
48
+ - features/storage.feature
49
+ - features/support/env.rb
50
+ - fixtures/inactive/.gitkeep
51
+ - fixtures/typical-modified/build/index.html
52
+ - fixtures/typical-modified/build/javascripts/main.js
53
+ - fixtures/typical-modified/build/stylesheets/main.css
54
+ - fixtures/typical-modified/config.rb
55
+ - fixtures/typical-modified/source/index.html.haml
56
+ - fixtures/typical-modified/source/javascripts/main.js.coffee
57
+ - fixtures/typical-modified/source/layouts/layout.haml
58
+ - fixtures/typical-modified/source/stylesheets/main.css.sass
59
+ - fixtures/typical/build/index.html
60
+ - fixtures/typical/build/javascripts/main.js
61
+ - fixtures/typical/build/stylesheets/main.css
62
+ - fixtures/typical/config.rb
63
+ - fixtures/typical/source/index.html.haml
64
+ - fixtures/typical/source/javascripts/main.js.coffee
65
+ - fixtures/typical/source/layouts/layout.haml
66
+ - fixtures/typical/source/stylesheets/main.css.sass
67
+ - lib/middleman-diff.rb
68
+ - lib/middleman-diff/cli.rb
69
+ - lib/middleman-diff/extension.rb
70
+ - lib/middleman-diff/preview.rb
71
+ - lib/middleman_extension.rb
72
+ - middleman-diff.gemspec
73
+ homepage: https://github.com/AndrewKvalheim/middleman-diff
74
+ licenses:
75
+ - MIT
76
+ metadata: {}
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: '2.1'
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 2.2.2
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Preview what's changed in your Middleman build.
97
+ test_files:
98
+ - features/diff.feature
99
+ - features/extension.feature
100
+ - features/hooks.feature
101
+ - features/keep.feature
102
+ - features/step_definitions/diff_steps.rb
103
+ - features/step_definitions/filesystem_steps.rb
104
+ - features/step_definitions/output_steps.rb
105
+ - features/storage.feature
106
+ - features/support/env.rb
107
+ - fixtures/inactive/.gitkeep
108
+ - fixtures/typical-modified/build/index.html
109
+ - fixtures/typical-modified/build/javascripts/main.js
110
+ - fixtures/typical-modified/build/stylesheets/main.css
111
+ - fixtures/typical-modified/config.rb
112
+ - fixtures/typical-modified/source/index.html.haml
113
+ - fixtures/typical-modified/source/javascripts/main.js.coffee
114
+ - fixtures/typical-modified/source/layouts/layout.haml
115
+ - fixtures/typical-modified/source/stylesheets/main.css.sass
116
+ - fixtures/typical/build/index.html
117
+ - fixtures/typical/build/javascripts/main.js
118
+ - fixtures/typical/build/stylesheets/main.css
119
+ - fixtures/typical/config.rb
120
+ - fixtures/typical/source/index.html.haml
121
+ - fixtures/typical/source/javascripts/main.js.coffee
122
+ - fixtures/typical/source/layouts/layout.haml
123
+ - fixtures/typical/source/stylesheets/main.css.sass
124
+ has_rdoc: