Compare commits

...

66 commits

Author SHA1 Message Date
Thomas Reynolds b6167b1369 Fix #2019 2016-12-03 11:32:09 -08:00
Thomas Reynolds 30217d2c04 Change how config options are passed to Thor. Removes new Thor warnings from #2017 2016-11-29 20:14:19 -08:00
Thomas Reynolds 073f273fe4 Prep 2016-11-25 14:03:56 -08:00
Thomas Reynolds e30f413376 Fix broken block ignore form. 2016-11-25 13:59:43 -08:00
Stanislav a680fb30c5 Add bower_components ignore (#2010) 2016-11-23 09:34:53 -08:00
Jonathan Allard 42e31c8c5e Make .html implicit for page IDs (#1996)
* Make .html implicit for page IDs

* Add Pry gem

* Add setting :page_id_generator to override page ID derivation
2016-11-16 21:00:16 -08:00
sandstrom 046d15cfa5 Fix addressable require (#2009) 2016-11-16 20:59:25 -08:00
Thomas Reynolds 5adea781c9 Fix up tests 2016-11-04 08:23:33 -07:00
James Pearson 97082d5fc4 Added addressable to the gemfile (#2001)
addressable is required for middleman init, but was not installed as part of a fresh install of Middleman
2016-11-04 07:56:30 -07:00
René Klačan 604c0e2b5d Fix source watcher configuration (#1999)
* Fix source watcher configuration

* Keep old Sources#initialize signature

* Poll source on path change
2016-10-31 10:50:03 -07:00
Mike Vastola 7c968b9572 Updates to support Rails 5, Rack 3 and Sinatra 2 (beta) (#1984)
* Updates to support Rails 5, Rack 3 and Sinatra 2 (beta).

- Bump upper boundary of version for Rack dependency from 2.0 to 3 (exclusive).
- Version bump sinatra for CI testing to >= 2.0.0.beta2.
- Also replaces use of String#hash in middleman-core/features/asset_host.feature
to ensure sufficiently random variables are returned.

Closes middleman/middleman#1983.

* Testing revert of the version requirements...

To confirm my changes don't cause a regression for any of:
- Rails < 5
- Sinatra < 2
- Rack < 2

* Revert "Testing revert of the version requirements..."

This reverts commit 5cf4c2a07c0814eefa573358b1bc9b0eeb62f9c1.
2016-09-13 10:25:17 +02:00
Kevin Glowacz 197093b36c Tilt 2 (#1974)
* Updates for mappings change in tilt 2

* drop RedcarpetTemplate::Redcarpet2 which was removed in tilt 2

* require Tilt 2.0 or higher

* Make use of tilt 2's extensions_for method instead
2016-09-09 00:18:34 +02:00
Kevin Glowacz ea2115f3f8 Allow for activesupport 4.2 again (#1976)
There is no current reason to remove support for 4.2
This now makes for a backwards compatible change whereas before this would
have called for a new major version of middleman-core
2016-08-30 17:22:31 -07:00
Thomas Reynolds 07651c63a6 Update Ruby version requirement. 2016-08-13 15:41:19 -07:00
Mark Rowe 65462cbc43 Improve performance of ignoring files (#1971)
* Determine the type of ignore pattern once per pattern.

Performing this work when checking when each file was ignored accounted
for around 4.5 of the 6 seconds that processing ignored files was taking
on a site with ~14,000 files and a small number of ignore patterns.
After this change, processing ignored files takes less than 1.5 seconds.

* Cache the normalized paths on Resource and SourceFile.

Normalizing the paths is expensive, so avoid doing it multiple
times. `Util::normalize_path` is marked as memoized, but this
is not effective as:

1. `memoize` doesn't appear to work with module functions.
2. Checking whether we have a memoized value is as expensive as
   normalizing the path.

This further drops the time it takes to process ignored files on a site
with ~14,000 files from ~1.5 seconds to ~0.6 seconds.
2016-08-12 16:33:18 -07:00
Eliott Appleford c264b05906 Merge pull request #1970 from bdash/source_watcher-poll_once-perf
Eliminate quadratic behavior in SourceWatcher::poll_once!
2016-08-11 10:02:38 +01:00
Mark Rowe dcd36a4f99 Eliminate quadratic behavior in SourceWatcher::poll_once!.
Both `Array#reject` and `Array#include?` have linear time
complexity. This results in quadratic time complexity when
`Array#include?` is called within `Array#reject`'s block. Using
`Array`'s difference operator gives the same result in linear time.

In a site with ~14,000 files, this drops the time taken by some calls to
`SourceWatcher::poll_once!` from ~15 seconds each to just a few
milliseconds.
2016-08-11 00:24:42 -07:00
Thomas Reynolds 7027b4933a Update .travis.yml 2016-08-03 13:00:25 -07:00
Peter Sankauskas cbad571338 Updating to activesupport version 5 (#1967) 2016-08-03 12:59:57 -07:00
sandstrom ffef14deb4 Create ISSUE_TEMPLATE.md (#1966) 2016-07-29 09:00:10 -07:00
Thomas Reynolds 62dba443a0 Fix japanese characters encoding in URLs 2016-07-10 17:03:22 -07:00
Adam Heath 389e3f5a8c Add prefix option to asset_hash (#1949)
This allows manually changing the filename so that fiel header changes
can be reflected on the CDN. E.g. if you turn on crossOrigin serving
(CORS) the asset hash doesn't change, but the CDN cache needs to be
broken in order to pickup the new header.
2016-07-02 17:55:25 -07:00
Thomas Reynolds ea39d16d81 Try to be safe 2016-06-23 12:41:23 -07:00
Peter Suschlik 1581bfc27e Convert latency option to a Fixnum (#1928)
As @vill pointed out in https://github.com/middleman/middleman/issues/1866#issuecomment-222869287
passing `--watcher-latency=2` fails because the gem `listen` expects `latency` to be an `Fixnum`.

This commit fixes this issue.
2016-06-01 14:19:13 -07:00
Thomas Reynolds e8f10fe3c2 prep 2016-05-31 13:15:37 -07:00
Thomas Reynolds 1efa585c11 Fix #1866 2016-05-31 13:15:37 -07:00
Shawn Van Ittersum 0d5c9e4313 Prevent overwrite of Slim embedded options (#1927)
* Fix middleman/middleman#1925: Slim embedded options overwrite

* Remove context_hack from Slim renderer

* Remove debugging output
2016-05-31 13:15:21 -07:00
Thomas Reynolds 51ccfe1143 only encode if current path is broken 2016-05-25 11:25:24 -07:00
Thomas Reynolds 4ffaa9dde5 Try to encode URI before parsing so spaces in paths work. Fixes #1914 2016-05-25 11:13:59 -07:00
Thomas Reynolds 6440d53e7a Add support for dotenv 2016-05-25 10:54:49 -07:00
Ben Hollis 38a9025560 Fix asset_url with asset_hash (#1919)
* Fix asset_url with asset_hash.

* Fix asset hashes.
2016-05-22 12:31:53 -07:00
Steven Sloan 5de9e86a55 allow partial lookups without a current_resource (#1912)
current_resource is only needed for relative lookups, so for lookups from source allow them to run without a current resource.
2016-05-13 13:01:21 -07:00
Thomas Reynolds ccc1cc1288 Fix ordering in tests 2016-05-11 11:48:21 -07:00
Thomas Reynolds 849fc65260 prep 2016-05-11 10:59:48 -07:00
Matthew Lehner 3e4187568b require the try core extension (#1911) 2016-05-10 15:17:28 -07:00
PiotrMisiurek 1c57626445 Fix contract for Sitemap::Store.register_resource_list_manipulator (#1907)
Contract said that optional param priority can be only a number.
But the code also handle the boolean as a value to be compatibile
with old versions

Change contract to accept both Num and Bool
2016-05-06 00:12:03 -07:00
Steven Sloan cf4d40caff loosen contract on Resource#source_file to Maybe[String] (#1906)
this could legitimately return nil if there is no file_descriptor, as would be the case for a StringResource
2016-05-05 09:08:29 -07:00
Dennis Günnewig 599cf1e6d3 Use https:// to clone templates (#1901)
Using git://-protocol for cloning git repositories does not work via
HTTP proxies. By replacing it with https:// instead it works for more
users.
2016-04-29 14:23:55 -07:00
Thomas Reynolds 3ebd902ec3 Move capybara dep 2016-04-28 15:44:50 -07:00
Thomas Reynolds 158c3e9f25 Test new ruby 2016-04-28 08:47:48 -07:00
Thomas Reynolds cdcd2bd42d Expose development? and production? helpers to template context. Related #1895 2016-04-26 09:24:49 -07:00
Thomas Bruketta 4918704800 Allow numbers to be unique page_ids (#1886) 2016-04-25 09:51:11 -07:00
Nick Giancola 8a8ee768ac Fix/issue 1889 (#1892)
* Add regression test for infinite loop issue in Util::step_through_extensions (#1889)

* Prevent infinite loop when encountering files where base filename is a possible templating engine
2016-04-25 09:50:51 -07:00
Thomas Reynolds 71a20bb3ee Merge pull request #1891 from danielbayerlein/incompatibility-of-listen
Incompatibility of listen with Ruby < 2.2
2016-04-24 16:59:07 -07:00
Daniel Bayerlein ce58073539 Incompatibility of listen with Ruby < 2.2 fixed 2016-04-24 09:57:13 +02:00
Thomas Reynolds 13d62cb276 Experiment with non-rack rewriters 2016-04-22 15:52:42 -07:00
Thomas Reynolds 0f2bc1e0ea Minor perf tweaks 2016-04-21 16:12:33 -07:00
Thomas Reynolds a14934e08b Merge pull request #1888 from mortonfox/patch-1
Fix RubyInstaller Devkit link.
2016-04-20 14:22:42 -07:00
Morton Fox a95f721490 Fix RubyInstaller Devkit link. 2016-04-20 00:27:15 -04:00
Thomas Reynolds 2b0f720850 Bad merge 2016-04-19 11:54:00 -07:00
Thomas Reynolds b386dcdc40 Fix #1884 for realz 2016-04-19 11:08:23 -07:00
Thomas Reynolds 0ac5650229 Throw when trying to overwrite a template context value. Fixes #1884 2016-04-19 11:06:51 -07:00
Thomas Reynolds 7e3baed196 Throw when trying to overwrite a template context value. Fixes #1884 2016-04-19 10:37:23 -07:00
Thomas Reynolds 09a7d89fd3 Throw when trying to overwrite a template context value. Fixes #1884 2016-04-19 10:36:49 -07:00
Thomas Reynolds 6872e07d34 Expose extensions in config. Helps middleman/middleman-sprockets#111 2016-04-17 13:02:23 -07:00
Thomas Reynolds a01656df39 Steps should try passing unknown methods to config context before failing. Fixes #1879 2016-04-14 11:30:46 -07:00
Thomas Reynolds f2535f4fda Bump dep 2016-04-13 09:23:28 -07:00
Thomas Reynolds dd2413857e prep 2016-04-12 13:12:09 -07:00
Thomas Reynolds b058d26564 Bump fast image 2016-04-12 13:05:46 -07:00
Thomas Reynolds b794961916 Only rewrite urls in sitemap. Fixes #1873 2016-04-12 12:53:50 -07:00
Thomas Reynolds 4791e01f10 Merge pull request #1877 from middleman/bugfix/restarting-external-pipeline
Allow restarting external-pipeline without orphaning processes
2016-04-12 10:23:38 -07:00
Thomas Reynolds ac974ca05f Allow restarting external-pipeline without orphaning processes 2016-04-12 10:00:09 -07:00
Thomas Reynolds c7669609e6 Merge pull request #1876 from middleman/bugfix/global-collection-steps
Make global config access work inside steps
2016-04-11 16:23:07 -07:00
Thomas Reynolds e99649b33e Make global config access work inside steps 2016-04-11 16:02:31 -07:00
Thomas Reynolds ec213efb95 Merge pull request #1871 from luskjh/sprockets-readme-link-change
Update link in README to sprockets repository.
2016-04-08 13:39:57 -05:00
Joshua Lusk 21f4f40e21 Update README.md 2016-04-06 12:37:15 -04:00
114 changed files with 1131 additions and 337 deletions

2
.gitignore vendored
View file

@ -1,4 +1,6 @@
.byebug_history
npm-debug.log npm-debug.log
manifest.yaml
/.bundle /.bundle
.DS_Store .DS_Store
coverage coverage

View file

@ -67,3 +67,5 @@ Style/MultilineBlockChain:
Enabled: false Enabled: false
Style/SpecialGlobalVars: Style/SpecialGlobalVars:
Enabled: false Enabled: false
Style/FrozenStringLiteralComment:
Enabled: false

View file

@ -5,17 +5,14 @@ before_script:
- bundle update - bundle update
rvm: rvm:
- ruby-head - ruby-head
- 2.3.0 - 2.3.1
- 2.2.4 - 2.2.4
- 2.1
- 2.0
os: os:
- linux - linux
# - osx # - osx
matrix: matrix:
fast_finish: true fast_finish: true
allow_failures: allow_failures:
- rvm: 2.3.0
- rvm: ruby-head - rvm: ruby-head
env: env:
global: global:

View file

@ -1,6 +1,49 @@
master master
=== ===
# 4.1.13
* Change how config options are passed to Thor. Removes new Thor warnings from #2017
# 4.1.12
* Fix broken `ignore { |p| true }` form.
# 4.1.11
* Upgrade to Rack 2.
# 4.1.10
* Fix unicode issues in URL deeplinks.
* Add prefix option to asset_hash (#1949)
# 4.1.9
* Fix `--watcher-*` CLI flags.
* Allow spaces in paths to work with `link_to`. Fixes #1914
* Add support for dotenv
* Fix asset_url with asset_hash (#1919)
* Allow partial lookups without a current_resource (#1912)
# 4.1.8
* Expose `development?` and `production?` helpers to template context.
* require the `try` core extension (#1911)
* Fix contract for Sitemap::Store.register_resource_list_manipulator (#1907)
* Loosen contract on Resource#source_file to Maybe[String] (#1906)
* Let collection loops access ConfigContext for helpers. #1879
* Use https:// to clone templates (#1901)
* Allow numbers to be unique page_ids (#1886)
* Prevent infinite loop when encountering files where base filename is a possible templating engine
# 4.1.7
* Upgrade fastimage to 2.0
* Fix shutdown of external_pipeline commands when config.rb is changed. #1877
* Allow calls to `app.` to work as collections after initial config parse. #1876
# 4.1.5-4.1.6 # 4.1.5-4.1.6
* Fix file recursion when looking for possible asset dependencies. Major preview server performance improvement. * Fix file recursion when looking for possible asset dependencies. Major preview server performance improvement.

14
Gemfile
View file

@ -5,12 +5,16 @@ gem 'rake', '~> 10.3', require: false
gem 'yard', '~> 0.8', require: false gem 'yard', '~> 0.8', require: false
# Test tools # Test tools
gem 'pry', '~> 0.10', group: :development, require: false gem 'byebug'
gem 'pry-byebug'
gem 'pry-stack_explorer'
gem 'aruba', '~> 0.7.4', require: false gem 'aruba', '~> 0.7.4', require: false
gem 'rspec', '~> 3.0', require: false gem 'rspec', '~> 3.0', require: false
gem 'cucumber', '~> 2.0', require: false gem 'cucumber', '~> 2.0', require: false
gem 'addressable', '~> 2.4.0', require: false
# Pry tools
gem 'pry'
gem 'pry-stack_explorer'
gem 'pry-rescue'
# Optional middleman dependencies, included for tests # Optional middleman dependencies, included for tests
gem 'haml', '>= 4.0.5', require: false gem 'haml', '>= 4.0.5', require: false
@ -20,7 +24,7 @@ gem 'kramdown', '~> 1.2', require: false
gem 'slim', '>= 2.0', require: false gem 'slim', '>= 2.0', require: false
gem 'liquid', '>= 2.6', require: false gem 'liquid', '>= 2.6', require: false
gem 'stylus', '>= 1.0', require: false gem 'stylus', '>= 1.0', require: false
gem 'sinatra', '>= 1.4', require: false gem 'sinatra', '>= 2.0.0.beta2', require: false
gem 'redcarpet', '>= 3.1', require: false gem 'redcarpet', '>= 3.1', require: false
# Dns server to test preview server # Dns server to test preview server
@ -28,7 +32,7 @@ gem 'rubydns', '~> 1.0.1', require: false
# To test javascript # To test javascript
gem 'poltergeist', '~> 1.8', require: false gem 'poltergeist', '~> 1.8', require: false
gem 'phantomjs', '~> 1.9.8.0', require: false gem 'phantomjs', '~> 2.1.1.0', require: false
# For less, note there is no compatible JS runtime for windows # For less, note there is no compatible JS runtime for windows
gem 'therubyrhino', '>= 2.0', platforms: :jruby gem 'therubyrhino', '>= 2.0', platforms: :jruby

9
ISSUE_TEMPLATE.md Normal file
View file

@ -0,0 +1,9 @@
## Expected behavior and actual behavior
## Steps to reproduce the problem (from a clean middleman installation)
## Additional information
- Ruby version:
- Middleman version:
- OS version:

View file

@ -10,7 +10,7 @@ The last few years have seen an explosion in the amount and variety of tools dev
* [Sass](http://sass-lang.com/) for DRY stylesheets * [Sass](http://sass-lang.com/) for DRY stylesheets
* [CoffeeScript](http://coffeescript.org/) for safer and less verbose javascript * [CoffeeScript](http://coffeescript.org/) for safer and less verbose javascript
* Multiple asset management solutions, including [Sprockets](https://github.com/sstephenson/sprockets) * Multiple asset management solutions, including [Sprockets](https://github.com/rails/sprockets)
* [ERb](http://ruby-doc.org/stdlib-2.0.0/libdoc/erb/rdoc/ERB.html) & [Haml](http://haml.info/) for dynamic pages and simplified HTML syntax * [ERb](http://ruby-doc.org/stdlib-2.0.0/libdoc/erb/rdoc/ERB.html) & [Haml](http://haml.info/) for dynamic pages and simplified HTML syntax
**Middleman** gives the stand-alone developer access to all these tools and many, many more. Why would you use a stand-alone framework instead of Ruby on Rails? **Middleman** gives the stand-alone developer access to all these tools and many, many more. Why would you use a stand-alone framework instead of Ruby on Rails?
@ -121,6 +121,6 @@ Copyright (c) 2010-2015 Thomas Reynolds. MIT Licensed, see [LICENSE] for details
[codeclimate]: https://codeclimate.com/github/middleman/middleman [codeclimate]: https://codeclimate.com/github/middleman/middleman
[gittip]: https://www.gittip.com/middleman/ [gittip]: https://www.gittip.com/middleman/
[rubyinstaller]: http://rubyinstaller.org/ [rubyinstaller]: http://rubyinstaller.org/
[RubyInstaller-Devkit]: http:rubyinstaller.org/add-ons/devkit/ [RubyInstaller-Devkit]: http://rubyinstaller.org/add-ons/devkit/
[rubydoc]: http://rubydoc.info/github/middleman/middleman [rubydoc]: http://rubydoc.info/github/middleman/middleman
[LICENSE]: https://github.com/middleman/middleman/blob/master/LICENSE.md [LICENSE]: https://github.com/middleman/middleman/blob/master/LICENSE.md

View file

@ -9,6 +9,9 @@ end
require "middleman-core/load_paths" require "middleman-core/load_paths"
Middleman.setup_load_paths Middleman.setup_load_paths
require 'dotenv'
::Dotenv.load
require 'middleman-core' require 'middleman-core'
require 'middleman-core/logger' require 'middleman-core/logger'
@ -22,12 +25,10 @@ module Middleman::Cli
if setting.default.is_a?(String) || setting.default.is_a?(NilClass) if setting.default.is_a?(String) || setting.default.is_a?(NilClass)
base.class_option setting.key, base.class_option setting.key,
type: :string, type: :string,
default: :undefined,
desc: setting.description desc: setting.description
elsif setting.default.is_a?(TrueClass) || setting.default.is_a?(FalseClass) elsif setting.default.is_a?(TrueClass) || setting.default.is_a?(FalseClass)
base.class_option setting.key, base.class_option setting.key,
type: :boolean, type: :boolean,
default: :undefined,
desc: setting.description desc: setting.description
end end
end end
@ -46,6 +47,8 @@ end
::Middleman::Logger.singleton(3) ::Middleman::Logger.singleton(3)
::Middleman::Cli.config = ::Middleman::Application.new do ::Middleman::Cli.config = ::Middleman::Application.new do
#
config[:environment] = (ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development').to_sym
config[:mode] = :config config[:mode] = :config
config[:exit_before_ready] = true config[:exit_before_ready] = true
config[:watcher_disable] = true config[:watcher_disable] = true

View file

@ -10,7 +10,7 @@ module Middleman::Cli
class_option :environment, class_option :environment,
aliases: '-e', aliases: '-e',
default: :production default: ENV['MM_ENV'] || ENV['RACK_ENV'] || :production
class_option :clean, class_option :clean,
type: :boolean, type: :boolean,
default: true, default: true,
@ -29,7 +29,7 @@ module Middleman::Cli
default: false, default: false,
desc: 'Print debug messages' desc: 'Print debug messages'
class_option :instrument, class_option :instrument,
type: :string, type: :boolean,
default: false, default: false,
desc: 'Print instrument messages' desc: 'Print instrument messages'
class_option :profile, class_option :profile,
@ -64,7 +64,7 @@ module Middleman::Cli
config[:mode] = :build config[:mode] = :build
config[:show_exceptions] = false config[:show_exceptions] = false
config[:cli_options] = cli_options.each_with_object({}) do |(k, v), sum| config[:cli_options] = cli_options.each_with_object({}) do |(k, v), sum|
sum[k] = v unless v == :undefined sum[k] = v
end end
end end

View file

@ -113,7 +113,7 @@ module Middleman::Cli
end end
def repository_path(repo) def repository_path(repo)
repo.include?('://') || repo.include?('git@') ? repo : "git://github.com/#{repo}.git" repo.include?('://') || repo.include?('git@') ? repo : "https://github.com/#{repo}.git"
end end
# Add to CLI # Add to CLI

View file

@ -17,7 +17,7 @@ module Middleman::Cli
default: false, default: false,
desc: 'Print debug messages' desc: 'Print debug messages'
class_option :instrument, class_option :instrument,
type: :string, type: :boolean,
default: false, default: false,
desc: 'Print instrument messages' desc: 'Print instrument messages'
class_option :profile, class_option :profile,

View file

@ -17,7 +17,7 @@ Gem::Specification.new do |s|
s.test_files = `git ls-files -z -- {fixtures,features}/*`.split("\0") s.test_files = `git ls-files -z -- {fixtures,features}/*`.split("\0")
s.executable = 'middleman' s.executable = 'middleman'
s.require_path = 'lib' s.require_path = 'lib'
s.required_ruby_version = '>= 2.0.0' s.required_ruby_version = '>= 2.2.0'
# CLI # CLI
s.add_dependency('thor', ['>= 0.17.0', '< 2.0']) s.add_dependency('thor', ['>= 0.17.0', '< 2.0'])

View file

@ -111,28 +111,29 @@ Feature: Assets get file hashes appended to them and references to them are upda
Given a fixture app "asset-hash-host-app" Given a fixture app "asset-hash-host-app"
And a file named "config.rb" with: And a file named "config.rb" with:
""" """
set :sass_source_maps, false
activate :asset_hash activate :asset_hash
activate :directory_indexes activate :directory_indexes
activate :asset_host, host: 'http://middlemanapp.com' activate :asset_host, host: 'http://middlemanapp.com'
""" """
Given the Server is running at "asset-hash-host-app" Given the Server is running at "asset-hash-host-app"
When I go to "/" When I go to "/"
Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.css"' Then I should see 'href="http://middlemanapp.com/stylesheets/site-7474cadd.css"'
Then I should see 'href="http://middlemanapp.com/stylesheets/fragment-7000b132.css"' Then I should see 'href="http://middlemanapp.com/stylesheets/fragment-2902933e.css"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg#test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg#test"'
When I go to "/subdir/" When I go to "/subdir/"
Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.css"' Then I should see 'href="http://middlemanapp.com/stylesheets/site-7474cadd.css"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"'
When I go to "/other/" When I go to "/other/"
Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.css"' Then I should see 'href="http://middlemanapp.com/stylesheets/site-7474cadd.css"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg#test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg#test"'
When I go to "/stylesheets/fragment-7000b132.css" When I go to "/stylesheets/fragment-2902933e.css"
And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg");' And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg");'
And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg?test");' And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg?test");'
And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test");' And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test");'
@ -142,28 +143,29 @@ Feature: Assets get file hashes appended to them and references to them are upda
Given a fixture app "asset-hash-host-app" Given a fixture app "asset-hash-host-app"
And a file named "config.rb" with: And a file named "config.rb" with:
""" """
set :sass_source_maps, false
activate :asset_host, host: 'http://middlemanapp.com' activate :asset_host, host: 'http://middlemanapp.com'
activate :directory_indexes activate :directory_indexes
activate :asset_hash activate :asset_hash
""" """
Given the Server is running at "asset-hash-host-app" Given the Server is running at "asset-hash-host-app"
When I go to "/" When I go to "/"
Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.css"' Then I should see 'href="http://middlemanapp.com/stylesheets/site-7474cadd.css"'
Then I should see 'href="http://middlemanapp.com/stylesheets/fragment-7000b132.css"' Then I should see 'href="http://middlemanapp.com/stylesheets/fragment-2902933e.css"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg#test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg#test"'
When I go to "/subdir/" When I go to "/subdir/"
Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.css"' Then I should see 'href="http://middlemanapp.com/stylesheets/site-7474cadd.css"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"'
When I go to "/other/" When I go to "/other/"
Then I should see 'href="http://middlemanapp.com/stylesheets/site-210612a0.css"' Then I should see 'href="http://middlemanapp.com/stylesheets/site-7474cadd.css"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test"'
And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg#test"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg#test"'
When I go to "/stylesheets/fragment-7000b132.css" When I go to "/stylesheets/fragment-2902933e.css"
And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg")' And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg")'
And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg?test")' And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg?test")'
And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test")' And I should see 'url("http://middlemanapp.com/images/100px-5fd6fb90.jpg?#test")'
@ -306,3 +308,17 @@ Feature: Assets get file hashes appended to them and references to them are upda
| javascripts/application.js.map | | javascripts/application.js.map |
And the file "javascripts/application-4553338c.js" should contain "//# sourceMappingURL=application.js-22cc2b5f.map" And the file "javascripts/application-4553338c.js" should contain "//# sourceMappingURL=application.js-22cc2b5f.map"
Scenario: Hashes can contain a prefix
Given a successfully built app at "asset-hash-prefix"
When I cd to "build"
Then the following files should exist:
| index.html |
| javascripts/application-myprefix-4553338c.js |
| javascripts/application.js-myprefix-22cc2b5f.map |
| index.html |
And the following files should not exist:
| javascripts/application.js |
| javascripts/application.js.map |
And the file "javascripts/application-myprefix-4553338c.js" should contain "//# sourceMappingURL=application.js-myprefix-22cc2b5f.map"

View file

@ -25,7 +25,8 @@ Feature: Alternate between multiple asset hosts
And a file named "config.rb" with: And a file named "config.rb" with:
""" """
activate :asset_host, host: Proc.new { |asset| activate :asset_host, host: Proc.new { |asset|
"http://assets%d.example.com" % (asset.hash % 4) hash = Digest::MD5.digest(asset).bytes.map!(&:ord).reduce(&:+)
"http://assets%d.example.com" % (hash % 4)
} }
""" """
And the Server is running And the Server is running

View file

@ -144,6 +144,33 @@ Feature: Collections
And I should see 'Article: Blog3 Another Article' And I should see 'Article: Blog3 Another Article'
And I should see 'Article: Blog2 Yet Another Article' And I should see 'Article: Blog2 Yet Another Article'
Scenario: Work with local helpers
Given a fixture app "collections-app"
And a file named "config.rb" with:
"""
module TestHelper
def help_me
"ok"
end
end
include TestHelper
data.articles.each_with_index do |a, i|
proxy "/#{i}-#{help_me}.html", a
end
"""
And a file named "data/articles.yaml" with:
"""
---
- "/blog1/2011-01-01-new-article.html"
- "/blog2/2011-01-02-another-article.html"
"""
Given the Server is running at "collections-app"
When I go to "0-ok.html"
Then I should see 'Newer Article Content'
When I go to "1-ok.html"
Then I should see 'Another Article Content'
Scenario: Collected data update with file changes Scenario: Collected data update with file changes
Given a fixture app "collections-app" Given a fixture app "collections-app"

View file

@ -22,7 +22,7 @@ Feature: Neighboring YAML Front Matter
Then I should not see "---" Then I should not see "---"
When I go to "/raw-front-matter.php.frontmatter" When I go to "/raw-front-matter.php.frontmatter"
Then I should see "File Not Found" Then I should see "File Not Found"
Scenario: YAML not on first line, with encoding Scenario: YAML not on first line, with encoding
Given the Server is running at "frontmatter-neighbor-app" Given the Server is running at "frontmatter-neighbor-app"
When I go to "/front-matter-encoding.html" When I go to "/front-matter-encoding.html"
@ -35,7 +35,7 @@ Feature: Neighboring YAML Front Matter
Given the Server is running at "frontmatter-neighbor-app" Given the Server is running at "frontmatter-neighbor-app"
And the file "source/front-matter-change.html.erb" has the contents And the file "source/front-matter-change.html.erb" has the contents
""" """
<%= current_page.data.title %> FileA <%= current_page.data.title %>
""" """
And the file "source/front-matter-change.html.erb.frontmatter" has the contents And the file "source/front-matter-change.html.erb.frontmatter" has the contents
""" """
@ -43,6 +43,8 @@ Feature: Neighboring YAML Front Matter
title: Hello World title: Hello World
layout: false layout: false
--- ---
FileB
""" """
When I go to "/front-matter-change.html" When I go to "/front-matter-change.html"
Then I should see "Hello World" Then I should see "Hello World"
@ -52,6 +54,8 @@ Feature: Neighboring YAML Front Matter
title: Hola Mundo title: Hola Mundo
layout: false layout: false
--- ---
FileC
""" """
When I go to "/front-matter-change.html" When I go to "/front-matter-change.html"
Then I should see "Hola Mundo" Then I should see "Hola Mundo"

View file

@ -40,19 +40,29 @@ Feature: link_to helper
""" """
absolute: <%= link_to "Needs Index", "/needs_index.html", relative: true %> absolute: <%= link_to "Needs Index", "/needs_index.html", relative: true %>
relative: <%= link_to "Relative", "needs_index.html", relative: true %> relative: <%= link_to "Relative", "needs_index.html", relative: true %>
absolute spaces: <%= link_to "Spaces Index", "/evil spaces.html", relative: true %>
relative spaces: <%= link_to "Spaces Relative", "evil spaces.html", relative: true %>
""" """
And a file named "source/link_to/sub.html.erb" with: And a file named "source/link_to/sub.html.erb" with:
""" """
absolute: <%= link_to "Needs Index", "/needs_index.html", relative: true %> absolute: <%= link_to "Needs Index", "/needs_index.html", relative: true %>
relative: <%= link_to "Relative", "../needs_index.html", relative: true %> relative: <%= link_to "Relative", "../needs_index.html", relative: true %>
absolute spaces: <%= link_to "Spaces Index", "/evil spaces.html", relative: true %>
relative spaces: <%= link_to "Spaces Relative", "../evil spaces.html", relative: true %>
""" """
And the Server is running at "indexable-app" And the Server is running at "indexable-app"
When I go to "/link_to.html" When I go to "/link_to.html"
Then I should see 'absolute: <a href="needs_index.html">Needs Index</a>' Then I should see 'absolute: <a href="needs_index.html">Needs Index</a>'
Then I should see 'relative: <a href="needs_index.html">Relative</a>' Then I should see 'relative: <a href="needs_index.html">Relative</a>'
Then I should see 'absolute spaces: <a href="evil%20spaces.html">Spaces Index</a>'
Then I should see 'relative spaces: <a href="evil%20spaces.html">Spaces Relative</a>'
When I go to "/link_to/sub.html" When I go to "/link_to/sub.html"
Then I should see 'absolute: <a href="../needs_index.html">Needs Index</a>' Then I should see 'absolute: <a href="../needs_index.html">Needs Index</a>'
Then I should see 'relative: <a href="../needs_index.html">Relative</a>' Then I should see 'relative: <a href="../needs_index.html">Relative</a>'
Then I should see 'absolute spaces: <a href="../evil%20spaces.html">Spaces Index</a>'
Then I should see 'relative spaces: <a href="../evil%20spaces.html">Spaces Relative</a>'
Scenario: link_to relative works with strip_index_file Scenario: link_to relative works with strip_index_file
Given a fixture app "indexable-app" Given a fixture app "indexable-app"
@ -113,7 +123,7 @@ Feature: link_to helper
When I go to "/link_to/sub.html" When I go to "/link_to/sub.html"
Then I should see 'absolute: <a href="../needs_index.html">Needs Index</a>' Then I should see 'absolute: <a href="../needs_index.html">Needs Index</a>'
Then I should see 'relative: <a href="../needs_index.html">Relative</a>' Then I should see 'relative: <a href="../needs_index.html">Relative</a>'
Scenario: link_to knows about directory indexes Scenario: link_to knows about directory indexes
Given a fixture app "indexable-app" Given a fixture app "indexable-app"
And a file named "source/link_to.html.erb" with: And a file named "source/link_to.html.erb" with:

View file

@ -4,7 +4,7 @@ Feature: i18n Paths
Given a fixture app "empty-app" Given a fixture app "empty-app"
And a file named "data/pages.yml" with: And a file named "data/pages.yml" with:
""" """
- hello.html - hello.html
""" """
And a file named "locales/en.yml" with: And a file named "locales/en.yml" with:
""" """
@ -50,24 +50,24 @@ Feature: i18n Paths
Given the Server is running at "empty-app" Given the Server is running at "empty-app"
When I go to "/hello.html" When I go to "/hello.html"
Then I should see "Page: Hello" Then I should see "Page: Hello"
Then I should see '<a class="current" href="/index.html">Current Home</a>' Then I should see '<a href="/index.html" class="current">Current Home</a>'
Then I should see '<a title="Other Home" href="/es/index.html">Other Home</a>' Then I should see '<a href="/es/index.html" title="Other Home">Other Home</a>'
Then I should see '<a class="current" href="/index.html"><span>Home: Current Block</span></a>' Then I should see '<a href="/index.html" class="current"><span>Home: Current Block</span></a>'
Then I should see '<a title="Other Home" href="/es/index.html"><span>Home: Other Block</span></a>' Then I should see '<a href="/es/index.html" title="Other Home"><span>Home: Other Block</span></a>'
Then I should see '<a class="current" href="/hello.html">Current hello.html</a>' Then I should see '<a href="/hello.html" class="current">Current hello.html</a>'
Then I should see '<a title="Other hello.html" href="/es/hola.html">Other hello.html</a>' Then I should see '<a href="/es/hola.html" title="Other hello.html">Other hello.html</a>'
Then I should see '<a class="current" href="/hello.html"><span>Current Block</span></a>' Then I should see '<a href="/hello.html" class="current"><span>Current Block</span></a>'
Then I should see '<a title="Other hello.html" href="/es/hola.html"><span>Other Block</span></a>' Then I should see '<a href="/es/hola.html" title="Other hello.html"><span>Other Block</span></a>'
When I go to "/es/hola.html" When I go to "/es/hola.html"
Then I should see "Page: Hola" Then I should see "Page: Hola"
Then I should see '<a class="current" href="/es/index.html">Current Home</a>' Then I should see '<a href="/es/index.html" class="current">Current Home</a>'
Then I should see '<a title="Other Home" href="/index.html">Other Home</a>' Then I should see '<a href="/index.html" title="Other Home">Other Home</a>'
Then I should see '<a class="current" href="/es/index.html"><span>Home: Current Block</span></a>' Then I should see '<a href="/es/index.html" class="current"><span>Home: Current Block</span></a>'
Then I should see '<a title="Other Home" href="/index.html"><span>Home: Other Block</span></a>' Then I should see '<a href="/index.html" title="Other Home"><span>Home: Other Block</span></a>'
Then I should see '<a class="current" href="/es/hola.html">Current hello.html</a>' Then I should see '<a href="/es/hola.html" class="current">Current hello.html</a>'
Then I should see '<a title="Other hello.html" href="/hello.html">Other hello.html</a>' Then I should see '<a href="/hello.html" title="Other hello.html">Other hello.html</a>'
Then I should see '<a class="current" href="/es/hola.html"><span>Current Block</span></a>' Then I should see '<a href="/es/hola.html" class="current"><span>Current Block</span></a>'
Then I should see '<a title="Other hello.html" href="/hello.html"><span>Other Block</span></a>' Then I should see '<a href="/hello.html" title="Other hello.html"><span>Other Block</span></a>'
Scenario: link_to is i18n aware and supports relative_links Scenario: link_to is i18n aware and supports relative_links
Given a fixture app "empty-app" Given a fixture app "empty-app"
@ -124,30 +124,30 @@ Feature: i18n Paths
Then I should see "assets/css/main.css" Then I should see "assets/css/main.css"
When I go to "/hello.html" When I go to "/hello.html"
Then I should see "Page: Hello" Then I should see "Page: Hello"
Then I should see '<a class="current" href="index.html">Current Home</a>' Then I should see '<a href="index.html" class="current">Current Home</a>'
Then I should see '<a title="Other Home" href="es/index.html">Other Home</a>' Then I should see '<a href="es/index.html" title="Other Home">Other Home</a>'
Then I should see '<a class="current" href="index.html"><span>Home: Current Block</span></a>' Then I should see '<a href="index.html" class="current"><span>Home: Current Block</span></a>'
Then I should see '<a title="Other Home" href="es/index.html"><span>Home: Other Block</span></a>' Then I should see '<a href="es/index.html" title="Other Home"><span>Home: Other Block</span></a>'
Then I should see '<a class="current" href="hello.html">Current hello.html</a>' Then I should see '<a href="hello.html" class="current">Current hello.html</a>'
Then I should see '<a title="Other hello.html" href="es/hola.html">Other hello.html</a>' Then I should see '<a href="es/hola.html" title="Other hello.html">Other hello.html</a>'
Then I should see '<a class="current" href="hello.html"><span>Current Block</span></a>' Then I should see '<a href="hello.html" class="current"><span>Current Block</span></a>'
Then I should see '<a title="Other hello.html" href="es/hola.html"><span>Other Block</span></a>' Then I should see '<a href="es/hola.html" title="Other hello.html"><span>Other Block</span></a>'
When I go to "/es/hola.html" When I go to "/es/hola.html"
Then I should see "Page: Hola" Then I should see "Page: Hola"
Then I should see '<a class="current" href="index.html">Current Home</a>' Then I should see '<a href="index.html" class="current">Current Home</a>'
Then I should see '<a title="Other Home" href="../index.html">Other Home</a>' Then I should see '<a href="../index.html" title="Other Home">Other Home</a>'
Then I should see '<a class="current" href="index.html"><span>Home: Current Block</span></a>' Then I should see '<a href="index.html" class="current"><span>Home: Current Block</span></a>'
Then I should see '<a title="Other Home" href="../index.html"><span>Home: Other Block</span></a>' Then I should see '<a href="../index.html" title="Other Home"><span>Home: Other Block</span></a>'
Then I should see '<a class="current" href="hola.html">Current hello.html</a>' Then I should see '<a href="hola.html" class="current">Current hello.html</a>'
Then I should see '<a title="Other hello.html" href="../hello.html">Other hello.html</a>' Then I should see '<a href="../hello.html" title="Other hello.html">Other hello.html</a>'
Then I should see '<a class="current" href="hola.html"><span>Current Block</span></a>' Then I should see '<a href="hola.html" class="current"><span>Current Block</span></a>'
Then I should see '<a title="Other hello.html" href="../hello.html"><span>Other Block</span></a>' Then I should see '<a href="../hello.html" title="Other hello.html"><span>Other Block</span></a>'
Scenario: url_for is i18n aware Scenario: url_for is i18n aware
Given a fixture app "empty-app" Given a fixture app "empty-app"
And a file named "data/pages.yml" with: And a file named "data/pages.yml" with:
""" """
- hello.html - hello.html
- article.html - article.html
""" """
And a file named "locales/en.yml" with: And a file named "locales/en.yml" with:

View file

@ -0,0 +1,41 @@
Feature: Markdown support in Slim
In order to test support of the Slim markdown filter
Scenario: Markdown filter in Slim works
Given a fixture app "markdown-in-slim-app"
And a file named "config.rb" with:
"""
set :markdown_engine, :redcarpet
activate :directory_indexes
"""
And a file named "source/markdown_filter.html.slim" with:
"""
markdown:
# H1
paragraph
"""
Given the Server is running at "markdown-in-slim-app"
When I go to "/markdown_filter/"
Then I should see ">H1</h1>"
Then I should see "<p>paragraph</p>"
Scenario: Markdown filter in Slim uses our link_to and image_tag helpers
Given a fixture app "markdown-in-slim-app"
And a file named "config.rb" with:
"""
set :markdown_engine, :redcarpet
activate :directory_indexes
"""
And a file named "source/link_and_image.html.slim" with:
"""
markdown:
[A link](/link_target.html)
![image](blank.gif)
"""
Given the Server is running at "markdown-in-slim-app"
When I go to "/link_and_image/"
Then I should see "/link_target/"
Then I should see 'src="/images/blank.gif"'

View file

@ -3,14 +3,60 @@ Feature: Page IDs
Scenario: link_to works with blocks (erb) Scenario: link_to works with blocks (erb)
Given the Server is running at "page-id-app" Given the Server is running at "page-id-app"
When I go to "/index.html" When I go to "/index.html"
Then I should see "I am: index.html" Then I should see "I am: index"
And I should see "URL1: /fm.html" And I should see "URL1: /fm.html"
And I should see "URL2: /2.html" And I should see "URL2: /2.html"
And I should see 'URL3: <a href="/3.html">Hi</a>' And I should see 'URL3: <a href="/3.html">Hi</a>'
And I should see 'URL4: <a href="/overwrites/from-default.html">Sym</a>' And I should see 'URL4: <a href="/overwrites/from-default.html">Sym</a>'
And I should see 'URL5: <a href="/implicit.html">Imp</a>'
And I should see 'URL6: <a href="/folder/foldern.html">Foldern</a>'
And I should see 'URL7: <a href="/feed.xml">Feed</a>'
When I go to "/fm.html" When I go to "/fm.html"
Then I should see "I am: frontmatter" Then I should see "I am: frontmatter"
When I go to "/implicit.html"
Then I should see "I am: implicit"
When I go to "/feed.xml"
Then I should see "I am: feed.xml"
When I go to "/folder/foldern.html"
Then I should see "I am: folder/foldern"
When I go to "/1.html"
Then I should see "I am: page1"
When I go to "/2.html"
Then I should see "I am: page2"
When I go to "/3.html"
Then I should see "I am: page3"
When I go to "/overwrites/from-default.html"
Then I should see "I am: something-else"
When I go to "/overwrites/from-frontmatter.html"
Then I should see "I am: from_frontmatter"
Scenario: Override page ID derivation with a proc
Given a fixture app "page-id-app"
And app "page-id-app" is using config "proc"
And the Server is running at "page-id-app"
When I go to "/index.html"
Then I should see "I am: index.html-foo"
And I should see "URL1: /fm.html"
And I should see "URL2: /2.html"
And I should see 'URL3: <a href="/3.html">Hi</a>'
And I should see 'URL4: <a href="/overwrites/from-default.html">Sym</a>'
And I should see 'URL8: <a href="/implicit.html">Imp</a>'
And I should see 'URL9: <a href="/folder/foldern.html">Foldern</a>'
And I should see 'URL10: <a href="/feed.xml">Feed</a>'
When I go to "/fm.html"
Then I should see "I am: frontmatter"
When I go to "/implicit.html"
Then I should see "I am: implicit.html-foo"
When I go to "/feed.xml"
Then I should see "I am: feed.xml-foo"
When I go to "/folder/foldern.html"
Then I should see "I am: folder/foldern.html-foo"
When I go to "/1.html" When I go to "/1.html"
Then I should see "I am: page1" Then I should see "I am: page1"

View file

@ -120,7 +120,7 @@ Feature: Relative Assets
""" """
And the Server is running at "relative-assets-app" And the Server is running at "relative-assets-app"
When I go to "/sub/image_tag.html" When I go to "/sub/image_tag.html"
Then I should see '<img src="../img/blank.gif" />' Then I should see '<img src="../img/blank.gif"'
Scenario: Relative assets should not break data URIs in image_tag Scenario: Relative assets should not break data URIs in image_tag
Given a fixture app "relative-assets-app" Given a fixture app "relative-assets-app"

View file

@ -0,0 +1,123 @@
Feature: Relative Assets (Helpers Only)
Scenario: Rendering css with the feature enabled
Given a fixture app "relative-assets-app"
And a file named "config.rb" with:
"""
activate :relative_assets, helpers_only: true
"""
And a file named "source/stylesheets/relative_assets.css.sass.erb" with:
"""
h1
background: url("<%= asset_url('images/blank.gif') %>")
h2
background: url("<%= asset_url('/images/blank2.gif') %>")
"""
And a file named "source/javascripts/application.js.erb" with:
"""
function foo() {
var img = document.createElement('img');
img.src = '<%= asset_url("images/100px.jpg") %>';
var body = document.getElementsByTagName('body')[0];
body.insertBefore(img, body.firstChild);
}
window.onload = foo;
"""
And a file named "source/stylesheets/fonts3.css.erb" with:
"""
@font-face {
font-family: 'Roboto2';
src: url(<%= asset_url("/fonts/roboto/roboto-regular-webfont.eot") %>);
src: url(<%= asset_url("/fonts/roboto/roboto-regular-webfont.eot?#iefix") %>) format('embedded-opentype'),
url(<%= asset_url("/fonts/roboto/roboto-regular-webfont.woff") %>) format('woff'),
url(<%= asset_url("/fonts/roboto/roboto-regular-webfont.ttf") %>) format('truetype'),
url(<%= asset_url("/fonts/roboto/roboto-regular-webfont.svg#robotoregular") %>) format('svg');
font-weight: normal;
font-style: normal;
}
"""
And the Server is running at "relative-assets-app"
When I go to "/stylesheets/relative_assets.css"
Then I should see 'url("../images/blank.gif'
And I should see 'url("../images/blank2.gif'
When I go to "/javascripts/application.js"
Then I should not see "../"
When I go to "/stylesheets/fonts3.css"
Then I should see 'url(../fonts/roboto/roboto-regular-webfont.eot'
And I should see 'url(../fonts/roboto/roboto-regular-webfont.woff'
And I should see 'url(../fonts/roboto/roboto-regular-webfont.ttf'
And I should see 'url(../fonts/roboto/roboto-regular-webfont.svg'
Scenario: Relative css reference with directory indexes
Given a fixture app "relative-assets-app"
And a file named "config.rb" with:
"""
activate :directory_indexes
activate :relative_assets, helpers_only: true
"""
And the Server is running at "relative-assets-app"
When I go to "/relative_image/index.html"
Then I should see "../stylesheets/relative_assets.css"
Scenario: Relative assets via image_tag
Given a fixture app "relative-assets-app"
And a file named "config.rb" with:
"""
activate :relative_assets, helpers_only: true
"""
And a file named "source/sub/image_tag.html.erb" with:
"""
<%= image_tag '/img/blank.gif' %>
"""
And the Server is running at "relative-assets-app"
When I go to "/sub/image_tag.html"
Then I should see '<img src="../img/blank.gif"'
Scenario: Relative assets should not break data URIs in image_tag
Given a fixture app "relative-assets-app"
And a file named "config.rb" with:
"""
activate :relative_assets, helpers_only: true
"""
And a file named "source/sub/image_tag.html.erb" with:
"""
<%= image_tag "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" %>
"""
And the Server is running at "relative-assets-app"
When I go to "/sub/image_tag.html"
Then I should see '<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" />'
Scenario: URLs are not rewritten for rewrite ignored paths
Given a fixture app "relative-assets-app"
And a file named "config.rb" with:
"""
activate :relative_assets, rewrite_ignore: [
'/stylesheets/fonts3.css',
], helpers_only: true
"""
And a file named "source/stylesheets/relative_assets.css.sass.erb" with:
"""
h1
background: url("<%= asset_url('images/blank.gif') %>")
h2
background: url("<%= asset_url('/images/blank2.gif') %>")
"""
And a file named "source/stylesheets/fonts3.css.erb" with:
"""
@font-face {
font-family: 'Roboto2';
src: url(<%= asset_url("/fonts/roboto/roboto-regular-webfont.eot") %>);
src: url(<%= asset_url("/fonts/roboto/roboto-regular-webfont.eot?#iefix") %>) format('embedded-opentype'),
url(<%= asset_url("/fonts/roboto/roboto-regular-webfont.woff") %>) format('woff'),
url(<%= asset_url("/fonts/roboto/roboto-regular-webfont.ttf") %>) format('truetype'),
url(<%= asset_url("/fonts/roboto/roboto-regular-webfont.svg#robotoregular") %>) format('svg');
font-weight: normal;
font-style: normal;
}
"""
And the Server is running at "relative-assets-app"
When I go to "/stylesheets/relative_assets.css"
Then I should see 'url("../images/blank.gif'
When I go to "/stylesheets/fonts3.css"
Then I should see 'url(/fonts/roboto/roboto-regular-webfont.eot'

View file

@ -0,0 +1,40 @@
Feature: Sass/SCSS support in Slim
In order to test support of the Slim sass and scss filters
Scenario: Sass filter in Slim works
Given a fixture app "sass-in-slim-app"
And a file named "config.rb" with:
"""
activate :directory_indexes
"""
And a file named "source/sass_filter.html.slim" with:
"""
sass:
.sass
margin: 0
"""
Given the Server is running at "sass-in-slim-app"
When I go to "/sass_filter/"
Then I should see "text/css"
Then I should see ".sass"
Then I should see "margin:0"
Scenario: SCSS filter in Slim works
Given a fixture app "sass-in-slim-app"
And a file named "config.rb" with:
"""
activate :directory_indexes
"""
And a file named "source/scss_filter.html.slim" with:
"""
scss:
.scss {
margin: 0;
}
"""
Given the Server is running at "sass-in-slim-app"
When I go to "/scss_filter/"
Then I should see "text/css"
Then I should see ".scss"
Then I should see "margin:0"

View file

@ -0,0 +1,26 @@
Feature: Don't allow template locals to overwrite template helpers
Scenario: Normal Template
Given an empty app
And a file named "config.rb" with:
"""
class TestExt < ::Middleman::Extension
expose_to_template foo: :foo
def foo
"bar"
end
end
::Middleman::Extensions.register :test, TestExt
activate :test
page "/index.html", locals: { foo: false }
"""
And a file named "source/index.html.erb" with:
"""
<%= foo %>
"""
Given a built app at "empty_app"
Then the exit status should be 1

View file

@ -0,0 +1,7 @@
activate :asset_hash,
prefix: "myprefix-"
activate :relative_assets
activate :directory_indexes

View file

@ -0,0 +1,16 @@
class Middleware
def initialize(app)
@app = app
end
def call(env)
status, headers, response = @app.call(env)
body = ''
response.each {|part| body += part }
if (env["PATH_INFO"] =~ /css$/)
body += "\n/* Added by Rack filter */"
status, headers, response = Rack::Response.new(body, status, headers).finish
end
[status, headers, response]
end
end

View file

@ -0,0 +1,6 @@
<% content_for :head do %>
<title>The Middleman!</title>
<% end %>
<h1>Testing the sitemap hashing</h1>
<br /><br /><br />

View file

@ -0,0 +1,2 @@
function foo(){var message="HEY THERE FRIEND!";var para=document.createElement("p");para.innerHTML=message;var body=document.getElementsByTagName("body")[0];body.insertBefore(para,body.firstChild)}window.onload=foo;
//# sourceMappingURL=application.js.map

View file

@ -0,0 +1 @@
{"version":3,"sources":["source/javascripts/application.js"],"names":["foo","message","para","document","createElement","innerHTML","body","getElementsByTagName","insertBefore","firstChild","window","onload"],"mappings":"AAAA,QAASA,OACP,GAAIC,SAAU,mBACd,IAAIC,MAAOC,SAASC,cAAc,IAClCF,MAAKG,UAAYJ,OACb,IAAIK,MAAOH,SAASI,qBAAqB,QAAQ,EAC/CD,MAAKE,aAAaN,KAAMI,KAAKG,YAGpCC,OAAOC,OAASX"}

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<%= javascript_include_tag "application" %>
<%= yield_content :head %>
</head>
<body class="<%= page_classes %>">
<div id="main" role="main">
<%= yield %>
</div>
</body>
</html>

View file

@ -0,0 +1,7 @@
%w(1 2 3).each do |n|
proxy "/#{n}.html", "/index.html", id: "page#{n}"
end
page "/overwrites/*", id: :"something-else"
config[:page_id_generator] = ->(path){ path + "-foo" }

View file

@ -0,0 +1 @@
I am: <%= current_resource.page_id %>

View file

@ -0,0 +1 @@
I am: <%= current_resource.page_id %>

View file

@ -0,0 +1 @@
I am: <%= current_resource.page_id %>

View file

@ -4,3 +4,11 @@ URL1: <%= url_for "frontmatter" %>
URL2: <%= url_for "page2" %> URL2: <%= url_for "page2" %>
URL3: <%= link_to "Hi", "page3" %> URL3: <%= link_to "Hi", "page3" %>
URL4: <%= link_to "Sym", :"something-else" %> URL4: <%= link_to "Sym", :"something-else" %>
URL5: <%= link_to "Imp", :implicit %>
URL6: <%= link_to "Foldern", "folder/foldern" %>
URL7: <%= link_to "Feed", "feed.xml" %>
<%# If custom proc %>
URL8: <%= link_to "Imp", "implicit.html-foo" %>
URL9: <%= link_to "Foldern", "folder/foldern.html-foo" %>
URL10: <%= link_to "Feed", "feed.xml-foo" %>

View file

@ -203,6 +203,7 @@ module Middleman
define_setting :watcher_disable, false, 'If the Listen watcher should not run' define_setting :watcher_disable, false, 'If the Listen watcher should not run'
define_setting :watcher_force_polling, false, 'If the Listen watcher should run in polling mode' define_setting :watcher_force_polling, false, 'If the Listen watcher should run in polling mode'
define_setting :watcher_latency, nil, 'The Listen watcher latency' define_setting :watcher_latency, nil, 'The Listen watcher latency'
define_setting :watcher_wait_for_delay, 0.5, 'The Listen watcher delay between calls when changes exist'
# Delegate convenience methods off to their implementations # Delegate convenience methods off to their implementations
def_delegator :"::Middleman::Logger", :singleton, :logger def_delegator :"::Middleman::Logger", :singleton, :logger
@ -235,7 +236,8 @@ module Middleman
:before, # Before Rack requests :before, # Before Rack requests
:before_render, :before_render,
:after_render, :after_render,
:before_server :before_server,
:reload
]) ])
@middleware = Set.new @middleware = Set.new
@ -265,6 +267,8 @@ module Middleman
# Evaluate a passed block if given # Evaluate a passed block if given
config_context.instance_exec(&block) if block_given? config_context.instance_exec(&block) if block_given?
apply_cli_options
execute_callbacks(:before_sitemap) execute_callbacks(:before_sitemap)
# Initialize the Sitemap # Initialize the Sitemap
@ -275,8 +279,6 @@ module Middleman
# Before config is parsed, before extensions get to it. # Before config is parsed, before extensions get to it.
execute_callbacks(:initialized) execute_callbacks(:initialized)
apply_cli_options
# Before config is parsed. Mostly used for extensions. # Before config is parsed. Mostly used for extensions.
execute_callbacks(:before_configuration) execute_callbacks(:before_configuration)
@ -343,11 +345,11 @@ module Middleman
# Clean up missing Tilt exts # Clean up missing Tilt exts
def prune_tilt_templates! def prune_tilt_templates!
::Tilt.mappings.each_key do |key| ::Tilt.default_mapping.lazy_map.each_key do |key|
begin begin
::Tilt[".#{key}"] ::Tilt[".#{key}"]
rescue LoadError, NameError rescue LoadError, NameError
::Tilt.mappings.delete(key) ::Tilt.default_mapping.lazy_map.delete(key)
end end
end end
end end

View file

@ -8,7 +8,7 @@ module Middleman
attr_reader :app attr_reader :app
# Whitelist methods that can reach out. # Whitelist methods that can reach out.
def_delegators :@app, :config, :logger, :use, :map, :mime_type, :files, :root, :build?, :server?, :environment? def_delegators :@app, :config, :logger, :use, :map, :mime_type, :files, :root, :build?, :server?, :environment?, :extensions
def_delegator :"@app.extensions", :activate def_delegator :"@app.extensions", :activate
def initialize(app, template_context_class) def initialize(app, template_context_class)
@ -23,7 +23,7 @@ module Middleman
end end
def include(mod) def include(mod)
self.extend(mod) extend(mod)
end end
def helpers(*helper_modules, &block) def helpers(*helper_modules, &block)

View file

@ -1,3 +1,4 @@
require 'monitor'
require 'middleman-core/core_extensions/collections/pagination' require 'middleman-core/core_extensions/collections/pagination'
require 'middleman-core/core_extensions/collections/step_context' require 'middleman-core/core_extensions/collections/step_context'
require 'middleman-core/core_extensions/collections/lazy_root' require 'middleman-core/core_extensions/collections/lazy_root'
@ -41,6 +42,8 @@ module Middleman
@values_by_name = {} @values_by_name = {}
@collector_roots = [] @collector_roots = []
@lock = Monitor.new
end end
def before_configuration def before_configuration
@ -81,27 +84,35 @@ module Middleman
Contract ResourceList => ResourceList Contract ResourceList => ResourceList
def manipulate_resource_list(resources) def manipulate_resource_list(resources)
@collector_roots.each do |pair| @lock.synchronize do
dataset = pair[:block].call(app, resources) @collector_roots.each do |pair|
pair[:root].realize!(dataset) dataset = pair[:block].call(app, resources)
end pair[:root].realize!(dataset)
end
ctx = StepContext.new ctx = StepContext.new(app)
leaves = @leaves.dup StepContext.current = ctx
@collectors_by_name.each do |k, v| leaves = @leaves.dup
@values_by_name[k] = v.value(ctx)
leaves.delete v
end
# Execute code paths @collectors_by_name.each do |k, v|
leaves.each do |v| @values_by_name[k] = v.value(ctx)
v.value(ctx) leaves.delete v
end end
# Inject descriptors # Execute code paths
ctx.descriptors.reduce(resources) do |sum, d| leaves.each do |v|
d.execute_descriptor(app, sum) v.value(ctx)
end
# Inject descriptors
results = ctx.descriptors.reduce(resources) do |sum, d|
d.execute_descriptor(app, sum)
end
StepContext.current = nil
results
end end
end end
end end

View file

@ -2,23 +2,30 @@ module Middleman
module CoreExtensions module CoreExtensions
module Collections module Collections
class StepContext class StepContext
def self.add_to_context(name, &func) class << self
send(:define_method, :"_internal_#{name}", &func) attr_accessor :current
def add_to_context(name, &func)
send(:define_method, :"_internal_#{name}", &func)
end
end end
attr_reader :descriptors attr_reader :descriptors
def initialize def initialize(app)
@app = app
@descriptors = [] @descriptors = []
end end
def method_missing(name, *args, &block) def method_missing(name, *args, &block)
internal = :"_internal_#{name}" internal = :"_internal_#{name}"
return super unless respond_to?(internal) if respond_to?(internal)
send(internal, *args, &block).tap do |r|
send(internal, *args, &block).tap do |r| @descriptors << r if r.respond_to?(:execute_descriptor)
@descriptors << r if r.respond_to?(:execute_descriptor) end
else
@app.config_context.send(name, *args, &block)
end end
end end
end end

View file

@ -88,6 +88,8 @@ module Middleman
def update_files(updated_files, removed_files) def update_files(updated_files, removed_files)
updated_files.each(&method(:touch_file)) updated_files.each(&method(:touch_file))
removed_files.each(&method(:remove_file)) removed_files.each(&method(:remove_file))
@app.sitemap.rebuild_resource_list!(:touched_data_file)
end end
# Update the internal cache for a given file path # Update the internal cache for a given file path

View file

@ -1,4 +1,5 @@
require 'padrino-helpers' require 'padrino-helpers'
require 'middleman-core/contracts'
# Don't fail on invalid locale, that's not what our current # Don't fail on invalid locale, that's not what our current
# users expect. # users expect.

View file

@ -28,10 +28,7 @@ module Middleman
super super
# Setup source collection. # Setup source collection.
@sources = ::Middleman::Sources.new(app, @sources = ::Middleman::Sources.new(app)
disable_watcher: app.config[:watcher_disable],
force_polling: app.config[:watcher_force_polling],
latency: app.config[:watcher_latency])
# Add default ignores. # Add default ignores.
IGNORES.each do |key, value| IGNORES.each do |key, value|
@ -55,6 +52,13 @@ module Middleman
# @return [void] # @return [void]
Contract Any Contract Any
def after_configuration def after_configuration
@watcher.update_config(
disable_watcher: app.config[:watcher_disable],
force_polling: app.config[:watcher_force_polling],
latency: app.config[:watcher_latency],
wait_for_delay: app.config[:watcher_wait_for_delay]
)
if @original_source_dir != app.config[:source] if @original_source_dir != app.config[:source]
@watcher.update_path(app.config[:source]) @watcher.update_path(app.config[:source])
end end

View file

@ -73,18 +73,20 @@ module Middleman::CoreExtensions
return [{}, nil] unless file return [{}, nil] unless file
return @cache[file[:full_path]] if @cache.key?(file[:full_path]) file_path = file[:full_path].to_s
@cache[file[:full_path]] = ::Middleman::Util::Data.parse( @cache[file_path] ||= begin
file, ::Middleman::Util::Data.parse(
app.config[:frontmatter_delims] file,
) app.config[:frontmatter_delims]
)
end
end end
Contract ArrayOf[IsA['Middleman::SourceFile']], ArrayOf[IsA['Middleman::SourceFile']] => Any Contract ArrayOf[IsA['Middleman::SourceFile']], ArrayOf[IsA['Middleman::SourceFile']] => Any
def clear_data(updated_files, removed_files) def clear_data(updated_files, removed_files)
(updated_files + removed_files).each do |file| (updated_files + removed_files).each do |file|
@cache.delete(file[:full_path]) @cache.delete(file[:full_path].to_s)
end end
end end
end end

View file

@ -213,6 +213,8 @@ class Middleman::CoreExtensions::Internationalization < ::Middleman::Extension
def on_file_changed(_updated_files, _removed_files) def on_file_changed(_updated_files, _removed_files)
::I18n.load_path |= app.files.by_type(:locales).files.map { |p| p[:full_path].to_s } ::I18n.load_path |= app.files.by_type(:locales).files.map { |p| p[:full_path].to_s }
::I18n.reload! ::I18n.reload!
@app.sitemap.rebuild_resource_list!(:touched_locale_file)
end end
def configure_i18n def configure_i18n

View file

@ -1,6 +1,6 @@
require 'rack' require 'rack'
require 'rack/response' require 'rack/response'
require 'addressable/uri' require 'memoist'
require 'middleman-core/util' require 'middleman-core/util'
require 'middleman-core/contracts' require 'middleman-core/contracts'
@ -11,13 +11,12 @@ module Middleman
expose_to_application rewrite_inline_urls: :add expose_to_application rewrite_inline_urls: :add
IGNORE_DESCRIPTOR = Or[Regexp, RespondTo[:call], String]
REWRITER_DESCRIPTOR = { REWRITER_DESCRIPTOR = {
id: Symbol, id: Symbol,
proc: Or[Proc, Method], proc: Or[Proc, Method],
url_extensions: ArrayOf[String], url_extensions: ArrayOf[String],
source_extensions: ArrayOf[String], source_extensions: ArrayOf[String],
ignore: ArrayOf[IGNORE_DESCRIPTOR], ignore: ArrayOf[::Middleman::Util::IGNORE_DESCRIPTOR],
after: Maybe[Symbol] after: Maybe[Symbol]
}.freeze }.freeze
@ -33,6 +32,8 @@ module Middleman
end end
def after_configuration def after_configuration
return if @rewriters.empty?
rewriters = @rewriters.values.sort do |a, b| rewriters = @rewriters.values.sort do |a, b|
if b[:after] && b[:after] == a[:id] if b[:after] && b[:after] == a[:id]
1 1
@ -45,6 +46,7 @@ module Middleman
end end
class Rack class Rack
extend Memoist
include Contracts include Contracts
Contract RespondTo[:call], { Contract RespondTo[:call], {
@ -55,6 +57,17 @@ module Middleman
@rack_app = app @rack_app = app
@middleman_app = options.fetch(:middleman_app) @middleman_app = options.fetch(:middleman_app)
@rewriters = options.fetch(:rewriters) @rewriters = options.fetch(:rewriters)
all_source_exts = @rewriters
.reduce([]) { |sum, rewriter| sum + rewriter[:source_extensions] }
.flatten
.uniq
@source_exts_regex_text = Regexp.union(all_source_exts).to_s
@all_asset_exts = @rewriters
.reduce([]) { |sum, rewriter| sum + rewriter[:url_extensions] }
.flatten
.uniq
end end
def call(env) def call(env)
@ -63,27 +76,16 @@ module Middleman
# Allow configuration or upstream request to skip all rewriting # Allow configuration or upstream request to skip all rewriting
return [status, headers, response] if env['bypass_inline_url_rewriter'] == 'true' return [status, headers, response] if env['bypass_inline_url_rewriter'] == 'true'
all_source_exts = @rewriters
.reduce([]) { |sum, rewriter| sum + rewriter[:source_extensions] }
.flatten
.uniq
source_exts_regex_text = Regexp.union(all_source_exts).to_s
all_asset_exts = @rewriters
.reduce([]) { |sum, rewriter| sum + rewriter[:url_extensions] }
.flatten
.uniq
path = ::Middleman::Util.full_path(env['PATH_INFO'], @middleman_app) path = ::Middleman::Util.full_path(env['PATH_INFO'], @middleman_app)
return [status, headers, response] unless path =~ /(^\/$)|(#{source_exts_regex_text}$)/ return [status, headers, response] unless path =~ /(^\/$)|(#{@source_exts_regex_text}$)/
return [status, headers, response] unless body = ::Middleman::Util.extract_response_text(response) return [status, headers, response] unless body = ::Middleman::Util.extract_response_text(response)
dirpath = ::Pathname.new(File.dirname(path)) dirpath = ::Pathname.new(File.dirname(path))
rewritten = ::Middleman::Util.instrument 'inline_url_rewriter', path: path do rewritten = ::Middleman::Util.instrument 'inline_url_rewriter', path: path do
::Middleman::Util.rewrite_paths(body, path, all_asset_exts) do |asset_path| ::Middleman::Util.rewrite_paths(body, path, @all_asset_exts, @middleman_app) do |asset_path|
uri = ::Addressable::URI.parse(asset_path) uri = ::Middleman::Util.parse_uri(asset_path)
relative_path = uri.host.nil? relative_path = uri.host.nil?
@ -106,7 +108,7 @@ module Middleman
next unless source_exts.include?(::File.extname(path)) next unless source_exts.include?(::File.extname(path))
ignore = rewriter.fetch(:ignore) ignore = rewriter.fetch(:ignore)
next if ignore.any? { |r| should_ignore?(r, full_asset_path) } next if ignore.any? { |r| ::Middleman::Util.should_ignore?(r, full_asset_path) }
rewrite_ignore = Array(rewriter[:rewrite_ignore] || []) rewrite_ignore = Array(rewriter[:rewrite_ignore] || [])
next if rewrite_ignore.any? { |i| ::Middleman::Util.path_match(i, path) } next if rewrite_ignore.any? { |i| ::Middleman::Util.path_match(i, path) }
@ -127,23 +129,6 @@ module Middleman
headers headers
).finish ).finish
end end
Contract IGNORE_DESCRIPTOR, String => Bool
def should_ignore?(validator, value)
if validator.is_a? Regexp
# Treat as Regexp
!!(value =~ validator)
elsif validator.respond_to? :call
# Treat as proc
validator.call(value)
elsif validator.is_a? String
# Treat as glob
File.fnmatch(value, validator)
else
# If some unknown thing, don't ignore
false
end
end
end end
end end
end end

View file

@ -1,4 +1,5 @@
require 'forwardable' require 'forwardable'
require 'memoist'
require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/class/attribute'
require 'middleman-core/configuration' require 'middleman-core/configuration'
require 'middleman-core/contracts' require 'middleman-core/contracts'
@ -66,6 +67,8 @@ module Middleman
# @see http://middlemanapp.com/advanced/custom/ Middleman Custom Extensions Documentation # @see http://middlemanapp.com/advanced/custom/ Middleman Custom Extensions Documentation
class Extension class Extension
extend Forwardable extend Forwardable
extend Memoist
include Contracts include Contracts
def_delegator :@app, :logger def_delegator :@app, :logger
@ -490,15 +493,14 @@ module Middleman
class ConfigExtension < Extension class ConfigExtension < Extension
def initialize(app, config={}, &block) def initialize(app, config={}, &block)
@descriptors = {} @descriptors = {}
@wrapped = {} @ready = false
self.class.exposed_to_config.each do |k, v| self.class.exposed_to_config.each do |k, v|
@descriptors[k] = [] @descriptors[k] = []
define_singleton_method(:"__original_#{v}", &method(v)) define_singleton_method(:"__original_#{v}", &method(v))
define_singleton_method(v) do |*args, &b| define_singleton_method(v) do |*args, &b|
@descriptors[k] << method(:"__original_#{v}").call(*args, &b) proxy_method_call(k, v, args, &b)
@app.sitemap.rebuild_resource_list!(:"first_run_change_#{v}")
end end
end end
@ -506,11 +508,24 @@ module Middleman
end end
def after_configuration def after_configuration
context = self
self.class.exposed_to_config.each do |k, v| self.class.exposed_to_config.each do |k, v|
::Middleman::CoreExtensions::Collections::StepContext.add_to_context(k, &method(:"__original_#{v}")) ::Middleman::CoreExtensions::Collections::StepContext.add_to_context(k) do |*args, &b|
r = context.method(:"__original_#{v}").call(*args, &b)
descriptors << r if r.respond_to?(:execute_descriptor)
end
end end
end end
def ready
@ready = true
# @descriptors.each do |k, v|
# @descriptors[k] = []
# end
end
# Update the main sitemap resource list # Update the main sitemap resource list
# @return Array<Middleman::Sitemap::Resource> # @return Array<Middleman::Sitemap::Resource>
Contract ResourceList => ResourceList Contract ResourceList => ResourceList
@ -519,5 +534,25 @@ module Middleman
c.execute_descriptor(app, sum) c.execute_descriptor(app, sum)
end end
end end
Contract Symbol, Symbol, ArrayOf[Any], Maybe[Proc] => Any
def proxy_method_call(k, v, args, &b)
if @ready
ctx = ::Middleman::CoreExtensions::Collections::StepContext.current
r = method(:"__original_#{v}").call(*args, &b)
if r.respond_to?(:execute_descriptor)
if ctx
ctx.descriptors << r
else
@descriptors[k] << r
@app.sitemap.rebuild_resource_list!(:"first_run_change_#{v}")
end
end
else
@descriptors[k] << method(:"__original_#{v}").call(*args, &b)
@app.sitemap.rebuild_resource_list!(:"first_run_change_#{v}")
end
end
end end
end end

View file

@ -6,6 +6,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
option :exts, nil, 'List of extensions that get asset hashes appended to them.' option :exts, nil, 'List of extensions that get asset hashes appended to them.'
option :ignore, [], 'Regexes of filenames to skip adding asset hashes to' option :ignore, [], 'Regexes of filenames to skip adding asset hashes to'
option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites' option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites'
option :prefix, '', 'Prefix for hash'
def initialize(app, options_hash={}, &block) def initialize(app, options_hash={}, &block)
super super
@ -32,7 +33,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
Contract String, Or[String, Pathname], Any => Maybe[String] Contract String, Or[String, Pathname], Any => Maybe[String]
def rewrite_url(asset_path, dirpath, _request_path) def rewrite_url(asset_path, dirpath, _request_path)
uri = ::Addressable::URI.parse(asset_path) uri = ::Middleman::Util.parse_uri(asset_path)
relative_path = !uri.path.start_with?('/') relative_path = !uri.path.start_with?('/')
full_asset_path = if relative_path full_asset_path = if relative_path
@ -92,7 +93,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
::Digest::SHA1.hexdigest(response.body)[0..7] ::Digest::SHA1.hexdigest(response.body)[0..7]
end end
resource.destination_path = resource.destination_path.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" } resource.destination_path = resource.destination_path.sub(/\.(\w+)$/) { |ext| "-#{options.prefix}#{digest}#{ext}" }
resource resource
end end

View file

@ -20,7 +20,7 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension
Contract String, Or[String, Pathname], Any => String Contract String, Or[String, Pathname], Any => String
def rewrite_url(asset_path, dirpath, _request_path) def rewrite_url(asset_path, dirpath, _request_path)
uri = ::Addressable::URI.parse(asset_path) uri = ::Middleman::Util.parse_uri(asset_path)
relative_path = uri.path[0..0] != '/' relative_path = uri.path[0..0] != '/'
full_asset_path = if relative_path full_asset_path = if relative_path
@ -37,4 +37,5 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension
File.join(asset_prefix, full_asset_path) File.join(asset_prefix, full_asset_path)
end end
memoize :rewrite_url
end end

View file

@ -12,6 +12,7 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension
return if app.mode?(:config) return if app.mode?(:config)
require 'servolux'
require 'thread' require 'thread'
require 'fileutils' require 'fileutils'
@ -25,31 +26,63 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension
latency: options[:latency], latency: options[:latency],
frontmatter: false frontmatter: false
@current_thread = nil
app.reload(&method(:reload!))
logger.info "== Executing: `#{options[:command]}`" logger.info "== Executing: `#{options[:command]}`"
if app.build? || options[:disable_background_execution] if app.build? || options[:disable_background_execution]
watch_command! watch_command!(false)
@watcher.poll_once!
else else
::Thread.new { watch_command! } watch_command!(true)
end end
end end
def watch_command! def reload!
::IO.popen(options[:command], 'r') do |pipe| if @current_thread
while buf = pipe.gets logger.info "== Stopping: `#{options[:command]}`"
@current_thread.stop
@current_thread = nil
end
end
def watch_command!(async)
@current_thread = ::Servolux::Child.new(
command: options[:command],
suspend: 2
)
@current_thread.start
watch_thread = Thread.new do
while buf = @current_thread.io.gets
without_newline = buf.sub(/\n$/, '') without_newline = buf.sub(/\n$/, '')
logger.info "== External: #{without_newline}" unless without_newline.empty? logger.info "== External: #{without_newline}" unless without_newline.empty?
end end
@current_thread.wait
if !@current_thread.exitstatus.nil? && @current_thread.exitstatus != 0
logger.error '== External: Command failed with non-zero exit status'
exit(1)
end
end end
unless $?.success? watch_thread.join unless async
logger.error '== External: Command failed with non-zero exit status'
exit(1)
end
@watcher.poll_once!
rescue ::Errno::ENOENT => e rescue ::Errno::ENOENT => e
logger.error "== External: Command failed with message: #{e.message}" logger.error "== External: Command failed with message: #{e.message}"
exit(1) exit(1)
end end
private
def print_command(stdout)
while buf = stdout.gets
without_newline = buf.sub(/\n$/, '')
logger.info "== External: #{without_newline}" unless without_newline.empty?
end
end
end end

View file

@ -1,3 +1,5 @@
require 'active_support/core_ext/object/try'
require 'memoist'
require 'middleman-core/contracts' require 'middleman-core/contracts'
# Minify CSS Extension # Minify CSS Extension
@ -30,6 +32,7 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
# Rack middleware to look for CSS and compress it # Rack middleware to look for CSS and compress it
class Rack class Rack
extend Memoist
include Contracts include Contracts
INLINE_CSS_REGEX = /(<style[^>]*>\s*(?:\/\*<!\[CDATA\[\*\/\n)?)(.*?)((?:(?:\n\s*)?\/\*\]\]>\*\/)?\s*<\/style>)/m INLINE_CSS_REGEX = /(<style[^>]*>\s*(?:\/\*<!\[CDATA\[\*\/\n)?)(.*?)((?:(?:\n\s*)?\/\*\]\]>\*\/)?\s*<\/style>)/m
@ -69,7 +72,7 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
end end
if minified if minified
headers['Content-Length'] = ::Rack::Utils.bytesize(minified).to_s headers['Content-Length'] = minified.bytesize.to_s
response = [minified] response = [minified]
end end
@ -82,8 +85,9 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
# @param [String] path # @param [String] path
# @return [Boolean] # @return [Boolean]
def ignore?(path) def ignore?(path)
@ignore.any? { |ignore| Middleman::Util.path_match(ignore, path) } @ignore.any? { |ignore| ::Middleman::Util.path_match(ignore, path) }
end end
memoize :ignore?
# Whether this type of content can be minified # Whether this type of content can be minified
# @param [String, nil] content_type # @param [String, nil] content_type
@ -91,6 +95,7 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
def minifiable?(content_type) def minifiable?(content_type)
@content_types.include?(content_type) @content_types.include?(content_type)
end end
memoize :minifiable?
# Whether this type of content contains inline content that can be minified # Whether this type of content contains inline content that can be minified
# @param [String, nil] content_type # @param [String, nil] content_type
@ -98,6 +103,7 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
def minifiable_inline?(content_type) def minifiable_inline?(content_type)
@inline_content_types.include?(content_type) @inline_content_types.include?(content_type)
end end
memoize :minifiable_inline?
# Minify the content # Minify the content
# @param [String] content # @param [String] content
@ -105,6 +111,7 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
def minify(content) def minify(content)
@compressor.compress(content) @compressor.compress(content)
end end
memoize :minify
# Detect and minify inline content # Detect and minify inline content
# @param [String] content # @param [String] content
@ -114,5 +121,6 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
$1 + minify($2) + $3 $1 + minify($2) + $3
end end
end end
memoize :minify_inline
end end
end end

View file

@ -1,4 +1,6 @@
require 'active_support/core_ext/object/try'
require 'middleman-core/contracts' require 'middleman-core/contracts'
require 'memoist'
# Minify Javascript Extension # Minify Javascript Extension
class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
@ -22,6 +24,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
# Rack middleware to look for JS and compress it # Rack middleware to look for JS and compress it
class Rack class Rack
extend Memoist
include Contracts include Contracts
INLINE_JS_REGEX = /(<script[^>]*>\s*(?:\/\/(?:(?:<!--)|(?:<!\[CDATA\[))\n)?)(.*?)((?:(?:\n\s*)?\/\/(?:(?:-->)|(?:\]\]>)))?\s*<\/script>)/m INLINE_JS_REGEX = /(<script[^>]*>\s*(?:\/\/(?:(?:<!--)|(?:<!\[CDATA\[))\n)?)(.*?)((?:(?:\n\s*)?\/\/(?:(?:-->)|(?:\]\]>)))?\s*<\/script>)/m
@ -61,7 +64,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
end end
if minified if minified
headers['Content-Length'] = ::Rack::Utils.bytesize(minified).to_s headers['Content-Length'] = minified.bytesize.to_s
response = [minified] response = [minified]
end end
@ -76,6 +79,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
def ignore?(path) def ignore?(path)
@ignore.any? { |ignore| Middleman::Util.path_match(ignore, path) } @ignore.any? { |ignore| Middleman::Util.path_match(ignore, path) }
end end
memoize :ignore?
# Whether this type of content can be minified # Whether this type of content can be minified
# @param [String, nil] content_type # @param [String, nil] content_type
@ -83,6 +87,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
def minifiable?(content_type) def minifiable?(content_type)
@content_types.include?(content_type) @content_types.include?(content_type)
end end
memoize :minifiable?
# Whether this type of content contains inline content that can be minified # Whether this type of content contains inline content that can be minified
# @param [String, nil] content_type # @param [String, nil] content_type
@ -90,6 +95,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
def minifiable_inline?(content_type) def minifiable_inline?(content_type)
@inline_content_types.include?(content_type) @inline_content_types.include?(content_type)
end end
memoize :minifiable_inline?
# Minify the content # Minify the content
# @param [String] content # @param [String] content
@ -100,6 +106,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
warn "WARNING: Couldn't compress JavaScript in #{@path}: #{e.message}" warn "WARNING: Couldn't compress JavaScript in #{@path}: #{e.message}"
content content
end end
memoize :minify
# Detect and minify inline content # Detect and minify inline content
# @param [String] content # @param [String] content
@ -119,5 +126,6 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
end end
end end
end end
memoize :minify_inline
end end
end end

View file

@ -2,15 +2,18 @@ require 'addressable/uri'
# Relative Assets extension # Relative Assets extension
class Middleman::Extensions::RelativeAssets < ::Middleman::Extension class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
option :exts, nil, 'List of extensions that get cache busters strings appended to them.' option :exts, nil, 'List of extensions that get converted to relative paths.'
option :sources, %w(.css .htm .html .xhtml), 'List of extensions that are searched for relative assets.' option :sources, %w(.css .htm .html .xhtml), 'List of extensions that are searched for relative assets.'
option :ignore, [], 'Regexes of filenames to skip adding query strings to' option :ignore, [], 'Regexes of filenames to skip converting to relative paths.'
option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites' option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites.'
option :helpers_only, false, 'Allow only Ruby helpers to change paths.'
def initialize(app, options_hash={}, &block) def initialize(app, options_hash={}, &block)
super super
app.rewrite_inline_urls id: :asset_hash, return if options[:helpers_only]
app.rewrite_inline_urls id: :relative_assets,
url_extensions: options.exts || app.config[:asset_extensions], url_extensions: options.exts || app.config[:asset_extensions],
source_extensions: options.sources, source_extensions: options.sources,
ignore: options.ignore, ignore: options.ignore,
@ -18,22 +21,43 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
proc: method(:rewrite_url) proc: method(:rewrite_url)
end end
helpers do def mark_as_relative(file_path, opts, current_resource)
# asset_url override for relative assets result = opts.dup
# @param [String] path
# @param [String] prefix
# @param [Hash] options Additional options.
# @return [String]
def asset_url(path, prefix='', options={})
options[:relative] = true unless options.key?(:relative)
super(path, prefix, options) valid_exts = options.sources
return result unless current_resource
return result unless valid_exts.include?(current_resource.ext)
rewrite_ignores = Array(options.rewrite_ignore || [])
path = current_resource.destination_path
return result if rewrite_ignores.any? do |i|
::Middleman::Util.path_match(i, path) || ::Middleman::Util.path_match(i, "/#{path}")
end
return result if Array(options.ignore || []).any? do |r|
::Middleman::Util.should_ignore?(r, file_path)
end
result[:relative] = true unless result.key?(:relative)
result
end
helpers do
def asset_url(path, prefix='', options={})
super(path, prefix, app.extensions[:relative_assets].mark_as_relative(super, options, current_resource))
end
def asset_path(kind, source, options={})
super(kind, source, app.extensions[:relative_assets].mark_as_relative(super, options, current_resource))
end end
end end
Contract String, Or[String, Pathname], Any => Maybe[String] Contract String, Or[String, Pathname], Any => Maybe[String]
def rewrite_url(asset_path, dirpath, request_path) def rewrite_url(asset_path, dirpath, request_path)
uri = ::Addressable::URI.parse(asset_path) uri = ::Middleman::Util.parse_uri(asset_path)
return if uri.path[0..0] != '/' return if uri.path[0..0] != '/'
@ -50,4 +74,5 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
result result
end end
memoize :rewrite_url
end end

View file

@ -3,8 +3,8 @@ require 'active_support/core_ext/string/output_safety'
require 'active_support/core_ext/module/delegation' require 'active_support/core_ext/module/delegation'
require 'middleman-core/contracts' require 'middleman-core/contracts'
::Tilt.mappings.delete('html') # WTF, Tilt? ::Tilt.default_mapping.lazy_map.delete('html')
::Tilt.mappings.delete('csv') ::Tilt.default_mapping.lazy_map.delete('csv')
module Middleman module Middleman
class FileRenderer class FileRenderer
@ -59,7 +59,7 @@ module Middleman
# Overwrite with frontmatter options # Overwrite with frontmatter options
options = options.deep_merge(options[:renderer_options]) if options[:renderer_options] options = options.deep_merge(options[:renderer_options]) if options[:renderer_options]
template_class = ::Tilt[path] template_class = ::Middleman::Util.tilt_class(path)
# Allow hooks to manipulate the template before render # Allow hooks to manipulate the template before render
body = @app.callbacks_for(:before_render).reduce(body) do |sum, callback| body = @app.callbacks_for(:before_render).reduce(body) do |sum, callback|
@ -99,12 +99,12 @@ module Middleman
def template_data_for_file def template_data_for_file
file = @app.files.find(:source, @path) file = @app.files.find(:source, @path)
if @app.extensions[:front_matter] || (file && !file[:types].include?(:no_frontmatter)) if @app.extensions[:front_matter] && (file && !file[:types].include?(:no_frontmatter))
result = @app.extensions[:front_matter].template_data_for_file(@path) result = @app.extensions[:front_matter].template_data_for_file(@path)
return result unless result.nil? return result unless result.nil?
end end
file ? file.read : File.read(@path) file ? file.read : ::File.read(@path)
end end
protected protected
@ -122,9 +122,9 @@ module Middleman
# Find all the engines which handle this extension in tilt. Look for # Find all the engines which handle this extension in tilt. Look for
# config variables of that name and merge it # config variables of that name and merge it
extension_class = ::Tilt[ext] extension_class = ::Middleman::Util.tilt_class(ext)
::Tilt.mappings.each do |mapping_ext, engines|
next unless engines.include? extension_class ::Tilt.default_mapping.extensions_for(extension_class).each do |mapping_ext|
engine_options = @app.config[mapping_ext.to_sym] || {} engine_options = @app.config[mapping_ext.to_sym] || {}
options.merge!(engine_options) options.merge!(engine_options)
end end

View file

@ -103,6 +103,8 @@ module Middleman
def reload def reload
app.logger.info '== The Middleman is reloading' app.logger.info '== The Middleman is reloading'
app.execute_callbacks(:reload)
begin begin
app = initialize_new_app app = initialize_new_app
rescue => e rescue => e
@ -141,7 +143,7 @@ module Middleman
app = ::Middleman::Application.new do app = ::Middleman::Application.new do
config[:cli_options] = cli_options.each_with_object({}) do |(k, v), sum| config[:cli_options] = cli_options.each_with_object({}) do |(k, v), sum|
sum[k] = v unless v == :undefined sum[k] = v
end end
ready do ready do
@ -158,6 +160,9 @@ module Middleman
path: root, path: root,
only: match_against only: match_against
# Hack around bower_components in root.
watcher.listener.ignore(/^bower_components/)
# Hack around node_modules in root. # Hack around node_modules in root.
watcher.listener.ignore(/^node_modules/) watcher.listener.ignore(/^node_modules/)
@ -202,7 +207,7 @@ module Middleman
end end
def possible_from_cli(key, config) def possible_from_cli(key, config)
if @cli_options[key] && @cli_options[key] != :undefined if @cli_options[key]
@cli_options[key] @cli_options[key]
else else
config[key] config[key]

View file

@ -133,9 +133,15 @@ module Middleman
# Immediately send static file # Immediately send static file
def send_file(resource, env) def send_file(resource, env)
file = ::Rack::File.new nil file = ::Rack::File.new nil
file.path = resource.file_descriptor[:full_path] path = resource.file_descriptor[:full_path]
response = file.serving(env) if !file.respond_to?(:path=)
request = ::Rack::Request.new(env)
response = file.serving(request, path)
else
file.path = path
response = file.serving(env)
end
status = response[0] status = response[0]
response[1]['Content-Encoding'] = 'gzip' if %w(.svgz .gz).include?(resource.ext) response[1]['Content-Encoding'] = 'gzip' if %w(.svgz .gz).include?(resource.ext)
# Do not set Content-Type if status is 1xx, 204, 205 or 304, otherwise # Do not set Content-Type if status is 1xx, 204, 205 or 304, otherwise

View file

@ -3,7 +3,7 @@ require 'active_support/core_ext/module/attribute_accessors'
module Middleman module Middleman
module Renderers module Renderers
class RedcarpetTemplate < ::Tilt::RedcarpetTemplate::Redcarpet2 class RedcarpetTemplate < ::Tilt::RedcarpetTemplate
# because tilt has decided to convert these # because tilt has decided to convert these
# in the wrong direction # in the wrong direction
ALIASES = { ALIASES = {

View file

@ -105,10 +105,8 @@ module Middleman
end end
end end
SASS_MODULE = if defined?(::SassC) if defined?(::SassC)
::SassC ::SassC::Script::Functions.send :include, ::Middleman::Sass::Functions
else elsif defined?(::Sass)
::Sass ::Sass::Script::Functions.send :include, ::Middleman::Sass::Functions
end end
SASS_MODULE::Script::Functions.send :include, ::Middleman::Sass::Functions

View file

@ -12,13 +12,9 @@ class ::Slim::Template
def initialize(file, line, opts, &block) def initialize(file, line, opts, &block)
if opts.key?(:context) if opts.key?(:context)
context_hack = {
context: opts[:context]
}
::Slim::Embedded::SassEngine.disable_option_validator! ::Slim::Embedded::SassEngine.disable_option_validator!
%w(sass scss markdown).each do |engine| %w(sass scss markdown).each do |engine|
::Slim::Embedded.options[engine.to_sym] = context_hack (::Slim::Embedded.options[engine.to_sym] ||= {})[:context] = opts[:context]
end end
end end

View file

@ -14,16 +14,31 @@ module Middleman
Contract Or[String, Regexp, Proc] => RespondTo[:execute_descriptor] Contract Or[String, Regexp, Proc] => RespondTo[:execute_descriptor]
def ignore(path=nil, &block) def ignore(path=nil, &block)
@app.sitemap.invalidate_resources_not_ignored_cache! @app.sitemap.invalidate_resources_not_ignored_cache!
IgnoreDescriptor.new(path, block)
if path.is_a? Regexp
RegexpIgnoreDescriptor.new(path)
elsif path.is_a? String
path_clean = ::Middleman::Util.normalize_path(path)
if path_clean.include?('*') # It's a glob
GlobIgnoreDescriptor.new(path_clean)
else
StringIgnoreDescriptor.new(path_clean)
end
elsif block
BlockIgnoreDescriptor.new(nil, block)
else
IgnoreDescriptor.new(path, block)
end
end end
IgnoreDescriptor = Struct.new(:path, :block) do IgnoreDescriptor = Struct.new(:path, :block) do
def execute_descriptor(_app, resources) def execute_descriptor(_app, resources)
resources.map do |r| resources.map do |r|
# Ignore based on the source path (without template extensions) # Ignore based on the source path (without template extensions)
if ignored?(r.path) if ignored?(r.normalized_path)
r.ignore! r.ignore!
elsif !r.is_a?(ProxyResource) && r.file_descriptor && ignored?(r.file_descriptor[:relative_path].to_s) elsif !r.is_a?(ProxyResource) && r.file_descriptor && ignored?(r.file_descriptor.normalized_relative_path)
# This allows files to be ignored by their source file name (with template extensions) # This allows files to be ignored by their source file name (with template extensions)
r.ignore! r.ignore!
end end
@ -33,27 +48,38 @@ module Middleman
end end
def ignored?(match_path) def ignored?(match_path)
match_path = ::Middleman::Util.normalize_path(match_path) raise NotImplementedError
end
end
if path.is_a? Regexp class RegexpIgnoreDescriptor < IgnoreDescriptor
match_path =~ path def ignored?(match_path)
elsif path.is_a? String match_path =~ path
path_clean = ::Middleman::Util.normalize_path(path) end
end
if path_clean.include?('*') # It's a glob class GlobIgnoreDescriptor < IgnoreDescriptor
if defined?(::File::FNM_EXTGLOB) def ignored?(match_path)
::File.fnmatch(path_clean, match_path, ::File::FNM_EXTGLOB) if defined?(::File::FNM_EXTGLOB)
else ::File.fnmatch(path, match_path, ::File::FNM_EXTGLOB)
::File.fnmatch(path_clean, match_path) else
end ::File.fnmatch(path, match_path)
else
match_path == path_clean
end
elsif block
block.call(match_path)
end end
end end
end end
class StringIgnoreDescriptor < IgnoreDescriptor
def ignored?(match_path)
match_path == path
end
end
class BlockIgnoreDescriptor < IgnoreDescriptor
def ignored?(match_path)
block.call(match_path)
end
end
end end
end end
end end

View file

@ -47,7 +47,7 @@ module Middleman
) )
if should_ignore if should_ignore
d = ::Middleman::Sitemap::Extensions::Ignores::IgnoreDescriptor.new(target) d = ::Middleman::Sitemap::Extensions::Ignores::StringIgnoreDescriptor.new(target)
d.execute_descriptor(app, resources) d.execute_descriptor(app, resources)
end end

View file

@ -53,8 +53,7 @@ module Middleman
def render(*) def render(*)
url = ::Middleman::Util.url_for(@store.app, @request_path, url = ::Middleman::Util.url_for(@store.app, @request_path,
relative: false, relative: false,
find_resource: true find_resource: true)
)
if output if output
output.call(path, url) output.call(path, url)

View file

@ -75,19 +75,19 @@ module Middleman
Contract Bool Contract Bool
def template? def template?
return false if file_descriptor.nil? return false if file_descriptor.nil?
!::Tilt[file_descriptor[:full_path].to_s].nil? !::Middleman::Util.tilt_class(file_descriptor[:full_path].to_s).nil?
end end
# Backwards compatible method for turning descriptor into a string. # Backwards compatible method for turning descriptor into a string.
# @return [String] # @return [String]
Contract String Contract Maybe[String]
def source_file def source_file
file_descriptor && file_descriptor[:full_path].to_s file_descriptor && file_descriptor[:full_path].to_s
end end
Contract Or[Symbol, String] Contract Or[Symbol, String, Fixnum]
def page_id def page_id
metadata[:page][:id] || destination_path metadata[:page][:id] || make_implicit_page_id(destination_path)
end end
# Merge in new metadata specific to this resource. # Merge in new metadata specific to this resource.
@ -197,10 +197,41 @@ module Middleman
options[:content_type] || ::Rack::Mime.mime_type(ext, nil) options[:content_type] || ::Rack::Mime.mime_type(ext, nil)
end end
# The normalized source path of this resource (relative to the source directory,
# without template extensions)
# @return [String]
def normalized_path
@normalized_path ||= ::Middleman::Util.normalize_path @path
end
def to_s def to_s
"#<#{self.class} path=#{@path}>" "#<#{self.class} path=#{@path}>"
end end
alias inspect to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s alias inspect to_s # Ruby 2.0 calls inspect for NoMethodError instead of to_s
protected
# Makes a page id based on path (when not otherwise given)
#
# Removes .html extension and potential leading slashes or dots
# eg. "foo/bar/baz.foo.html" => "foo/bar/baz.foo"
Contract String => String
def make_implicit_page_id(path)
@id ||= begin
if prok = @app.config[:page_id_generator]
return prok.call(path)
end
basename = if ext == ".html"
File.basename(path, ext)
else
File.basename(path)
end
# Remove leading dot or slash if present
File.join(File.dirname(path), basename).gsub(/^\.?\//, '')
end
end
end end
class StringResource < Resource class StringResource < Resource

Some files were not shown because too many files have changed in this diff Show more