Compare commits
2 Commits
master
...
feature/ma
Author | SHA1 | Date |
---|---|---|
Thomas Reynolds | 086c49a387 | |
Thomas Reynolds | 3b41335582 |
|
@ -16,6 +16,7 @@ docs
|
|||
.ruby-gemset
|
||||
.*.swp
|
||||
build
|
||||
manifest.yaml
|
||||
doc
|
||||
.yardoc
|
||||
tmp
|
||||
|
|
|
@ -67,5 +67,3 @@ Style/MultilineBlockChain:
|
|||
Enabled: false
|
||||
Style/SpecialGlobalVars:
|
||||
Enabled: false
|
||||
Style/FrozenStringLiteralComment:
|
||||
Enabled: false
|
||||
|
|
|
@ -5,14 +5,17 @@ before_script:
|
|||
- bundle update
|
||||
rvm:
|
||||
- ruby-head
|
||||
- 2.3.1
|
||||
- 2.3.0
|
||||
- 2.2.4
|
||||
- 2.1
|
||||
- 2.0
|
||||
os:
|
||||
- linux
|
||||
# - osx
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- rvm: 2.3.0
|
||||
- rvm: ruby-head
|
||||
env:
|
||||
global:
|
||||
|
|
32
CHANGELOG.md
32
CHANGELOG.md
|
@ -1,41 +1,9 @@
|
|||
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
|
||||
|
||||
|
|
14
Gemfile
14
Gemfile
|
@ -9,12 +9,6 @@ gem 'byebug'
|
|||
gem 'aruba', '~> 0.7.4', require: false
|
||||
gem 'rspec', '~> 3.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
|
||||
gem 'haml', '>= 4.0.5', require: false
|
||||
|
@ -24,19 +18,19 @@ gem 'kramdown', '~> 1.2', require: false
|
|||
gem 'slim', '>= 2.0', require: false
|
||||
gem 'liquid', '>= 2.6', require: false
|
||||
gem 'stylus', '>= 1.0', require: false
|
||||
gem 'sinatra', '>= 2.0.0.beta2', require: false
|
||||
gem 'sinatra', '>= 1.4', require: false
|
||||
gem 'redcarpet', '>= 3.1', require: false
|
||||
|
||||
# Dns server to test preview server
|
||||
gem 'rubydns', '~> 1.0.1', require: false
|
||||
|
||||
# To test javascript
|
||||
gem 'poltergeist', '~> 1.8', require: false
|
||||
gem 'phantomjs', '~> 2.1.1.0', require: false
|
||||
gem 'poltergeist', '~> 1.9', require: false
|
||||
gem 'phantomjs', '~> 2.1.1', require: false
|
||||
|
||||
# For less, note there is no compatible JS runtime for windows
|
||||
gem 'therubyrhino', '>= 2.0', platforms: :jruby
|
||||
gem 'therubyracer', '>= 0.12', platforms: :ruby
|
||||
gem 'therubyracer', '>= 0.12.1', platforms: :ruby
|
||||
|
||||
# Code Quality
|
||||
gem 'rubocop', '~> 0.24', require: false
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
## Expected behavior and actual behavior
|
||||
|
||||
## Steps to reproduce the problem (from a clean middleman installation)
|
||||
|
||||
## Additional information
|
||||
|
||||
- Ruby version:
|
||||
- Middleman version:
|
||||
- OS version:
|
|
@ -121,6 +121,6 @@ Copyright (c) 2010-2015 Thomas Reynolds. MIT Licensed, see [LICENSE] for details
|
|||
[codeclimate]: https://codeclimate.com/github/middleman/middleman
|
||||
[gittip]: https://www.gittip.com/middleman/
|
||||
[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
|
||||
[LICENSE]: https://github.com/middleman/middleman/blob/master/LICENSE.md
|
||||
|
|
|
@ -9,9 +9,6 @@ end
|
|||
require "middleman-core/load_paths"
|
||||
Middleman.setup_load_paths
|
||||
|
||||
require 'dotenv'
|
||||
::Dotenv.load
|
||||
|
||||
require 'middleman-core'
|
||||
require 'middleman-core/logger'
|
||||
|
||||
|
@ -25,10 +22,12 @@ module Middleman::Cli
|
|||
if setting.default.is_a?(String) || setting.default.is_a?(NilClass)
|
||||
base.class_option setting.key,
|
||||
type: :string,
|
||||
default: :undefined,
|
||||
desc: setting.description
|
||||
elsif setting.default.is_a?(TrueClass) || setting.default.is_a?(FalseClass)
|
||||
base.class_option setting.key,
|
||||
type: :boolean,
|
||||
default: :undefined,
|
||||
desc: setting.description
|
||||
end
|
||||
end
|
||||
|
@ -47,8 +46,6 @@ end
|
|||
|
||||
::Middleman::Logger.singleton(3)
|
||||
::Middleman::Cli.config = ::Middleman::Application.new do
|
||||
#
|
||||
config[:environment] = (ENV['MM_ENV'] || ENV['RACK_ENV'] || 'development').to_sym
|
||||
config[:mode] = :config
|
||||
config[:exit_before_ready] = true
|
||||
config[:watcher_disable] = true
|
||||
|
|
|
@ -10,7 +10,7 @@ module Middleman::Cli
|
|||
|
||||
class_option :environment,
|
||||
aliases: '-e',
|
||||
default: ENV['MM_ENV'] || ENV['RACK_ENV'] || :production
|
||||
default: :production
|
||||
class_option :clean,
|
||||
type: :boolean,
|
||||
default: true,
|
||||
|
@ -19,6 +19,10 @@ module Middleman::Cli
|
|||
type: :boolean,
|
||||
default: true,
|
||||
desc: 'Output files in parallel (--no-parallel to disable)'
|
||||
class_option :manifest,
|
||||
type: :boolean,
|
||||
default: false,
|
||||
desc: 'Use a manifest.yaml to optimize incremental builds'
|
||||
class_option :glob,
|
||||
type: :string,
|
||||
aliases: '-g',
|
||||
|
@ -29,7 +33,7 @@ module Middleman::Cli
|
|||
default: false,
|
||||
desc: 'Print debug messages'
|
||||
class_option :instrument,
|
||||
type: :boolean,
|
||||
type: :string,
|
||||
default: false,
|
||||
desc: 'Print instrument messages'
|
||||
class_option :profile,
|
||||
|
@ -64,14 +68,15 @@ module Middleman::Cli
|
|||
config[:mode] = :build
|
||||
config[:show_exceptions] = false
|
||||
config[:cli_options] = cli_options.each_with_object({}) do |(k, v), sum|
|
||||
sum[k] = v
|
||||
sum[k] = v unless v == :undefined
|
||||
end
|
||||
end
|
||||
|
||||
builder = Middleman::Builder.new(@app,
|
||||
glob: options['glob'],
|
||||
clean: options['clean'],
|
||||
parallel: options['parallel'])
|
||||
parallel: options['parallel'],
|
||||
manifest: options['manifest'])
|
||||
builder.thor = self
|
||||
builder.on_build_event(&method(:on_event))
|
||||
end
|
||||
|
|
|
@ -113,7 +113,7 @@ module Middleman::Cli
|
|||
end
|
||||
|
||||
def repository_path(repo)
|
||||
repo.include?('://') || repo.include?('git@') ? repo : "https://github.com/#{repo}.git"
|
||||
repo.include?('://') || repo.include?('git@') ? repo : "git://github.com/#{repo}.git"
|
||||
end
|
||||
|
||||
# Add to CLI
|
||||
|
|
|
@ -17,7 +17,7 @@ module Middleman::Cli
|
|||
default: false,
|
||||
desc: 'Print debug messages'
|
||||
class_option :instrument,
|
||||
type: :boolean,
|
||||
type: :string,
|
||||
default: false,
|
||||
desc: 'Print instrument messages'
|
||||
class_option :profile,
|
||||
|
|
|
@ -17,7 +17,7 @@ Gem::Specification.new do |s|
|
|||
s.test_files = `git ls-files -z -- {fixtures,features}/*`.split("\0")
|
||||
s.executable = 'middleman'
|
||||
s.require_path = 'lib'
|
||||
s.required_ruby_version = '>= 2.2.0'
|
||||
s.required_ruby_version = '>= 2.0.0'
|
||||
|
||||
# CLI
|
||||
s.add_dependency('thor', ['>= 0.17.0', '< 2.0'])
|
||||
|
|
|
@ -308,17 +308,3 @@ Feature: Assets get file hashes appended to them and references to them are upda
|
|||
| javascripts/application.js.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"
|
||||
|
|
|
@ -25,8 +25,7 @@ Feature: Alternate between multiple asset hosts
|
|||
And a file named "config.rb" with:
|
||||
"""
|
||||
activate :asset_host, host: Proc.new { |asset|
|
||||
hash = Digest::MD5.digest(asset).bytes.map!(&:ord).reduce(&:+)
|
||||
"http://assets%d.example.com" % (hash % 4)
|
||||
"http://assets%d.example.com" % (asset.hash % 4)
|
||||
}
|
||||
"""
|
||||
And the Server is running
|
||||
|
|
|
@ -40,29 +40,19 @@ Feature: link_to helper
|
|||
"""
|
||||
absolute: <%= link_to "Needs Index", "/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:
|
||||
"""
|
||||
absolute: <%= link_to "Needs Index", "/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"
|
||||
When I go to "/link_to.html"
|
||||
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 '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"
|
||||
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 '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
|
||||
Given a fixture app "indexable-app"
|
||||
|
@ -123,7 +113,7 @@ Feature: link_to helper
|
|||
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 'relative: <a href="../needs_index.html">Relative</a>'
|
||||
|
||||
|
||||
Scenario: link_to knows about directory indexes
|
||||
Given a fixture app "indexable-app"
|
||||
And a file named "source/link_to.html.erb" with:
|
||||
|
|
|
@ -4,7 +4,7 @@ Feature: i18n Paths
|
|||
Given a fixture app "empty-app"
|
||||
And a file named "data/pages.yml" with:
|
||||
"""
|
||||
- hello.html
|
||||
- hello.html
|
||||
"""
|
||||
And a file named "locales/en.yml" with:
|
||||
"""
|
||||
|
@ -50,24 +50,24 @@ Feature: i18n Paths
|
|||
Given the Server is running at "empty-app"
|
||||
When I go to "/hello.html"
|
||||
Then I should see "Page: Hello"
|
||||
Then I should see '<a href="/index.html" class="current">Current Home</a>'
|
||||
Then I should see '<a href="/es/index.html" title="Other Home">Other Home</a>'
|
||||
Then I should see '<a href="/index.html" class="current"><span>Home: Current 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 href="/hello.html" class="current">Current 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 href="/hello.html" class="current"><span>Current Block</span></a>'
|
||||
Then I should see '<a href="/es/hola.html" title="Other hello.html"><span>Other Block</span></a>'
|
||||
Then I should see '<a class="current" href="/index.html">Current Home</a>'
|
||||
Then I should see '<a title="Other Home" href="/es/index.html">Other Home</a>'
|
||||
Then I should see '<a class="current" href="/index.html"><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 class="current" href="/hello.html">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 class="current" href="/hello.html"><span>Current Block</span></a>'
|
||||
Then I should see '<a title="Other hello.html" href="/es/hola.html"><span>Other Block</span></a>'
|
||||
When I go to "/es/hola.html"
|
||||
Then I should see "Page: Hola"
|
||||
Then I should see '<a href="/es/index.html" class="current">Current Home</a>'
|
||||
Then I should see '<a href="/index.html" title="Other Home">Other Home</a>'
|
||||
Then I should see '<a href="/es/index.html" class="current"><span>Home: Current 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 href="/es/hola.html" class="current">Current hello.html</a>'
|
||||
Then I should see '<a href="/hello.html" title="Other hello.html">Other hello.html</a>'
|
||||
Then I should see '<a href="/es/hola.html" class="current"><span>Current Block</span></a>'
|
||||
Then I should see '<a href="/hello.html" title="Other hello.html"><span>Other Block</span></a>'
|
||||
Then I should see '<a class="current" href="/es/index.html">Current Home</a>'
|
||||
Then I should see '<a title="Other Home" href="/index.html">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 title="Other Home" href="/index.html"><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 title="Other hello.html" href="/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 title="Other hello.html" href="/hello.html"><span>Other Block</span></a>'
|
||||
|
||||
Scenario: link_to is i18n aware and supports relative_links
|
||||
Given a fixture app "empty-app"
|
||||
|
@ -124,30 +124,30 @@ Feature: i18n Paths
|
|||
Then I should see "assets/css/main.css"
|
||||
When I go to "/hello.html"
|
||||
Then I should see "Page: Hello"
|
||||
Then I should see '<a href="index.html" class="current">Current Home</a>'
|
||||
Then I should see '<a href="es/index.html" title="Other Home">Other Home</a>'
|
||||
Then I should see '<a href="index.html" class="current"><span>Home: Current 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 href="hello.html" class="current">Current 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 href="hello.html" class="current"><span>Current Block</span></a>'
|
||||
Then I should see '<a href="es/hola.html" title="Other hello.html"><span>Other Block</span></a>'
|
||||
Then I should see '<a class="current" href="index.html">Current Home</a>'
|
||||
Then I should see '<a title="Other Home" href="es/index.html">Other Home</a>'
|
||||
Then I should see '<a class="current" href="index.html"><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 class="current" href="hello.html">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 class="current" href="hello.html"><span>Current Block</span></a>'
|
||||
Then I should see '<a title="Other hello.html" href="es/hola.html"><span>Other Block</span></a>'
|
||||
When I go to "/es/hola.html"
|
||||
Then I should see "Page: Hola"
|
||||
Then I should see '<a href="index.html" class="current">Current Home</a>'
|
||||
Then I should see '<a href="../index.html" title="Other Home">Other Home</a>'
|
||||
Then I should see '<a href="index.html" class="current"><span>Home: Current 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 href="hola.html" class="current">Current hello.html</a>'
|
||||
Then I should see '<a href="../hello.html" title="Other hello.html">Other hello.html</a>'
|
||||
Then I should see '<a href="hola.html" class="current"><span>Current Block</span></a>'
|
||||
Then I should see '<a href="../hello.html" title="Other hello.html"><span>Other Block</span></a>'
|
||||
Then I should see '<a class="current" href="index.html">Current Home</a>'
|
||||
Then I should see '<a title="Other Home" href="../index.html">Other Home</a>'
|
||||
Then I should see '<a class="current" href="index.html"><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 class="current" href="hola.html">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 class="current" href="hola.html"><span>Current Block</span></a>'
|
||||
Then I should see '<a title="Other hello.html" href="../hello.html"><span>Other Block</span></a>'
|
||||
|
||||
Scenario: url_for is i18n aware
|
||||
Given a fixture app "empty-app"
|
||||
And a file named "data/pages.yml" with:
|
||||
"""
|
||||
- hello.html
|
||||
- hello.html
|
||||
- article.html
|
||||
"""
|
||||
And a file named "locales/en.yml" with:
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
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"'
|
|
@ -3,60 +3,14 @@ Feature: Page IDs
|
|||
Scenario: link_to works with blocks (erb)
|
||||
Given the Server is running at "page-id-app"
|
||||
When I go to "/index.html"
|
||||
Then I should see "I am: index"
|
||||
Then I should see "I am: index.html"
|
||||
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 '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"
|
||||
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"
|
||||
Then I should see "I am: page1"
|
||||
|
|
|
@ -120,7 +120,7 @@ Feature: Relative Assets
|
|||
"""
|
||||
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"'
|
||||
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"
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
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'
|
|
@ -1,40 +0,0 @@
|
|||
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"
|
|
@ -1,26 +0,0 @@
|
|||
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
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
activate :asset_hash,
|
||||
prefix: "myprefix-"
|
||||
|
||||
activate :relative_assets
|
||||
|
||||
activate :directory_indexes
|
|
@ -1,16 +0,0 @@
|
|||
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
|
|
@ -1,6 +0,0 @@
|
|||
<% content_for :head do %>
|
||||
<title>The Middleman!</title>
|
||||
<% end %>
|
||||
|
||||
<h1>Testing the sitemap hashing</h1>
|
||||
<br /><br /><br />
|
|
@ -1,2 +0,0 @@
|
|||
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
|
|
@ -1 +0,0 @@
|
|||
{"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"}
|
|
@ -1,17 +0,0 @@
|
|||
<!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>
|
|
@ -1,7 +0,0 @@
|
|||
%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" }
|
|
@ -1 +0,0 @@
|
|||
I am: <%= current_resource.page_id %>
|
|
@ -1 +0,0 @@
|
|||
I am: <%= current_resource.page_id %>
|
|
@ -1 +0,0 @@
|
|||
I am: <%= current_resource.page_id %>
|
|
@ -4,11 +4,3 @@ URL1: <%= url_for "frontmatter" %>
|
|||
URL2: <%= url_for "page2" %>
|
||||
URL3: <%= link_to "Hi", "page3" %>
|
||||
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" %>
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<%= partial "/partials/test" %>
|
|
@ -203,7 +203,6 @@ module Middleman
|
|||
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_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
|
||||
def_delegator :"::Middleman::Logger", :singleton, :logger
|
||||
|
@ -237,7 +236,9 @@ module Middleman
|
|||
:before_render,
|
||||
:after_render,
|
||||
:before_server,
|
||||
:reload
|
||||
:reload,
|
||||
:render_layout,
|
||||
:render_partial
|
||||
])
|
||||
|
||||
@middleware = Set.new
|
||||
|
@ -267,8 +268,6 @@ module Middleman
|
|||
# Evaluate a passed block if given
|
||||
config_context.instance_exec(&block) if block_given?
|
||||
|
||||
apply_cli_options
|
||||
|
||||
execute_callbacks(:before_sitemap)
|
||||
|
||||
# Initialize the Sitemap
|
||||
|
@ -279,6 +278,8 @@ module Middleman
|
|||
# Before config is parsed, before extensions get to it.
|
||||
execute_callbacks(:initialized)
|
||||
|
||||
apply_cli_options
|
||||
|
||||
# Before config is parsed. Mostly used for extensions.
|
||||
execute_callbacks(:before_configuration)
|
||||
|
||||
|
@ -345,11 +346,11 @@ module Middleman
|
|||
|
||||
# Clean up missing Tilt exts
|
||||
def prune_tilt_templates!
|
||||
::Tilt.default_mapping.lazy_map.each_key do |key|
|
||||
::Tilt.mappings.each_key do |key|
|
||||
begin
|
||||
::Tilt[".#{key}"]
|
||||
rescue LoadError, NameError
|
||||
::Tilt.default_mapping.lazy_map.delete(key)
|
||||
::Tilt.mappings.delete(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,15 +2,20 @@ require 'pathname'
|
|||
require 'fileutils'
|
||||
require 'tempfile'
|
||||
require 'parallel'
|
||||
require 'set'
|
||||
require 'digest/sha1'
|
||||
require 'middleman-core/rack'
|
||||
require 'middleman-core/callback_manager'
|
||||
require 'middleman-core/contracts'
|
||||
require 'middleman-core/dependencies'
|
||||
|
||||
module Middleman
|
||||
class Builder
|
||||
extend Forwardable
|
||||
include Contracts
|
||||
|
||||
OutputResult = Struct.new(:path, :source_path, :depends_on)
|
||||
|
||||
# Make app & events available to `after_build` callbacks.
|
||||
attr_reader :app, :events
|
||||
|
||||
|
@ -23,6 +28,8 @@ module Middleman
|
|||
# Sort order, images, fonts, js/css and finally everything else.
|
||||
SORT_ORDER = %w(.png .jpeg .jpg .gif .bmp .svg .svgz .webp .ico .woff .woff2 .otf .ttf .eot .js .css).freeze
|
||||
|
||||
MANIFEST_FILE = 'manifest.yaml'
|
||||
|
||||
# Create a new Builder instance.
|
||||
# @param [Middleman::Application] app The app to build.
|
||||
# @param [Hash] opts The builder options
|
||||
|
@ -38,6 +45,11 @@ module Middleman
|
|||
@glob = opts.fetch(:glob)
|
||||
@cleaning = opts.fetch(:clean)
|
||||
@parallel = opts.fetch(:parallel, true)
|
||||
@manifest = opts.fetch(:manifest, false)
|
||||
@cleaning = @glob = false if @manifest
|
||||
|
||||
@layout_files = Set.new
|
||||
@partial_files = Set.new
|
||||
|
||||
rack_app = ::Middleman::Rack.new(@app).to_app
|
||||
@rack = ::Rack::MockRequest.new(rack_app)
|
||||
|
@ -62,13 +74,23 @@ module Middleman
|
|||
end
|
||||
|
||||
::Middleman::Util.instrument 'builder.prerender' do
|
||||
prerender_css
|
||||
prerender_css unless @manifest
|
||||
end
|
||||
|
||||
::Middleman::Profiling.start
|
||||
|
||||
::Middleman::Util.instrument 'builder.output' do
|
||||
output_files
|
||||
files =
|
||||
# if @manifest && m = load_manifest!
|
||||
# incremental_resources = calculate_incremental(m)
|
||||
|
||||
# logger.debug '== Building files'
|
||||
# output_resources(incremental_resources)
|
||||
# else
|
||||
output_files
|
||||
# end
|
||||
|
||||
build_manifest!(files) if @manifest && !@has_error
|
||||
end
|
||||
|
||||
::Middleman::Profiling.report('build')
|
||||
|
@ -81,6 +103,7 @@ module Middleman
|
|||
@app.execute_callbacks(:after_build, [self])
|
||||
end
|
||||
|
||||
|
||||
!@has_error
|
||||
end
|
||||
|
||||
|
@ -93,6 +116,7 @@ module Middleman
|
|||
css_files = ::Middleman::Util.instrument 'builder.prerender.output' do
|
||||
resources = @app.sitemap.resources.select { |resource| resource.ext == '.css' }
|
||||
output_resources(resources)
|
||||
resources
|
||||
end
|
||||
|
||||
::Middleman::Util.instrument 'builder.prerender.check-files' do
|
||||
|
@ -108,7 +132,7 @@ module Middleman
|
|||
|
||||
# Find all the files we need to output and do so.
|
||||
# @return [Array<Resource>] List of resources that were output.
|
||||
Contract ResourceList
|
||||
Contract ArrayOf[OutputResult]
|
||||
def output_files
|
||||
logger.debug '== Building files'
|
||||
|
||||
|
@ -129,7 +153,7 @@ module Middleman
|
|||
output_resources(resources)
|
||||
end
|
||||
|
||||
Contract ResourceList => ResourceList
|
||||
Contract ResourceList => ArrayOf[OutputResult]
|
||||
def output_resources(resources)
|
||||
results = if @parallel
|
||||
::Parallel.map(resources, &method(:output_resource))
|
||||
|
@ -141,20 +165,20 @@ module Middleman
|
|||
|
||||
if @cleaning && !@has_error
|
||||
results.each do |p|
|
||||
next unless p.exist?
|
||||
next unless p[:path].exist?
|
||||
|
||||
# handle UTF-8-MAC filename on MacOS
|
||||
cleaned_name = if RUBY_PLATFORM =~ /darwin/
|
||||
p.to_s.encode('UTF-8', 'UTF-8-MAC')
|
||||
p[:path].to_s.encode('UTF-8', 'UTF-8-MAC')
|
||||
else
|
||||
p
|
||||
p[:path]
|
||||
end
|
||||
|
||||
@to_clean.delete(Pathname(cleaned_name))
|
||||
end
|
||||
end
|
||||
|
||||
resources
|
||||
results
|
||||
end
|
||||
|
||||
# Figure out the correct event mode.
|
||||
|
@ -166,7 +190,7 @@ module Middleman
|
|||
if !output_file.exist?
|
||||
:created
|
||||
else
|
||||
FileUtils.compare_file(source.to_s, output_file.to_s) ? :identical : :updated
|
||||
::FileUtils.compare_file(source.to_s, output_file.to_s) ? :identical : :updated
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -218,11 +242,21 @@ module Middleman
|
|||
# Try to output a resource and capture errors.
|
||||
# @param [Middleman::Sitemap::Resource] resource The resource.
|
||||
# @return [void]
|
||||
Contract IsA['Middleman::Sitemap::Resource'] => Or[Pathname, Bool]
|
||||
Contract IsA['Middleman::Sitemap::Resource'] => Or[OutputResult, Bool]
|
||||
def output_resource(resource)
|
||||
::Middleman::Util.instrument 'builder.output.resource', path: File.basename(resource.destination_path) do
|
||||
output_file = @build_dir + resource.destination_path.gsub('%20', ' ')
|
||||
|
||||
depends_on = Set.new
|
||||
|
||||
@app.render_layout do |f|
|
||||
depends_on << f[:full_path]
|
||||
end
|
||||
|
||||
@app.render_partial do |f|
|
||||
depends_on << f[:full_path]
|
||||
end
|
||||
|
||||
begin
|
||||
if resource.binary?
|
||||
export_file!(output_file, resource.file_descriptor[:full_path])
|
||||
|
@ -242,7 +276,7 @@ module Middleman
|
|||
return false
|
||||
end
|
||||
|
||||
output_file
|
||||
OutputResult.new(output_file.to_s, resource.destination_path, depends_on)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -299,5 +333,86 @@ module Middleman
|
|||
|
||||
execute_callbacks(:on_build_event, [event_type, target, extra])
|
||||
end
|
||||
|
||||
def load_manifest!
|
||||
return nil unless File.exist?(MANIFEST_FILE)
|
||||
|
||||
deps = ::Middleman::Dependencies.new
|
||||
|
||||
m = ::YAML.load(File.read(MANIFEST_FILE))
|
||||
|
||||
all_files = Set.new(@app.files.files.map { |f| f[:full_path].relative_path_from(@app.root_path).to_s })
|
||||
ruby_files = Set.new(Dir[File.join(app.root, "**/*.rb")].map { |f| Pathname(f).relative_path_from(@app.root_path).to_s }) << "Gemfile.lock"
|
||||
|
||||
locales_path = app.extensions[:i18n] && app.extensions[:i18n].options[:data]
|
||||
|
||||
partial_and_layout_files = all_files.select do |f|
|
||||
f.start_with?(app.config[:layouts_dir] + "/") || f.split("/").any? { |d| d.start_with?("_") } || (locales_path && f.start_with?(locales_path + "/"))
|
||||
end
|
||||
|
||||
@global_paths = Set.new(partial_and_layout_files) + ruby_files
|
||||
|
||||
# Add file refs
|
||||
all_files.each do |f|
|
||||
deps.record!(f, m[f])
|
||||
end
|
||||
|
||||
(all_files + ruby_files).select do |f|
|
||||
if m[f]
|
||||
dig = ::Digest::SHA1.file(f).to_s
|
||||
dig != m[f]
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
rescue ::Psych::SyntaxError => error
|
||||
logger.error "Manifest file (#{MANIFEST_FILE}) was malformed."
|
||||
end
|
||||
|
||||
def calculate_incremental(manifest)
|
||||
logger.debug '== Calculating incremental build files'
|
||||
|
||||
if manifest.empty?
|
||||
logger.debug "== No files changed"
|
||||
return []
|
||||
end
|
||||
|
||||
resources = @app.sitemap.resources.sort_by { |resource| SORT_ORDER.index(resource.ext) || 100 }
|
||||
|
||||
if changed = manifest.select { |p| @global_paths.include?(p) }
|
||||
if changed.length > 0
|
||||
logger.debug "== Global file changed: #{changed}"
|
||||
return resources
|
||||
end
|
||||
end
|
||||
|
||||
resources.select do |r|
|
||||
if r.file_descriptor
|
||||
path = r.file_descriptor[:full_path].relative_path_from(@app.root_path).to_s
|
||||
manifest.include?(path)
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Contract ArrayOf[OutputResult] => Any
|
||||
def build_manifest!(files)
|
||||
require 'byebug'
|
||||
byebug
|
||||
all_files = Set.new(@app.files.files.map { |f| f[:full_path].to_s })
|
||||
ruby_files = Set.new(Dir[File.join(app.root, "**/*.rb")])
|
||||
|
||||
gemfile_path = File.expand_path("Gemfile.lock", @app.root)
|
||||
ruby_files << gemfile_path if File.exist?(gemfile_path)
|
||||
|
||||
manifest = (all_files + ruby_files).each_with_object({}) do |source_file, sum|
|
||||
path = Pathname(source_file).relative_path_from(@app.root_path).to_s
|
||||
sum[path] = ::Digest::SHA1.file(source_file).to_s
|
||||
end
|
||||
|
||||
::File.write(MANIFEST_FILE, manifest.to_yaml)
|
||||
trigger(:created, MANIFEST_FILE)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ module Middleman
|
|||
attr_reader :app
|
||||
|
||||
# Whitelist methods that can reach out.
|
||||
def_delegators :@app, :config, :logger, :use, :map, :mime_type, :files, :root, :build?, :server?, :environment?, :extensions
|
||||
def_delegators :@app, :config, :logger, :use, :map, :mime_type, :files, :root, :build?, :server?, :environment?
|
||||
def_delegator :"@app.extensions", :activate
|
||||
|
||||
def initialize(app, template_context_class)
|
||||
|
@ -23,7 +23,7 @@ module Middleman
|
|||
end
|
||||
|
||||
def include(mod)
|
||||
extend(mod)
|
||||
self.extend(mod)
|
||||
end
|
||||
|
||||
def helpers(*helper_modules, &block)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
require 'padrino-helpers'
|
||||
require 'middleman-core/contracts'
|
||||
|
||||
# Don't fail on invalid locale, that's not what our current
|
||||
# users expect.
|
||||
|
|
|
@ -28,7 +28,10 @@ module Middleman
|
|||
super
|
||||
|
||||
# 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.
|
||||
IGNORES.each do |key, value|
|
||||
|
@ -52,13 +55,6 @@ module Middleman
|
|||
# @return [void]
|
||||
Contract Any
|
||||
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]
|
||||
@watcher.update_path(app.config[:source])
|
||||
end
|
||||
|
|
|
@ -73,20 +73,18 @@ module Middleman::CoreExtensions
|
|||
|
||||
return [{}, nil] unless file
|
||||
|
||||
file_path = file[:full_path].to_s
|
||||
return @cache[file[:full_path]] if @cache.key?(file[:full_path])
|
||||
|
||||
@cache[file_path] ||= begin
|
||||
::Middleman::Util::Data.parse(
|
||||
file,
|
||||
app.config[:frontmatter_delims]
|
||||
)
|
||||
end
|
||||
@cache[file[:full_path]] = ::Middleman::Util::Data.parse(
|
||||
file,
|
||||
app.config[:frontmatter_delims]
|
||||
)
|
||||
end
|
||||
|
||||
Contract ArrayOf[IsA['Middleman::SourceFile']], ArrayOf[IsA['Middleman::SourceFile']] => Any
|
||||
def clear_data(updated_files, removed_files)
|
||||
(updated_files + removed_files).each do |file|
|
||||
@cache.delete(file[:full_path].to_s)
|
||||
@cache.delete(file[:full_path])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require 'rack'
|
||||
require 'rack/response'
|
||||
require 'memoist'
|
||||
require 'addressable/uri'
|
||||
require 'middleman-core/util'
|
||||
require 'middleman-core/contracts'
|
||||
|
||||
|
@ -11,12 +11,13 @@ module Middleman
|
|||
|
||||
expose_to_application rewrite_inline_urls: :add
|
||||
|
||||
IGNORE_DESCRIPTOR = Or[Regexp, RespondTo[:call], String]
|
||||
REWRITER_DESCRIPTOR = {
|
||||
id: Symbol,
|
||||
proc: Or[Proc, Method],
|
||||
url_extensions: ArrayOf[String],
|
||||
source_extensions: ArrayOf[String],
|
||||
ignore: ArrayOf[::Middleman::Util::IGNORE_DESCRIPTOR],
|
||||
ignore: ArrayOf[IGNORE_DESCRIPTOR],
|
||||
after: Maybe[Symbol]
|
||||
}.freeze
|
||||
|
||||
|
@ -32,8 +33,6 @@ module Middleman
|
|||
end
|
||||
|
||||
def after_configuration
|
||||
return if @rewriters.empty?
|
||||
|
||||
rewriters = @rewriters.values.sort do |a, b|
|
||||
if b[:after] && b[:after] == a[:id]
|
||||
1
|
||||
|
@ -46,7 +45,6 @@ module Middleman
|
|||
end
|
||||
|
||||
class Rack
|
||||
extend Memoist
|
||||
include Contracts
|
||||
|
||||
Contract RespondTo[:call], {
|
||||
|
@ -57,17 +55,6 @@ module Middleman
|
|||
@rack_app = app
|
||||
@middleman_app = options.fetch(:middleman_app)
|
||||
@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
|
||||
|
||||
def call(env)
|
||||
|
@ -76,16 +63,27 @@ module Middleman
|
|||
# Allow configuration or upstream request to skip all rewriting
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
dirpath = ::Pathname.new(File.dirname(path))
|
||||
|
||||
rewritten = ::Middleman::Util.instrument 'inline_url_rewriter', path: path do
|
||||
::Middleman::Util.rewrite_paths(body, path, @all_asset_exts, @middleman_app) do |asset_path|
|
||||
uri = ::Middleman::Util.parse_uri(asset_path)
|
||||
::Middleman::Util.rewrite_paths(body, path, all_asset_exts, @middleman_app) do |asset_path|
|
||||
uri = ::Addressable::URI.parse(asset_path)
|
||||
|
||||
relative_path = uri.host.nil?
|
||||
|
||||
|
@ -108,7 +106,7 @@ module Middleman
|
|||
next unless source_exts.include?(::File.extname(path))
|
||||
|
||||
ignore = rewriter.fetch(:ignore)
|
||||
next if ignore.any? { |r| ::Middleman::Util.should_ignore?(r, full_asset_path) }
|
||||
next if ignore.any? { |r| should_ignore?(r, full_asset_path) }
|
||||
|
||||
rewrite_ignore = Array(rewriter[:rewrite_ignore] || [])
|
||||
next if rewrite_ignore.any? { |i| ::Middleman::Util.path_match(i, path) }
|
||||
|
@ -129,6 +127,23 @@ module Middleman
|
|||
headers
|
||||
).finish
|
||||
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
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
require 'forwardable'
|
||||
require 'memoist'
|
||||
require 'active_support/core_ext/class/attribute'
|
||||
require 'middleman-core/configuration'
|
||||
require 'middleman-core/contracts'
|
||||
|
@ -67,8 +66,6 @@ module Middleman
|
|||
# @see http://middlemanapp.com/advanced/custom/ Middleman Custom Extensions Documentation
|
||||
class Extension
|
||||
extend Forwardable
|
||||
extend Memoist
|
||||
|
||||
include Contracts
|
||||
|
||||
def_delegator :@app, :logger
|
||||
|
@ -513,7 +510,7 @@ module Middleman
|
|||
self.class.exposed_to_config.each do |k, 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)
|
||||
self.descriptors << r if r.respond_to?(:execute_descriptor)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,7 +6,6 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
|||
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 :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites'
|
||||
option :prefix, '', 'Prefix for hash'
|
||||
|
||||
def initialize(app, options_hash={}, &block)
|
||||
super
|
||||
|
@ -33,7 +32,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
|||
|
||||
Contract String, Or[String, Pathname], Any => Maybe[String]
|
||||
def rewrite_url(asset_path, dirpath, _request_path)
|
||||
uri = ::Middleman::Util.parse_uri(asset_path)
|
||||
uri = ::Addressable::URI.parse(asset_path)
|
||||
relative_path = !uri.path.start_with?('/')
|
||||
|
||||
full_asset_path = if relative_path
|
||||
|
@ -93,7 +92,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension
|
|||
::Digest::SHA1.hexdigest(response.body)[0..7]
|
||||
end
|
||||
|
||||
resource.destination_path = resource.destination_path.sub(/\.(\w+)$/) { |ext| "-#{options.prefix}#{digest}#{ext}" }
|
||||
resource.destination_path = resource.destination_path.sub(/\.(\w+)$/) { |ext| "-#{digest}#{ext}" }
|
||||
resource
|
||||
end
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension
|
|||
|
||||
Contract String, Or[String, Pathname], Any => String
|
||||
def rewrite_url(asset_path, dirpath, _request_path)
|
||||
uri = ::Middleman::Util.parse_uri(asset_path)
|
||||
uri = ::Addressable::URI.parse(asset_path)
|
||||
relative_path = uri.path[0..0] != '/'
|
||||
|
||||
full_asset_path = if relative_path
|
||||
|
@ -37,5 +37,4 @@ class Middleman::Extensions::AssetHost < ::Middleman::Extension
|
|||
|
||||
File.join(asset_prefix, full_asset_path)
|
||||
end
|
||||
memoize :rewrite_url
|
||||
end
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
require 'active_support/core_ext/object/try'
|
||||
require 'memoist'
|
||||
require 'middleman-core/contracts'
|
||||
|
||||
# Minify CSS Extension
|
||||
|
@ -32,7 +30,6 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
|
|||
|
||||
# Rack middleware to look for CSS and compress it
|
||||
class Rack
|
||||
extend Memoist
|
||||
include Contracts
|
||||
INLINE_CSS_REGEX = /(<style[^>]*>\s*(?:\/\*<!\[CDATA\[\*\/\n)?)(.*?)((?:(?:\n\s*)?\/\*\]\]>\*\/)?\s*<\/style>)/m
|
||||
|
||||
|
@ -72,7 +69,7 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
|
|||
end
|
||||
|
||||
if minified
|
||||
headers['Content-Length'] = minified.bytesize.to_s
|
||||
headers['Content-Length'] = ::Rack::Utils.bytesize(minified).to_s
|
||||
response = [minified]
|
||||
end
|
||||
|
||||
|
@ -85,9 +82,8 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
|
|||
# @param [String] path
|
||||
# @return [Boolean]
|
||||
def ignore?(path)
|
||||
@ignore.any? { |ignore| ::Middleman::Util.path_match(ignore, path) }
|
||||
@ignore.any? { |ignore| Middleman::Util.path_match(ignore, path) }
|
||||
end
|
||||
memoize :ignore?
|
||||
|
||||
# Whether this type of content can be minified
|
||||
# @param [String, nil] content_type
|
||||
|
@ -95,7 +91,6 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
|
|||
def minifiable?(content_type)
|
||||
@content_types.include?(content_type)
|
||||
end
|
||||
memoize :minifiable?
|
||||
|
||||
# Whether this type of content contains inline content that can be minified
|
||||
# @param [String, nil] content_type
|
||||
|
@ -103,7 +98,6 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
|
|||
def minifiable_inline?(content_type)
|
||||
@inline_content_types.include?(content_type)
|
||||
end
|
||||
memoize :minifiable_inline?
|
||||
|
||||
# Minify the content
|
||||
# @param [String] content
|
||||
|
@ -111,7 +105,6 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
|
|||
def minify(content)
|
||||
@compressor.compress(content)
|
||||
end
|
||||
memoize :minify
|
||||
|
||||
# Detect and minify inline content
|
||||
# @param [String] content
|
||||
|
@ -121,6 +114,5 @@ class Middleman::Extensions::MinifyCss < ::Middleman::Extension
|
|||
$1 + minify($2) + $3
|
||||
end
|
||||
end
|
||||
memoize :minify_inline
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
require 'active_support/core_ext/object/try'
|
||||
require 'middleman-core/contracts'
|
||||
require 'memoist'
|
||||
|
||||
# Minify Javascript Extension
|
||||
class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
|
||||
|
@ -24,7 +22,6 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
|
|||
|
||||
# Rack middleware to look for JS and compress it
|
||||
class Rack
|
||||
extend Memoist
|
||||
include Contracts
|
||||
INLINE_JS_REGEX = /(<script[^>]*>\s*(?:\/\/(?:(?:<!--)|(?:<!\[CDATA\[))\n)?)(.*?)((?:(?:\n\s*)?\/\/(?:(?:-->)|(?:\]\]>)))?\s*<\/script>)/m
|
||||
|
||||
|
@ -64,7 +61,7 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
|
|||
end
|
||||
|
||||
if minified
|
||||
headers['Content-Length'] = minified.bytesize.to_s
|
||||
headers['Content-Length'] = ::Rack::Utils.bytesize(minified).to_s
|
||||
response = [minified]
|
||||
end
|
||||
|
||||
|
@ -79,7 +76,6 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
|
|||
def ignore?(path)
|
||||
@ignore.any? { |ignore| Middleman::Util.path_match(ignore, path) }
|
||||
end
|
||||
memoize :ignore?
|
||||
|
||||
# Whether this type of content can be minified
|
||||
# @param [String, nil] content_type
|
||||
|
@ -87,7 +83,6 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
|
|||
def minifiable?(content_type)
|
||||
@content_types.include?(content_type)
|
||||
end
|
||||
memoize :minifiable?
|
||||
|
||||
# Whether this type of content contains inline content that can be minified
|
||||
# @param [String, nil] content_type
|
||||
|
@ -95,7 +90,6 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
|
|||
def minifiable_inline?(content_type)
|
||||
@inline_content_types.include?(content_type)
|
||||
end
|
||||
memoize :minifiable_inline?
|
||||
|
||||
# Minify the content
|
||||
# @param [String] content
|
||||
|
@ -106,7 +100,6 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
|
|||
warn "WARNING: Couldn't compress JavaScript in #{@path}: #{e.message}"
|
||||
content
|
||||
end
|
||||
memoize :minify
|
||||
|
||||
# Detect and minify inline content
|
||||
# @param [String] content
|
||||
|
@ -126,6 +119,5 @@ class Middleman::Extensions::MinifyJavascript < ::Middleman::Extension
|
|||
end
|
||||
end
|
||||
end
|
||||
memoize :minify_inline
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,18 +2,15 @@ require 'addressable/uri'
|
|||
|
||||
# Relative Assets extension
|
||||
class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
|
||||
option :exts, nil, 'List of extensions that get converted to relative paths.'
|
||||
option :exts, nil, 'List of extensions that get cache busters strings appended to them.'
|
||||
option :sources, %w(.css .htm .html .xhtml), 'List of extensions that are searched for relative assets.'
|
||||
option :ignore, [], 'Regexes of filenames to skip converting to relative paths.'
|
||||
option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites.'
|
||||
option :helpers_only, false, 'Allow only Ruby helpers to change paths.'
|
||||
option :ignore, [], 'Regexes of filenames to skip adding query strings to'
|
||||
option :rewrite_ignore, [], 'Regexes of filenames to skip processing for path rewrites'
|
||||
|
||||
def initialize(app, options_hash={}, &block)
|
||||
super
|
||||
|
||||
return if options[:helpers_only]
|
||||
|
||||
app.rewrite_inline_urls id: :relative_assets,
|
||||
app.rewrite_inline_urls id: :asset_hash,
|
||||
url_extensions: options.exts || app.config[:asset_extensions],
|
||||
source_extensions: options.sources,
|
||||
ignore: options.ignore,
|
||||
|
@ -21,43 +18,22 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
|
|||
proc: method(:rewrite_url)
|
||||
end
|
||||
|
||||
def mark_as_relative(file_path, opts, current_resource)
|
||||
result = opts.dup
|
||||
|
||||
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
|
||||
# asset_url override for relative assets
|
||||
# @param [String] path
|
||||
# @param [String] prefix
|
||||
# @param [Hash] options Additional options.
|
||||
# @return [String]
|
||||
def asset_url(path, prefix='', options={})
|
||||
super(path, prefix, app.extensions[:relative_assets].mark_as_relative(super, options, current_resource))
|
||||
end
|
||||
options[:relative] = true unless options.key?(:relative)
|
||||
|
||||
def asset_path(kind, source, options={})
|
||||
super(kind, source, app.extensions[:relative_assets].mark_as_relative(super, options, current_resource))
|
||||
super(path, prefix, options)
|
||||
end
|
||||
end
|
||||
|
||||
Contract String, Or[String, Pathname], Any => Maybe[String]
|
||||
def rewrite_url(asset_path, dirpath, request_path)
|
||||
uri = ::Middleman::Util.parse_uri(asset_path)
|
||||
uri = ::Addressable::URI.parse(asset_path)
|
||||
|
||||
return if uri.path[0..0] != '/'
|
||||
|
||||
|
@ -74,5 +50,4 @@ class Middleman::Extensions::RelativeAssets < ::Middleman::Extension
|
|||
|
||||
result
|
||||
end
|
||||
memoize :rewrite_url
|
||||
end
|
||||
|
|
|
@ -3,8 +3,8 @@ require 'active_support/core_ext/string/output_safety'
|
|||
require 'active_support/core_ext/module/delegation'
|
||||
require 'middleman-core/contracts'
|
||||
|
||||
::Tilt.default_mapping.lazy_map.delete('html')
|
||||
::Tilt.default_mapping.lazy_map.delete('csv')
|
||||
::Tilt.mappings.delete('html') # WTF, Tilt?
|
||||
::Tilt.mappings.delete('csv')
|
||||
|
||||
module Middleman
|
||||
class FileRenderer
|
||||
|
@ -59,7 +59,7 @@ module Middleman
|
|||
# Overwrite with frontmatter options
|
||||
options = options.deep_merge(options[:renderer_options]) if options[:renderer_options]
|
||||
|
||||
template_class = ::Middleman::Util.tilt_class(path)
|
||||
template_class = ::Tilt[path]
|
||||
|
||||
# Allow hooks to manipulate the template before render
|
||||
body = @app.callbacks_for(:before_render).reduce(body) do |sum, callback|
|
||||
|
@ -99,12 +99,12 @@ module Middleman
|
|||
def template_data_for_file
|
||||
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)
|
||||
return result unless result.nil?
|
||||
end
|
||||
|
||||
file ? file.read : ::File.read(@path)
|
||||
file ? file.read : File.read(@path)
|
||||
end
|
||||
|
||||
protected
|
||||
|
@ -122,9 +122,9 @@ module Middleman
|
|||
|
||||
# Find all the engines which handle this extension in tilt. Look for
|
||||
# config variables of that name and merge it
|
||||
extension_class = ::Middleman::Util.tilt_class(ext)
|
||||
|
||||
::Tilt.default_mapping.extensions_for(extension_class).each do |mapping_ext|
|
||||
extension_class = ::Tilt[ext]
|
||||
::Tilt.mappings.each do |mapping_ext, engines|
|
||||
next unless engines.include? extension_class
|
||||
engine_options = @app.config[mapping_ext.to_sym] || {}
|
||||
options.merge!(engine_options)
|
||||
end
|
||||
|
|
|
@ -143,7 +143,7 @@ module Middleman
|
|||
|
||||
app = ::Middleman::Application.new do
|
||||
config[:cli_options] = cli_options.each_with_object({}) do |(k, v), sum|
|
||||
sum[k] = v
|
||||
sum[k] = v unless v == :undefined
|
||||
end
|
||||
|
||||
ready do
|
||||
|
@ -160,9 +160,6 @@ module Middleman
|
|||
path: root,
|
||||
only: match_against
|
||||
|
||||
# Hack around bower_components in root.
|
||||
watcher.listener.ignore(/^bower_components/)
|
||||
|
||||
# Hack around node_modules in root.
|
||||
watcher.listener.ignore(/^node_modules/)
|
||||
|
||||
|
@ -207,7 +204,7 @@ module Middleman
|
|||
end
|
||||
|
||||
def possible_from_cli(key, config)
|
||||
if @cli_options[key]
|
||||
if @cli_options[key] && @cli_options[key] != :undefined
|
||||
@cli_options[key]
|
||||
else
|
||||
config[key]
|
||||
|
|
|
@ -133,15 +133,9 @@ module Middleman
|
|||
|
||||
# Immediately send static file
|
||||
def send_file(resource, env)
|
||||
file = ::Rack::File.new nil
|
||||
path = resource.file_descriptor[:full_path]
|
||||
if !file.respond_to?(:path=)
|
||||
request = ::Rack::Request.new(env)
|
||||
response = file.serving(request, path)
|
||||
else
|
||||
file.path = path
|
||||
response = file.serving(env)
|
||||
end
|
||||
file = ::Rack::File.new nil
|
||||
file.path = resource.file_descriptor[:full_path]
|
||||
response = file.serving(env)
|
||||
status = response[0]
|
||||
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
|
||||
|
|
|
@ -3,7 +3,7 @@ require 'active_support/core_ext/module/attribute_accessors'
|
|||
|
||||
module Middleman
|
||||
module Renderers
|
||||
class RedcarpetTemplate < ::Tilt::RedcarpetTemplate
|
||||
class RedcarpetTemplate < ::Tilt::RedcarpetTemplate::Redcarpet2
|
||||
# because tilt has decided to convert these
|
||||
# in the wrong direction
|
||||
ALIASES = {
|
||||
|
|
|
@ -105,8 +105,10 @@ module Middleman
|
|||
end
|
||||
end
|
||||
|
||||
if defined?(::SassC)
|
||||
::SassC::Script::Functions.send :include, ::Middleman::Sass::Functions
|
||||
elsif defined?(::Sass)
|
||||
::Sass::Script::Functions.send :include, ::Middleman::Sass::Functions
|
||||
SASS_MODULE = if defined?(::SassC)
|
||||
::SassC
|
||||
else
|
||||
::Sass
|
||||
end
|
||||
|
||||
SASS_MODULE::Script::Functions.send :include, ::Middleman::Sass::Functions
|
||||
|
|
|
@ -12,9 +12,13 @@ class ::Slim::Template
|
|||
|
||||
def initialize(file, line, opts, &block)
|
||||
if opts.key?(:context)
|
||||
context_hack = {
|
||||
context: opts[:context]
|
||||
}
|
||||
|
||||
::Slim::Embedded::SassEngine.disable_option_validator!
|
||||
%w(sass scss markdown).each do |engine|
|
||||
(::Slim::Embedded.options[engine.to_sym] ||= {})[:context] = opts[:context]
|
||||
::Slim::Embedded.options[engine.to_sym] = context_hack
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -14,31 +14,16 @@ module Middleman
|
|||
Contract Or[String, Regexp, Proc] => RespondTo[:execute_descriptor]
|
||||
def ignore(path=nil, &block)
|
||||
@app.sitemap.invalidate_resources_not_ignored_cache!
|
||||
|
||||
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
|
||||
IgnoreDescriptor.new(path, block)
|
||||
end
|
||||
|
||||
IgnoreDescriptor = Struct.new(:path, :block) do
|
||||
def execute_descriptor(_app, resources)
|
||||
resources.map do |r|
|
||||
# Ignore based on the source path (without template extensions)
|
||||
if ignored?(r.normalized_path)
|
||||
if ignored?(r.path)
|
||||
r.ignore!
|
||||
elsif !r.is_a?(ProxyResource) && r.file_descriptor && ignored?(r.file_descriptor.normalized_relative_path)
|
||||
elsif !r.is_a?(ProxyResource) && r.file_descriptor && ignored?(r.file_descriptor[:relative_path].to_s)
|
||||
# This allows files to be ignored by their source file name (with template extensions)
|
||||
r.ignore!
|
||||
end
|
||||
|
@ -48,38 +33,27 @@ module Middleman
|
|||
end
|
||||
|
||||
def ignored?(match_path)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
match_path = ::Middleman::Util.normalize_path(match_path)
|
||||
|
||||
class RegexpIgnoreDescriptor < IgnoreDescriptor
|
||||
def ignored?(match_path)
|
||||
match_path =~ path
|
||||
end
|
||||
end
|
||||
if path.is_a? Regexp
|
||||
match_path =~ path
|
||||
elsif path.is_a? String
|
||||
path_clean = ::Middleman::Util.normalize_path(path)
|
||||
|
||||
class GlobIgnoreDescriptor < IgnoreDescriptor
|
||||
def ignored?(match_path)
|
||||
if defined?(::File::FNM_EXTGLOB)
|
||||
::File.fnmatch(path, match_path, ::File::FNM_EXTGLOB)
|
||||
else
|
||||
::File.fnmatch(path, match_path)
|
||||
if path_clean.include?('*') # It's a glob
|
||||
if defined?(::File::FNM_EXTGLOB)
|
||||
::File.fnmatch(path_clean, match_path, ::File::FNM_EXTGLOB)
|
||||
else
|
||||
::File.fnmatch(path_clean, match_path)
|
||||
end
|
||||
else
|
||||
match_path == path_clean
|
||||
end
|
||||
elsif block
|
||||
block.call(match_path)
|
||||
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
|
||||
|
|
|
@ -47,7 +47,7 @@ module Middleman
|
|||
)
|
||||
|
||||
if should_ignore
|
||||
d = ::Middleman::Sitemap::Extensions::Ignores::StringIgnoreDescriptor.new(target)
|
||||
d = ::Middleman::Sitemap::Extensions::Ignores::IgnoreDescriptor.new(target)
|
||||
d.execute_descriptor(app, resources)
|
||||
end
|
||||
|
||||
|
|
|
@ -53,7 +53,8 @@ module Middleman
|
|||
def render(*)
|
||||
url = ::Middleman::Util.url_for(@store.app, @request_path,
|
||||
relative: false,
|
||||
find_resource: true)
|
||||
find_resource: true
|
||||
)
|
||||
|
||||
if output
|
||||
output.call(path, url)
|
||||
|
|
|
@ -75,19 +75,19 @@ module Middleman
|
|||
Contract Bool
|
||||
def template?
|
||||
return false if file_descriptor.nil?
|
||||
!::Middleman::Util.tilt_class(file_descriptor[:full_path].to_s).nil?
|
||||
!::Tilt[file_descriptor[:full_path].to_s].nil?
|
||||
end
|
||||
|
||||
# Backwards compatible method for turning descriptor into a string.
|
||||
# @return [String]
|
||||
Contract Maybe[String]
|
||||
Contract String
|
||||
def source_file
|
||||
file_descriptor && file_descriptor[:full_path].to_s
|
||||
end
|
||||
|
||||
Contract Or[Symbol, String, Fixnum]
|
||||
Contract Or[Symbol, String]
|
||||
def page_id
|
||||
metadata[:page][:id] || make_implicit_page_id(destination_path)
|
||||
metadata[:page][:id] || destination_path
|
||||
end
|
||||
|
||||
# Merge in new metadata specific to this resource.
|
||||
|
@ -197,41 +197,10 @@ module Middleman
|
|||
options[:content_type] || ::Rack::Mime.mime_type(ext, nil)
|
||||
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
|
||||
"#<#{self.class} path=#{@path}>"
|
||||
end
|
||||
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
|
||||
|
||||
class StringResource < Resource
|
||||
|
|
|
@ -102,7 +102,7 @@ module Middleman
|
|||
# @param [Numeric] priority Sets the order of this resource list manipulator relative to the rest. By default this is 50, and manipulators run in the order they are registered, but if a priority is provided then this will run ahead of or behind other manipulators.
|
||||
# @param [Symbol] custom_name The method name to execute.
|
||||
# @return [void]
|
||||
Contract Symbol, RespondTo[:manipulate_resource_list], Maybe[Num, Bool], Maybe[Symbol] => Any
|
||||
Contract Symbol, RespondTo[:manipulate_resource_list], Maybe[Num], Maybe[Symbol] => Any
|
||||
def register_resource_list_manipulator(name, manipulator, priority=50, custom_name=nil)
|
||||
# The third argument used to be a boolean - handle those who still pass one
|
||||
priority = 50 unless priority.is_a? Numeric
|
||||
|
|
|
@ -8,10 +8,6 @@ module Middleman
|
|||
::Middleman::Sources.file_cache[full_path] ||= {}
|
||||
::Middleman::Sources.file_cache[full_path][version] ||= ::File.read(full_path)
|
||||
end
|
||||
|
||||
def normalized_relative_path
|
||||
@normalized_relative_path ||= ::Middleman::Util.normalize_path relative_path.to_s
|
||||
end
|
||||
end
|
||||
|
||||
# Sources handle multiple on-disk collections of files which make up
|
||||
|
@ -56,13 +52,15 @@ module Middleman
|
|||
# @param [Hash] options Global options.
|
||||
# @param [Array] watchers Default watchers.
|
||||
Contract IsA['Middleman::Application'], Maybe[Hash], Maybe[Array] => Any
|
||||
def initialize(app, _options={}, watchers=[])
|
||||
def initialize(app, options={}, watchers=[])
|
||||
@app = app
|
||||
@watchers = watchers
|
||||
@sorted_watchers = @watchers.dup.freeze
|
||||
|
||||
::Middleman::Sources.file_cache = {}
|
||||
|
||||
@options = options
|
||||
|
||||
# Set of procs wanting to be notified of changes
|
||||
@on_change_callbacks = ::Hamster::Vector.empty
|
||||
|
||||
|
@ -170,7 +168,7 @@ module Middleman
|
|||
# @return [Middleman::Sources]
|
||||
Contract Symbol => ::Middleman::Sources
|
||||
def by_type(type)
|
||||
self.class.new @app, nil, watchers.select { |d| d.type == type }
|
||||
self.class.new @app, @options, watchers.select { |d| d.type == type }
|
||||
end
|
||||
|
||||
# Get all files for this collection of watchers.
|
||||
|
|
|
@ -75,10 +75,9 @@ module Middleman
|
|||
@ignored = options.fetch(:ignored, proc { false })
|
||||
@only = Array(options.fetch(:only, []))
|
||||
|
||||
@disable_watcher = app.build?
|
||||
@force_polling = false
|
||||
@latency = nil
|
||||
@wait_for_delay = nil
|
||||
@disable_watcher = app.build? || @parent.options.fetch(:disable_watcher, false)
|
||||
@force_polling = @parent.options.fetch(:force_polling, false)
|
||||
@latency = @parent.options.fetch(:latency, nil)
|
||||
|
||||
@listener = nil
|
||||
|
||||
|
@ -96,20 +95,13 @@ module Middleman
|
|||
def update_path(directory)
|
||||
@directory = Pathname(File.expand_path(directory, app.root))
|
||||
|
||||
without_listener_running do
|
||||
update([], @files.values.map { |source_file| source_file[:full_path] })
|
||||
end
|
||||
stop_listener! if @listener
|
||||
|
||||
update([], @files.values.map { |source_file| source_file[:full_path] })
|
||||
|
||||
poll_once!
|
||||
end
|
||||
|
||||
def update_config(options={})
|
||||
without_listener_running do
|
||||
@disable_watcher = options.fetch(:disable_watcher, false)
|
||||
@force_polling = options.fetch(:force_polling, false)
|
||||
@latency = options.fetch(:latency, nil)
|
||||
@wait_for_delay = options.fetch(:wait_for_delay, nil)
|
||||
end
|
||||
listen! unless @disable_watcher
|
||||
end
|
||||
|
||||
# Stop watching.
|
||||
|
@ -168,10 +160,10 @@ module Middleman
|
|||
|
||||
config = {
|
||||
force_polling: @force_polling,
|
||||
wait_for_delay: 0.5
|
||||
}
|
||||
|
||||
config[:wait_for_delay] = @wait_for_delay.try(:to_f) || 0.5
|
||||
config[:latency] = @latency.to_f if @latency
|
||||
config[:latency] = @latency if @latency
|
||||
|
||||
@listener = ::Listen.to(@directory.to_s, config, &method(:on_listener_change))
|
||||
|
||||
|
@ -207,7 +199,7 @@ module Middleman
|
|||
Contract ArrayOf[Pathname]
|
||||
def poll_once!
|
||||
updated = ::Middleman::Util.all_files_under(@directory.to_s, &method(:should_not_recurse?))
|
||||
removed = @files.keys - updated
|
||||
removed = @files.keys.reject { |p| updated.include?(p) }
|
||||
|
||||
result = update(updated, removed)
|
||||
|
||||
|
@ -306,15 +298,9 @@ module Middleman
|
|||
relative_path = path.relative_path_from(directory)
|
||||
relative_path = File.join(destination_dir, relative_path) if destination_dir
|
||||
|
||||
types << :no_frontmatter if partial?(relative_path.to_s)
|
||||
|
||||
::Middleman::SourceFile.new(Pathname(relative_path), path, directory, types, 0)
|
||||
end
|
||||
|
||||
def partial?(relative_path)
|
||||
relative_path.split(::File::SEPARATOR).any? { |p| p.start_with?('_') }
|
||||
end
|
||||
|
||||
Contract IsA['Middleman::SourceFile'] => Any
|
||||
def record_file_change(f)
|
||||
if @files[f[:full_path]]
|
||||
|
@ -351,20 +337,5 @@ module Middleman
|
|||
@only.any? { |reg| file[:relative_path].to_s =~ reg }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def without_listener_running
|
||||
listener_running = @listener && @listener.processing?
|
||||
|
||||
stop_listener! if listener_running
|
||||
|
||||
yield
|
||||
|
||||
if listener_running
|
||||
poll_once!
|
||||
listen!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,7 +23,7 @@ module Middleman
|
|||
attr_accessor :current_engine
|
||||
|
||||
# Shorthand references to global values on the app instance.
|
||||
def_delegators :@app, :config, :logger, :sitemap, :server?, :build?, :environment?, :environment, :data, :extensions, :root, :development?, :production?
|
||||
def_delegators :@app, :config, :logger, :sitemap, :server?, :build?, :environment?, :environment, :data, :extensions, :root
|
||||
|
||||
# Initialize a context with the current app and predefined locals and options hashes.
|
||||
#
|
||||
|
@ -84,7 +84,6 @@ module Middleman
|
|||
# Reset stored buffer, regardless of success
|
||||
restore_buffer(buf_was)
|
||||
end
|
||||
|
||||
# Render the layout, with the contents of the block inside.
|
||||
concat_safe_content render_file(layout_file, @locs, @opts) { content }
|
||||
ensure
|
||||
|
@ -127,34 +126,32 @@ module Middleman
|
|||
# @return [String]
|
||||
Contract String, Maybe[Bool] => Maybe[IsA['Middleman::SourceFile']]
|
||||
def locate_partial(partial_path, try_static=true)
|
||||
partial_file = nil
|
||||
lookup_stack = []
|
||||
non_root = partial_path.to_s.sub(/^\//, '')
|
||||
return unless resource = sitemap.find_resource_by_destination_path(current_path)
|
||||
|
||||
# Look for partials relative to the current path
|
||||
current_dir = resource.file_descriptor[:relative_path].dirname
|
||||
non_root = partial_path.to_s.sub(/^\//, '')
|
||||
relative_dir = current_dir + Pathname(non_root)
|
||||
|
||||
non_root_no_underscore = non_root.sub(/^_/, '').sub(/\/_/, '/')
|
||||
relative_dir_no_underscore = current_dir + Pathname(non_root_no_underscore)
|
||||
|
||||
if resource = current_resource
|
||||
current_dir = resource.file_descriptor[:relative_path].dirname
|
||||
relative_dir = current_dir + Pathname(non_root)
|
||||
relative_dir_no_underscore = current_dir + Pathname(non_root_no_underscore)
|
||||
end
|
||||
partial_file = nil
|
||||
|
||||
lookup_stack.push [relative_dir.to_s,
|
||||
{ preferred_engine: resource.file_descriptor[:relative_path]
|
||||
.extname[1..-1].to_sym }] if relative_dir
|
||||
lookup_stack.push [non_root]
|
||||
lookup_stack.push [non_root,
|
||||
{ try_static: try_static }]
|
||||
lookup_stack.push [relative_dir_no_underscore.to_s,
|
||||
{ try_static: try_static }] if relative_dir_no_underscore
|
||||
lookup_stack.push [non_root_no_underscore,
|
||||
{ try_static: try_static }]
|
||||
|
||||
lookup_stack.each do |args|
|
||||
[
|
||||
[relative_dir.to_s, { preferred_engine: resource.file_descriptor[:relative_path].extname[1..-1].to_sym }],
|
||||
[non_root],
|
||||
[non_root, { try_static: try_static }],
|
||||
[relative_dir_no_underscore.to_s, { try_static: try_static }],
|
||||
[non_root_no_underscore, { try_static: try_static }]
|
||||
].each do |args|
|
||||
partial_file = ::Middleman::TemplateRenderer.resolve_template(@app, *args)
|
||||
break if partial_file
|
||||
end
|
||||
|
||||
partial_file
|
||||
@app.execute_callbacks(:render_partial, [partial_file]) if partial_file
|
||||
|
||||
partial_file || nil
|
||||
end
|
||||
|
||||
def current_path
|
||||
|
@ -190,7 +187,7 @@ module Middleman
|
|||
# handles cases like `style.css.sass.erb`
|
||||
content = nil
|
||||
|
||||
while ::Middleman::Util.tilt_class(path)
|
||||
while ::Tilt[path]
|
||||
begin
|
||||
opts[:template_body] = content if content
|
||||
|
||||
|
|
|
@ -61,10 +61,12 @@ module Middleman
|
|||
|
||||
# If we're specifically looking for a preferred engine
|
||||
if options.key?(:preferred_engine)
|
||||
extension_class = ::Middleman::Util.tilt_class(options[:preferred_engine])
|
||||
extension_class = ::Tilt[options[:preferred_engine]]
|
||||
|
||||
# Get a list of extensions for a preferred engine
|
||||
preferred_engines += ::Tilt.default_mapping.extensions_for(extension_class)
|
||||
preferred_engines += ::Tilt.mappings.select do |_, engines|
|
||||
engines.include? extension_class
|
||||
end.keys
|
||||
end
|
||||
|
||||
preferred_engines << '*'
|
||||
|
@ -87,7 +89,7 @@ module Middleman
|
|||
app.files.find(:source, path_with_ext, globbing)
|
||||
end
|
||||
|
||||
found_template = file if file && (preferred_engine.nil? || ::Middleman::Util.tilt_class(file[:full_path].to_s))
|
||||
found_template = file if file && (preferred_engine.nil? || ::Tilt[file[:full_path]])
|
||||
break if found_template
|
||||
end
|
||||
|
||||
|
@ -131,33 +133,22 @@ module Middleman
|
|||
# Add extension helpers to context.
|
||||
@app.extensions.add_exposed_to_context(context)
|
||||
|
||||
locals.each do |k, _|
|
||||
next unless context.respond_to?(k) && ![:current_path, :paginate, :page_articles, :blog_controller, :lang, :locale].include?(k.to_sym)
|
||||
|
||||
msg = "Template local `#{k}` tried to overwrite an existing context value. Please rename the key when passing to `locals`"
|
||||
|
||||
if @app.build?
|
||||
throw msg
|
||||
else
|
||||
@app.logger.error(msg)
|
||||
end
|
||||
end
|
||||
|
||||
content = ::Middleman::Util.instrument 'builder.output.resource.render-template', path: File.basename(path) do
|
||||
_render_with_all_renderers(path, locals, context, options, &block)
|
||||
_render_with_all_renderers(path, locs, context, opts, &block)
|
||||
end
|
||||
|
||||
# If we need a layout and have a layout, use it
|
||||
layout_file = fetch_layout(engine, options)
|
||||
if layout_file
|
||||
content = if layout_file = fetch_layout(engine, options)
|
||||
layout_renderer = ::Middleman::FileRenderer.new(@app, layout_file[:relative_path].to_s)
|
||||
@app.execute_callbacks(:render_layout, [layout_file])
|
||||
|
||||
::Middleman::Util.instrument 'builder.output.resource.render-layout', path: File.basename(layout_file[:relative_path].to_s) do
|
||||
content = ::Middleman::Util.instrument 'builder.output.resource.render-layout', path: File.basename(layout_file[:relative_path].to_s) do
|
||||
if layout_file = fetch_layout(engine, options)
|
||||
layout_renderer = ::Middleman::FileRenderer.new(@app, layout_file[:relative_path].to_s)
|
||||
layout_renderer.render(locals, options, context) { content }
|
||||
else
|
||||
content
|
||||
end
|
||||
else
|
||||
content
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -176,7 +167,7 @@ module Middleman
|
|||
# handles cases like `style.css.sass.erb`
|
||||
content = nil
|
||||
|
||||
while ::Middleman::Util.tilt_class(path)
|
||||
while ::Tilt[path]
|
||||
begin
|
||||
opts[:template_body] = content if content
|
||||
|
||||
|
|
|
@ -47,13 +47,14 @@ module Middleman
|
|||
# @return [Boolean]
|
||||
Contract String => Bool
|
||||
def nonbinary_mime?(mime)
|
||||
if mime.start_with?('text/')
|
||||
case
|
||||
when mime.start_with?('text/')
|
||||
true
|
||||
elsif mime.include?('xml') && !mime.include?('officedocument')
|
||||
when mime.include?('xml') && !mime.include?('officedocument')
|
||||
true
|
||||
elsif mime.include?('json')
|
||||
when mime.include?('json')
|
||||
true
|
||||
elsif mime.include?('javascript')
|
||||
when mime.include?('javascript')
|
||||
true
|
||||
else
|
||||
false
|
||||
|
|
|
@ -3,7 +3,6 @@ require 'json'
|
|||
require 'pathname'
|
||||
require 'backports/2.1.0/array/to_h'
|
||||
require 'hashie'
|
||||
require 'memoist'
|
||||
|
||||
require 'middleman-core/util/binary'
|
||||
require 'middleman-core/contracts'
|
||||
|
@ -37,7 +36,6 @@ module Middleman
|
|||
end
|
||||
|
||||
module Data
|
||||
extend Memoist
|
||||
include Contracts
|
||||
|
||||
module_function
|
||||
|
@ -57,7 +55,20 @@ module Middleman
|
|||
return [{}, nil]
|
||||
end
|
||||
|
||||
match = build_regex(frontmatter_delims).match(content) || {}
|
||||
start_delims, stop_delims = frontmatter_delims
|
||||
.values
|
||||
.flatten(1)
|
||||
.transpose
|
||||
.map(&::Regexp.method(:union))
|
||||
|
||||
match = /
|
||||
\A(?:[^\r\n]*coding:[^\r\n]*\r?\n)?
|
||||
(?<start>#{start_delims})[ ]*\r?\n
|
||||
(?<frontmatter>.*?)[ ]*\r?\n?
|
||||
^(?<stop>#{stop_delims})[ ]*\r?\n?
|
||||
\r?\n?
|
||||
(?<additional_content>.*)
|
||||
/mx.match(content) || {}
|
||||
|
||||
unless match[:frontmatter]
|
||||
case known_type
|
||||
|
@ -87,53 +98,27 @@ module Middleman
|
|||
end
|
||||
end
|
||||
|
||||
def build_regex(frontmatter_delims)
|
||||
start_delims, stop_delims = frontmatter_delims
|
||||
.values
|
||||
.flatten(1)
|
||||
.transpose
|
||||
.map(&::Regexp.method(:union))
|
||||
|
||||
/
|
||||
\A(?:[^\r\n]*coding:[^\r\n]*\r?\n)?
|
||||
(?<start>#{start_delims})[ ]*\r?\n
|
||||
(?<frontmatter>.*?)[ ]*\r?\n?
|
||||
^(?<stop>#{stop_delims})[ ]*\r?\n?
|
||||
\r?\n?
|
||||
(?<additional_content>.*)
|
||||
/mx
|
||||
end
|
||||
memoize :build_regex
|
||||
|
||||
# Parse YAML frontmatter out of a string
|
||||
# @param [String] content
|
||||
# @return [Hash]
|
||||
Contract String, Pathname => Hash
|
||||
Contract String, Pathname, Bool => Hash
|
||||
def parse_yaml(content, full_path)
|
||||
c = ::Middleman::Util.instrument 'parse.yaml' do
|
||||
::YAML.load(content)
|
||||
end
|
||||
c ? symbolize_recursive(c) : {}
|
||||
symbolize_recursive(::YAML.load(content) || {})
|
||||
rescue StandardError, ::Psych::SyntaxError => error
|
||||
warn "YAML Exception parsing #{full_path}: #{error.message}"
|
||||
{}
|
||||
end
|
||||
memoize :parse_yaml
|
||||
|
||||
# Parse JSON frontmatter out of a string
|
||||
# @param [String] content
|
||||
# @return [Hash]
|
||||
Contract String, Pathname => Hash
|
||||
def parse_json(content, full_path)
|
||||
c = ::Middleman::Util.instrument 'parse.json' do
|
||||
::JSON.parse(content)
|
||||
end
|
||||
c ? symbolize_recursive(c) : {}
|
||||
symbolize_recursive(::JSON.parse(content) || {})
|
||||
rescue StandardError => error
|
||||
warn "JSON Exception parsing #{full_path}: #{error.message}"
|
||||
{}
|
||||
end
|
||||
memoize :parse_json
|
||||
|
||||
def symbolize_recursive(value)
|
||||
case value
|
||||
|
|
|
@ -54,12 +54,16 @@ module Middleman
|
|||
result.encode('UTF-8', 'UTF-8-MAC')
|
||||
end
|
||||
|
||||
Contract String => Bool
|
||||
def tilt_recognizes?(path)
|
||||
@@tilt_lookup_cache ||= {}
|
||||
@@tilt_lookup_cache[path] ||= ::Tilt[path]
|
||||
end
|
||||
|
||||
Contract String => String
|
||||
def step_through_extensions(path)
|
||||
while ::Middleman::Util.tilt_class(path)
|
||||
while tilt_recognizes?(path)
|
||||
ext = ::File.extname(path)
|
||||
break if ext.empty?
|
||||
|
||||
yield ext if block_given?
|
||||
|
||||
# Strip templating extensions as long as Tilt knows them
|
||||
|
|
|
@ -1,41 +1,24 @@
|
|||
# Core Pathname library used for traversal
|
||||
require 'pathname'
|
||||
require 'uri'
|
||||
require 'addressable/uri'
|
||||
require 'memoist'
|
||||
require 'tilt'
|
||||
|
||||
require 'middleman-core/contracts'
|
||||
|
||||
# rubocop:disable ModuleLength
|
||||
module Middleman
|
||||
module Util
|
||||
extend Memoist
|
||||
include Contracts
|
||||
|
||||
module_function
|
||||
|
||||
Contract String => ::Addressable::URI
|
||||
def parse_uri(uri)
|
||||
::Addressable::URI.parse(uri)
|
||||
end
|
||||
memoize :parse_uri
|
||||
|
||||
Contract String => Any
|
||||
def tilt_class(path)
|
||||
::Tilt[path]
|
||||
end
|
||||
memoize :tilt_class
|
||||
|
||||
# Normalize a path to not include a leading slash
|
||||
# @param [String] path
|
||||
# @return [String]
|
||||
Contract String => String
|
||||
def normalize_path(path)
|
||||
# The tr call works around a bug in Ruby's Unicode handling
|
||||
# The tr call works around a bug in Ruby's Unicode handling
|
||||
::URI.decode(path).sub(%r{^/}, '').tr('', '')
|
||||
end
|
||||
memoize :normalize_path
|
||||
end
|
||||
|
||||
# This is a separate method from normalize_path in case we
|
||||
# change how we normalize paths
|
||||
|
@ -43,26 +26,6 @@ module Middleman
|
|||
def strip_leading_slash(path)
|
||||
path.sub(%r{^/}, '')
|
||||
end
|
||||
memoize :strip_leading_slash
|
||||
|
||||
IGNORE_DESCRIPTOR = Or[Regexp, RespondTo[:call], String]
|
||||
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
|
||||
memoize :should_ignore?
|
||||
|
||||
# Get the path of a file of a given type
|
||||
#
|
||||
|
@ -111,16 +74,14 @@ module Middleman
|
|||
raise ArgumentError, '#asset_url must be run in a context with current_resource if relative: true'
|
||||
end
|
||||
|
||||
uri = ::Middleman::Util.parse_uri(path)
|
||||
uri = URI(path)
|
||||
path = uri.path
|
||||
|
||||
# Ensure the url we pass into find_resource_by_destination_path is not a
|
||||
# relative path, since it only takes absolute url paths.
|
||||
dest_path = url_for(app, path, options.merge(relative: false))
|
||||
|
||||
result = if resource = app.sitemap.find_resource_by_path(dest_path)
|
||||
resource.url
|
||||
elsif resource = app.sitemap.find_resource_by_destination_path(dest_path)
|
||||
result = if resource = app.sitemap.find_resource_by_destination_path(dest_path)
|
||||
resource.url
|
||||
else
|
||||
path = ::File.join(prefix, path)
|
||||
|
@ -131,15 +92,9 @@ module Middleman
|
|||
end
|
||||
end
|
||||
|
||||
final_result = ::Addressable::URI.encode(
|
||||
relative_path_from_resource(
|
||||
options[:current_resource],
|
||||
result,
|
||||
options[:relative]
|
||||
)
|
||||
)
|
||||
final_result = ::URI.encode(relative_path_from_resource(options[:current_resource], result, options[:relative]))
|
||||
|
||||
result_uri = ::Middleman::Util.parse_uri(final_result)
|
||||
result_uri = URI(final_result)
|
||||
result_uri.query = uri.query
|
||||
result_uri.fragment = uri.fragment
|
||||
result_uri.to_s
|
||||
|
@ -152,8 +107,7 @@ module Middleman
|
|||
def url_for(app, path_or_resource, options={})
|
||||
if path_or_resource.is_a?(String) || path_or_resource.is_a?(Symbol)
|
||||
r = app.sitemap.find_resource_by_page_id(path_or_resource)
|
||||
|
||||
path_or_resource = r ? r : path_or_resource.to_s
|
||||
path_or_resource = r if r
|
||||
end
|
||||
|
||||
# Handle Resources and other things which define their own url method
|
||||
|
@ -165,8 +119,8 @@ module Middleman
|
|||
|
||||
# Try to parse URL
|
||||
begin
|
||||
uri = ::Middleman::Util.parse_uri(url)
|
||||
rescue ::Addressable::URI::InvalidURIError
|
||||
uri = URI(url)
|
||||
rescue ::URI::InvalidURIError
|
||||
# Nothing we can do with it, it's not really a URI
|
||||
return url
|
||||
end
|
||||
|
@ -209,13 +163,7 @@ module Middleman
|
|||
|
||||
if resource
|
||||
uri.path = if this_resource
|
||||
::Addressable::URI.encode(
|
||||
relative_path_from_resource(
|
||||
this_resource,
|
||||
resource_url,
|
||||
effective_relative
|
||||
)
|
||||
)
|
||||
::URI.encode(relative_path_from_resource(this_resource, resource_url, effective_relative))
|
||||
else
|
||||
resource_url
|
||||
end
|
||||
|
@ -293,20 +241,20 @@ module Middleman
|
|||
# @return [Boolean] Whether the path matches the matcher
|
||||
Contract PATH_MATCHER, String => Bool
|
||||
def path_match(matcher, path)
|
||||
if matcher.is_a?(String)
|
||||
case
|
||||
when matcher.is_a?(String)
|
||||
if matcher.include? '*'
|
||||
::File.fnmatch(matcher, path)
|
||||
else
|
||||
path == matcher
|
||||
end
|
||||
elsif matcher.respond_to?(:match)
|
||||
when matcher.respond_to?(:match)
|
||||
!!(path =~ matcher)
|
||||
elsif matcher.respond_to?(:call)
|
||||
when matcher.respond_to?(:call)
|
||||
matcher.call(path)
|
||||
else
|
||||
::File.fnmatch(matcher.to_s, path)
|
||||
end
|
||||
end
|
||||
memoize :path_match
|
||||
end
|
||||
end
|
||||
|
|
|
@ -38,7 +38,7 @@ module Middleman
|
|||
current_resource = app.sitemap.find_resource_by_destination_path(path)
|
||||
|
||||
begin
|
||||
uri = ::Middleman::Util.parse_uri(asset_path)
|
||||
uri = ::Addressable::URI.parse(asset_path)
|
||||
|
||||
if uri.relative? && uri.host.nil? && !(asset_path =~ /^[^\/].*[a-z]+\.[a-z]+\/.*/)
|
||||
dest_path = ::Middleman::Util.url_for(app, asset_path, relative: false, current_resource: current_resource)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module Middleman
|
||||
# Current Version
|
||||
# @return [String]
|
||||
VERSION = '4.1.14'.freeze unless const_defined?(:VERSION)
|
||||
VERSION = '4.1.7'.freeze unless const_defined?(:VERSION)
|
||||
end
|
||||
|
|
|
@ -16,29 +16,27 @@ Gem::Specification.new do |s|
|
|||
s.files = `git ls-files -z`.split("\0")
|
||||
s.test_files = `git ls-files -z -- {fixtures,features}/*`.split("\0")
|
||||
s.require_path = 'lib'
|
||||
s.required_ruby_version = '>= 2.2.0'
|
||||
s.required_ruby_version = '>= 2.0.0'
|
||||
|
||||
# Core
|
||||
s.add_dependency('bundler', ['~> 1.1'])
|
||||
s.add_dependency('rack', ['>= 1.4.5', '< 3'])
|
||||
s.add_dependency('tilt', ['~> 2.0'])
|
||||
s.add_dependency('rack', ['>= 1.4.5', '< 2.0'])
|
||||
s.add_dependency('tilt', ['~> 1.4.1'])
|
||||
s.add_dependency('erubis')
|
||||
s.add_dependency('fast_blank')
|
||||
s.add_dependency('parallel')
|
||||
s.add_dependency('servolux')
|
||||
s.add_dependency('dotenv')
|
||||
|
||||
# Helpers
|
||||
s.add_dependency('activesupport', ['>= 4.2', '< 5.1'])
|
||||
s.add_dependency('activesupport', ['~> 4.2'])
|
||||
s.add_dependency('padrino-helpers', ['~> 0.13.0'])
|
||||
s.add_dependency("addressable", ["~> 2.3"])
|
||||
s.add_dependency('memoist', ['~> 0.14'])
|
||||
|
||||
# Watcher
|
||||
s.add_dependency('listen', ['~> 3.0.0'])
|
||||
s.add_dependency('listen', ['~> 3.0'])
|
||||
|
||||
# Tests
|
||||
s.add_development_dependency("capybara", ["~> 2.5.0"])
|
||||
s.add_dependency("capybara", ["~> 2.5.0"])
|
||||
|
||||
# i18n
|
||||
s.add_dependency('i18n', ['~> 0.7.0'])
|
||||
|
|
|
@ -162,13 +162,6 @@ describe Middleman::Util do
|
|||
expect( Middleman::Util.asset_url( @mm, '/how/about/that.html' ) ).to eq '/how/about/that/'
|
||||
end
|
||||
|
||||
it "returns a resource url when asset_hash is on" do
|
||||
Given.fixture 'asset-hash-app'
|
||||
@mm = Middleman::Application.new
|
||||
|
||||
expect( Middleman::Util.asset_url( @mm, '100px.png', 'images') ).to match %r|/images/100px-[a-f0-9]+.png|
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "::find_related_files" do
|
||||
|
@ -211,20 +204,4 @@ describe Middleman::Util do
|
|||
expect(related).to include File.expand_path("source/stylesheets/include2.css.scss")
|
||||
end
|
||||
end
|
||||
|
||||
describe "::step_through_extensions" do
|
||||
it "returns the base name after templating engine extensions are removed" do
|
||||
result = Middleman::Util.step_through_extensions('my_file.html.haml.erb')
|
||||
expect(result).to eq 'my_file.html'
|
||||
end
|
||||
|
||||
it "does not loop infinitely when file name is a possible templating engine" do
|
||||
expect do
|
||||
Timeout::timeout(3.0) do
|
||||
result = Middleman::Util.step_through_extensions("markdown.scss")
|
||||
expect(result).to eq "markdown"
|
||||
end
|
||||
end.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,7 +16,7 @@ Gem::Specification.new do |s|
|
|||
s.files = `git ls-files -z`.split("\0")
|
||||
s.test_files = `git ls-files -z -- {fixtures,features}/*`.split("\0")
|
||||
s.require_path = 'lib'
|
||||
s.required_ruby_version = '>= 2.2.0'
|
||||
s.required_ruby_version = '>= 2.0.0'
|
||||
|
||||
s.add_dependency('middleman-core', Middleman::VERSION)
|
||||
s.add_dependency('middleman-cli', Middleman::VERSION)
|
||||
|
|
Loading…
Reference in New Issue