This commit is contained in:
parent
8f66077dd0
commit
179268a4f6
|
@ -31,7 +31,7 @@ module Middleman::Cli
|
||||||
template 'extension/gemspec', File.join(name, "#{name}.gemspec")
|
template 'extension/gemspec', File.join(name, "#{name}.gemspec")
|
||||||
template 'extension/Gemfile', File.join(name, 'Gemfile')
|
template 'extension/Gemfile', File.join(name, 'Gemfile')
|
||||||
template 'extension/lib/lib.rb', File.join(name, 'lib', "#{name}.rb")
|
template 'extension/lib/lib.rb', File.join(name, 'lib', "#{name}.rb")
|
||||||
template 'extension/lib/lib/extension.rb', File.join(name, 'lib', name, "extension.rb")
|
template 'extension/lib/lib/extension.rb', File.join(name, 'lib', name, 'extension.rb')
|
||||||
template 'extension/features/support/env.rb', File.join(name, 'features', 'support', 'env.rb')
|
template 'extension/features/support/env.rb', File.join(name, 'features', 'support', 'env.rb')
|
||||||
empty_directory File.join(name, 'fixtures')
|
empty_directory File.join(name, 'fixtures')
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,7 +42,7 @@ Feature: Run the preview server
|
||||||
Inspect your site configuration at "http://
|
Inspect your site configuration at "http://
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ruby-2.1
|
@wip
|
||||||
Scenario: Start the server with defaults in verbose mode, when a local mdns server resolves the local hostname
|
Scenario: Start the server with defaults in verbose mode, when a local mdns server resolves the local hostname
|
||||||
Given I start a mdns server for the local hostname
|
Given I start a mdns server for the local hostname
|
||||||
When I run `middleman server --verbose` interactively
|
When I run `middleman server --verbose` interactively
|
||||||
|
@ -360,7 +360,6 @@ Feature: Run the preview server
|
||||||
The Middleman preview server is bound to ":::65432", "0.0.0.0:65432"
|
The Middleman preview server is bound to ":::65432", "0.0.0.0:65432"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ruby-2.1
|
|
||||||
@wip
|
@wip
|
||||||
Scenario: Start the server when port is blocked by other middleman instance
|
Scenario: Start the server when port is blocked by other middleman instance
|
||||||
Given `middleman server` is running in background
|
Given `middleman server` is running in background
|
||||||
|
|
|
@ -12,7 +12,7 @@ Feature: Ignoring paths
|
||||||
And the following files should not exist:
|
And the following files should not exist:
|
||||||
| build/plain.html |
|
| build/plain.html |
|
||||||
| build/about.html |
|
| build/about.html |
|
||||||
|
|
||||||
Scenario: Ignore a single path (server)
|
Scenario: Ignore a single path (server)
|
||||||
Given a fixture app "ignore-app"
|
Given a fixture app "ignore-app"
|
||||||
And a file named "config.rb" with:
|
And a file named "config.rb" with:
|
||||||
|
@ -28,6 +28,35 @@ Feature: Ignoring paths
|
||||||
When I go to "/about.html"
|
When I go to "/about.html"
|
||||||
Then I should see "File Not Found"
|
Then I should see "File Not Found"
|
||||||
|
|
||||||
|
Scenario: Ignoring collected values
|
||||||
|
Given a fixture app "ignore-app"
|
||||||
|
And a file named "data/ignores.yaml" with:
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
- "plain"
|
||||||
|
"""
|
||||||
|
And a file named "config.rb" with:
|
||||||
|
"""
|
||||||
|
data.ignores.each do |name|
|
||||||
|
ignore "#{name}.html"
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
And the Server is running
|
||||||
|
When I go to "/plain.html"
|
||||||
|
Then I should see "File Not Found"
|
||||||
|
When I go to "/about.html"
|
||||||
|
Then I should not see "File Not Found"
|
||||||
|
|
||||||
|
When the file "data/ignores.yaml" has the contents
|
||||||
|
"""
|
||||||
|
---
|
||||||
|
- "about"
|
||||||
|
"""
|
||||||
|
When I go to "/plain.html"
|
||||||
|
Then I should not see "File Not Found"
|
||||||
|
When I go to "/about.html"
|
||||||
|
Then I should see "File Not Found"
|
||||||
|
|
||||||
Scenario: Ignore a globbed path (build)
|
Scenario: Ignore a globbed path (build)
|
||||||
Given a fixture app "ignore-app"
|
Given a fixture app "ignore-app"
|
||||||
And a file named "config.rb" with:
|
And a file named "config.rb" with:
|
||||||
|
@ -47,7 +76,7 @@ Feature: Ignoring paths
|
||||||
| build/reports/index.html |
|
| build/reports/index.html |
|
||||||
| build/reports/another.html |
|
| build/reports/another.html |
|
||||||
| build/images/icons/messages.png |
|
| build/images/icons/messages.png |
|
||||||
|
|
||||||
Scenario: Ignore a globbed path (server)
|
Scenario: Ignore a globbed path (server)
|
||||||
Given a fixture app "ignore-app"
|
Given a fixture app "ignore-app"
|
||||||
And a file named "config.rb" with:
|
And a file named "config.rb" with:
|
||||||
|
@ -93,7 +122,7 @@ Feature: Ignoring paths
|
||||||
| build/reports/index.html |
|
| build/reports/index.html |
|
||||||
| build/reports/another.html |
|
| build/reports/another.html |
|
||||||
| build/images/icons/messages.png |
|
| build/images/icons/messages.png |
|
||||||
|
|
||||||
Scenario: Ignore a regex (server)
|
Scenario: Ignore a regex (server)
|
||||||
Given a fixture app "ignore-app"
|
Given a fixture app "ignore-app"
|
||||||
And a file named "config.rb" with:
|
And a file named "config.rb" with:
|
||||||
|
@ -118,4 +147,4 @@ Feature: Ignoring paths
|
||||||
When I go to "/reports/another.html"
|
When I go to "/reports/another.html"
|
||||||
Then I should see "File Not Found"
|
Then I should see "File Not Found"
|
||||||
When I go to "/images/icons/messages.png"
|
When I go to "/images/icons/messages.png"
|
||||||
Then I should see "File Not Found"
|
Then I should see "File Not Found"
|
||||||
|
|
|
@ -4,4 +4,4 @@ import_path File.expand_path("bower_components/", root)
|
||||||
|
|
||||||
import_path File.expand_path("bower_components", root) do |target_path, original_path|
|
import_path File.expand_path("bower_components", root) do |target_path, original_path|
|
||||||
target_path.sub('bower_components', 'bower_components2')
|
target_path.sub('bower_components', 'bower_components2')
|
||||||
end
|
end
|
||||||
|
|
|
@ -100,7 +100,9 @@ module Middleman
|
||||||
end
|
end
|
||||||
|
|
||||||
# Inject descriptors
|
# Inject descriptors
|
||||||
resources + ctx.descriptors.map { |d| d.to_resource(app) }
|
ctx.descriptors.reduce(resources) do |sum, d|
|
||||||
|
d.execute_descriptor(app, sum)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
require 'hamster'
|
|
||||||
|
|
||||||
module Middleman
|
module Middleman
|
||||||
module CoreExtensions
|
module CoreExtensions
|
||||||
module Collections
|
module Collections
|
||||||
|
@ -11,15 +9,16 @@ module Middleman
|
||||||
attr_reader :descriptors
|
attr_reader :descriptors
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@descriptors = ::Hamster::Set.empty
|
@descriptors = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def method_missing(name, *args, &block)
|
def method_missing(name, *args, &block)
|
||||||
internal = :"_internal_#{name}"
|
internal = :"_internal_#{name}"
|
||||||
if respond_to?(internal)
|
|
||||||
@descriptors = @descriptors.add(send(internal, *args, &block))
|
return super unless respond_to?(internal)
|
||||||
else
|
|
||||||
super
|
send(internal, *args, &block).tap do |r|
|
||||||
|
@descriptors << r if r.respond_to?(:execute_descriptor)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -185,7 +185,9 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
|
||||||
sum[abs_path][desc.locale] = '/' + desc.path
|
sum[abs_path][desc.locale] = '/' + desc.path
|
||||||
end
|
end
|
||||||
|
|
||||||
resources + new_resources.map { |r| r.to_resource(app) }
|
new_resources.reduce(resources) do |sum, r|
|
||||||
|
r.execute_descriptor(app, sum)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Contract String, Symbol => String
|
Contract String, Symbol => String
|
||||||
|
@ -255,10 +257,10 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
|
||||||
end
|
end
|
||||||
|
|
||||||
LocalizedPageDescriptor = Struct.new(:path, :source_path, :locale) do
|
LocalizedPageDescriptor = Struct.new(:path, :source_path, :locale) do
|
||||||
def to_resource(app)
|
def execute_descriptor(app, resources)
|
||||||
r = ::Middleman::Sitemap::ProxyResource.new(app.sitemap, path, source_path)
|
r = ::Middleman::Sitemap::ProxyResource.new(app.sitemap, path, source_path)
|
||||||
r.add_metadata options: { locale: locale }
|
r.add_metadata options: { locale: locale }
|
||||||
r
|
resources + [r]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -469,4 +469,38 @@ module Middleman
|
||||||
@app.ready(&method(:ready)) if respond_to?(:ready)
|
@app.ready(&method(:ready)) if respond_to?(:ready)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class ConfigExtension < Extension
|
||||||
|
def initialize(app, config={}, &block)
|
||||||
|
@descriptors = {}
|
||||||
|
@wrapped = {}
|
||||||
|
|
||||||
|
self.class.exposed_to_config.each do |k, v|
|
||||||
|
@descriptors[k] = []
|
||||||
|
|
||||||
|
define_singleton_method(:"__original_#{v}", &method(v))
|
||||||
|
define_singleton_method(v) do |*args, &block|
|
||||||
|
@descriptors[k] << method(:"__original_#{v}").call(*args, &block)
|
||||||
|
@app.sitemap.rebuild_resource_list!(:"first_run_change_#{v}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def after_configuration
|
||||||
|
self.class.exposed_to_config.each do |k, v|
|
||||||
|
::Middleman::CoreExtensions::Collections::StepContext.add_to_context(k, &method(:"__original_#{v}"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Update the main sitemap resource list
|
||||||
|
# @return Array<Middleman::Sitemap::Resource>
|
||||||
|
Contract ResourceList => ResourceList
|
||||||
|
def manipulate_resource_list(resources)
|
||||||
|
@descriptors.values.flatten.reduce(resources) do |sum, c|
|
||||||
|
c.execute_descriptor(app, sum)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,9 +15,7 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension
|
||||||
@watcher = app.files.watch :source,
|
@watcher = app.files.watch :source,
|
||||||
path: File.expand_path(options[:source], app.root),
|
path: File.expand_path(options[:source], app.root),
|
||||||
latency: options[:latency]
|
latency: options[:latency]
|
||||||
end
|
|
||||||
|
|
||||||
def ready
|
|
||||||
logger.info "== Executing: `#{options[:command]}`"
|
logger.info "== Executing: `#{options[:command]}`"
|
||||||
|
|
||||||
if app.build? || options[:disable_background_execution]
|
if app.build? || options[:disable_background_execution]
|
||||||
|
|
|
@ -22,7 +22,7 @@ module Middleman
|
||||||
|
|
||||||
# Set BUNDLE_GEMFILE and run Bundler setup. Raises an exception if there is no Gemfile
|
# Set BUNDLE_GEMFILE and run Bundler setup. Raises an exception if there is no Gemfile
|
||||||
def setup_bundler
|
def setup_bundler
|
||||||
ENV['BUNDLE_GEMFILE'] ||= File.join(findup('Gemfile', ENV['MM_ROOT']), "Gemfile")
|
ENV['BUNDLE_GEMFILE'] ||= File.join(findup('Gemfile', ENV['MM_ROOT']), 'Gemfile')
|
||||||
|
|
||||||
unless File.exist?(ENV['BUNDLE_GEMFILE'])
|
unless File.exist?(ENV['BUNDLE_GEMFILE'])
|
||||||
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../../../Gemfile', __FILE__)
|
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../../../Gemfile', __FILE__)
|
||||||
|
|
|
@ -2,58 +2,56 @@ module Middleman
|
||||||
module Sitemap
|
module Sitemap
|
||||||
module Extensions
|
module Extensions
|
||||||
# Class to handle managing ignores
|
# Class to handle managing ignores
|
||||||
class Ignores < Extension
|
class Ignores < ConfigExtension
|
||||||
self.resource_list_manipulator_priority = 0
|
self.resource_list_manipulator_priority = 0
|
||||||
|
|
||||||
# Expose `create_ignore` as `app.ignore`
|
|
||||||
expose_to_application ignore: :create_ignore
|
|
||||||
|
|
||||||
# Expose `create_ignore` to config as `ignore`
|
|
||||||
expose_to_config ignore: :create_ignore
|
expose_to_config ignore: :create_ignore
|
||||||
|
|
||||||
def initialize(app, config={}, &block)
|
|
||||||
super
|
|
||||||
|
|
||||||
# Array of callbacks which can assign ignored
|
|
||||||
@ignored_callbacks = Set.new
|
|
||||||
|
|
||||||
@app.sitemap.define_singleton_method(:ignored?, &method(:ignored?))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Ignore a path or add an ignore callback
|
# Ignore a path or add an ignore callback
|
||||||
# @param [String, Regexp] path Path glob expression, or path regex
|
# @param [String, Regexp] path Path glob expression, or path regex
|
||||||
# @return [void]
|
# @return [IgnoreDescriptor]
|
||||||
Contract Maybe[Or[String, Regexp]], Maybe[Proc] => Any
|
Contract Maybe[Or[String, Regexp]], Maybe[Proc] => RespondTo[:execute_descriptor]
|
||||||
def create_ignore(path=nil, &block)
|
def create_ignore(path=nil, &block)
|
||||||
if path.is_a? Regexp
|
|
||||||
@ignored_callbacks << proc { |p| p =~ path }
|
|
||||||
elsif path.is_a? String
|
|
||||||
path_clean = ::Middleman::Util.normalize_path(path)
|
|
||||||
if path_clean.include?('*') # It's a glob
|
|
||||||
if defined? File::FNM_EXTGLOB
|
|
||||||
@ignored_callbacks << proc { |p| File.fnmatch(path_clean, p, File::FNM_EXTGLOB) }
|
|
||||||
else
|
|
||||||
@ignored_callbacks << proc { |p| File.fnmatch(path_clean, p) }
|
|
||||||
end
|
|
||||||
else
|
|
||||||
# Add a specific-path ignore unless that path is already covered
|
|
||||||
return if ignored?(path_clean)
|
|
||||||
@ignored_callbacks << proc { |p| p == path_clean }
|
|
||||||
end
|
|
||||||
elsif block_given?
|
|
||||||
@ignored_callbacks << block
|
|
||||||
end
|
|
||||||
|
|
||||||
@app.sitemap.invalidate_resources_not_ignored_cache!
|
@app.sitemap.invalidate_resources_not_ignored_cache!
|
||||||
|
IgnoreDescriptor.new(path, block)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Whether a path is ignored
|
IgnoreDescriptor = Struct.new(:path, :block) do
|
||||||
# @param [String] path
|
def execute_descriptor(_app, resources)
|
||||||
# @return [Boolean]
|
resources.map do |r|
|
||||||
Contract String => Bool
|
# Ignore based on the source path (without template extensions)
|
||||||
def ignored?(path)
|
if ignored?(r.path)
|
||||||
path_clean = ::Middleman::Util.normalize_path(path)
|
r.ignore!
|
||||||
@ignored_callbacks.any? { |b| b.call(path_clean) }
|
else
|
||||||
|
# This allows files to be ignored by their source file name (with template extensions)
|
||||||
|
r.ignore! if !r.is_a?(ProxyResource) && r.file_descriptor && ignored?(r.file_descriptor[:relative_path].to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
r
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def ignored?(match_path)
|
||||||
|
match_path = ::Middleman::Util.normalize_path(match_path)
|
||||||
|
|
||||||
|
if path.is_a? Regexp
|
||||||
|
match_path =~ path
|
||||||
|
elsif path.is_a? String
|
||||||
|
path_clean = ::Middleman::Util.normalize_path(path)
|
||||||
|
|
||||||
|
if path_clean.include?('*') # It's a glob
|
||||||
|
if defined?(::File::FNM_EXTGLOB)
|
||||||
|
::File.fnmatch(path_clean, match_path, ::File::FNM_EXTGLOB)
|
||||||
|
else
|
||||||
|
::File.fnmatch(path_clean, match_path)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
match_path == path_clean
|
||||||
|
end
|
||||||
|
elsif block_given?
|
||||||
|
block.call(match_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,46 +4,45 @@ require 'middleman-core/contracts'
|
||||||
module Middleman
|
module Middleman
|
||||||
module Sitemap
|
module Sitemap
|
||||||
module Extensions
|
module Extensions
|
||||||
class Import < Extension
|
class Import < ConfigExtension
|
||||||
self.resource_list_manipulator_priority = 1
|
self.resource_list_manipulator_priority = 1
|
||||||
|
|
||||||
ImportFileDescriptor = Struct.new(:from, :to)
|
|
||||||
ImportPathDescriptor = Struct.new(:from, :renameProc)
|
|
||||||
|
|
||||||
# Expose `create_import_file` to config as `import_file`
|
# Expose `create_import_file` to config as `import_file`
|
||||||
expose_to_config import_file: :create_import_file
|
expose_to_config import_file: :create_import_file
|
||||||
|
|
||||||
# Expose `create_import_path` to config as `import_path`
|
# Expose `create_import_path` to config as `import_path`
|
||||||
expose_to_config import_path: :create_import_path
|
expose_to_config import_path: :create_import_path
|
||||||
|
|
||||||
def initialize(app, config={}, &block)
|
ImportFileDescriptor = Struct.new(:from, :to) do
|
||||||
super
|
def execute_descriptor(app, resources)
|
||||||
|
resources + [
|
||||||
@import_file_configs = Set.new
|
::Middleman::Sitemap::Resource.new(app.sitemap, to, from)
|
||||||
@import_path_configs = Set.new
|
]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_configuration
|
ImportPathDescriptor = Struct.new(:from, :renameProc) do
|
||||||
::Middleman::CoreExtensions::Collections::StepContext.add_to_context(:import_file, &method(:create_import_file))
|
def execute_descriptor(app, resources)
|
||||||
::Middleman::CoreExtensions::Collections::StepContext.add_to_context(:import_path, &method(:create_import_path))
|
resources + ::Middleman::Util.glob_directory(File.join(from, '**/*'))
|
||||||
|
.reject { |path| File.directory?(path) }
|
||||||
|
.map do |path|
|
||||||
|
target_path = Pathname(path).relative_path_from(Pathname(from).parent).to_s
|
||||||
|
|
||||||
|
::Middleman::Sitemap::Resource.new(
|
||||||
|
app.sitemap,
|
||||||
|
renameProc.call(target_path, path),
|
||||||
|
path
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Import an external file into `source`
|
# Import an external file into `source`
|
||||||
# @param [String] from The original path.
|
# @param [String] from The original path.
|
||||||
# @param [String] to The new path.
|
# @param [String] to The new path.
|
||||||
# @return [void]
|
# @return [void]
|
||||||
Contract String, String => Any
|
|
||||||
def create_import_file(from, to)
|
|
||||||
@import_file_configs << create_anonymous_import_file(from, to)
|
|
||||||
@app.sitemap.rebuild_resource_list!(:added_import_file)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Import an external file into `source`
|
|
||||||
# @param [String] from The original path.
|
|
||||||
# @param [String] to The new path.
|
|
||||||
# @return [ImportFileDescriptor]
|
|
||||||
Contract String, String => ImportFileDescriptor
|
Contract String, String => ImportFileDescriptor
|
||||||
def create_anonymous_import_file(from, to)
|
def create_import_file(from, to)
|
||||||
ImportFileDescriptor.new(
|
ImportFileDescriptor.new(
|
||||||
File.expand_path(from, @app.root),
|
File.expand_path(from, @app.root),
|
||||||
::Middleman::Util.normalize_path(to)
|
::Middleman::Util.normalize_path(to)
|
||||||
|
@ -54,54 +53,13 @@ module Middleman
|
||||||
# @param [String] from The original path.
|
# @param [String] from The original path.
|
||||||
# @param [Proc] block Renaming method
|
# @param [Proc] block Renaming method
|
||||||
# @return [void]
|
# @return [void]
|
||||||
Contract String, Maybe[Proc] => Any
|
Contract String, Maybe[Proc] => ImportPathDescriptor
|
||||||
def create_import_path(from, &block)
|
def create_import_path(from, &block)
|
||||||
rename_proc = block_given? ? block : proc { |path| path }
|
|
||||||
@import_path_configs << create_anonymous_import_path(from, rename_proc)
|
|
||||||
@app.sitemap.rebuild_resource_list!(:added_import_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Import an external glob into `source`
|
|
||||||
# @param [String] from The original path.
|
|
||||||
# @param [Proc] block Renaming method
|
|
||||||
# @return [ImportPathDescriptor]
|
|
||||||
Contract String, Proc => ImportPathDescriptor
|
|
||||||
def create_anonymous_import_path(from, block)
|
|
||||||
ImportPathDescriptor.new(
|
ImportPathDescriptor.new(
|
||||||
from,
|
from,
|
||||||
block
|
block_given? ? block : proc { |path| path }
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
Contract IsA['Middleman::SourceFile'] => Bool
|
|
||||||
def ignored?(file)
|
|
||||||
@app.config[:ignored_sitemap_matchers].any? { |_, fn| fn.call(file, @app) }
|
|
||||||
end
|
|
||||||
|
|
||||||
# Update the main sitemap resource list
|
|
||||||
# @return Array<Middleman::Sitemap::Resource>
|
|
||||||
Contract ResourceList => ResourceList
|
|
||||||
def manipulate_resource_list(resources)
|
|
||||||
resources + @import_file_configs.map { |c|
|
|
||||||
::Middleman::Sitemap::Resource.new(
|
|
||||||
@app.sitemap,
|
|
||||||
c[:to],
|
|
||||||
c[:from]
|
|
||||||
)
|
|
||||||
} + @import_path_configs.flat_map { |c|
|
|
||||||
::Middleman::Util.glob_directory(File.join(c[:from], '**/*'))
|
|
||||||
.reject { |path| File.directory?(path) }
|
|
||||||
.map do |path|
|
|
||||||
target_path = Pathname(path).relative_path_from(Pathname(c[:from]).parent).to_s
|
|
||||||
|
|
||||||
::Middleman::Sitemap::Resource.new(
|
|
||||||
@app.sitemap,
|
|
||||||
c[:renameProc].call(target_path, path),
|
|
||||||
path
|
|
||||||
)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,62 +6,33 @@ module Middleman
|
||||||
module Extensions
|
module Extensions
|
||||||
# Manages the list of proxy configurations and manipulates the sitemap
|
# Manages the list of proxy configurations and manipulates the sitemap
|
||||||
# to include new resources based on those configurations
|
# to include new resources based on those configurations
|
||||||
class MoveFile < Extension
|
class MoveFile < ConfigExtension
|
||||||
MoveFileDescriptor = Struct.new(:from, :to)
|
|
||||||
|
|
||||||
self.resource_list_manipulator_priority = 101
|
self.resource_list_manipulator_priority = 101
|
||||||
|
|
||||||
# Expose `create_move_file` to config as `move_file`
|
# Expose `create_move_file` to config as `move_file`
|
||||||
expose_to_config move_file: :create_move_file
|
expose_to_config move_file: :create_move_file
|
||||||
|
|
||||||
def initialize(app, config={}, &block)
|
MoveFileDescriptor = Struct.new(:from, :to) do
|
||||||
super
|
def execute_descriptor(_app, resources)
|
||||||
|
resources.each do |r|
|
||||||
|
r.destination_path = to if from == r.path || from == r.destination_path
|
||||||
|
end
|
||||||
|
|
||||||
@move_configs = Set.new
|
resources
|
||||||
end
|
end
|
||||||
|
|
||||||
def after_configuration
|
|
||||||
::Middleman::CoreExtensions::Collections::StepContext.add_to_context(:move_file, &method(:create_move_file))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Setup a move from one path to another
|
# Setup a move from one path to another
|
||||||
# @param [String] from The original path.
|
# @param [String] from The original path.
|
||||||
# @param [String] to The new path.
|
# @param [String] to The new path.
|
||||||
# @return [void]
|
# @return [void]
|
||||||
Contract String, String => Any
|
|
||||||
def create_move_file(from, to)
|
|
||||||
@move_configs << create_anonymous_move(from, to)
|
|
||||||
@app.sitemap.rebuild_resource_list!(:added_move_file)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Setup a move from one path to another
|
|
||||||
# @param [String] from The original path.
|
|
||||||
# @param [String] to The new path.
|
|
||||||
# @return [MoveFileDescriptor]
|
|
||||||
Contract String, String => MoveFileDescriptor
|
Contract String, String => MoveFileDescriptor
|
||||||
def create_anonymous_move(from, to)
|
def create_move_file(from, to)
|
||||||
MoveFileDescriptor.new(
|
MoveFileDescriptor.new(
|
||||||
::Middleman::Util.normalize_path(from),
|
::Middleman::Util.normalize_path(from),
|
||||||
::Middleman::Util.normalize_path(to)
|
::Middleman::Util.normalize_path(to)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Update the main sitemap resource list
|
|
||||||
# @return Array<Middleman::Sitemap::Resource>
|
|
||||||
Contract ResourceList => ResourceList
|
|
||||||
def manipulate_resource_list(resources)
|
|
||||||
resources.each do |r|
|
|
||||||
matches = @move_configs.select do |c|
|
|
||||||
c.from == r.path || c.from == r.destination_path
|
|
||||||
end
|
|
||||||
|
|
||||||
if c = matches.last
|
|
||||||
r.destination_path = c.to
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
resources
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,28 +6,12 @@ module Middleman
|
||||||
module Extensions
|
module Extensions
|
||||||
# Manages the list of proxy configurations and manipulates the sitemap
|
# Manages the list of proxy configurations and manipulates the sitemap
|
||||||
# to include new resources based on those configurations
|
# to include new resources based on those configurations
|
||||||
class Proxies < Extension
|
class Proxies < ConfigExtension
|
||||||
self.resource_list_manipulator_priority = 0
|
self.resource_list_manipulator_priority = 0
|
||||||
|
|
||||||
# Expose `create_proxy` as `app.proxy`
|
|
||||||
expose_to_application proxy: :create_proxy
|
|
||||||
|
|
||||||
# Expose `create_proxy` to config as `proxy`
|
# Expose `create_proxy` to config as `proxy`
|
||||||
expose_to_config proxy: :create_proxy
|
expose_to_config proxy: :create_proxy
|
||||||
|
|
||||||
def initialize(app, config={}, &block)
|
|
||||||
super
|
|
||||||
|
|
||||||
@proxy_configs = Set.new
|
|
||||||
@post_config = false
|
|
||||||
end
|
|
||||||
|
|
||||||
def after_configuration
|
|
||||||
@post_config = true
|
|
||||||
|
|
||||||
::Middleman::CoreExtensions::Collections::StepContext.add_to_context(:proxy, &method(:create_anonymous_proxy))
|
|
||||||
end
|
|
||||||
|
|
||||||
# Setup a proxy from a path to a target
|
# Setup a proxy from a path to a target
|
||||||
# @param [String] path The new, proxied path to create
|
# @param [String] path The new, proxied path to create
|
||||||
# @param [String] target The existing path that should be proxied to. This must be a real resource, not another proxy.
|
# @param [String] target The existing path that should be proxied to. This must be a real resource, not another proxy.
|
||||||
|
@ -36,51 +20,35 @@ module Middleman
|
||||||
# @option opts [Boolean] directory_indexes Whether or not the `:directory_indexes` extension applies to these paths.
|
# @option opts [Boolean] directory_indexes Whether or not the `:directory_indexes` extension applies to these paths.
|
||||||
# @option opts [Hash] locals Local variables for the template. These will be available when the template renders.
|
# @option opts [Hash] locals Local variables for the template. These will be available when the template renders.
|
||||||
# @option opts [Hash] data Extra metadata to add to the page. This is the same as frontmatter, though frontmatter will take precedence over metadata defined here. Available via {Resource#data}.
|
# @option opts [Hash] data Extra metadata to add to the page. This is the same as frontmatter, though frontmatter will take precedence over metadata defined here. Available via {Resource#data}.
|
||||||
# @return [void]
|
# @return [ProxyDescriptor]
|
||||||
Contract String, String, Maybe[Hash] => Any
|
Contract String, String, Maybe[Hash] => RespondTo[:execute_descriptor]
|
||||||
def create_proxy(path, target, opts={})
|
def create_proxy(path, target, opts={})
|
||||||
options = opts.dup
|
|
||||||
@app.ignore(target) if options.delete(:ignore)
|
|
||||||
|
|
||||||
@proxy_configs << create_anonymous_proxy(path, target, options)
|
|
||||||
@app.sitemap.rebuild_resource_list!(:added_proxy)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Setup a proxy from a path to a target
|
|
||||||
# @param [String] path The new, proxied path to create
|
|
||||||
# @param [String] target The existing path that should be proxied to. This must be a real resource, not another proxy.
|
|
||||||
# @option opts [Boolean] ignore Ignore the target from the sitemap (so only the new, proxy resource ends up in the output)
|
|
||||||
# @option opts [Symbol, Boolean, String] layout The layout name to use (e.g. `:article`) or `false` to disable layout.
|
|
||||||
# @option opts [Boolean] directory_indexes Whether or not the `:directory_indexes` extension applies to these paths.
|
|
||||||
# @option opts [Hash] locals Local variables for the template. These will be available when the template renders.
|
|
||||||
# @option opts [Hash] data Extra metadata to add to the page. This is the same as frontmatter, though frontmatter will take precedence over metadata defined here. Available via {Resource#data}.
|
|
||||||
# @return [void]
|
|
||||||
def create_anonymous_proxy(path, target, options={})
|
|
||||||
ProxyDescriptor.new(
|
ProxyDescriptor.new(
|
||||||
::Middleman::Util.normalize_path(path),
|
::Middleman::Util.normalize_path(path),
|
||||||
::Middleman::Util.normalize_path(target),
|
::Middleman::Util.normalize_path(target),
|
||||||
options
|
opts.dup
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Update the main sitemap resource list
|
|
||||||
# @return Array<Middleman::Sitemap::Resource>
|
|
||||||
Contract ResourceList => ResourceList
|
|
||||||
def manipulate_resource_list(resources)
|
|
||||||
resources + @proxy_configs.map { |c| c.to_resource(@app) }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
ProxyDescriptor = Struct.new(:path, :target, :metadata) do
|
ProxyDescriptor = Struct.new(:path, :target, :metadata) do
|
||||||
def to_resource(app)
|
def execute_descriptor(app, resources)
|
||||||
ProxyResource.new(app.sitemap, path, target).tap do |p|
|
md = metadata.dup
|
||||||
md = metadata.dup
|
should_ignore = md.delete(:ignore)
|
||||||
p.add_metadata(
|
|
||||||
locals: md.delete(:locals) || {},
|
r = ProxyResource.new(app.sitemap, path, target)
|
||||||
page: md.delete(:data) || {},
|
r.add_metadata(
|
||||||
options: md
|
locals: md.delete(:locals) || {},
|
||||||
)
|
page: md.delete(:data) || {},
|
||||||
|
options: md
|
||||||
|
)
|
||||||
|
|
||||||
|
if should_ignore
|
||||||
|
d = ::Middleman::Sitemap::Extensions::Ignores::IgnoreDescriptor.new(target)
|
||||||
|
d.execute_descriptor(app, resources)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
resources + [r]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,6 +38,8 @@ module Middleman
|
||||||
Contract METADATA_HASH
|
Contract METADATA_HASH
|
||||||
attr_reader :metadata
|
attr_reader :metadata
|
||||||
|
|
||||||
|
attr_accessor :ignored
|
||||||
|
|
||||||
# Initialize resource with parent store and URL
|
# Initialize resource with parent store and URL
|
||||||
# @param [Middleman::Sitemap::Store] store
|
# @param [Middleman::Sitemap::Store] store
|
||||||
# @param [String] path
|
# @param [String] path
|
||||||
|
@ -47,6 +49,7 @@ module Middleman
|
||||||
@store = store
|
@store = store
|
||||||
@app = @store.app
|
@app = @store.app
|
||||||
@path = path
|
@path = path
|
||||||
|
@ignored = false
|
||||||
|
|
||||||
source = Pathname(source) if source && source.is_a?(String)
|
source = Pathname(source) if source && source.is_a?(String)
|
||||||
|
|
||||||
|
@ -173,15 +176,7 @@ module Middleman
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
Contract Bool
|
Contract Bool
|
||||||
def ignored?
|
def ignored?
|
||||||
return true if @ignored
|
@ignored
|
||||||
# Ignore based on the source path (without template extensions)
|
|
||||||
return true if @app.sitemap.ignored?(path)
|
|
||||||
# This allows files to be ignored by their source file name (with template extensions)
|
|
||||||
if !self.is_a?(ProxyResource) && file_descriptor && @app.sitemap.ignored?(file_descriptor[:relative_path].to_s)
|
|
||||||
true
|
|
||||||
else
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# The preferred MIME content type for this resource based on extension or metadata
|
# The preferred MIME content type for this resource based on extension or metadata
|
||||||
|
|
|
@ -3,12 +3,6 @@ require 'active_support/core_ext/hash/deep_merge'
|
||||||
require 'monitor'
|
require 'monitor'
|
||||||
require 'hamster'
|
require 'hamster'
|
||||||
|
|
||||||
# Ignores
|
|
||||||
Middleman::Extensions.register :sitemap_ignore, auto_activate: :before_configuration do
|
|
||||||
require 'middleman-core/sitemap/extensions/ignores'
|
|
||||||
Middleman::Sitemap::Extensions::Ignores
|
|
||||||
end
|
|
||||||
|
|
||||||
# Files on Disk
|
# Files on Disk
|
||||||
Middleman::Extensions.register :sitemap_ondisk, auto_activate: :before_configuration do
|
Middleman::Extensions.register :sitemap_ondisk, auto_activate: :before_configuration do
|
||||||
require 'middleman-core/sitemap/extensions/on_disk'
|
require 'middleman-core/sitemap/extensions/on_disk'
|
||||||
|
@ -45,6 +39,12 @@ Middleman::Extensions.register :sitemap_move_files, auto_activate: :before_confi
|
||||||
Middleman::Sitemap::Extensions::MoveFile
|
Middleman::Sitemap::Extensions::MoveFile
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Ignores
|
||||||
|
Middleman::Extensions.register :sitemap_ignore, auto_activate: :before_configuration do
|
||||||
|
require 'middleman-core/sitemap/extensions/ignores'
|
||||||
|
Middleman::Sitemap::Extensions::Ignores
|
||||||
|
end
|
||||||
|
|
||||||
require 'middleman-core/contracts'
|
require 'middleman-core/contracts'
|
||||||
|
|
||||||
module Middleman
|
module Middleman
|
||||||
|
@ -108,14 +108,15 @@ module Middleman
|
||||||
[m[:priority], n]
|
[m[:priority], n]
|
||||||
end
|
end
|
||||||
|
|
||||||
rebuild_resource_list!(:registered_new)
|
rebuild_resource_list!(:"registered_new_manipulator_#{name}")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Rebuild the list of resources from scratch, using registed manipulators
|
# Rebuild the list of resources from scratch, using registed manipulators
|
||||||
# @return [void]
|
# @return [void]
|
||||||
Contract Maybe[Symbol] => Any
|
Contract Maybe[Symbol] => Any
|
||||||
def rebuild_resource_list!(_name=nil)
|
def rebuild_resource_list!(name=nil)
|
||||||
@lock.synchronize do
|
@lock.synchronize do
|
||||||
|
@app.logger.debug "== Requesting resource list rebuilding: #{name}"
|
||||||
@needs_sitemap_rebuild = true
|
@needs_sitemap_rebuild = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -159,7 +160,7 @@ module Middleman
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Invalidate our cached view of resource that are not ingnored. If your extension
|
# Invalidate our cached view of resource that are not ignored. If your extension
|
||||||
# adds ways to ignore files, you should call this to make sure #resources works right.
|
# adds ways to ignore files, you should call this to make sure #resources works right.
|
||||||
def invalidate_resources_not_ignored_cache!
|
def invalidate_resources_not_ignored_cache!
|
||||||
@resources_not_ignored = nil
|
@resources_not_ignored = nil
|
||||||
|
|
Loading…
Reference in a new issue