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
|
||||
====
|
||||
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
|
||||
====
|
||||
|
|
|
@ -15,15 +15,12 @@ Feature: Builder
|
|||
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/Child folder/regular_file(example).txt" should exist at "test-app"
|
||||
And cleanup built app at "test-app"
|
||||
|
||||
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 "index.html" should not exist at "glob-app"
|
||||
And cleanup built app at "glob-app"
|
||||
|
||||
# Scenario: Force relative assets
|
||||
# Given a built app at "relative-app" with flags "--relative"
|
||||
# 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"
|
||||
And "should_be_ignored2.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 "a_folder/needs_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
|
||||
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_ignored2.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
|
||||
Given the Server is running at "test-app"
|
||||
|
|
|
@ -3,7 +3,6 @@ Feature: Web Fonts
|
|||
Scenario: Checking built folder for content
|
||||
Given a built app at "fonts-app"
|
||||
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
|
||||
Given the Server is running at "fonts-app"
|
||||
|
|
|
@ -23,7 +23,6 @@ Feature: Sprockets
|
|||
Scenario: Multiple engine files should build correctly
|
||||
Given a built app at "test-app"
|
||||
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
|
||||
Given the Server is running at "test-app"
|
||||
|
|
|
@ -11,6 +11,10 @@ end
|
|||
Given /^a built app at "([^"]*)"$/ do |path|
|
||||
root = File.dirname(File.dirname(File.dirname(__FILE__)))
|
||||
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"))
|
||||
`cd #{target} && #{build_cmd}`
|
||||
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
|
||||
module Middleman
|
||||
# Auto-load modules on-demand
|
||||
autoload :Base, "middleman/base"
|
||||
autoload :Sitemap, "middleman/sitemap"
|
||||
autoload :Builder, "middleman/builder"
|
||||
autoload :CLI, "middleman/cli"
|
||||
autoload :Templates, "middleman/templates"
|
||||
autoload :Guard, "middleman/guard"
|
||||
autoload :Base, "middleman/base"
|
||||
autoload :Builder, "middleman/builder"
|
||||
autoload :CLI, "middleman/cli"
|
||||
autoload :Templates, "middleman/templates"
|
||||
autoload :Guard, "middleman/guard"
|
||||
|
||||
# Custom Renderers
|
||||
module Renderers
|
||||
|
@ -80,6 +79,11 @@ module Middleman
|
|||
end
|
||||
|
||||
module CoreExtensions
|
||||
# Guard Proxy
|
||||
autoload :FileWatcher, "middleman/core_extensions/file_watcher"
|
||||
|
||||
autoload :Sitemap, "middleman/core_extensions/sitemap"
|
||||
|
||||
# Add Builder callbacks
|
||||
autoload :Builder, "middleman/core_extensions/builder"
|
||||
|
||||
|
@ -187,13 +191,14 @@ module Middleman
|
|||
:AccessLog => []
|
||||
}
|
||||
|
||||
app = ::Middleman.server
|
||||
app.set :environment, options[:environment].to_sym
|
||||
opts[:app] = app.new
|
||||
app_class = options[:app] ||= ::Middleman.server
|
||||
app_class.set :environment, options[:environment].to_sym
|
||||
opts[:app] = app_class.new
|
||||
opts[:server] = 'thin'
|
||||
|
||||
$stderr.puts "== The Middleman is standing watch on port #{opts[:Port]}"
|
||||
::Rack::Server.new(opts).start
|
||||
server = ::Rack::Server.new(opts)
|
||||
server.start
|
||||
server
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -38,6 +38,12 @@ module Middleman::Base
|
|||
|
||||
app.set :views, "source"
|
||||
|
||||
# Add Builder Callbacks
|
||||
app.register Middleman::CoreExtensions::FileWatcher
|
||||
|
||||
# Sitemap
|
||||
app.register Middleman::CoreExtensions::Sitemap
|
||||
|
||||
# Add Builder Callbacks
|
||||
app.register Middleman::CoreExtensions::Builder
|
||||
|
||||
|
@ -92,7 +98,8 @@ module Middleman::Base
|
|||
# See if Tilt cannot handle this file
|
||||
app.before_processing(:base) do |result|
|
||||
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
|
||||
extensionless_path, template_engine = result
|
||||
|
|
|
@ -12,9 +12,6 @@ module Middleman
|
|||
config = args.last.is_a?(Hash) ? args.pop : {}
|
||||
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}/, "")
|
||||
|
||||
begin
|
||||
|
@ -22,8 +19,6 @@ module Middleman
|
|||
|
||||
request_path.gsub!(/\s/, "%20")
|
||||
response = Middleman::Builder.shared_rack.get(request_path)
|
||||
|
||||
dequeue_file_from destination if cleaning?
|
||||
|
||||
create_file destination, nil, config do
|
||||
response.body
|
||||
|
@ -31,54 +26,6 @@ module Middleman
|
|||
rescue
|
||||
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
|
||||
|
||||
class Builder < Thor::Group
|
||||
|
@ -114,15 +61,11 @@ module Middleman
|
|||
def build_all_files
|
||||
self.class.shared_rack
|
||||
|
||||
if options.has_key?("glob")
|
||||
action GlobAction.new(self, SHARED_SERVER.views, SHARED_SERVER.build_dir, { :force => true, :glob => options["glob"] })
|
||||
else
|
||||
action DirectoryAction.new(self, SHARED_SERVER.views, SHARED_SERVER.build_dir, { :force => true })
|
||||
opts = { }
|
||||
opts[:glob] = options["glob"] if options.has_key?("glob")
|
||||
opts[:clean] = options["clean"] if options.has_key?("clean")
|
||||
|
||||
SHARED_SERVER.proxied_paths.each do |url, proxy|
|
||||
tilt_template(url.gsub(/^\//, "#{SHARED_SERVER.build_dir}/"), { :force => true })
|
||||
end
|
||||
end
|
||||
action GlobAction.new(self, SHARED_SERVER, opts)
|
||||
end
|
||||
|
||||
@@hooks = {}
|
||||
|
@ -143,113 +86,99 @@ module Middleman
|
|||
end
|
||||
end
|
||||
|
||||
class BaseAction < ::Thor::Actions::EmptyDirectory
|
||||
class GlobAction < ::Thor::Actions::EmptyDirectory
|
||||
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))
|
||||
@block = block
|
||||
super(base, destination, { :recursive => true }.merge(config))
|
||||
|
||||
super(base, destination, config)
|
||||
end
|
||||
|
||||
def invoke!
|
||||
base.clean! destination
|
||||
queue_current_paths if cleaning?
|
||||
execute!
|
||||
clean! if cleaning?
|
||||
end
|
||||
|
||||
def revoke!
|
||||
execute!
|
||||
end
|
||||
|
||||
|
||||
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)
|
||||
file_destination = File.join(given_destination, file_source.gsub(source, '.'))
|
||||
file_destination.gsub!('/./', '/')
|
||||
|
||||
handled_by_tilt = ::Tilt.mappings.has_key?(file_extension.gsub(/^\./, ""))
|
||||
if handled_by_tilt
|
||||
file_destination.gsub!(file_extension, "")
|
||||
end
|
||||
|
||||
destination = base.tilt_template(file_source, file_destination, config, &@block)
|
||||
end
|
||||
end
|
||||
|
||||
class GlobAction < BaseAction
|
||||
def clean!
|
||||
files = @cleaning_queue.select { |q| File.file? q }
|
||||
directories = @cleaning_queue.select { |q| File.directory? q }
|
||||
|
||||
protected
|
||||
def execute!
|
||||
Dir[File.join(source, @config[:glob])].each do |path|
|
||||
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)
|
||||
files.each do |f|
|
||||
base.remove_file f, :force => true
|
||||
end
|
||||
|
||||
handle_path(path)
|
||||
directories = directories.sort_by {|d| d.length }.reverse!
|
||||
|
||||
true
|
||||
directories.each do |d|
|
||||
base.remove_file d, :force => true if directory_empty? d
|
||||
end
|
||||
end
|
||||
|
||||
def cleaning?
|
||||
@config.has_key?(:clean) && @config[:clean]
|
||||
end
|
||||
|
||||
def directory_empty?(directory)
|
||||
Dir["#{directory}/*"].empty?
|
||||
end
|
||||
|
||||
def queue_current_paths
|
||||
@cleaning_queue = []
|
||||
Find.find(@destination) do |path|
|
||||
next if path.match(/\/\./)
|
||||
unless path == destination
|
||||
@cleaning_queue << path.sub(@destination, destination[/([^\/]+?)$/])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class DirectoryAction < BaseAction
|
||||
def invoke!
|
||||
base.empty_directory given_destination, config
|
||||
super
|
||||
end
|
||||
|
||||
protected
|
||||
def handle_directory(lookup, &block)
|
||||
lookup = File.join(lookup, '*')
|
||||
def execute!
|
||||
paths = @app.sitemap.all_paths.sort do |a, b|
|
||||
a_dir = a.split("/").first
|
||||
b_dir = b.split("/").first
|
||||
|
||||
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
|
||||
if a_dir == @app.images_dir
|
||||
-1
|
||||
elsif b_dir == SHARED_SERVER.images_dir
|
||||
elsif b_dir == @app.images_dir
|
||||
1
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
|
||||
results = results.select(&block) if block_given?
|
||||
|
||||
results.each do |file_source|
|
||||
if File.directory?(file_source)
|
||||
handle_directory(file_source)
|
||||
paths.each do |path|
|
||||
file_source = path
|
||||
file_destination = File.join(given_destination, file_source.gsub(source, '.'))
|
||||
file_destination.gsub!('/./', '/')
|
||||
|
||||
if @app.sitemap.generic_path?(file_source)
|
||||
# no-op
|
||||
elsif @app.sitemap.proxied_path?(file_source)
|
||||
file_source = @app.sitemap.path_target(file_source)
|
||||
elsif @app.sitemap.ignored_path?(file_source)
|
||||
next
|
||||
end
|
||||
|
||||
handle_path(file_source)
|
||||
end
|
||||
end
|
||||
|
||||
def execute!
|
||||
handle_directory(source) do |path|
|
||||
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
|
||||
@cleaning_queue.delete(file_destination) if cleaning?
|
||||
|
||||
if @config[:glob]
|
||||
next unless File.fnmatch(@config[:glob], file_source)
|
||||
end
|
||||
|
||||
base.tilt_template(file_source, file_destination, { :force => true })
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -59,7 +59,7 @@ module Middleman::CoreExtensions::Features
|
|||
feature = Middleman::Features.const_get(feature)
|
||||
end
|
||||
|
||||
$stderr.puts "== Activating: #{feature}" if logging?
|
||||
puts "== Activating: #{feature}" if logging?
|
||||
register feature
|
||||
end
|
||||
|
||||
|
@ -75,12 +75,10 @@ module Middleman::CoreExtensions::Features
|
|||
|
||||
# Load features before starting server
|
||||
def new
|
||||
set :sitemap, ::Middleman::Sitemap.new(self)
|
||||
|
||||
# Check for and evaluate local configuration
|
||||
local_config = File.join(self.root, "config.rb")
|
||||
if File.exists? local_config
|
||||
$stderr.puts "== Reading: Local config" if logging?
|
||||
puts "== Reading: Local config" if logging?
|
||||
class_eval File.read(local_config)
|
||||
set :app_file, File.expand_path(local_config)
|
||||
end
|
||||
|
@ -94,7 +92,7 @@ module Middleman::CoreExtensions::Features
|
|||
|
||||
if logging?
|
||||
extensions.each do |ext|
|
||||
$stderr.puts "== Extension: #{ext}"
|
||||
puts "== Extension: #{ext}"
|
||||
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
|
||||
def ignore(path)
|
||||
# New sitemap based ignore
|
||||
settings.sitemap.ignore_path(path)
|
||||
|
||||
settings.excluded_paths << paths_for_url(path)
|
||||
settings.excluded_paths.flatten!
|
||||
settings.excluded_paths.uniq!
|
||||
end
|
||||
|
||||
# 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?
|
||||
|
||||
if options.has_key?(:proxy)
|
||||
# New sitemap based proxy
|
||||
settings.sitemap.set_path(url, options[:proxy])
|
||||
|
||||
settings.proxied_paths[url] = options[:proxy]
|
||||
if options.has_key?(:ignore) && options[:ignore]
|
||||
settings.ignore(options[:proxy])
|
||||
end
|
||||
|
@ -79,17 +72,11 @@ module Middleman::CoreExtensions::Routing
|
|||
|
||||
paths_for_url(url).each do |p|
|
||||
get(p) do
|
||||
# New sitemap based rerouting
|
||||
if settings.sitemap.path_is_proxy?(url)
|
||||
request["is_proxy"] = true
|
||||
request.path_info = settings.sitemap.path_target(url)
|
||||
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
|
||||
process_request(options)
|
||||
end
|
||||
|
|
|
@ -1,88 +1,116 @@
|
|||
require 'find'
|
||||
|
||||
module Middleman
|
||||
class Sitemap
|
||||
def self.singleton
|
||||
@@singleton || nil
|
||||
module Middleman::CoreExtensions::Sitemap
|
||||
class << self
|
||||
def registered(app)
|
||||
app.set :sitemap, SitemapStore.new(app)
|
||||
end
|
||||
|
||||
alias :included :registered
|
||||
end
|
||||
|
||||
class SitemapStore
|
||||
def initialize(app)
|
||||
@app = app
|
||||
@map = {}
|
||||
@ignored_paths = nil
|
||||
@generic_paths = nil
|
||||
@proxied_paths = nil
|
||||
@ignored_paths = false
|
||||
@generic_paths = false
|
||||
@proxied_paths = false
|
||||
|
||||
@source = File.expand_path(@app.views, @app.root)
|
||||
|
||||
|
||||
build_static_map
|
||||
|
||||
each do |request, destination|
|
||||
$stderr.puts request
|
||||
|
||||
@app.on_file_change do |file|
|
||||
touch_file(file)
|
||||
end
|
||||
|
||||
@app.on_file_delete do |file|
|
||||
remove_file(file)
|
||||
end
|
||||
|
||||
@@singleton = self
|
||||
end
|
||||
|
||||
# Check to see if we know about a specific path
|
||||
def path_exists?(path)
|
||||
path = path.sub(/^\//, "")
|
||||
@map.has_key?(path)
|
||||
end
|
||||
|
||||
def path_is_proxy?(path)
|
||||
path = path.sub(/^\//, "")
|
||||
return false if !path_exists?(path)
|
||||
@map[path].is_a?(String)
|
||||
end
|
||||
|
||||
def path_target(path)
|
||||
path = path.sub(/^\//, "")
|
||||
@map[path]
|
||||
end
|
||||
|
||||
def set_path(path, target=true)
|
||||
path = path.sub(/^\//, "")
|
||||
target = target.sub(/^\//, "") if target.is_a?(String)
|
||||
|
||||
@map[path] = target
|
||||
|
||||
@ignored_paths = nil if target.nil?
|
||||
@generic_paths = nil if target === true
|
||||
@proxied_paths = nil if target.is_a?(String)
|
||||
@ignored_paths = false if target === false
|
||||
@generic_paths = false if target === true
|
||||
@proxied_paths = false if target.is_a?(String)
|
||||
end
|
||||
|
||||
def ignore_path(path)
|
||||
set_path(path, nil)
|
||||
set_path(path, false)
|
||||
end
|
||||
|
||||
def each(&block)
|
||||
@map.each do |k, v|
|
||||
next if v.nil?
|
||||
|
||||
yield(k, v)
|
||||
end
|
||||
end
|
||||
|
||||
def all_paths
|
||||
@map.keys
|
||||
end
|
||||
|
||||
def ignored_path?(path)
|
||||
path = path.sub(/^\//, "")
|
||||
ignored_paths.include?(path)
|
||||
end
|
||||
|
||||
def ignored_paths
|
||||
@ignored_paths ||= begin
|
||||
ignored = []
|
||||
each do |k, v|
|
||||
ignored << k unless v.nil?
|
||||
ignored << k if v === false
|
||||
end
|
||||
ignored
|
||||
end
|
||||
end
|
||||
|
||||
def generic_path?(path)
|
||||
path = path.sub(/^\//, "")
|
||||
generic_paths.include?(path)
|
||||
end
|
||||
|
||||
def generic_paths
|
||||
@generic_paths ||= begin
|
||||
generic = []
|
||||
each do |k, v|
|
||||
generic << k unless v === true
|
||||
generic << k if v === true
|
||||
end
|
||||
generic
|
||||
end
|
||||
end
|
||||
|
||||
def proxied_path?(path)
|
||||
path = path.sub(/^\//, "")
|
||||
proxied_paths.include?(path)
|
||||
end
|
||||
|
||||
def proxied_paths
|
||||
@proxied_paths ||= begin
|
||||
proxied = []
|
||||
each do |k, v|
|
||||
proxied << k unless target.is_a?(String)
|
||||
proxied << k if v.is_a?(String)
|
||||
end
|
||||
proxied
|
||||
end
|
||||
|
@ -101,16 +129,12 @@ module Middleman
|
|||
end
|
||||
|
||||
def remove_path(path)
|
||||
if @map.has_key?(path)
|
||||
@map.delete(path)
|
||||
end
|
||||
path = path.sub(/^\//, "")
|
||||
@map.delete(path) if path_exists?(path)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def build_static_map
|
||||
# found_template = resolve_template(request_path, :raise_exceptions => false)
|
||||
|
||||
Find.find(@source) do |file|
|
||||
add_file(file)
|
||||
end
|
||||
|
@ -152,34 +176,4 @@ module Middleman
|
|||
true
|
||||
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 Guard
|
||||
def self.add_guard(&block)
|
||||
@additional_guards ||= []
|
||||
@additional_guards << block
|
||||
# Deprecation Warning
|
||||
end
|
||||
|
||||
def self.start(options={}, livereload={})
|
||||
|
@ -20,16 +19,10 @@ module Middleman
|
|||
end
|
||||
|
||||
guardfile_contents = %Q{
|
||||
guard 'middlemanconfig'#{options_hash} do
|
||||
watch("config.rb")
|
||||
watch(%r{^lib/^[^\.](.*)\.rb$})
|
||||
guard 'middleman'#{options_hash} do
|
||||
watch(%r{(.*)})
|
||||
end
|
||||
}
|
||||
|
||||
(@additional_guards || []).each do |block|
|
||||
result = block.call(options, livereload)
|
||||
guardfile_contents << result unless result.nil?
|
||||
end
|
||||
|
||||
::Guard.start({ :guardfile_contents => guardfile_contents })
|
||||
end
|
||||
|
@ -37,7 +30,7 @@ module Middleman
|
|||
end
|
||||
|
||||
module Guard
|
||||
class MiddlemanConfig < Guard
|
||||
class Middleman < Guard
|
||||
def initialize(watchers = [], options = {})
|
||||
super
|
||||
@options = options
|
||||
|
@ -48,14 +41,46 @@ module Guard
|
|||
end
|
||||
|
||||
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_start
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def server_start
|
||||
@app = ::Middleman.server
|
||||
|
||||
puts "== The Middleman is standing watch on port #{@options[:Port]}"
|
||||
@server_job = fork do
|
||||
::Middleman.start_server(@options)
|
||||
opts = @options.dup
|
||||
opts[:app] = @app
|
||||
::Middleman.start_server(opts)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -64,9 +89,7 @@ module Guard
|
|||
Process.kill("KILL", @server_job)
|
||||
Process.wait @server_job
|
||||
@server_job = nil
|
||||
# @server_options[:app] = nil
|
||||
@app = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require "middleman/sitemap"
|
||||
end
|
Loading…
Reference in a new issue