sitemap works, tests pass
This commit is contained in:
parent
41a5d9bbee
commit
b5561227f8
32 changed files with 305 additions and 250 deletions
|
@ -1,6 +1,8 @@
|
||||||
2.1.pre
|
2.1.pre
|
||||||
====
|
====
|
||||||
Finally support Compass in Sprockets! Thanks to @xdite and @petebrowne
|
Finally support Compass in Sprockets! Thanks to @xdite and @petebrowne
|
||||||
|
Middleman::Sitemap object representing the known world
|
||||||
|
Middleman::FileWatcher proxies file change events
|
||||||
|
|
||||||
2.0.14
|
2.0.14
|
||||||
====
|
====
|
||||||
|
|
|
@ -15,15 +15,12 @@ Feature: Builder
|
||||||
Then "spaces in file.html" should exist at "test-app" and include "spaces"
|
Then "spaces in file.html" should exist at "test-app" and include "spaces"
|
||||||
Then "images/Read me (example).txt" should exist at "test-app"
|
Then "images/Read me (example).txt" should exist at "test-app"
|
||||||
Then "images/Child folder/regular_file(example).txt" should exist at "test-app"
|
Then "images/Child folder/regular_file(example).txt" should exist at "test-app"
|
||||||
And cleanup built app at "test-app"
|
|
||||||
|
|
||||||
Scenario: Build glob
|
Scenario: Build glob
|
||||||
Given a built app at "glob-app" with flags "--glob '**/*.sass'"
|
Given a built app at "glob-app" with flags "--glob '*.css'"
|
||||||
Then "stylesheets/site.css" should exist at "glob-app" and include "html"
|
Then "stylesheets/site.css" should exist at "glob-app" and include "html"
|
||||||
Then "index.html" should not exist at "glob-app"
|
Then "index.html" should not exist at "glob-app"
|
||||||
And cleanup built app at "glob-app"
|
|
||||||
|
|
||||||
# Scenario: Force relative assets
|
# Scenario: Force relative assets
|
||||||
# Given a built app at "relative-app" with flags "--relative"
|
# Given a built app at "relative-app" with flags "--relative"
|
||||||
# Then "stylesheets/relative_assets.css" should exist at "relative-app" and include "../"
|
# Then "stylesheets/relative_assets.css" should exist at "relative-app" and include "../"
|
||||||
# And cleanup built app at "relative-app"
|
|
|
@ -7,4 +7,3 @@ Feature: Build Clean
|
||||||
Then "should_be_ignored.html" should not exist at "clean-app"
|
Then "should_be_ignored.html" should not exist at "clean-app"
|
||||||
And "should_be_ignored2.html" should not exist at "clean-app"
|
And "should_be_ignored2.html" should not exist at "clean-app"
|
||||||
And "should_be_ignored3.html" should not exist at "clean-app"
|
And "should_be_ignored3.html" should not exist at "clean-app"
|
||||||
And cleanup built app at "clean-app"
|
|
|
@ -11,7 +11,6 @@ Feature: Directory Index
|
||||||
Then "needs_index.html" should not exist at "indexable-app"
|
Then "needs_index.html" should not exist at "indexable-app"
|
||||||
Then "a_folder/needs_index.html" should not exist at "indexable-app"
|
Then "a_folder/needs_index.html" should not exist at "indexable-app"
|
||||||
Then "leave_me_alone/index.html" should not exist at "indexable-app"
|
Then "leave_me_alone/index.html" should not exist at "indexable-app"
|
||||||
And cleanup built app at "indexable-app"
|
|
||||||
|
|
||||||
Scenario: Preview normal file
|
Scenario: Preview normal file
|
||||||
Given the Server is running at "indexable-app"
|
Given the Server is running at "indexable-app"
|
||||||
|
|
|
@ -10,7 +10,6 @@ Feature: Dynamic Pages
|
||||||
Then "should_be_ignored.html" should not exist at "test-app"
|
Then "should_be_ignored.html" should not exist at "test-app"
|
||||||
Then "should_be_ignored2.html" should not exist at "test-app"
|
Then "should_be_ignored2.html" should not exist at "test-app"
|
||||||
Then "should_be_ignored3.html" should not exist at "test-app"
|
Then "should_be_ignored3.html" should not exist at "test-app"
|
||||||
And cleanup built app at "test-app"
|
|
||||||
|
|
||||||
Scenario: Preview basic proxy
|
Scenario: Preview basic proxy
|
||||||
Given the Server is running at "test-app"
|
Given the Server is running at "test-app"
|
||||||
|
|
|
@ -3,7 +3,6 @@ Feature: Web Fonts
|
||||||
Scenario: Checking built folder for content
|
Scenario: Checking built folder for content
|
||||||
Given a built app at "fonts-app"
|
Given a built app at "fonts-app"
|
||||||
Then "stylesheets/fonts.css" should exist at "fonts-app" and include "/fonts/StMarie-Thin.otf"
|
Then "stylesheets/fonts.css" should exist at "fonts-app" and include "/fonts/StMarie-Thin.otf"
|
||||||
And cleanup built app at "fonts-app"
|
|
||||||
|
|
||||||
Scenario: Rendering scss
|
Scenario: Rendering scss
|
||||||
Given the Server is running at "fonts-app"
|
Given the Server is running at "fonts-app"
|
||||||
|
|
|
@ -23,7 +23,6 @@ Feature: Sprockets
|
||||||
Scenario: Multiple engine files should build correctly
|
Scenario: Multiple engine files should build correctly
|
||||||
Given a built app at "test-app"
|
Given a built app at "test-app"
|
||||||
Then "javascripts/multiple_engines.js" should exist at "test-app" and include "Hello One"
|
Then "javascripts/multiple_engines.js" should exist at "test-app" and include "Hello One"
|
||||||
And cleanup built app at "test-app"
|
|
||||||
|
|
||||||
Scenario: Sprockets CSS require //require
|
Scenario: Sprockets CSS require //require
|
||||||
Given the Server is running at "test-app"
|
Given the Server is running at "test-app"
|
||||||
|
|
|
@ -11,6 +11,10 @@ end
|
||||||
Given /^a built app at "([^"]*)"$/ do |path|
|
Given /^a built app at "([^"]*)"$/ do |path|
|
||||||
root = File.dirname(File.dirname(File.dirname(__FILE__)))
|
root = File.dirname(File.dirname(File.dirname(__FILE__)))
|
||||||
target = File.join(root, "fixtures", path)
|
target = File.join(root, "fixtures", path)
|
||||||
|
|
||||||
|
build_target = File.join(target, "build")
|
||||||
|
FileUtils.rm_rf(build_target)
|
||||||
|
|
||||||
build_cmd = File.expand_path(File.join(root, "bin", "middleman build"))
|
build_cmd = File.expand_path(File.join(root, "bin", "middleman build"))
|
||||||
`cd #{target} && #{build_cmd}`
|
`cd #{target} && #{build_cmd}`
|
||||||
end
|
end
|
||||||
|
|
1
fixtures/clean-app/build/fake.html
Normal file
1
fixtures/clean-app/build/fake.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
I am real
|
5
fixtures/clean-app/build/fake/one.html
Normal file
5
fixtures/clean-app/build/fake/one.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
layout: false
|
||||||
|
---
|
||||||
|
|
||||||
|
I am real: one
|
5
fixtures/clean-app/build/fake/two.html
Normal file
5
fixtures/clean-app/build/fake/two.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
layout: false
|
||||||
|
---
|
||||||
|
|
||||||
|
I am real: two
|
12
fixtures/clean-app/build/index.html
Normal file
12
fixtures/clean-app/build/index.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>My Sample Site</title>
|
||||||
|
<!-- Comment in layout -->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Welcome</h1>
|
||||||
|
<h2 id='h2'>H2</h2>
|
||||||
|
|
||||||
|
<p>Paragraph</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
1
fixtures/clean-app/build/real.html
Normal file
1
fixtures/clean-app/build/real.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
I am real
|
5
fixtures/clean-app/build/real/index.html
Normal file
5
fixtures/clean-app/build/real/index.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
layout: false
|
||||||
|
---
|
||||||
|
|
||||||
|
I am real:
|
1
fixtures/clean-app/build/static.html
Normal file
1
fixtures/clean-app/build/static.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Static, no code!
|
1
fixtures/clean-app/build/target_ignore.html
Normal file
1
fixtures/clean-app/build/target_ignore.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<h1>Ignore me! 3</h1>
|
BIN
fixtures/fonts-app/build/fonts/StMarie-Thin.otf
Normal file
BIN
fixtures/fonts-app/build/fonts/StMarie-Thin.otf
Normal file
Binary file not shown.
3
fixtures/fonts-app/build/stylesheets/fonts.css
Normal file
3
fixtures/fonts-app/build/stylesheets/fonts.css
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
@font-face {
|
||||||
|
font-family: "St Marie";
|
||||||
|
src: url('/fonts/StMarie-Thin.otf') format('opentype'); }
|
46
fixtures/glob-app/build/stylesheets/site.css
Normal file
46
fixtures/glob-app/build/stylesheets/site.css
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
html, body, div, span, applet, object, iframe,
|
||||||
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
|
a, abbr, acronym, address, big, cite, code,
|
||||||
|
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||||
|
small, strike, strong, sub, sup, tt, var,
|
||||||
|
b, u, i, center,
|
||||||
|
dl, dt, dd, ol, ul, li,
|
||||||
|
fieldset, form, label, legend,
|
||||||
|
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||||
|
article, aside, canvas, details, embed,
|
||||||
|
figure, figcaption, footer, header, hgroup,
|
||||||
|
menu, nav, output, ruby, section, summary,
|
||||||
|
time, mark, audio, video {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
font: inherit;
|
||||||
|
vertical-align: baseline; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
line-height: 1; }
|
||||||
|
|
||||||
|
ol, ul {
|
||||||
|
list-style: none; }
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0; }
|
||||||
|
|
||||||
|
caption, th, td {
|
||||||
|
text-align: left;
|
||||||
|
font-weight: normal;
|
||||||
|
vertical-align: middle; }
|
||||||
|
|
||||||
|
q, blockquote {
|
||||||
|
quotes: none; }
|
||||||
|
q:before, q:after, blockquote:before, blockquote:after {
|
||||||
|
content: "";
|
||||||
|
content: none; }
|
||||||
|
|
||||||
|
a img {
|
||||||
|
border: none; }
|
||||||
|
|
||||||
|
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary {
|
||||||
|
display: block; }
|
|
@ -0,0 +1 @@
|
||||||
|
Indexable
|
1
fixtures/indexable-app/build/leave_me_alone.html
Normal file
1
fixtures/indexable-app/build/leave_me_alone.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Stay away
|
1
fixtures/indexable-app/build/needs_index/index.html
Normal file
1
fixtures/indexable-app/build/needs_index/index.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Indexable
|
1
fixtures/indexable-app/build/regular/index.html
Normal file
1
fixtures/indexable-app/build/regular/index.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Regular
|
|
@ -61,12 +61,11 @@ require "sinatra/base"
|
||||||
# Top-level Middleman object
|
# Top-level Middleman object
|
||||||
module Middleman
|
module Middleman
|
||||||
# Auto-load modules on-demand
|
# Auto-load modules on-demand
|
||||||
autoload :Base, "middleman/base"
|
autoload :Base, "middleman/base"
|
||||||
autoload :Sitemap, "middleman/sitemap"
|
autoload :Builder, "middleman/builder"
|
||||||
autoload :Builder, "middleman/builder"
|
autoload :CLI, "middleman/cli"
|
||||||
autoload :CLI, "middleman/cli"
|
autoload :Templates, "middleman/templates"
|
||||||
autoload :Templates, "middleman/templates"
|
autoload :Guard, "middleman/guard"
|
||||||
autoload :Guard, "middleman/guard"
|
|
||||||
|
|
||||||
# Custom Renderers
|
# Custom Renderers
|
||||||
module Renderers
|
module Renderers
|
||||||
|
@ -80,6 +79,11 @@ module Middleman
|
||||||
end
|
end
|
||||||
|
|
||||||
module CoreExtensions
|
module CoreExtensions
|
||||||
|
# Guard Proxy
|
||||||
|
autoload :FileWatcher, "middleman/core_extensions/file_watcher"
|
||||||
|
|
||||||
|
autoload :Sitemap, "middleman/core_extensions/sitemap"
|
||||||
|
|
||||||
# Add Builder callbacks
|
# Add Builder callbacks
|
||||||
autoload :Builder, "middleman/core_extensions/builder"
|
autoload :Builder, "middleman/core_extensions/builder"
|
||||||
|
|
||||||
|
@ -187,13 +191,14 @@ module Middleman
|
||||||
:AccessLog => []
|
:AccessLog => []
|
||||||
}
|
}
|
||||||
|
|
||||||
app = ::Middleman.server
|
app_class = options[:app] ||= ::Middleman.server
|
||||||
app.set :environment, options[:environment].to_sym
|
app_class.set :environment, options[:environment].to_sym
|
||||||
opts[:app] = app.new
|
opts[:app] = app_class.new
|
||||||
opts[:server] = 'thin'
|
opts[:server] = 'thin'
|
||||||
|
|
||||||
$stderr.puts "== The Middleman is standing watch on port #{opts[:Port]}"
|
server = ::Rack::Server.new(opts)
|
||||||
::Rack::Server.new(opts).start
|
server.start
|
||||||
|
server
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,12 @@ module Middleman::Base
|
||||||
|
|
||||||
app.set :views, "source"
|
app.set :views, "source"
|
||||||
|
|
||||||
|
# Add Builder Callbacks
|
||||||
|
app.register Middleman::CoreExtensions::FileWatcher
|
||||||
|
|
||||||
|
# Sitemap
|
||||||
|
app.register Middleman::CoreExtensions::Sitemap
|
||||||
|
|
||||||
# Add Builder Callbacks
|
# Add Builder Callbacks
|
||||||
app.register Middleman::CoreExtensions::Builder
|
app.register Middleman::CoreExtensions::Builder
|
||||||
|
|
||||||
|
@ -92,7 +98,8 @@ module Middleman::Base
|
||||||
# See if Tilt cannot handle this file
|
# See if Tilt cannot handle this file
|
||||||
app.before_processing(:base) do |result|
|
app.before_processing(:base) do |result|
|
||||||
request_path = request.path_info.gsub("%20", " ")
|
request_path = request.path_info.gsub("%20", " ")
|
||||||
should_be_ignored = !(request["is_proxy"]) && settings.excluded_paths.include?("/#{request_path}")
|
|
||||||
|
should_be_ignored = !(request["is_proxy"]) && settings.sitemap.ignored_path?("/#{request_path}")
|
||||||
|
|
||||||
if result && !should_be_ignored
|
if result && !should_be_ignored
|
||||||
extensionless_path, template_engine = result
|
extensionless_path, template_engine = result
|
||||||
|
|
|
@ -12,9 +12,6 @@ module Middleman
|
||||||
config = args.last.is_a?(Hash) ? args.pop : {}
|
config = args.last.is_a?(Hash) ? args.pop : {}
|
||||||
destination = args.first || source
|
destination = args.first || source
|
||||||
|
|
||||||
# source = File.expand_path(find_in_source_paths(source.to_s))
|
|
||||||
# context = instance_eval('binding')
|
|
||||||
|
|
||||||
request_path = destination.sub(/^#{SHARED_SERVER.build_dir}/, "")
|
request_path = destination.sub(/^#{SHARED_SERVER.build_dir}/, "")
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
@ -23,62 +20,12 @@ module Middleman
|
||||||
request_path.gsub!(/\s/, "%20")
|
request_path.gsub!(/\s/, "%20")
|
||||||
response = Middleman::Builder.shared_rack.get(request_path)
|
response = Middleman::Builder.shared_rack.get(request_path)
|
||||||
|
|
||||||
dequeue_file_from destination if cleaning?
|
|
||||||
|
|
||||||
create_file destination, nil, config do
|
create_file destination, nil, config do
|
||||||
response.body
|
response.body
|
||||||
end if response.status == 200
|
end if response.status == 200
|
||||||
rescue
|
rescue
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def clean!(destination)
|
|
||||||
return unless cleaning?
|
|
||||||
queue_current_paths_from destination
|
|
||||||
add_clean_up_callback
|
|
||||||
end
|
|
||||||
|
|
||||||
def cleaning?
|
|
||||||
options.has_key?("clean") && options["clean"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_clean_up_callback
|
|
||||||
clean_up_callback = lambda do
|
|
||||||
files = @cleaning_queue.select { |q| File.file? q }
|
|
||||||
directories = @cleaning_queue.select { |q| File.directory? q }
|
|
||||||
|
|
||||||
files.each { |f| remove_file f, :force => true }
|
|
||||||
|
|
||||||
directories = directories.sort_by {|d| d.length }.reverse!
|
|
||||||
|
|
||||||
directories.each do |d|
|
|
||||||
remove_file d, :force => true if directory_empty? d
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.class.after_run :clean_up_callback do
|
|
||||||
clean_up_callback.call
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def directory_empty?(directory)
|
|
||||||
Dir["#{directory}/*"].empty?
|
|
||||||
end
|
|
||||||
|
|
||||||
def queue_current_paths_from(destination)
|
|
||||||
@cleaning_queue = []
|
|
||||||
Find.find(destination) do |path|
|
|
||||||
next if path.match(/\/\./)
|
|
||||||
unless path == destination
|
|
||||||
@cleaning_queue << path.sub(destination, destination[/([^\/]+?)$/])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def dequeue_file_from(destination)
|
|
||||||
@cleaning_queue.delete_if {|q| q == destination }
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Builder < Thor::Group
|
class Builder < Thor::Group
|
||||||
|
@ -114,15 +61,11 @@ module Middleman
|
||||||
def build_all_files
|
def build_all_files
|
||||||
self.class.shared_rack
|
self.class.shared_rack
|
||||||
|
|
||||||
if options.has_key?("glob")
|
opts = { }
|
||||||
action GlobAction.new(self, SHARED_SERVER.views, SHARED_SERVER.build_dir, { :force => true, :glob => options["glob"] })
|
opts[:glob] = options["glob"] if options.has_key?("glob")
|
||||||
else
|
opts[:clean] = options["clean"] if options.has_key?("clean")
|
||||||
action DirectoryAction.new(self, SHARED_SERVER.views, SHARED_SERVER.build_dir, { :force => true })
|
|
||||||
|
|
||||||
SHARED_SERVER.proxied_paths.each do |url, proxy|
|
action GlobAction.new(self, SHARED_SERVER, opts)
|
||||||
tilt_template(url.gsub(/^\//, "#{SHARED_SERVER.build_dir}/"), { :force => true })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@hooks = {}
|
@@hooks = {}
|
||||||
|
@ -143,18 +86,23 @@ module Middleman
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class BaseAction < ::Thor::Actions::EmptyDirectory
|
class GlobAction < ::Thor::Actions::EmptyDirectory
|
||||||
attr_reader :source
|
attr_reader :source
|
||||||
|
|
||||||
def initialize(base, source, destination=nil, config={}, &block)
|
def initialize(base, app, config={}, &block)
|
||||||
|
@app = app
|
||||||
|
source = @app.views
|
||||||
|
@destination = @app.build_dir
|
||||||
|
|
||||||
@source = File.expand_path(base.find_in_source_paths(source.to_s))
|
@source = File.expand_path(base.find_in_source_paths(source.to_s))
|
||||||
@block = block
|
|
||||||
super(base, destination, { :recursive => true }.merge(config))
|
super(base, destination, config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def invoke!
|
def invoke!
|
||||||
base.clean! destination
|
queue_current_paths if cleaning?
|
||||||
execute!
|
execute!
|
||||||
|
clean! if cleaning?
|
||||||
end
|
end
|
||||||
|
|
||||||
def revoke!
|
def revoke!
|
||||||
|
@ -162,94 +110,75 @@ module Middleman
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
def handle_path(file_source)
|
|
||||||
# Skip partials prefixed with an underscore while still handling files prefixed with 2 consecutive underscores
|
|
||||||
return unless file_source.gsub(SHARED_SERVER.root, '').split('/').select { |p| p[/^_[^_]/] }.empty?
|
|
||||||
|
|
||||||
file_extension = File.extname(file_source)
|
def clean!
|
||||||
file_destination = File.join(given_destination, file_source.gsub(source, '.'))
|
files = @cleaning_queue.select { |q| File.file? q }
|
||||||
file_destination.gsub!('/./', '/')
|
directories = @cleaning_queue.select { |q| File.directory? q }
|
||||||
|
|
||||||
handled_by_tilt = ::Tilt.mappings.has_key?(file_extension.gsub(/^\./, ""))
|
files.each do |f|
|
||||||
if handled_by_tilt
|
base.remove_file f, :force => true
|
||||||
file_destination.gsub!(file_extension, "")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
destination = base.tilt_template(file_source, file_destination, config, &@block)
|
directories = directories.sort_by {|d| d.length }.reverse!
|
||||||
|
|
||||||
|
directories.each do |d|
|
||||||
|
base.remove_file d, :force => true if directory_empty? d
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
class GlobAction < BaseAction
|
def cleaning?
|
||||||
|
@config.has_key?(:clean) && @config[:clean]
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
def directory_empty?(directory)
|
||||||
def execute!
|
Dir["#{directory}/*"].empty?
|
||||||
Dir[File.join(source, @config[:glob])].each do |path|
|
end
|
||||||
file_name = path.gsub(SHARED_SERVER.views + "/", "")
|
|
||||||
if file_name == "layouts"
|
|
||||||
false
|
|
||||||
elsif file_name.include?("layout.") && file_name.split(".").length == 2
|
|
||||||
false
|
|
||||||
else
|
|
||||||
next if File.directory?(path)
|
|
||||||
|
|
||||||
handle_path(path)
|
def queue_current_paths
|
||||||
|
@cleaning_queue = []
|
||||||
true
|
Find.find(@destination) do |path|
|
||||||
|
next if path.match(/\/\./)
|
||||||
|
unless path == destination
|
||||||
|
@cleaning_queue << path.sub(@destination, destination[/([^\/]+?)$/])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
class DirectoryAction < BaseAction
|
def execute!
|
||||||
def invoke!
|
paths = @app.sitemap.all_paths.sort do |a, b|
|
||||||
base.empty_directory given_destination, config
|
a_dir = a.split("/").first
|
||||||
super
|
b_dir = b.split("/").first
|
||||||
end
|
|
||||||
|
|
||||||
protected
|
if a_dir == @app.images_dir
|
||||||
def handle_directory(lookup, &block)
|
|
||||||
lookup = File.join(lookup, '*')
|
|
||||||
|
|
||||||
results = Dir[lookup].sort do |a, b|
|
|
||||||
simple_a = a.gsub(SHARED_SERVER.root + "/", '').gsub(SHARED_SERVER.views + "/", '')
|
|
||||||
simple_b = b.gsub(SHARED_SERVER.root + "/", '').gsub(SHARED_SERVER.views + "/", '')
|
|
||||||
|
|
||||||
a_dir = simple_a.split("/").first
|
|
||||||
b_dir = simple_b.split("/").first
|
|
||||||
|
|
||||||
if a_dir == SHARED_SERVER.images_dir
|
|
||||||
-1
|
-1
|
||||||
elsif b_dir == SHARED_SERVER.images_dir
|
elsif b_dir == @app.images_dir
|
||||||
1
|
1
|
||||||
else
|
else
|
||||||
0
|
0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
results = results.select(&block) if block_given?
|
paths.each do |path|
|
||||||
|
file_source = path
|
||||||
|
file_destination = File.join(given_destination, file_source.gsub(source, '.'))
|
||||||
|
file_destination.gsub!('/./', '/')
|
||||||
|
|
||||||
results.each do |file_source|
|
if @app.sitemap.generic_path?(file_source)
|
||||||
if File.directory?(file_source)
|
# no-op
|
||||||
handle_directory(file_source)
|
elsif @app.sitemap.proxied_path?(file_source)
|
||||||
|
file_source = @app.sitemap.path_target(file_source)
|
||||||
|
elsif @app.sitemap.ignored_path?(file_source)
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
handle_path(file_source)
|
@cleaning_queue.delete(file_destination) if cleaning?
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def execute!
|
if @config[:glob]
|
||||||
handle_directory(source) do |path|
|
next unless File.fnmatch(@config[:glob], file_source)
|
||||||
file_name = path.gsub(SHARED_SERVER.views + "/", "")
|
|
||||||
if file_name == "layouts"
|
|
||||||
false
|
|
||||||
elsif file_name.include?("layout.") && file_name.split(".").length == 2
|
|
||||||
false
|
|
||||||
else
|
|
||||||
true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
base.tilt_template(file_source, file_destination, { :force => true })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -59,7 +59,7 @@ module Middleman::CoreExtensions::Features
|
||||||
feature = Middleman::Features.const_get(feature)
|
feature = Middleman::Features.const_get(feature)
|
||||||
end
|
end
|
||||||
|
|
||||||
$stderr.puts "== Activating: #{feature}" if logging?
|
puts "== Activating: #{feature}" if logging?
|
||||||
register feature
|
register feature
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -75,12 +75,10 @@ module Middleman::CoreExtensions::Features
|
||||||
|
|
||||||
# Load features before starting server
|
# Load features before starting server
|
||||||
def new
|
def new
|
||||||
set :sitemap, ::Middleman::Sitemap.new(self)
|
|
||||||
|
|
||||||
# Check for and evaluate local configuration
|
# Check for and evaluate local configuration
|
||||||
local_config = File.join(self.root, "config.rb")
|
local_config = File.join(self.root, "config.rb")
|
||||||
if File.exists? local_config
|
if File.exists? local_config
|
||||||
$stderr.puts "== Reading: Local config" if logging?
|
puts "== Reading: Local config" if logging?
|
||||||
class_eval File.read(local_config)
|
class_eval File.read(local_config)
|
||||||
set :app_file, File.expand_path(local_config)
|
set :app_file, File.expand_path(local_config)
|
||||||
end
|
end
|
||||||
|
@ -94,7 +92,7 @@ module Middleman::CoreExtensions::Features
|
||||||
|
|
||||||
if logging?
|
if logging?
|
||||||
extensions.each do |ext|
|
extensions.each do |ext|
|
||||||
$stderr.puts "== Extension: #{ext}"
|
puts "== Extension: #{ext}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
30
lib/middleman/core_extensions/file_watcher.rb
Normal file
30
lib/middleman/core_extensions/file_watcher.rb
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
module Middleman::CoreExtensions::FileWatcher
|
||||||
|
class << self
|
||||||
|
def registered(app)
|
||||||
|
app.extend ClassMethods
|
||||||
|
end
|
||||||
|
alias :included :registered
|
||||||
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
def file_did_change(path)
|
||||||
|
@run_after_file_change ||= []
|
||||||
|
@run_after_file_change.each { |block| block.call(path) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_file_change(&block)
|
||||||
|
@run_after_file_change ||= []
|
||||||
|
@run_after_file_change << block
|
||||||
|
end
|
||||||
|
|
||||||
|
def file_did_delete(path)
|
||||||
|
@run_after_file_delete ||= []
|
||||||
|
@run_after_file_delete.each { |block| block.call(path) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_file_delete(&block)
|
||||||
|
@run_after_file_delete ||= []
|
||||||
|
@run_after_file_delete << block
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -48,12 +48,7 @@ module Middleman::CoreExtensions::Routing
|
||||||
|
|
||||||
# Keep a path from building
|
# Keep a path from building
|
||||||
def ignore(path)
|
def ignore(path)
|
||||||
# New sitemap based ignore
|
|
||||||
settings.sitemap.ignore_path(path)
|
settings.sitemap.ignore_path(path)
|
||||||
|
|
||||||
settings.excluded_paths << paths_for_url(path)
|
|
||||||
settings.excluded_paths.flatten!
|
|
||||||
settings.excluded_paths.uniq!
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# The page method allows the layout to be set on a specific path
|
# The page method allows the layout to be set on a specific path
|
||||||
|
@ -64,10 +59,8 @@ module Middleman::CoreExtensions::Routing
|
||||||
options[:layout] = settings.layout if options[:layout].nil?
|
options[:layout] = settings.layout if options[:layout].nil?
|
||||||
|
|
||||||
if options.has_key?(:proxy)
|
if options.has_key?(:proxy)
|
||||||
# New sitemap based proxy
|
|
||||||
settings.sitemap.set_path(url, options[:proxy])
|
settings.sitemap.set_path(url, options[:proxy])
|
||||||
|
|
||||||
settings.proxied_paths[url] = options[:proxy]
|
|
||||||
if options.has_key?(:ignore) && options[:ignore]
|
if options.has_key?(:ignore) && options[:ignore]
|
||||||
settings.ignore(options[:proxy])
|
settings.ignore(options[:proxy])
|
||||||
end
|
end
|
||||||
|
@ -79,17 +72,11 @@ module Middleman::CoreExtensions::Routing
|
||||||
|
|
||||||
paths_for_url(url).each do |p|
|
paths_for_url(url).each do |p|
|
||||||
get(p) do
|
get(p) do
|
||||||
# New sitemap based rerouting
|
|
||||||
if settings.sitemap.path_is_proxy?(url)
|
if settings.sitemap.path_is_proxy?(url)
|
||||||
request["is_proxy"] = true
|
request["is_proxy"] = true
|
||||||
request.path_info = settings.sitemap.path_target(url)
|
request.path_info = settings.sitemap.path_target(url)
|
||||||
end
|
end
|
||||||
|
|
||||||
if settings.proxied_paths.has_key?(url)
|
|
||||||
request["is_proxy"] = true
|
|
||||||
request.path_info = settings.proxied_paths[url]
|
|
||||||
end
|
|
||||||
|
|
||||||
instance_eval(&block) if has_block
|
instance_eval(&block) if has_block
|
||||||
process_request(options)
|
process_request(options)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,88 +1,116 @@
|
||||||
require 'find'
|
require 'find'
|
||||||
|
|
||||||
module Middleman
|
module Middleman::CoreExtensions::Sitemap
|
||||||
class Sitemap
|
class << self
|
||||||
def self.singleton
|
def registered(app)
|
||||||
@@singleton || nil
|
app.set :sitemap, SitemapStore.new(app)
|
||||||
end
|
end
|
||||||
|
alias :included :registered
|
||||||
|
end
|
||||||
|
|
||||||
|
class SitemapStore
|
||||||
def initialize(app)
|
def initialize(app)
|
||||||
@app = app
|
@app = app
|
||||||
@map = {}
|
@map = {}
|
||||||
@ignored_paths = nil
|
@ignored_paths = false
|
||||||
@generic_paths = nil
|
@generic_paths = false
|
||||||
@proxied_paths = nil
|
@proxied_paths = false
|
||||||
|
|
||||||
@source = File.expand_path(@app.views, @app.root)
|
@source = File.expand_path(@app.views, @app.root)
|
||||||
|
|
||||||
build_static_map
|
build_static_map
|
||||||
|
|
||||||
each do |request, destination|
|
@app.on_file_change do |file|
|
||||||
$stderr.puts request
|
touch_file(file)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@singleton = self
|
@app.on_file_delete do |file|
|
||||||
|
remove_file(file)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check to see if we know about a specific path
|
# Check to see if we know about a specific path
|
||||||
def path_exists?(path)
|
def path_exists?(path)
|
||||||
|
path = path.sub(/^\//, "")
|
||||||
@map.has_key?(path)
|
@map.has_key?(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def path_is_proxy?(path)
|
def path_is_proxy?(path)
|
||||||
|
path = path.sub(/^\//, "")
|
||||||
return false if !path_exists?(path)
|
return false if !path_exists?(path)
|
||||||
@map[path].is_a?(String)
|
@map[path].is_a?(String)
|
||||||
end
|
end
|
||||||
|
|
||||||
def path_target(path)
|
def path_target(path)
|
||||||
|
path = path.sub(/^\//, "")
|
||||||
@map[path]
|
@map[path]
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_path(path, target=true)
|
def set_path(path, target=true)
|
||||||
|
path = path.sub(/^\//, "")
|
||||||
|
target = target.sub(/^\//, "") if target.is_a?(String)
|
||||||
|
|
||||||
@map[path] = target
|
@map[path] = target
|
||||||
|
|
||||||
@ignored_paths = nil if target.nil?
|
@ignored_paths = false if target === false
|
||||||
@generic_paths = nil if target === true
|
@generic_paths = false if target === true
|
||||||
@proxied_paths = nil if target.is_a?(String)
|
@proxied_paths = false if target.is_a?(String)
|
||||||
end
|
end
|
||||||
|
|
||||||
def ignore_path(path)
|
def ignore_path(path)
|
||||||
set_path(path, nil)
|
set_path(path, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
def each(&block)
|
def each(&block)
|
||||||
@map.each do |k, v|
|
@map.each do |k, v|
|
||||||
next if v.nil?
|
|
||||||
|
|
||||||
yield(k, v)
|
yield(k, v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def all_paths
|
||||||
|
@map.keys
|
||||||
|
end
|
||||||
|
|
||||||
|
def ignored_path?(path)
|
||||||
|
path = path.sub(/^\//, "")
|
||||||
|
ignored_paths.include?(path)
|
||||||
|
end
|
||||||
|
|
||||||
def ignored_paths
|
def ignored_paths
|
||||||
@ignored_paths ||= begin
|
@ignored_paths ||= begin
|
||||||
ignored = []
|
ignored = []
|
||||||
each do |k, v|
|
each do |k, v|
|
||||||
ignored << k unless v.nil?
|
ignored << k if v === false
|
||||||
end
|
end
|
||||||
ignored
|
ignored
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def generic_path?(path)
|
||||||
|
path = path.sub(/^\//, "")
|
||||||
|
generic_paths.include?(path)
|
||||||
|
end
|
||||||
|
|
||||||
def generic_paths
|
def generic_paths
|
||||||
@generic_paths ||= begin
|
@generic_paths ||= begin
|
||||||
generic = []
|
generic = []
|
||||||
each do |k, v|
|
each do |k, v|
|
||||||
generic << k unless v === true
|
generic << k if v === true
|
||||||
end
|
end
|
||||||
generic
|
generic
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def proxied_path?(path)
|
||||||
|
path = path.sub(/^\//, "")
|
||||||
|
proxied_paths.include?(path)
|
||||||
|
end
|
||||||
|
|
||||||
def proxied_paths
|
def proxied_paths
|
||||||
@proxied_paths ||= begin
|
@proxied_paths ||= begin
|
||||||
proxied = []
|
proxied = []
|
||||||
each do |k, v|
|
each do |k, v|
|
||||||
proxied << k unless target.is_a?(String)
|
proxied << k if v.is_a?(String)
|
||||||
end
|
end
|
||||||
proxied
|
proxied
|
||||||
end
|
end
|
||||||
|
@ -101,16 +129,12 @@ module Middleman
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_path(path)
|
def remove_path(path)
|
||||||
if @map.has_key?(path)
|
path = path.sub(/^\//, "")
|
||||||
@map.delete(path)
|
@map.delete(path) if path_exists?(path)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def build_static_map
|
def build_static_map
|
||||||
# found_template = resolve_template(request_path, :raise_exceptions => false)
|
|
||||||
|
|
||||||
Find.find(@source) do |file|
|
Find.find(@source) do |file|
|
||||||
add_file(file)
|
add_file(file)
|
||||||
end
|
end
|
||||||
|
@ -153,33 +177,3 @@ module Middleman
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module Guard
|
|
||||||
class MiddlemanSitemap < Guard
|
|
||||||
def initialize(watchers = [], options = {})
|
|
||||||
super
|
|
||||||
@options = options
|
|
||||||
end
|
|
||||||
|
|
||||||
def run_on_change(files)
|
|
||||||
files.each do |file|
|
|
||||||
::Middleman::Sitemap.singleton.touch_file(file)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def run_on_deletion(files)
|
|
||||||
files.each do |file|
|
|
||||||
::Middleman::Sitemap.singleton.remove_file(file)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Add Sitemap guard
|
|
||||||
Middleman::Guard.add_guard do
|
|
||||||
%Q{
|
|
||||||
guard 'middlemansitemap' do
|
|
||||||
watch(%r{^source/(.*)})
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
|
@ -9,8 +9,7 @@ end
|
||||||
module Middleman
|
module Middleman
|
||||||
module Guard
|
module Guard
|
||||||
def self.add_guard(&block)
|
def self.add_guard(&block)
|
||||||
@additional_guards ||= []
|
# Deprecation Warning
|
||||||
@additional_guards << block
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.start(options={}, livereload={})
|
def self.start(options={}, livereload={})
|
||||||
|
@ -20,24 +19,18 @@ module Middleman
|
||||||
end
|
end
|
||||||
|
|
||||||
guardfile_contents = %Q{
|
guardfile_contents = %Q{
|
||||||
guard 'middlemanconfig'#{options_hash} do
|
guard 'middleman'#{options_hash} do
|
||||||
watch("config.rb")
|
watch(%r{(.*)})
|
||||||
watch(%r{^lib/^[^\.](.*)\.rb$})
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
(@additional_guards || []).each do |block|
|
|
||||||
result = block.call(options, livereload)
|
|
||||||
guardfile_contents << result unless result.nil?
|
|
||||||
end
|
|
||||||
|
|
||||||
::Guard.start({ :guardfile_contents => guardfile_contents })
|
::Guard.start({ :guardfile_contents => guardfile_contents })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module Guard
|
module Guard
|
||||||
class MiddlemanConfig < Guard
|
class Middleman < Guard
|
||||||
def initialize(watchers = [], options = {})
|
def initialize(watchers = [], options = {})
|
||||||
super
|
super
|
||||||
@options = options
|
@options = options
|
||||||
|
@ -48,14 +41,46 @@ module Guard
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_on_change(paths)
|
def run_on_change(paths)
|
||||||
|
needs_to_restart = false
|
||||||
|
|
||||||
|
paths.each do |path|
|
||||||
|
if path.match(%{^config\.rb}) || path.match(%r{^lib/^[^\.](.*)\.rb$})
|
||||||
|
needs_to_restart = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if needs_to_restart
|
||||||
|
server_restart
|
||||||
|
elsif !@app.nil?
|
||||||
|
paths.each do |path|
|
||||||
|
@app.file_did_change(path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_on_deletion(paths)
|
||||||
|
if !@app.nil?
|
||||||
|
paths.each do |path|
|
||||||
|
@app.file_did_delete(path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def server_restart
|
||||||
server_stop
|
server_stop
|
||||||
server_start
|
server_start
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
def server_start
|
def server_start
|
||||||
|
@app = ::Middleman.server
|
||||||
|
|
||||||
|
puts "== The Middleman is standing watch on port #{@options[:Port]}"
|
||||||
@server_job = fork do
|
@server_job = fork do
|
||||||
::Middleman.start_server(@options)
|
opts = @options.dup
|
||||||
|
opts[:app] = @app
|
||||||
|
::Middleman.start_server(opts)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -64,9 +89,7 @@ module Guard
|
||||||
Process.kill("KILL", @server_job)
|
Process.kill("KILL", @server_job)
|
||||||
Process.wait @server_job
|
Process.wait @server_job
|
||||||
@server_job = nil
|
@server_job = nil
|
||||||
# @server_options[:app] = nil
|
@app = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
require "middleman/sitemap"
|
|
Loading…
Reference in a new issue