middleman 3.0.0.alpha.4 → 3.0.0.alpha.5

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.
Files changed (40) hide show
  1. data/.gitignore +1 -0
  2. data/.yardopts +7 -3
  3. data/CHANGELOG.md +4 -1
  4. data/bin/middleman +10 -24
  5. data/features/3rd_party_cli.feature +5 -0
  6. data/features/builder.feature +43 -25
  7. data/features/chained_templates.feature +8 -4
  8. data/features/clean_build.feature +24 -13
  9. data/features/cli.feature +121 -0
  10. data/features/coffee-script.feature +1 -1
  11. data/features/custom_layout_engines.feature +5 -2
  12. data/features/directory_index.feature +17 -10
  13. data/features/dynamic_pages.feature +11 -8
  14. data/features/fonts.feature +5 -2
  15. data/features/sprockets.feature +4 -2
  16. data/fixtures/3rd-party-command/config.rb +10 -0
  17. data/lib/middleman.rb +19 -12
  18. data/lib/middleman/base.rb +19 -5
  19. data/lib/middleman/cli.rb +36 -112
  20. data/lib/middleman/{builder.rb → cli/build.rb} +60 -51
  21. data/lib/middleman/cli/init.rb +47 -0
  22. data/lib/middleman/cli/server.rb +41 -0
  23. data/lib/middleman/core_extensions/assets.rb +1 -0
  24. data/lib/middleman/core_extensions/builder.rb +18 -0
  25. data/lib/middleman/core_extensions/compass.rb +6 -1
  26. data/lib/middleman/core_extensions/data.rb +66 -2
  27. data/lib/middleman/core_extensions/sprockets.rb +0 -1
  28. data/lib/middleman/guard.rb +41 -29
  29. data/lib/middleman/step_definitions.rb +7 -1
  30. data/lib/middleman/step_definitions/builder_steps.rb +22 -30
  31. data/lib/middleman/step_definitions/middleman_steps.rb +2 -0
  32. data/lib/middleman/templates.rb +12 -4
  33. data/lib/middleman/templates/default.rb +3 -1
  34. data/lib/middleman/templates/html5.rb +3 -1
  35. data/lib/middleman/templates/local.rb +5 -3
  36. data/lib/middleman/templates/mobile.rb +3 -1
  37. data/lib/middleman/version.rb +5 -1
  38. data/middleman-x86-mingw32.gemspec +11 -10
  39. data/middleman.gemspec +7 -11
  40. metadata +49 -44
@@ -0,0 +1,47 @@
1
+ module Middleman::Cli
2
+ class Init < Thor
3
+ check_unknown_options!
4
+
5
+ namespace :init
6
+
7
+ desc "init NAME [options]", "Create new project NAME"
8
+ available_templates = ::Middleman::Templates.registered.keys.join(", ")
9
+ # argument :name
10
+ method_option "template",
11
+ :aliases => "-T",
12
+ :default => "default",
13
+ :desc => "Use a project template: #{available_templates}"
14
+ method_option "css_dir",
15
+ :default => "stylesheets",
16
+ :desc => 'The path to the css files'
17
+ method_option "js_dir",
18
+ :default => "javascripts",
19
+ :desc => 'The path to the javascript files'
20
+ method_option "images_dir",
21
+ :default => "images",
22
+ :desc => 'The path to the image files'
23
+ method_option "rack",
24
+ :type => :boolean,
25
+ :default => false,
26
+ :desc => 'Include a config.ru file'
27
+ method_option "bundler",
28
+ :type => :boolean,
29
+ :default => false,
30
+ :desc => 'Create a Gemfile and use Bundler to manage gems'
31
+ def init(name)
32
+ key = options[:template].to_sym
33
+ unless ::Middleman::Templates.registered.has_key?(key)
34
+ raise Thor::Error.new "Unknown project template '#{key}'"
35
+ end
36
+
37
+ thor_group = ::Middleman::Templates.registered[key]
38
+ thor_group.new([name], options).invoke_all
39
+ end
40
+ end
41
+
42
+ Base.map({
43
+ "i" => "init",
44
+ "new" => "init",
45
+ "n" => "init"
46
+ })
47
+ end
@@ -0,0 +1,41 @@
1
+ module Middleman::Cli
2
+ class Server < Thor
3
+ check_unknown_options!
4
+
5
+ namespace :server
6
+
7
+ desc "server [options]", "Start the preview server"
8
+ method_option "environment",
9
+ :aliases => "-e",
10
+ :default => ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development',
11
+ :desc => "The environment Middleman will run under"
12
+ method_option :host,
13
+ :type => :string,
14
+ :aliases => "-h",
15
+ # :required => true,
16
+ :default => "0.0.0.0",
17
+ :desc => "Bind to HOST address"
18
+ method_option "port",
19
+ :aliases => "-p",
20
+ :default => "4567",
21
+ :desc => "The port Middleman will listen on"
22
+ method_option "debug",
23
+ :type => :boolean,
24
+ :default => false,
25
+ :desc => 'Print debug messages'
26
+ def server
27
+ params = {
28
+ :port => options["port"],
29
+ :host => options["host"],
30
+ :environment => options["environment"],
31
+ :debug => options["debug"]
32
+ }
33
+
34
+ puts "== The Middleman is loading"
35
+ Middleman::Guard.start(params)
36
+ end
37
+ end
38
+
39
+ Base.map({ "s" => "server" })
40
+ Base.default_task :server
41
+ end
@@ -21,6 +21,7 @@ module Middleman::CoreExtensions::Assets
21
21
  #
22
22
  # @param [String] path The path (such as "photo.jpg")
23
23
  # @param [String] prefix The type prefix (such as "images")
24
+ # @return [String] The fully qualified asset url
24
25
  def asset_url(path, prefix="")
25
26
  # Don't touch assets which already have a full path
26
27
  path.include?("://") ? path : File.join(http_prefix, prefix, path)
@@ -1,13 +1,22 @@
1
+ # Convenience methods to allow config.rb to talk to the Builder
1
2
  module Middleman::CoreExtensions::Builder
3
+
4
+ # Extension registered
2
5
  class << self
6
+ # @private
3
7
  def registered(app)
4
8
  app.define_hook :after_build
5
9
  app.extend ClassMethods
6
10
  app.send :include, InstanceMethods
7
11
  end
12
+ alias :included :registered
8
13
  end
9
14
 
15
+ # Build Class Methods
10
16
  module ClassMethods
17
+ # Get a list of callbacks which can modify a files build path
18
+ #
19
+ # @return [Array<Proc>]
11
20
  def build_reroute(&block)
12
21
  @build_rerouters ||= []
13
22
  @build_rerouters << block if block_given?
@@ -15,11 +24,20 @@ module Middleman::CoreExtensions::Builder
15
24
  end
16
25
  end
17
26
 
27
+ # Build Instance Methods
18
28
  module InstanceMethods
29
+ # Forward to class method
30
+ #
31
+ # @return [Array<Proc>]
19
32
  def build_reroute(&block)
20
33
  self.class.build_reroute(&block)
21
34
  end
22
35
 
36
+ # Run through callbacks and get the new values
37
+ #
38
+ # @param [String] destination The current destination of the built file
39
+ # @param [String] request_path The current request path of the file
40
+ # @return [Array<String>] The new values
23
41
  def reroute_builder(destination, request_path)
24
42
  result = [destination, request_path]
25
43
 
@@ -1,5 +1,10 @@
1
+ # Forward the settings on config.rb and the result of registered extensions
2
+ # to Compass
1
3
  module Middleman::CoreExtensions::Compass
4
+
5
+ # Extension registered
2
6
  class << self
7
+ # @private
3
8
  def registered(app)
4
9
  require "compass"
5
10
 
@@ -47,7 +52,7 @@ module Middleman::CoreExtensions::Compass
47
52
  config.output_style = :nested
48
53
  end
49
54
 
50
- # Required for relative paths
55
+ # Change paths when in build mode. Required for relative paths
51
56
  configure :build do
52
57
  ::Compass.configuration do |config|
53
58
  config.environment = :production
@@ -1,9 +1,17 @@
1
+ # Data formats
1
2
  require "yaml"
2
3
  require "active_support/json"
4
+
5
+ # Using Thor's indifferent hash access
3
6
  require "thor"
4
7
 
8
+ # The data extension parses YAML and JSON files in the data/ directory
9
+ # and makes them available to config.rb, templates and extensions
5
10
  module Middleman::CoreExtensions::Data
11
+
12
+ # Extension registered
6
13
  class << self
14
+ # @private
7
15
  def registered(app)
8
16
  app.set :data_dir, "data"
9
17
  app.send :include, InstanceMethods
@@ -11,7 +19,10 @@ module Middleman::CoreExtensions::Data
11
19
  alias :included :registered
12
20
  end
13
21
 
22
+ # Instance methods
14
23
  module InstanceMethods
24
+ # Setup data files before anything else so they are available when
25
+ # parsing config.rb
15
26
  def initialize
16
27
  file_changed DataStore.matcher do |file|
17
28
  data.touch_file(file) if file.match(%r{^#{data_dir}\/})
@@ -24,43 +35,77 @@ module Middleman::CoreExtensions::Data
24
35
  super
25
36
  end
26
37
 
38
+ # The data object
39
+ #
40
+ # @return [DataStore]
27
41
  def data
28
42
  @data ||= DataStore.new(self)
29
43
  end
30
44
 
31
45
  # Makes a hash available on the data var with a given name
46
+ #
47
+ # @param [Symbol] name Name of the data, used for namespacing
48
+ # @param [Hash] content The content for this data
49
+ # @return [void]
32
50
  def data_content(name, content)
33
51
  DataStore.data_content(name, content)
34
52
  end
35
53
 
36
54
  # Makes a hash available on the data var with a given name
55
+ #
56
+ # @param [Symbol] name Name of the data, used for namespacing
57
+ # @return [void]
37
58
  def data_callback(name, &block)
38
59
  DataStore.data_callback(name, block)
39
60
  end
40
61
  end
41
62
 
63
+ # The core logic behind the data extension.
42
64
  class DataStore
65
+
66
+ # Static methods
43
67
  class << self
68
+
69
+ # The regex which tells Middleman which files are for data
70
+ #
71
+ # @return [Regexp]
44
72
  def matcher
45
73
  %r{[\w-]+\.(yml|yaml|json)$}
46
74
  end
47
75
 
76
+ # Store static data hash
77
+ #
78
+ # @param [Symbol] name Name of the data, used for namespacing
79
+ # @param [Hash] content The content for this data
80
+ # @return [void]
48
81
  def data_content(name, content)
49
82
  @@local_sources ||= {}
50
83
  @@local_sources[name.to_s] = content
51
84
  end
52
85
 
86
+ # Store callback-based data
87
+ #
88
+ # @param [Symbol] name Name of the data, used for namespacing
89
+ # @param [Proc] proc The callback which will return data
90
+ # @return [void]
53
91
  def data_callback(name, proc)
54
92
  @@callback_sources ||= {}
55
93
  @@callback_sources[name.to_s] = proc
56
94
  end
57
95
  end
58
96
 
97
+ # Setup data store
98
+ #
99
+ # @param [Middleman::Base] app The current instance of Middleman
59
100
  def initialize(app)
60
101
  @app = app
61
102
  @local_data = {}
62
103
  end
63
104
 
105
+ # Update the internal cache for a given file path
106
+ #
107
+ # @param [String] file The file to be re-parsed
108
+ # @return [void]
64
109
  def touch_file(file)
65
110
  file = File.expand_path(file, @app.root)
66
111
  extension = File.extname(file)
@@ -74,16 +119,23 @@ module Middleman::CoreExtensions::Data
74
119
  return
75
120
  end
76
121
 
77
- # @app.logger.debug :data_update, Time.now, basename if @app.logging?
78
122
  @local_data[basename] = recursively_enhance(data)
79
123
  end
80
124
 
125
+ # Remove a given file from the internal cache
126
+ #
127
+ # @param [String] file The file to be cleared
128
+ # @return [void]
81
129
  def remove_file(file)
82
130
  extension = File.extname(file)
83
131
  basename = File.basename(file, extension)
84
132
  @local_data.delete(basename) if @local_data.has_key?(basename)
85
133
  end
86
134
 
135
+ # Get a hash hash from either internal static data or a callback
136
+ #
137
+ # @param [String, Symbol] path The name of the data namespace
138
+ # @return [Hash, nil]
87
139
  def data_for_path(path)
88
140
  response = nil
89
141
 
@@ -99,6 +151,10 @@ module Middleman::CoreExtensions::Data
99
151
  response
100
152
  end
101
153
 
154
+ # "Magically" find namespaces of data if they exist
155
+ #
156
+ # @param [String] path The namespace to search for
157
+ # @return [Hash, nil]
102
158
  def method_missing(path)
103
159
  if @local_data.has_key?(path.to_s)
104
160
  return @local_data[path.to_s]
@@ -113,6 +169,9 @@ module Middleman::CoreExtensions::Data
113
169
  super
114
170
  end
115
171
 
172
+ # Convert all the data into a static hash
173
+ #
174
+ # @return [Hash]
116
175
  def to_h
117
176
  data = {}
118
177
 
@@ -134,7 +193,12 @@ module Middleman::CoreExtensions::Data
134
193
  data
135
194
  end
136
195
 
137
- private
196
+ private
197
+ # Recursively convert a normal Hash into a HashWithIndifferentAccess
198
+ #
199
+ # @private
200
+ # @param [Hash] data Normal hash
201
+ # @return [Thor::CoreExt::HashWithIndifferentAccess]
138
202
  def recursively_enhance(data)
139
203
  if data.is_a? Hash
140
204
  data = Thor::CoreExt::HashWithIndifferentAccess.new(data)
@@ -1,5 +1,4 @@
1
1
  require 'pathname'
2
- require 'rbconfig'
3
2
  require "sprockets"
4
3
 
5
4
  module Middleman::CoreExtensions::Sprockets
@@ -6,8 +6,7 @@ require "guard/guard"
6
6
  require "net/http"
7
7
 
8
8
  # Support forking on Windows
9
- require "rbconfig"
10
- require "win32/process" if RbConfig::CONFIG['host_os'].downcase =~ %r{mingw}
9
+ require "win32/process" if Middleman::WINDOWS
11
10
 
12
11
  module Middleman::Guard
13
12
  def self.start(options={})
@@ -21,7 +20,8 @@ module Middleman::Guard
21
20
  watch(%r{(.*)})
22
21
  end
23
22
  },
24
- :watch_all_modifications => true
23
+ :watch_all_modifications => true,
24
+ :no_interactions => true
25
25
  })
26
26
  end
27
27
  end
@@ -41,36 +41,50 @@ module Guard
41
41
  def initialize(watchers = [], options = {})
42
42
  super
43
43
  @options = options
44
+
45
+ # Trap the interupt signal and shut down Guard (and thus the server) smoothly
46
+ trap(kill_command) do
47
+ ::Guard.stop
48
+ exit!(0)
49
+ end
44
50
  end
45
51
 
46
52
  # Start Middleman in a fork
47
53
  def start
48
- @server_job = fork do
49
- env = (@options[:environment] || "development").to_sym
50
- is_logging = @options.has_key?(:debug) && (@options[:debug] == "true")
51
- app = ::Middleman.server.inst do
52
- set :environment, env
53
- set :logging, is_logging
54
- end
55
-
56
- require "thin"
57
- ::Thin::Logging.silent = !is_logging
58
-
59
- app_rack = app.class.to_rack_app
60
-
61
- opts = @options.dup
62
- opts[:app] = app_rack
63
- puts "== The Middleman is standing watch on port #{opts[:port]||4567}"
64
- ::Middleman.start_server(opts)
54
+ if ::Middleman::JRUBY
55
+ thread = Thread.new { bootup }
56
+ thread.join
57
+ else
58
+ @server_job = fork { bootup }
65
59
  end
66
60
  end
67
61
 
62
+ def bootup
63
+ env = (@options[:environment] || "development").to_sym
64
+ is_logging = @options.has_key?(:debug) && (@options[:debug] == "true")
65
+ app = ::Middleman.server.inst do
66
+ set :environment, env
67
+ set :logging, is_logging
68
+ end
69
+
70
+ app_rack = app.class.to_rack_app
71
+
72
+ opts = @options.dup
73
+ opts[:app] = app_rack
74
+ opts[:logging] = is_logging
75
+ puts "== The Middleman is standing watch on port #{opts[:port]||4567}"
76
+ ::Middleman.start_server(opts)
77
+ end
78
+
68
79
  # Stop the forked Middleman
69
80
  def stop
70
81
  puts "== The Middleman is shutting down"
71
- Process.kill("KILL", @server_job)
72
- Process.wait @server_job
73
- @server_job = nil
82
+ if ::Middleman::JRUBY
83
+ else
84
+ Process.kill(kill_command, @server_job)
85
+ Process.wait @server_job
86
+ @server_job = nil
87
+ end
74
88
  end
75
89
 
76
90
  # Simply stop, then start
@@ -115,11 +129,9 @@ module Guard
115
129
  uri = URI.parse("http://#{@options[:host]}:#{@options[:port]}/__middleman__")
116
130
  Net::HTTP.post_form(uri, {}.merge(params))
117
131
  end
132
+
133
+ def kill_command
134
+ ::Middleman::WINDOWS ? 1 : :INT
135
+ end
118
136
  end
119
- end
120
-
121
- # Trap the interupt signal and shut down Guard (and thus the server) smoothly
122
- trap(:INT) do
123
- ::Guard.stop
124
- exit
125
137
  end
@@ -1,7 +1,13 @@
1
1
  MIDDLEMAN_ROOT_PATH = File.dirname(File.dirname(File.dirname(__FILE__)))
2
2
  MIDDLEMAN_BIN_PATH = File.join(MIDDLEMAN_ROOT_PATH, "bin")
3
+ ENV['PATH'] = "#{MIDDLEMAN_BIN_PATH}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
3
4
 
5
+ require "aruba/cucumber"
4
6
  require "middleman/step_definitions/middleman_steps"
5
7
  require "middleman/step_definitions/builder_steps"
6
8
  require "middleman/step_definitions/generator_steps"
7
- require "middleman/step_definitions/server_steps"
9
+ require "middleman/step_definitions/server_steps"
10
+
11
+ Before do
12
+ @aruba_timeout_seconds = 30
13
+ end