commit
55291edc65
|
@ -1,6 +1,7 @@
|
|||
# Built on Rack
|
||||
require "rack"
|
||||
require "rack/file"
|
||||
require "rack/lint"
|
||||
|
||||
module Middleman
|
||||
module CoreExtensions
|
||||
|
@ -75,6 +76,8 @@ module Middleman
|
|||
def to_rack_app(&block)
|
||||
inner_app = inst(&block)
|
||||
|
||||
app.use Rack::Lint
|
||||
|
||||
(@middleware || []).each do |m|
|
||||
app.use(m[0], *m[1], &m[2])
|
||||
end
|
||||
|
|
70
middleman-core/lib/middleman-core/meta_pages.rb
Normal file
70
middleman-core/lib/middleman-core/meta_pages.rb
Normal file
|
@ -0,0 +1,70 @@
|
|||
require 'rack/builder'
|
||||
require 'rack/static'
|
||||
require 'tilt'
|
||||
require 'middleman-core/meta_pages/sitemap_tree'
|
||||
|
||||
module Middleman
|
||||
module MetaPages
|
||||
# Metadata pages to be served in preview, in order to present information about the Middleman
|
||||
# application and its configuration. Analogous to Firefox/Chrome's "about:" pages.
|
||||
#
|
||||
# Built using a ghetto little Rack web framework cobbled together because I didn't want to depend
|
||||
# on Sinatra or figure out how to host Middleman inside Middleman.
|
||||
class Application
|
||||
def initialize(middleman)
|
||||
# Hold a reference to the middleman application
|
||||
@middleman = middleman
|
||||
|
||||
meta_pages = self
|
||||
@rack_app = Rack::Builder.new do
|
||||
# Serve assets from metadata/assets
|
||||
use Rack::Static, :urls => ["/assets"], :root => File.join(File.dirname(__FILE__), 'meta_pages')
|
||||
|
||||
map '/' do
|
||||
run meta_pages.method(:index)
|
||||
end
|
||||
|
||||
map '/sitemap' do
|
||||
run meta_pages.method(:sitemap)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def call(*args)
|
||||
@rack_app.call(*args)
|
||||
end
|
||||
|
||||
# The index page
|
||||
def index(env)
|
||||
template('index.html.erb')
|
||||
end
|
||||
|
||||
# Inspect the sitemap
|
||||
def sitemap(env)
|
||||
resources = @middleman.sitemap.resources(true)
|
||||
|
||||
sitemap_tree = SitemapTree.new
|
||||
|
||||
resources.each do |resource|
|
||||
sitemap_tree.add_resource resource
|
||||
end
|
||||
|
||||
template('sitemap.html.erb', :sitemap_tree => sitemap_tree)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Render a template with the given name and locals
|
||||
def template(template_name, locals={})
|
||||
template_path = File.join(File.dirname(__FILE__), 'meta_pages', 'templates', template_name)
|
||||
content = Tilt.new(template_path).render(nil, locals)
|
||||
response(content)
|
||||
end
|
||||
|
||||
# Respond to an HTML request
|
||||
def response(content)
|
||||
[ 200, {"Content-Type" => "text/html"}, Array(content) ]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
2
middleman-core/lib/middleman-core/meta_pages/assets/jquery-1.8.2.min.js
vendored
Normal file
2
middleman-core/lib/middleman-core/meta_pages/assets/jquery-1.8.2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
middleman-core/lib/middleman-core/meta_pages/assets/jquery.details-1.6.min.js
vendored
Normal file
6
middleman-core/lib/middleman-core/meta_pages/assets/jquery.details-1.6.min.js
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
(function(b){var d="open"in document.createElement("details"),e;b.fn.details=function(a){"open"===a&&(d?this.prop("open",!0):this.trigger("open"));"close"===a&&(d?this.prop("open",!1):this.trigger("close"));"init"===a&&e(b(this));if(!a){if(!d)return this.hasClass("open");var c=!1;this.each(function(){if(this.open)return c=!0,!1});return c}};e=function(a){a=a.not(".details-inited").addClass("details-inited");a.filter(".animated").each(function(){var a=b(this),d=a.children("summary").remove(),e=b("<div>").addClass("details-wrapper").append(a.children());
|
||||
a.append(e).prepend(d)});d||(a.each(function(){var a=b(this);a.children("summary").length||a.prepend("<summary>Details</summary>")}).children("summary").filter(":not(tabindex)").attr("tabindex",0).end().end().contents(":not(summary)").filter(function(){return 3===this.nodeType&&/[^\t\n\r ]/.test(this.data)}).wrap("<span>").end().end().filter(":not([open])").prop("open",!1).end().filter("[open]").addClass("open").prop("open",!0).end(),b.browser.msie&&9>b.browser.msie&&a.filter(":not(.open)").children().not("summary").hide())};
|
||||
b(function(){b("body").on("open.details","details.animated",function(){var a=b(this),c=a.children(".details-wrapper");c.hide();setTimeout(function(){c.slideDown(a.data("animation-speed"))},0)}).on("close.details","details.animated",function(){var a=b(this),c=a.children(".details-wrapper");setTimeout(function(){a.prop("open",!0).addClass("open");c.slideUp(a.data("animation-speed"),function(){a.prop("open",!1).removeClass("open")})},0)});if(d)b("body").on("click","summary",function(){var a=b(this).parent();
|
||||
a.prop("open")?a.trigger("close"):a.trigger("open")});else if(b("html").addClass("no-details"),b("head").prepend('<style>details{display:block}summary{cursor:pointer}details>summary::before{content:"\u25ba"}details.open>summary::before{content:"\u25bc"}details:not(.open)>:not(summary){display:none}</style>'),b("body").on("open.details","details",function(a){b(this).addClass("open").trigger("change.details");a.stopPropagation()}).on("close.details","details",function(a){b(this).removeClass("open").trigger("change.details");
|
||||
a.stopPropagation()}).on("toggle.details","details",function(a){var c=b(this);c.hasClass("open")?c.trigger("close"):c.trigger("open");a.stopPropagation()}).on("click","summary",function(){b(this).parent().trigger("toggle")}).on("keyup","summary",function(a){(32===a.keyCode||13===a.keyCode&&!b.browser.opera)&&b(this).parent().trigger("toggle")}),b.browser.msie&&9>b.browser.msie)b("body").on("open.details","details",function(){b(this).children().not("summary").show()}).on("close.details","details",
|
||||
function(){b(this).children().not("summary").hide()});e(b("details"))})})(jQuery);
|
|
@ -0,0 +1,15 @@
|
|||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
details > details {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
details.resource > summary {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.resource-details {
|
||||
margin-left: 15px;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
module Middleman
|
||||
module MetaPages
|
||||
# View class for a sitemap resource
|
||||
class SitemapResource
|
||||
include Padrino::Helpers::OutputHelpers
|
||||
include Padrino::Helpers::TagHelpers
|
||||
|
||||
def initialize(resource)
|
||||
@resource = resource
|
||||
end
|
||||
|
||||
def render
|
||||
content_tag :div, :class => 'resource-details' do
|
||||
content_tag :dl do
|
||||
content = ""
|
||||
resource_properties.each do |label, value|
|
||||
content << content_tag(:dt, label)
|
||||
content << content_tag(:dd, value)
|
||||
end
|
||||
content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# A hash of label to value for all the properties we want to display
|
||||
def resource_properties
|
||||
{
|
||||
'Path' => @resource.path,
|
||||
'Output Path' => File.join(@resource.app.build_dir, @resource.destination_path),
|
||||
'Url' => content_tag(:a, @resource.url, :href => @resource.url),
|
||||
#'Metadata' => @resource.metadata,
|
||||
'Source' => @resource.source_file
|
||||
}
|
||||
end
|
||||
|
||||
def css_classes
|
||||
['resource']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
53
middleman-core/lib/middleman-core/meta_pages/sitemap_tree.rb
Normal file
53
middleman-core/lib/middleman-core/meta_pages/sitemap_tree.rb
Normal file
|
@ -0,0 +1,53 @@
|
|||
require 'middleman-core/meta_pages/sitemap_resource'
|
||||
|
||||
module Middleman
|
||||
module MetaPages
|
||||
# View class for a sitemap tree
|
||||
class SitemapTree
|
||||
def initialize
|
||||
@children = {}
|
||||
end
|
||||
|
||||
def add_resource(resource)
|
||||
add_path(resource.path.split('/'), resource)
|
||||
end
|
||||
|
||||
def render
|
||||
content = ""
|
||||
@children.keys.sort_by(&:downcase).each do |path_part|
|
||||
subtree = @children[path_part]
|
||||
content << "<details class='#{subtree.css_classes.join(' ')}'>"
|
||||
content << "<summary>#{path_part}</summary>"
|
||||
content << subtree.render
|
||||
content << "</details>"
|
||||
end
|
||||
content
|
||||
end
|
||||
|
||||
def css_classes
|
||||
['tree']
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def add_path(path_parts, resource)
|
||||
first_part = path_parts.first
|
||||
|
||||
if path_parts.size == 1
|
||||
sitemap_class = SitemapResource
|
||||
# Allow special sitemap resources to use custom metadata view calsses
|
||||
sitemap_class = resource.meta_pages_class if resource.respond_to? :meta_pages_class
|
||||
|
||||
@children[first_part] = sitemap_class.new(resource)
|
||||
else
|
||||
@children[first_part] ||= SitemapTree.new
|
||||
@children[first_part].add_path(path_parts[1..-1], resource)
|
||||
end
|
||||
end
|
||||
|
||||
def to_s
|
||||
"Sitemap Tree"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Middleman Meta Pages</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Middleman Meta Pages</h1>
|
||||
|
||||
<p>Peer into the bowels of your Middleman application with these handy views!</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="sitemap/">Sitemap</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>Middleman Sitemap</title>
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="../assets/sitemap.css">
|
||||
<script src="../assets/jquery-1.8.2.min.js"></script>
|
||||
<script src="../assets/jquery.details-1.6.min.js"></script>
|
||||
<script src="../assets/sitemap.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Middleman Sitemap</h1>
|
||||
<a href="../">More meta pages</a>
|
||||
|
||||
<%= sitemap_tree.render %>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
require "webrick"
|
||||
require 'middleman-core/meta_pages'
|
||||
|
||||
module Middleman
|
||||
module PreviewServer
|
||||
|
@ -156,8 +157,16 @@ module Middleman
|
|||
@webrick ||= setup_webrick(@options[:debug] || false)
|
||||
|
||||
start_file_watcher
|
||||
|
||||
rack_app = app.class.to_rack_app
|
||||
|
||||
@webrick.mount "/", ::Rack::Handler::WEBrick, app.class.to_rack_app
|
||||
# Add in the meta pages application
|
||||
meta_app = Middleman::MetaPages::Application.new(app.class.inst)
|
||||
rack_app.map '/__middleman' do
|
||||
run meta_app
|
||||
end
|
||||
|
||||
@webrick.mount "/", ::Rack::Handler::WEBrick, rack_app
|
||||
end
|
||||
|
||||
# Detach the current Middleman::Application instance
|
||||
|
|
|
@ -66,7 +66,7 @@ module Middleman
|
|||
status, headers, response = @rack_app.call(env)
|
||||
|
||||
# We don't want to use this middleware when rendering files to figure out their hash!
|
||||
return [status, headers, response] if env["bypass_asset_hash"]
|
||||
return [status, headers, response] if env["bypass_asset_hash"] == 'true'
|
||||
|
||||
path = @middleman_app.full_path(env["PATH_INFO"])
|
||||
dirpath = Pathname.new(File.dirname(path))
|
||||
|
|
Loading…
Reference in a new issue