From 29bf25ace64793f423224da52eef5ad7c822a927 Mon Sep 17 00:00:00 2001 From: Thomas Reynolds Date: Mon, 7 Apr 2014 12:43:16 -0700 Subject: [PATCH] Extract compass support into extension, rewrite all features that rely on it to be pure Ruby --- Gemfile | 3 + Rakefile | 14 ++- middleman-cli/lib/middleman-cli/build.rb | 4 +- middleman-compass/.gitignore | 10 ++ middleman-compass/.travis.yml | 16 +++ middleman-compass/CONTRIBUTING.md | 43 +++++++ middleman-compass/Gemfile | 17 +++ middleman-compass/LICENSE.md | 20 +++ middleman-compass/README.md | 59 +++++++++ middleman-compass/Rakefile | 20 +++ .../features/compass-sprites.feature | 0 .../features/fonts.feature | 0 middleman-compass/features/support/env.rb | 8 ++ .../fixtures/compass-sprites-app/config.rb | 2 + .../source/images/icon/arrow_down.png | Bin .../source/images/icon/arrow_left.png | Bin .../source/images/icon/arrow_right.png | Bin .../source/images/icon/arrow_up.png | Bin .../source/stylesheets/site.css.scss | 0 .../fixtures/fonts-app}/config.rb | 0 .../fonts-app/source/fonts/StMarie-Thin.otf | Bin 0 -> 197044 bytes .../fonts-app/source/fonts/blank/blank.otf | 0 .../source/stylesheets/fonts.css.sass | 0 middleman-compass/lib/middleman-compass.rb | 6 + .../lib/middleman-compass/extension.rb | 63 ++++++++++ .../lib/middleman-compass/version.rb | 5 + middleman-compass/middleman-compass.gemspec | 20 +++ middleman-core/features/asset_hash.feature | 40 +++--- middleman-core/features/asset_host.feature | 48 +++---- middleman-core/features/cache_buster.feature | 2 +- middleman-core/features/minify_css.feature | 4 +- .../features/relative_assets.feature | 76 ++++-------- middleman-core/features/slim.feature | 2 + middleman-core/features/support/env.rb | 3 +- .../fixtures/asset-hash-host-app/config.rb | 4 +- .../asset-host-app/source/asset_host.html.erb | 21 +++- .../source/stylesheets/asset_host.css.sass | 49 +++++++- .../stylesheets/relative_assets.css.sass | 1 - .../source/stylesheets/site.css.sass | 4 +- .../source/stylesheets/fonts.css.scss | 6 + .../source/stylesheets/site.css.sass | 4 +- .../source/stylesheets/site.css.sass | 6 +- .../stylesheets/relative_assets.css.sass | 3 +- .../source/javascripts/application.js | 8 ++ .../stylesheets/relative_assets.css.sass | 3 +- .../source/stylesheets/site_scss.css.scss | 4 +- .../lib/middleman-core/core_extensions.rb | 8 -- .../middleman-core/core_extensions/compass.rb | 74 ----------- .../core_extensions/default_helpers.rb | 40 +----- .../core_extensions/extensions.rb | 17 ++- .../middleman-core/extensions/asset_hash.rb | 2 +- .../middleman-core/extensions/asset_host.rb | 64 ++++------ .../middleman-core/extensions/cache_buster.rb | 62 +++------- .../extensions/relative_assets.rb | 44 ++++--- .../middleware/inline_url_rewriter.rb | 2 +- .../lib/middleman-core/renderers/sass.rb | 25 +++- .../renderers/sass_functions.rb | 117 ++++++++++++++++++ .../lib/middleman-core/renderers/slim.rb | 2 +- .../step_definitions/server_steps.rb | 8 ++ .../lib/middleman-core/template_renderer.rb | 1 + middleman-core/lib/middleman-core/util.rb | 49 ++++++++ middleman-core/middleman-core.gemspec | 10 ++ middleman/middleman.gemspec | 6 +- 63 files changed, 766 insertions(+), 363 deletions(-) create mode 100644 middleman-compass/.gitignore create mode 100644 middleman-compass/.travis.yml create mode 100644 middleman-compass/CONTRIBUTING.md create mode 100644 middleman-compass/Gemfile create mode 100644 middleman-compass/LICENSE.md create mode 100644 middleman-compass/README.md create mode 100644 middleman-compass/Rakefile rename {middleman-core => middleman-compass}/features/compass-sprites.feature (100%) rename {middleman-core => middleman-compass}/features/fonts.feature (100%) create mode 100644 middleman-compass/features/support/env.rb create mode 100644 middleman-compass/fixtures/compass-sprites-app/config.rb rename {middleman-core => middleman-compass}/fixtures/compass-sprites-app/source/images/icon/arrow_down.png (100%) rename {middleman-core => middleman-compass}/fixtures/compass-sprites-app/source/images/icon/arrow_left.png (100%) rename {middleman-core => middleman-compass}/fixtures/compass-sprites-app/source/images/icon/arrow_right.png (100%) rename {middleman-core => middleman-compass}/fixtures/compass-sprites-app/source/images/icon/arrow_up.png (100%) rename {middleman-core => middleman-compass}/fixtures/compass-sprites-app/source/stylesheets/site.css.scss (100%) rename {middleman-core/fixtures/compass-sprites-app => middleman-compass/fixtures/fonts-app}/config.rb (100%) create mode 100755 middleman-compass/fixtures/fonts-app/source/fonts/StMarie-Thin.otf rename .gitmodules => middleman-compass/fixtures/fonts-app/source/fonts/blank/blank.otf (100%) rename {middleman-core => middleman-compass}/fixtures/fonts-app/source/stylesheets/fonts.css.sass (100%) create mode 100644 middleman-compass/lib/middleman-compass.rb create mode 100644 middleman-compass/lib/middleman-compass/extension.rb create mode 100644 middleman-compass/lib/middleman-compass/version.rb create mode 100644 middleman-compass/middleman-compass.gemspec create mode 100644 middleman-core/fixtures/fonts-app/source/stylesheets/fonts.css.scss create mode 100644 middleman-core/fixtures/relative-assets-app/source/javascripts/application.js delete mode 100644 middleman-core/lib/middleman-core/core_extensions/compass.rb create mode 100644 middleman-core/lib/middleman-core/renderers/sass_functions.rb diff --git a/Gemfile b/Gemfile index 37505ff9..04f5ee70 100644 --- a/Gemfile +++ b/Gemfile @@ -22,6 +22,8 @@ platforms :ruby do gem 'therubyracer' gem 'redcarpet', '~> 3.1' gem 'pry', require: false, group: :development + # gem 'pry-debugger', require: false, group: :development + # gem 'pry-stack_explorer', require: false, group: :development end platforms :jruby do @@ -35,5 +37,6 @@ gem 'rubocop', require: false # Middleman itself gem 'middleman-core', path: 'middleman-core' gem 'middleman-cli', path: 'middleman-cli' +gem 'middleman-compass', path: 'middleman-compass', require: false gem 'middleman-sprockets', github: 'middleman/middleman-sprockets', require: false gem 'middleman', path: 'middleman' diff --git a/Rakefile b/Rakefile index b48c1b51..16b61bd1 100644 --- a/Rakefile +++ b/Rakefile @@ -46,7 +46,6 @@ task :test do GEM_PATHS.each do |g| Dir.chdir("#{File.join(ROOT, g)}") { sh "#{Gem.ruby} -S rake test" } end - Rake::Task['rubocop'].invoke end desc 'Run specs for all middleman gems' @@ -56,10 +55,15 @@ task :spec do end end -require 'rubocop/rake_task' -desc 'Run RuboCop to check code consistency' -Rubocop::RakeTask.new(:rubocop) do |task| - task.fail_on_error = false +begin + require 'rubocop/rake_task' + if defined?(Rubocop) + desc 'Run RuboCop to check code consistency' + Rubocop::RakeTask.new(:rubocop) do |task| + task.fail_on_error = false + end + end +rescue LoadError end desc 'Run tests for all middleman gems' diff --git a/middleman-cli/lib/middleman-cli/build.rb b/middleman-cli/lib/middleman-cli/build.rb index 621e7d26..7b105629 100644 --- a/middleman-cli/lib/middleman-cli/build.rb +++ b/middleman-cli/lib/middleman-cli/build.rb @@ -187,9 +187,9 @@ module Middleman::Cli resource.ext == '.css' end.each(&method(:build_resource)) - logger.debug '== Checking for Compass sprites' + logger.debug '== Checking for generated images' - # Double-check for compass sprites + # Double-check for generated images @app.files.find_new_files((@source_dir + @app.config[:images_dir]).relative_path_from(@app.root_path)) @app.sitemap.ensure_resource_list_updated! diff --git a/middleman-compass/.gitignore b/middleman-compass/.gitignore new file mode 100644 index 00000000..be83c767 --- /dev/null +++ b/middleman-compass/.gitignore @@ -0,0 +1,10 @@ +.DS_Store +Gemfile.lock +Gemfile-v4.lock +tmp +.rbenv-* +.sass-cache +pkg +build +.ruby-version +.cache diff --git a/middleman-compass/.travis.yml b/middleman-compass/.travis.yml new file mode 100644 index 00000000..a032273c --- /dev/null +++ b/middleman-compass/.travis.yml @@ -0,0 +1,16 @@ +rvm: + - 1.9.3 + - 2.0.0 + - 2.1.1 + - jruby-19mode + +gemfile: + - Gemfile + - Gemfile-v4 + +script: "bundle exec rake test" + +env: TEST=true + +matrix: + fast_finish: true \ No newline at end of file diff --git a/middleman-compass/CONTRIBUTING.md b/middleman-compass/CONTRIBUTING.md new file mode 100644 index 00000000..97bdc981 --- /dev/null +++ b/middleman-compass/CONTRIBUTING.md @@ -0,0 +1,43 @@ +# Contributing +In the spirit of [free software][free-sw], **everyone** is encouraged to help +improve this project. + +[free-sw]: http://www.fsf.org/licensing/essays/free-sw.html + +Here are some ways *you* can contribute: + +* by using alpha, beta, and prerelease versions +* by reporting bugs +* by suggesting new features +* by writing or editing documentation +* by writing specifications +* by writing code ( **no patch is too small** : fix typos, add comments, clean up inconsistent whitespace ) +* by refactoring code +* by closing [issues][] +* by reviewing patches + +[issues]: https://github.com/middleman/middleman-compass/issues + +## Submitting an Issue +We use the [GitHub issue tracker][issues] to track bugs and features. Before +submitting a bug report or feature request, check to make sure it hasn't +already been submitted. When submitting a bug report, please include a [Gist][] +that includes a stack trace and any details that may be necessary to reproduce +the bug, including your gem version, Ruby version, and operating system. +Ideally, a bug report should include a pull request with failing specs. + +[gist]: https://gist.github.com/ + +## Submitting a Pull Request +1. [Fork the repository.][fork] +2. [Create a topic branch.][branch] +3. Add specs for your unimplemented feature or bug fix. +4. Run `bundle exec rake test`. If your specs pass, return to step 3. +5. Implement your feature or bug fix. +6. Run `bundle exec rake test`. If your specs fail, return to step 5. +7. Add, commit, and push your changes. +8. [Submit a pull request.][pr] + +[fork]: http://help.github.com/fork-a-repo/ +[branch]: http://learn.github.com/p/branching.html +[pr]: http://help.github.com/send-pull-requests/ diff --git a/middleman-compass/Gemfile b/middleman-compass/Gemfile new file mode 100644 index 00000000..e3a01e2e --- /dev/null +++ b/middleman-compass/Gemfile @@ -0,0 +1,17 @@ +source "https://rubygems.org" + +gem "middleman-cli", :github => "middleman/middleman", :branch => "master" +gem "middleman-core", :github => "middleman/middleman", :branch => "master" + +# Specify your gem's dependencies in middleman-sprockets.gemspec +gemspec + +gem "rake", "~> 10.0.3", :require => false +gem "yard", "~> 0.8.0", :require => false + +# Test tools +gem "cucumber" +gem "fivemat", "~> 1.2.1" +gem "aruba" +gem "rspec", "~> 2.14" +gem "builder", "~> 3.0" diff --git a/middleman-compass/LICENSE.md b/middleman-compass/LICENSE.md new file mode 100644 index 00000000..8ffe042d --- /dev/null +++ b/middleman-compass/LICENSE.md @@ -0,0 +1,20 @@ +Copyright (c) 2012-2013 Thomas Reynolds + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/middleman-compass/README.md b/middleman-compass/README.md new file mode 100644 index 00000000..c4d23d97 --- /dev/null +++ b/middleman-compass/README.md @@ -0,0 +1,59 @@ +# Middleman-compass + +`middleman-compass` is an extension for the [Middleman] static site generator that allows support for [Compass](http://compass-style.org) in your assets. + +## Installation + +If you're just getting started, install the `middleman` gem and generate a new project: + +``` +gem install middleman +middleman init MY_PROJECT +``` + +If you already have a Middleman project: Add `gem "middleman-compass"` to your `Gemfile` and run `bundle install` + +## Configuration + +``` +activate :compass +``` + +## Build & Dependency Status + +[![Gem Version](https://badge.fury.io/rb/middleman-compass.png)][gem] +[![Build Status](https://travis-ci.org/middleman/middleman-compass.png)][travis] +[![Dependency Status](https://gemnasium.com/middleman/middleman-compass.png?travis)][gemnasium] +[![Code Quality](https://codeclimate.com/github/middleman/middleman-compass.png)][codeclimate] + +## Community + +The official community forum is available at: http://forum.middlemanapp.com + +## Bug Reports + +Github Issues are used for managing bug reports and feature requests. If you run into issues, please search the issues and submit new problems: https://github.com/middleman/middleman-compass/issues + +The best way to get quick responses to your issues and swift fixes to your bugs is to submit detailed bug reports, include test cases and respond to developer questions in a timely manner. Even better, if you know Ruby, you can submit [Pull Requests](https://help.github.com/articles/using-pull-requests) containing Cucumber Features which describe how your feature should work or exploit the bug you are submitting. + +## How to Run Cucumber Tests + +1. Checkout Repository: `git clone https://github.com/middleman/middleman-compass.git` +2. Install Bundler: `gem install bundler` +3. Run `bundle install` inside the project root to install the gem dependencies. +4. Run test cases: `bundle exec rake test` + +## Donate + +[Click here to lend your support to Middleman](https://spacebox.io/s/4dXbHBorC3) + +## License + +Copyright (c) 2012-2013 Thomas Reynolds. MIT Licensed, see [LICENSE] for details. + +[middleman]: http://middlemanapp.com +[gem]: https://rubygems.org/gems/middleman-compass +[travis]: http://travis-ci.org/middleman/middleman-compass +[gemnasium]: https://gemnasium.com/middleman/middleman-compass +[codeclimate]: https://codeclimate.com/github/middleman/middleman-compass +[LICENSE]: https://github.com/middleman/middleman-compass/blob/master/LICENSE.md \ No newline at end of file diff --git a/middleman-compass/Rakefile b/middleman-compass/Rakefile new file mode 100644 index 00000000..e23e477b --- /dev/null +++ b/middleman-compass/Rakefile @@ -0,0 +1,20 @@ +require 'bundler' +Bundler::GemHelper.install_tasks + +require 'cucumber/rake/task' + +require 'middleman-core/version' + +Cucumber::Rake::Task.new(:cucumber, 'Run features that should pass') do |t| + exempt_tags = ["--tags ~@wip"] + t.cucumber_opts = "--color #{exempt_tags.join(" ")} --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}" +end + +require 'rake/clean' + +task :test => [:cucumber] + +desc "Build HTML documentation" +task :doc do + sh 'bundle exec yard' +end diff --git a/middleman-core/features/compass-sprites.feature b/middleman-compass/features/compass-sprites.feature similarity index 100% rename from middleman-core/features/compass-sprites.feature rename to middleman-compass/features/compass-sprites.feature diff --git a/middleman-core/features/fonts.feature b/middleman-compass/features/fonts.feature similarity index 100% rename from middleman-core/features/fonts.feature rename to middleman-compass/features/fonts.feature diff --git a/middleman-compass/features/support/env.rb b/middleman-compass/features/support/env.rb new file mode 100644 index 00000000..4494e443 --- /dev/null +++ b/middleman-compass/features/support/env.rb @@ -0,0 +1,8 @@ +PROJECT_ROOT_PATH = File.dirname(File.dirname(File.dirname(__FILE__))) +ENV['TEST'] = 'true' +ENV["AUTOLOAD_COMPASS"] = "true" +require "middleman-core" +require "middleman-core/step_definitions" +require File.join(PROJECT_ROOT_PATH, 'lib', 'middleman-compass') +require "erubis" + diff --git a/middleman-compass/fixtures/compass-sprites-app/config.rb b/middleman-compass/fixtures/compass-sprites-app/config.rb new file mode 100644 index 00000000..6347d3ab --- /dev/null +++ b/middleman-compass/fixtures/compass-sprites-app/config.rb @@ -0,0 +1,2 @@ +require 'middleman-compass' +activate :compass \ No newline at end of file diff --git a/middleman-core/fixtures/compass-sprites-app/source/images/icon/arrow_down.png b/middleman-compass/fixtures/compass-sprites-app/source/images/icon/arrow_down.png similarity index 100% rename from middleman-core/fixtures/compass-sprites-app/source/images/icon/arrow_down.png rename to middleman-compass/fixtures/compass-sprites-app/source/images/icon/arrow_down.png diff --git a/middleman-core/fixtures/compass-sprites-app/source/images/icon/arrow_left.png b/middleman-compass/fixtures/compass-sprites-app/source/images/icon/arrow_left.png similarity index 100% rename from middleman-core/fixtures/compass-sprites-app/source/images/icon/arrow_left.png rename to middleman-compass/fixtures/compass-sprites-app/source/images/icon/arrow_left.png diff --git a/middleman-core/fixtures/compass-sprites-app/source/images/icon/arrow_right.png b/middleman-compass/fixtures/compass-sprites-app/source/images/icon/arrow_right.png similarity index 100% rename from middleman-core/fixtures/compass-sprites-app/source/images/icon/arrow_right.png rename to middleman-compass/fixtures/compass-sprites-app/source/images/icon/arrow_right.png diff --git a/middleman-core/fixtures/compass-sprites-app/source/images/icon/arrow_up.png b/middleman-compass/fixtures/compass-sprites-app/source/images/icon/arrow_up.png similarity index 100% rename from middleman-core/fixtures/compass-sprites-app/source/images/icon/arrow_up.png rename to middleman-compass/fixtures/compass-sprites-app/source/images/icon/arrow_up.png diff --git a/middleman-core/fixtures/compass-sprites-app/source/stylesheets/site.css.scss b/middleman-compass/fixtures/compass-sprites-app/source/stylesheets/site.css.scss similarity index 100% rename from middleman-core/fixtures/compass-sprites-app/source/stylesheets/site.css.scss rename to middleman-compass/fixtures/compass-sprites-app/source/stylesheets/site.css.scss diff --git a/middleman-core/fixtures/compass-sprites-app/config.rb b/middleman-compass/fixtures/fonts-app/config.rb similarity index 100% rename from middleman-core/fixtures/compass-sprites-app/config.rb rename to middleman-compass/fixtures/fonts-app/config.rb diff --git a/middleman-compass/fixtures/fonts-app/source/fonts/StMarie-Thin.otf b/middleman-compass/fixtures/fonts-app/source/fonts/StMarie-Thin.otf new file mode 100755 index 0000000000000000000000000000000000000000..aa601879134eefe4ac115bb2e5a1d355ee952977 GIT binary patch literal 197044 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 au1&a_0Qw0uiB*eKZPXvY?e^?l>Hh= 4.0.0"]) + s.add_dependency('compass', ['>= 1.0.0.alpha.19']) +end diff --git a/middleman-core/features/asset_hash.feature b/middleman-core/features/asset_hash.feature index 27362377..3c39f833 100644 --- a/middleman-core/features/asset_hash.feature +++ b/middleman-core/features/asset_hash.feature @@ -10,7 +10,7 @@ Feature: Assets get a file hash appended to their and references to them are upd | images/100px-5fd6fb90.jpg | | images/100px-5fd6fb90.gif | | javascripts/application-1d8d5276.js | - | stylesheets/site-50eaa978.css | + | stylesheets/site-7474cadd.css | | index.html | | subdir/index.html | | other/index.html | @@ -22,15 +22,18 @@ Feature: Assets get a file hash appended to their and references to them are upd | stylesheets/site.css | And the file "javascripts/application-1d8d5276.js" should contain "img.src = '/images/100px-5fd6fb90.jpg'" - And the file "stylesheets/site-50eaa978.css" should contain "background-image: url('../images/100px-5fd6fb90.jpg')" + And the file "stylesheets/site-7474cadd.css" should contain: + """ + background-image: url("../images/100px-5fd6fb90.jpg") + """ And the file "index.html" should contain 'href="apple-touch-icon.png"' - And the file "index.html" should contain 'href="stylesheets/site-50eaa978.css"' + And the file "index.html" should contain 'href="stylesheets/site-7474cadd.css"' And the file "index.html" should contain 'src="javascripts/application-1d8d5276.js"' And the file "index.html" should contain 'src="images/100px-5fd6fb90.jpg"' - And the file "subdir/index.html" should contain 'href="../stylesheets/site-50eaa978.css"' + And the file "subdir/index.html" should contain 'href="../stylesheets/site-7474cadd.css"' And the file "subdir/index.html" should contain 'src="../javascripts/application-1d8d5276.js"' And the file "subdir/index.html" should contain 'src="../images/100px-5fd6fb90.jpg"' - And the file "other/index.html" should contain 'href="../stylesheets/site-50eaa978.css"' + And the file "other/index.html" should contain 'href="../stylesheets/site-7474cadd.css"' And the file "other/index.html" should contain 'src="../javascripts/application-1d8d5276.js"' And the file "other/index.html" should contain 'src="../images/100px-5fd6fb90.jpg"' @@ -38,32 +41,35 @@ Feature: Assets get a file hash appended to their and references to them are upd Given the Server is running at "asset-hash-app" When I go to "/" Then I should see 'href="apple-touch-icon.png"' - And I should see 'href="stylesheets/site-50eaa978.css"' + And I should see 'href="stylesheets/site-7474cadd.css"' And I should see 'src="javascripts/application-1d8d5276.js"' And I should see 'src="images/100px-5fd6fb90.jpg"' When I go to "/subdir/" - Then I should see 'href="../stylesheets/site-50eaa978.css"' + Then I should see 'href="../stylesheets/site-7474cadd.css"' And I should see 'src="../javascripts/application-1d8d5276.js"' And I should see 'src="../images/100px-5fd6fb90.jpg"' When I go to "/other/" - Then I should see 'href="../stylesheets/site-50eaa978.css"' + Then I should see 'href="../stylesheets/site-7474cadd.css"' And I should see 'src="../javascripts/application-1d8d5276.js"' And I should see 'src="../images/100px-5fd6fb90.jpg"' When I go to "/javascripts/application-1d8d5276.js" Then I should see "img.src = '/images/100px-5fd6fb90.jpg'" - When I go to "/stylesheets/site-50eaa978.css" - Then I should see "background-image: url('../images/100px-5fd6fb90.jpg')" + When I go to "/stylesheets/site-7474cadd.css" + Then I should see: + """ + background-image: url("../images/100px-5fd6fb90.jpg") + """ Scenario: Enabling an asset host still produces hashed files and references Given the Server is running at "asset-hash-host-app" When I go to "/" - Then I should see 'href="http://middlemanapp.com/stylesheets/site-54baaf3a.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/site-1fdf4fb5.css"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"' When I go to "/subdir/" - Then I should see 'href="http://middlemanapp.com/stylesheets/site-54baaf3a.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/site-1fdf4fb5.css"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"' When I go to "/other/" - Then I should see 'href="http://middlemanapp.com/stylesheets/site-54baaf3a.css"' + Then I should see 'href="http://middlemanapp.com/stylesheets/site-1fdf4fb5.css"' And I should see 'src="http://middlemanapp.com/images/100px-5fd6fb90.jpg"' # Asset helpers don't appear to work from Compass right now # When I go to "/stylesheets/site-e5a31a3e.css" @@ -98,11 +104,11 @@ Feature: Assets get a file hash appended to their and references to them are upd """ Given the Server is running at "asset-hash-app" When I go to "/" - Then I should see 'href="stylesheets/site-5770af52.css' - When I go to "stylesheets/site-5770af52.css" + Then I should see 'href="stylesheets/site-ac2166fd.css' + When I go to "stylesheets/site-ac2166fd.css" Then I should see 'background-image' Then I should see 'Added by Rack filter' - When I go to "stylesheets/site-50eaa978.css" + When I go to "stylesheets/site-7474cadd.css" Then I should see 'Not Found' Scenario: Hashed-asset files are not produced for ignored paths @@ -137,7 +143,7 @@ Feature: Assets get a file hash appended to their and references to them are upd | images/100px-5fd6fb90.jpg | | images/100px-5fd6fb90.gif | | javascripts/application-1d8d5276.js | - | stylesheets/site-50eaa978.css | + | stylesheets/site-7474cadd.css | # @wip Currently broken, we should move all asset-host functionality out of Compass and into something more similar to asset_hash with Rack-based rewrites # Scenario: Enabling an asset host and referencing assets in CSS with URL fragments are rewritten correctly diff --git a/middleman-core/features/asset_host.feature b/middleman-core/features/asset_host.feature index eb82f43b..19c6b14d 100644 --- a/middleman-core/features/asset_host.feature +++ b/middleman-core/features/asset_host.feature @@ -2,34 +2,6 @@ Feature: Alternate between multiple asset hosts In order to speed up page loading Scenario: Set single host globally - Given a fixture app "asset-host-app" - And a file named "config.rb" with: - """ - activate :asset_host - set :asset_host, "http://assets1.example.com" - """ - And the Server is running - When I go to "/asset_host.html" - Then I should see "http://assets1" - When I go to "/stylesheets/asset_host.css" - Then I should see "http://assets1" - - Scenario: Set proc host globally - Given a fixture app "asset-host-app" - And a file named "config.rb" with: - """ - activate :asset_host - set :asset_host do |asset| - "http://assets%d.example.com" % (asset.hash % 4) - end - """ - And the Server is running - When I go to "/asset_host.html" - Then I should see "http://assets" - When I go to "/stylesheets/asset_host.css" - Then I should see "http://assets" - - Scenario: Set single host with inline-option Given a fixture app "asset-host-app" And a file named "config.rb" with: """ @@ -41,6 +13,20 @@ Feature: Alternate between multiple asset hosts When I go to "/stylesheets/asset_host.css" Then I should see "http://assets1" + Scenario: Set single host with inline-option + Given a fixture app "asset-host-app" + And a file named "config.rb" with: + """ + activate :asset_host, host: "http://assets1.example.com" + """ + And the Server is running + When I go to "/asset_host.html" + Then I should see content matching %r{http://assets1.example.com/} + Then I should not see content matching %r{http://assets1.example.com//} + When I go to "/stylesheets/asset_host.css" + Then I should see content matching %r{http://assets1.example.com/} + Then I should not see content matching %r{http://assets1.example.com//} + Scenario: Set proc host with inline-option Given a fixture app "asset-host-app" And a file named "config.rb" with: @@ -51,6 +37,8 @@ Feature: Alternate between multiple asset hosts """ And the Server is running When I go to "/asset_host.html" - Then I should see "http://assets" + Then I should see content matching %r{http://assets1.example.com/} + Then I should not see content matching %r{http://assets1.example.com//} When I go to "/stylesheets/asset_host.css" - Then I should see "http://assets" \ No newline at end of file + Then I should see content matching %r{http://assets1.example.com/} + Then I should not see content matching %r{http://assets1.example.com//} \ No newline at end of file diff --git a/middleman-core/features/cache_buster.feature b/middleman-core/features/cache_buster.feature index 11040ba5..d452234e 100644 --- a/middleman-core/features/cache_buster.feature +++ b/middleman-core/features/cache_buster.feature @@ -5,7 +5,7 @@ Feature: Generate mtime-based query string for busting browser caches Given "cache_buster" feature is "disabled" And the Server is running at "cache-buster-app" When I go to "/stylesheets/relative_assets.css" - Then I should see "blank.gif'" + Then I should see 'blank.gif"' Scenario: Rendering html with the feature disabled Given "cache_buster" feature is "disabled" diff --git a/middleman-core/features/minify_css.feature b/middleman-core/features/minify_css.feature index 87238eb4..066eb530 100644 --- a/middleman-core/features/minify_css.feature +++ b/middleman-core/features/minify_css.feature @@ -8,7 +8,7 @@ Feature: Minify CSS """ And the Server is running at "minify-css-app" When I go to "/stylesheets/site.css" - Then I should see "50" lines + Then I should see "7" lines And I should see "only screen and (device-width" Scenario: Rendering external css with the feature enabled @@ -40,7 +40,7 @@ Feature: Minify CSS """ And the Server is running at "passthrough-app" When I go to "/stylesheets/site.css" - Then I should see "46" lines + Then I should see "5" lines Scenario: Rendering inline css with the feature disabled Given a fixture app "minify-css-app" diff --git a/middleman-core/features/relative_assets.feature b/middleman-core/features/relative_assets.feature index 1ebafdfa..05c069ce 100644 --- a/middleman-core/features/relative_assets.feature +++ b/middleman-core/features/relative_assets.feature @@ -6,7 +6,7 @@ Feature: Relative Assets And the Server is running at "relative-assets-app" When I go to "/stylesheets/relative_assets.css" Then I should not see "url('../" - And I should see "/images/blank.gif')" + And I should see '/images/blank.gif")' Scenario: Building css with the feature disabled Given a fixture app "relative-assets-app" @@ -15,7 +15,7 @@ Feature: Relative Assets """ Given a successfully built app at "relative-assets-app" When I cd to "build" - Then the file "stylesheets/relative_assets.css" should contain "url('/images/blank.gif')" + Then the file "stylesheets/relative_assets.css" should contain 'url("/images/blank.gif")' Scenario: Rendering html with the feature disabled Given "relative_assets" feature is "disabled" @@ -27,7 +27,9 @@ Feature: Relative Assets Given "relative_assets" feature is "enabled" 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" + Then I should see 'url("../images/blank.gif' + When I go to "/javascripts/application.js" + Then I should not see "../" Scenario: Building css with the feature enabled Given a fixture app "relative-assets-app" @@ -37,7 +39,8 @@ Feature: Relative Assets """ Given a successfully built app at "relative-assets-app" When I cd to "build" - Then the file "stylesheets/relative_assets.css" should contain "url('../images/blank.gif')" + Then the file "stylesheets/relative_assets.css" should contain 'url("../images/blank.gif")' + Then the file "javascripts/application.js" should not contain "../" Scenario: Relative css reference with directory indexes Given a fixture app "relative-assets-app" @@ -57,48 +60,18 @@ Feature: Relative Assets Then I should not see "/images/blank.gif" And I should see "images/blank.gif" - Scenario: Rendering css with a custom images_dir - Given "relative_assets" feature is "enabled" - And "images_dir" is set to "img" - And the Server is running at "relative-assets-app" - When I go to "/stylesheets/relative_assets.css" - Then I should see "url('../img/blank.gif')" - - Scenario: Building css with a custom images_dir - Given a fixture app "relative-assets-app" - And a file named "config.rb" with: - """ - set :images_dir, "img" - activate :relative_assets - """ - Given a successfully built app at "relative-assets-app" - When I cd to "build" - Then the file "stylesheets/relative_assets.css" should contain "url('../img/blank.gif')" - - Scenario: Rendering html with a custom images_dir - Given "relative_assets" feature is "enabled" - And "images_dir" is set to "img" - And the Server is running at "relative-assets-app" - When I go to "/relative_image.html" - Then I should not see "/images/blank.gif" - Then I should not see "/img/blank.gif" - And I should see "img/blank.gif" - Scenario: Rendering scss with the feature enabled Given "relative_assets" feature is "enabled" And the Server is running at "fonts-app" When I go to "/stylesheets/fonts.css" - Then I should see "url('../fonts/StMarie-Thin.otf" - And I should see "url('../fonts/blank/blank.otf" - - Scenario: Rendering scss with the feature enabled and a custom fonts_dir - Given "relative_assets" feature is "enabled" - And "fonts_dir" is set to "otf" - And the Server is running at "fonts-app" - When I go to "/stylesheets/fonts.css" - Then I should not see "url('../fonts/StMarie-Thin.otf" - And I should see "url('../otf/StMarie-Thin.otf" - And I should see "url('../otf/blank/blank.otf" + Then I should see: + """ + url("../fonts/StMarie-Thin.otf" + """ + And I should see: + """ + url("../fonts/blank/blank.otf" + """ Scenario: Building scss with the feature enabled Given a fixture app "fonts-app" @@ -108,21 +81,14 @@ Feature: Relative Assets """ Given a successfully built app at "fonts-app" When I cd to "build" - Then the file "stylesheets/fonts.css" should contain "url('../fonts/StMarie-Thin.otf')" - And the file "stylesheets/fonts.css" should contain "url('../fonts/blank/blank.otf')" - - Scenario: Building scss with the feature enabled and a custom fonts_dir - Given a fixture app "fonts-app" - And a file named "config.rb" with: + Then the file "stylesheets/fonts.css" should contain: """ - set :fonts_dir, "otf" - activate :relative_assets + url("../fonts/StMarie-Thin.otf") + """ + And the file "stylesheets/fonts.css" should contain: + """ + url("../fonts/blank/blank.otf") """ - Given a successfully built app at "fonts-app" - When I cd to "build" - Then the file "stylesheets/fonts.css" should not contain "url('../fonts/StMarie-Thin.otf')" - And the file "stylesheets/fonts.css" should contain "url('../otf/StMarie-Thin.otf')" - And the file "stylesheets/fonts.css" should contain "url('../otf/blank/blank.otf')" Scenario: Relative assets via image_tag Given a fixture app "relative-assets-app" diff --git a/middleman-core/features/slim.feature b/middleman-core/features/slim.feature index acf8b82c..02663f3a 100644 --- a/middleman-core/features/slim.feature +++ b/middleman-core/features/slim.feature @@ -24,6 +24,8 @@ Feature: Support slim templating language Given an empty app And a file named "config.rb" with: """ + require 'middleman-compass' + activate :compass """ And a file named "source/scss.html.slim" with: """ diff --git a/middleman-core/features/support/env.rb b/middleman-core/features/support/env.rb index ba524651..59bea134 100644 --- a/middleman-core/features/support/env.rb +++ b/middleman-core/features/support/env.rb @@ -1,5 +1,6 @@ ENV["TEST"] = "true" -ENV["AUTOLOAD_SPROCKETS"] = "false" +ENV["AUTOLOAD_SPROCKETS"] ||= "false" +ENV["AUTOLOAD_COMPASS"] ||= "false" require 'simplecov' SimpleCov.root(File.expand_path(File.dirname(__FILE__) + '/../..')) diff --git a/middleman-core/fixtures/asset-hash-host-app/config.rb b/middleman-core/fixtures/asset-hash-host-app/config.rb index f40e1c63..085caeb7 100644 --- a/middleman-core/fixtures/asset-hash-host-app/config.rb +++ b/middleman-core/fixtures/asset-hash-host-app/config.rb @@ -1,6 +1,4 @@ activate :asset_hash activate :directory_indexes -activate :asset_host - -set :asset_host, 'http://middlemanapp.com' +activate :asset_host, host: 'http://middlemanapp.com' diff --git a/middleman-core/fixtures/asset-host-app/source/asset_host.html.erb b/middleman-core/fixtures/asset-host-app/source/asset_host.html.erb index fb441334..dbef372a 100755 --- a/middleman-core/fixtures/asset-host-app/source/asset_host.html.erb +++ b/middleman-core/fixtures/asset-host-app/source/asset_host.html.erb @@ -1 +1,20 @@ -<%= image_tag "blank.gif" %> \ No newline at end of file +<%= image_tag "blank0.gif" %> +<%= image_tag "blank1.gif" %> +<%= image_tag "blank2.gif" %> +<%= image_tag "blank3.gif" %> +<%= image_tag "blank4.gif" %> +<%= image_tag "blank10.gif" %> +<%= image_tag "blank21.gif" %> +<%= image_tag "blank32.gif" %> +<%= image_tag "blank43.gif" %> +<%= image_tag "blank54.gif" %> +<%= image_tag "blank20.gif" %> +<%= image_tag "blank21.gif" %> +<%= image_tag "blank22.gif" %> +<%= image_tag "blank23.gif" %> +<%= image_tag "blank24.gif" %> +<%= image_tag "blank30.gif" %> +<%= image_tag "blank31.gif" %> +<%= image_tag "blank32.gif" %> +<%= image_tag "blank33.gif" %> +<%= image_tag "blank34.gif" %> \ No newline at end of file diff --git a/middleman-core/fixtures/asset-host-app/source/stylesheets/asset_host.css.sass b/middleman-core/fixtures/asset-host-app/source/stylesheets/asset_host.css.sass index 5a67f373..874297d9 100644 --- a/middleman-core/fixtures/asset-host-app/source/stylesheets/asset_host.css.sass +++ b/middleman-core/fixtures/asset-host-app/source/stylesheets/asset_host.css.sass @@ -1,3 +1,48 @@ -@import "compass" h1 - background: image-url("blank.gif") \ No newline at end of file + background: image-url("blank1.gif") +h2 + background: image-url("blank2.gif") +h3 + background: image-url("blank3.gif") +h4 + background: image-url("blank4.gif") +h5 + background: image-url("blank5.gif") +h6 + background: image-url("blank6.gif") +h7 + background: image-url("blank7.gif") +h8 + background: image-url("blank8.gif") +h11 + background: image-url("blank11.gif") +h12 + background: image-url("blank21.gif") +h13 + background: image-url("blank31.gif") +h14 + background: image-url("blank41.gif") +h15 + background: image-url("blank51.gif") +h16 + background: image-url("blank61.gif") +h17 + background: image-url("blank71.gif") +h18 + background: image-url("blank81.gif") +h21 + background: image-url("blank12.gif") +h22 + background: image-url("blank22.gif") +h23 + background: image-url("blank32.gif") +h24 + background: image-url("blank42.gif") +h25 + background: image-url("blank52.gif") +h26 + background: image-url("blank62.gif") +h27 + background: image-url("blank72.gif") +h28 + background: image-url("blank82.gif") \ No newline at end of file diff --git a/middleman-core/fixtures/cache-buster-app/source/stylesheets/relative_assets.css.sass b/middleman-core/fixtures/cache-buster-app/source/stylesheets/relative_assets.css.sass index 5a67f373..1ed5fcad 100755 --- a/middleman-core/fixtures/cache-buster-app/source/stylesheets/relative_assets.css.sass +++ b/middleman-core/fixtures/cache-buster-app/source/stylesheets/relative_assets.css.sass @@ -1,3 +1,2 @@ -@import "compass" h1 background: image-url("blank.gif") \ No newline at end of file diff --git a/middleman-core/fixtures/cache-buster-app/source/stylesheets/site.css.sass b/middleman-core/fixtures/cache-buster-app/source/stylesheets/site.css.sass index d143e05e..0ddfd8be 100755 --- a/middleman-core/fixtures/cache-buster-app/source/stylesheets/site.css.sass +++ b/middleman-core/fixtures/cache-buster-app/source/stylesheets/site.css.sass @@ -1 +1,3 @@ -@import "compass/reset" \ No newline at end of file +body { + background: white; +} \ No newline at end of file diff --git a/middleman-core/fixtures/fonts-app/source/stylesheets/fonts.css.scss b/middleman-core/fixtures/fonts-app/source/stylesheets/fonts.css.scss new file mode 100644 index 00000000..19075547 --- /dev/null +++ b/middleman-core/fixtures/fonts-app/source/stylesheets/fonts.css.scss @@ -0,0 +1,6 @@ +@font-face { + font-family: "St Marie"; + src: url("/fonts/StMarie-Thin.otf") format('opentype'); } +@font-face { + font-family: "St Marie"; + src: url("/fonts/blank/blank.otf") format('opentype'); } diff --git a/middleman-core/fixtures/minify-css-app/source/stylesheets/site.css.sass b/middleman-core/fixtures/minify-css-app/source/stylesheets/site.css.sass index 0cf9e7da..afb9ffdb 100755 --- a/middleman-core/fixtures/minify-css-app/source/stylesheets/site.css.sass +++ b/middleman-core/fixtures/minify-css-app/source/stylesheets/site.css.sass @@ -1,4 +1,6 @@ -@import "compass/reset" +body + margin: 0px + padding: 0px @media handheld, only screen and (device-width: 768px) body diff --git a/middleman-core/fixtures/passthrough-app/source/stylesheets/site.css.sass b/middleman-core/fixtures/passthrough-app/source/stylesheets/site.css.sass index d143e05e..47a66dce 100755 --- a/middleman-core/fixtures/passthrough-app/source/stylesheets/site.css.sass +++ b/middleman-core/fixtures/passthrough-app/source/stylesheets/site.css.sass @@ -1 +1,5 @@ -@import "compass/reset" \ No newline at end of file +body + padding: 0px + margin: 0 + div + background: white \ No newline at end of file diff --git a/middleman-core/fixtures/relative-app/source/stylesheets/relative_assets.css.sass b/middleman-core/fixtures/relative-app/source/stylesheets/relative_assets.css.sass index 5a67f373..77fd4605 100755 --- a/middleman-core/fixtures/relative-app/source/stylesheets/relative_assets.css.sass +++ b/middleman-core/fixtures/relative-app/source/stylesheets/relative_assets.css.sass @@ -1,3 +1,2 @@ -@import "compass" h1 - background: image-url("blank.gif") \ No newline at end of file + background: url("images/blank.gif") \ No newline at end of file diff --git a/middleman-core/fixtures/relative-assets-app/source/javascripts/application.js b/middleman-core/fixtures/relative-assets-app/source/javascripts/application.js new file mode 100644 index 00000000..7402bc83 --- /dev/null +++ b/middleman-core/fixtures/relative-assets-app/source/javascripts/application.js @@ -0,0 +1,8 @@ +function foo() { + var img = document.createElement('img'); + img.src = '/images/100px.jpg'; + var body = document.getElementsByTagName('body')[0]; + body.insertBefore(img, body.firstChild); +} + +window.onload = foo; \ No newline at end of file diff --git a/middleman-core/fixtures/relative-assets-app/source/stylesheets/relative_assets.css.sass b/middleman-core/fixtures/relative-assets-app/source/stylesheets/relative_assets.css.sass index 3c10c7cf..8aec4c51 100755 --- a/middleman-core/fixtures/relative-assets-app/source/stylesheets/relative_assets.css.sass +++ b/middleman-core/fixtures/relative-assets-app/source/stylesheets/relative_assets.css.sass @@ -1,3 +1,2 @@ -@import "compass" h1 - background: image-url("blank.gif") + background: url("/images/blank.gif") diff --git a/middleman-core/fixtures/scss-app/source/stylesheets/site_scss.css.scss b/middleman-core/fixtures/scss-app/source/stylesheets/site_scss.css.scss index 0cc04182..a44b6e67 100755 --- a/middleman-core/fixtures/scss-app/source/stylesheets/site_scss.css.scss +++ b/middleman-core/fixtures/scss-app/source/stylesheets/site_scss.css.scss @@ -1 +1,3 @@ -@import "compass/reset"; \ No newline at end of file +html, body { + width: 100%; +} \ No newline at end of file diff --git a/middleman-core/lib/middleman-core/core_extensions.rb b/middleman-core/lib/middleman-core/core_extensions.rb index 729ebdc3..9fd5f985 100644 --- a/middleman-core/lib/middleman-core/core_extensions.rb +++ b/middleman-core/lib/middleman-core/core_extensions.rb @@ -32,14 +32,6 @@ Middleman::Extensions.register :default_helpers, auto_activate: :before_configur Middleman::CoreExtensions::DefaultHelpers end -# Compass framework -begin - require 'middleman-core/core_extensions/compass' - Middleman::Extensions.register :compass, Middleman::CoreExtensions::Compass, auto_activate: :before_configuration -rescue LoadError - # Compass is not available, don't complain about it -end - # Lorem provides a handful of helpful prototyping methods to generate # words, paragraphs, fake images, names and email addresses. Middleman::Extensions.register :lorem, auto_activate: :before_configuration do diff --git a/middleman-core/lib/middleman-core/core_extensions/compass.rb b/middleman-core/lib/middleman-core/core_extensions/compass.rb deleted file mode 100644 index 1d3c13c0..00000000 --- a/middleman-core/lib/middleman-core/core_extensions/compass.rb +++ /dev/null @@ -1,74 +0,0 @@ -require 'middleman-core/renderers/sass' -require 'compass' - -class Middleman::CoreExtensions::Compass < ::Middleman::Extension - def initialize(app, options_hash={}, &block) - super - - # Hooks to manually update the compass config after we're - # done with it - app.define_hook :compass_config - - # Location of SASS/SCSS files external to source directory. - # @return [Array] - # config[:sass_assets_paths] = ["#{root}/assets/sass/", "/path/2/external/sass/repository/"] - app.config.define_setting :sass_assets_paths, [], 'Paths to extra SASS/SCSS files' - end - - def after_configuration - ::Compass.configuration do |compass_config| - compass_config.project_path = app.source_dir - compass_config.environment = :development - compass_config.cache = false - compass_config.sass_dir = app.config[:css_dir] - compass_config.css_dir = app.config[:css_dir] - compass_config.javascripts_dir = app.config[:js_dir] - compass_config.fonts_dir = app.config[:fonts_dir] - compass_config.images_dir = app.config[:images_dir] - compass_config.http_path = app.config[:http_prefix] - - app.config[:sass_assets_paths].each do |path| - compass_config.add_import_path path - end - - # Disable this initially, the cache_buster extension will - # re-enable it if requested. - compass_config.asset_cache_buster { |_| nil } - - # Disable this initially, the relative_assets extension will - - compass_config.relative_assets = false - - # Default output style - compass_config.output_style = :nested - - # No line-comments in test mode (changing paths mess with sha1) - compass_config.line_comments = false if ENV['TEST'] - end - - # Call hook - app.run_hook_for :compass_config, app, ::Compass.configuration - - # Tell Tilt to use it as well (for inline sass blocks) - ::Tilt.register 'sass', CompassSassTemplate - ::Tilt.prefer(CompassSassTemplate) - - # Tell Tilt to use it as well (for inline scss blocks) - ::Tilt.register 'scss', CompassScssTemplate - ::Tilt.prefer(CompassScssTemplate) - end - - # A Compass Sass template for Tilt, adding our options in - class CompassSassTemplate < ::Middleman::Renderers::Sass::SassPlusCSSFilenameTemplate - def sass_options - super.merge(::Compass.configuration.to_sass_engine_options) - end - end - - # A Compass Scss template for Tilt, adding our options in - class CompassScssTemplate < ::Middleman::Renderers::Sass::ScssPlusCSSFilenameTemplate - def sass_options - super.merge(::Compass.configuration.to_sass_engine_options) - end - end -end diff --git a/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb b/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb index aeaaf500..0388f7f7 100644 --- a/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb +++ b/middleman-core/lib/middleman-core/core_extensions/default_helpers.rb @@ -162,27 +162,7 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension # @param [Hash] options Data to pass through. # @return [String] def asset_path(kind, source, options={}) - return source if source.to_s.include?('//') || source.to_s.start_with?('data:') - - asset_folder = case kind - when :css - config[:css_dir] - when :js - config[:js_dir] - when :images - config[:images_dir] - when :fonts - config[:fonts_dir] - else - kind.to_s - end - - source = source.to_s.tr(' ', '') - ignore_extension = (kind == :images || kind == :fonts) # don't append extension - source << ".#{kind}" unless ignore_extension || source.end_with?(".#{kind}") - asset_folder = '' if source.start_with?('/') # absolute path - - asset_url(source, asset_folder, options) + ::Middleman::Util.asset_path(app, kind, source, options) end # Get the URL of an asset given a type/prefix @@ -190,22 +170,8 @@ class Middleman::CoreExtensions::DefaultHelpers < ::Middleman::Extension # @param [String] path The path (such as "photo.jpg") # @param [String] prefix The type prefix (such as "images") # @return [String] The fully qualified asset url - def asset_url(path, prefix='', _) - # Don't touch assets which already have a full path - if path.include?('//') || path.start_with?('data:') - path - else # rewrite paths to use their destination path - if resource = sitemap.find_resource_by_destination_path(url_for(path)) - resource.url - else - path = File.join(prefix, path) - if resource = sitemap.find_resource_by_path(path) - resource.url - else - File.join(config[:http_prefix], path) - end - end - end + def asset_url(path, prefix='', options={}) + ::Middleman::Util.asset_url(app, prefix, options) end # Given a source path (referenced either absolutely or relatively) diff --git a/middleman-core/lib/middleman-core/core_extensions/extensions.rb b/middleman-core/lib/middleman-core/core_extensions/extensions.rb index b6efa1d7..9db3a667 100644 --- a/middleman-core/lib/middleman-core/core_extensions/extensions.rb +++ b/middleman-core/lib/middleman-core/core_extensions/extensions.rb @@ -14,6 +14,12 @@ module Middleman app.define_hook :build_config app.define_hook :development_config + app.config.define_setting :autoload_sprockets, true, 'Automatically load sprockets at startup?' + app.config[:autoload_sprockets] = (ENV['AUTOLOAD_SPROCKETS'] == 'true') if ENV['AUTOLOAD_SPROCKETS'] + + app.config.define_setting :autoload_compass, true, 'Automatically load compass at startup?' + app.config[:autoload_compass] = (ENV['AUTOLOAD_COMPASS'] == 'true') if ENV['AUTOLOAD_COMPASS'] + app.extend ClassMethods app.delegate :configure, to: :"self.class" end @@ -90,7 +96,7 @@ module Middleman activate ext_name end - if ENV['AUTOLOAD_SPROCKETS'] != 'false' + if config[:autoload_sprockets] begin require 'middleman-sprockets' activate :sprockets @@ -99,6 +105,15 @@ module Middleman end end + if config[:autoload_compass] + begin + require 'middleman-compass' + activate :compass + rescue LoadError + # Compass is not available, don't complain about it + end + end + # Evaluate a passed block if given config_context.instance_exec(&block) if block_given? diff --git a/middleman-core/lib/middleman-core/extensions/asset_hash.rb b/middleman-core/lib/middleman-core/extensions/asset_hash.rb index c0f531d9..ab8f4fac 100644 --- a/middleman-core/lib/middleman-core/extensions/asset_hash.rb +++ b/middleman-core/lib/middleman-core/extensions/asset_hash.rb @@ -26,7 +26,7 @@ class Middleman::Extensions::AssetHash < ::Middleman::Extension :proc => method(:rewrite_url) end - def rewrite_url(asset_path, dirpath) + def rewrite_url(asset_path, dirpath, request_path) relative_path = Pathname.new(asset_path).relative? full_asset_path = if relative_path diff --git a/middleman-core/lib/middleman-core/extensions/asset_host.rb b/middleman-core/lib/middleman-core/extensions/asset_host.rb index 2234bdcf..f9f67cc0 100644 --- a/middleman-core/lib/middleman-core/extensions/asset_host.rb +++ b/middleman-core/lib/middleman-core/extensions/asset_host.rb @@ -1,51 +1,41 @@ - # Asset Host module class Middleman::Extensions::AssetHost < ::Middleman::Extension - option :host, nil, 'The asset host to use, or false for no asset host, or a Proc to determine asset host' + option :host, nil, 'The asset host to use or a Proc to determine asset host' + option :exts, %w(.css .png .jpg .jpeg .svg .svgz .js .gif), 'List of extensions that get cache busters strings appended to them.' + option :sources, %w(.htm .html .php .css .js), 'List of extensions that are searched for bustable assets.' + option :ignore, [], 'Regexes of filenames to skip adding query strings to' def initialize(app, options_hash={}, &block) super - # Backwards compatible API - app.config.define_setting :asset_host, nil, 'The asset host to use, or false for no asset host, or a Proc to determine asset host' - - app.compass_config do |config| - if asset_host = extensions[:asset_host].host - if asset_host.is_a?(Proc) - config.asset_host(&asset_host) - else - config.asset_host do |_| - asset_host - end - end - end - end if app.respond_to?(:compass_config) + require 'middleman-core/middleware/inline_url_rewriter' end - def host - app.config[:asset_host] || options[:host] + def after_configuration + app.use ::Middleman::Middleware::InlineURLRewriter, + :id => :asset_host, + :url_extensions => options.exts, + :source_extensions => options.sources, + :ignore => options.ignore, + :middleman_app => app, + :proc => method(:rewrite_url) end - helpers do - # Override default asset url helper to include asset hosts - # - # @param [String] path - # @param [String] prefix - # @param [Hash] options Data to pass through. - # @return [String] - def asset_url(path, prefix='', options={}) - controller = extensions[:asset_host] + def rewrite_url(asset_path, dirpath, request_path) + relative_path = Pathname.new(asset_path).relative? - original_output = super - return original_output unless controller.host - - asset_prefix = if controller.host.is_a?(Proc) - controller.host.call(original_output) - elsif controller.host.is_a?(String) - controller.host - end - - File.join(asset_prefix, original_output) + full_asset_path = if relative_path + dirpath.join(asset_path).to_s + else + asset_path end + + asset_prefix = if options[:host].is_a?(Proc) + options[:host].call(full_asset_path) + elsif options[:host].is_a?(String) + options[:host] + end + + File.join(asset_prefix, full_asset_path) end end diff --git a/middleman-core/lib/middleman-core/extensions/cache_buster.rb b/middleman-core/lib/middleman-core/extensions/cache_buster.rb index 7036d5fc..b6ffd1d9 100644 --- a/middleman-core/lib/middleman-core/extensions/cache_buster.rb +++ b/middleman-core/lib/middleman-core/extensions/cache_buster.rb @@ -1,56 +1,26 @@ # The Cache Buster extension class Middleman::Extensions::CacheBuster < ::Middleman::Extension + option :exts, %w(.css .png .jpg .jpeg .svg .svgz .js .gif), 'List of extensions that get cache busters strings appended to them.' + option :sources, %w(.htm .html .php .css .js), 'List of extensions that are searched for bustable assets.' + option :ignore, [], 'Regexes of filenames to skip adding query strings to' + def initialize(app, options_hash={}, &block) super - # After compass is setup, make it use the registered cache buster - app.compass_config do |config| - config.asset_cache_buster do |path, real_path| - real_path = real_path.path if real_path.is_a? File - real_path = real_path.gsub(File.join(app.root, app.config[:build_dir]), app.config[:source]) - if File.readable?(real_path) - File.mtime(real_path).strftime('%s') - else - logger.warn "WARNING: '#{File.basename(path)}' was not found (or cannot be read) in #{File.dirname(real_path)}" - end - end - end if app.respond_to?(:compass_config) + require 'middleman-core/middleware/inline_url_rewriter' end - helpers do - # asset_url override if we're using cache busting - # @param [String] path - # @param [String] prefix - # @param [Hash] options Data to pass through. - def asset_url(path, prefix='', options={}) - http_path = super + def after_configuration + app.use ::Middleman::Middleware::InlineURLRewriter, + :id => :cache_buster, + :url_extensions => options.exts, + :source_extensions => options.sources, + :ignore => options.ignore, + :middleman_app => app, + :proc => method(:rewrite_url) + end - if http_path.include?('://') || !%w(.css .png .jpg .jpeg .svg .svgz .js .gif).include?(File.extname(http_path)) - http_path - else - if respond_to?(:http_images_path) && prefix == http_images_path - prefix = images_dir - end - - real_path_static = File.join(prefix, path) - - if build? - real_path_dynamic = File.join(config[:build_dir], prefix, path) - real_path_dynamic = File.expand_path(real_path_dynamic, root) - http_path << '?' + File.mtime(real_path_dynamic).strftime('%s') if File.readable?(real_path_dynamic) - elsif resource = sitemap.find_resource_by_path(real_path_static) - if !resource.template? - http_path << '?' + File.mtime(resource.source_file).strftime('%s') - else - # It's a template, possible with partials. We can't really - # know when it's updated, so generate fresh cache buster every - # time during developement - http_path << '?' + Time.now.strftime('%s') - end - end - - http_path - end - end + def rewrite_url(asset_path, dirpath, request_path) + asset_path + '?' + Time.now.strftime('%s') end end diff --git a/middleman-core/lib/middleman-core/extensions/relative_assets.rb b/middleman-core/lib/middleman-core/extensions/relative_assets.rb index ec7d3cf0..474f914a 100644 --- a/middleman-core/lib/middleman-core/extensions/relative_assets.rb +++ b/middleman-core/lib/middleman-core/extensions/relative_assets.rb @@ -1,31 +1,37 @@ # Relative Assets extension class Middleman::Extensions::RelativeAssets < ::Middleman::Extension + option :exts, %w(.css .png .jpg .jpeg .svg .svgz .js .gif .ttf .otf .woff), 'List of extensions that get cache busters strings appended to them.' + option :sources, %w(.htm .html .css), 'List of extensions that are searched for relative assets.' + option :ignore, [], 'Regexes of filenames to skip adding query strings to' + def initialize(app, options_hash={}, &block) super - # After compass is setup, make it use the registered cache buster - app.compass_config do |config| - config.relative_assets = true - end if app.respond_to?(:compass_config) + require 'middleman-core/middleware/inline_url_rewriter' end - helpers do - # asset_url override for relative assets - # @param [String] path - # @param [String] prefix - # @param [Hash] options Data to pass through. - # @return [String] - def asset_url(path, prefix='', options={}) - path = super + def after_configuration + app.use ::Middleman::Middleware::InlineURLRewriter, + :id => :asset_hash, + :url_extensions => options.exts, + :source_extensions => options.sources, + :ignore => options.ignore, + :middleman_app => app, + :proc => method(:rewrite_url) + end - requested_resource = options[:current_resource] || current_resource + def rewrite_url(asset_path, dirpath, request_path) + relative_path = Pathname.new(asset_path).relative? - if path.include?('//') || path.start_with?('data:') || !requested_resource - path - else - current_dir = Pathname('/' + requested_resource.destination_path) - Pathname(path).relative_path_from(current_dir.dirname).to_s - end + full_asset_path = if relative_path + dirpath.join(asset_path).to_s + else + asset_path + end + + if !full_asset_path.include?('//') && !asset_path.start_with?('data:') + current_dir = Pathname('/' + request_path).dirname + Pathname(full_asset_path).relative_path_from(current_dir).to_s end end end diff --git a/middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb b/middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb index 4617b07d..d0fbc115 100644 --- a/middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb +++ b/middleman-core/lib/middleman-core/middleware/inline_url_rewriter.rb @@ -49,7 +49,7 @@ module Middleman asset_path end - @ignore.none? { |r| should_ignore?(r, full_asset_path) } && @proc.call(asset_path, dirpath) + @ignore.none? { |r| should_ignore?(r, full_asset_path) } && @proc.call(asset_path, dirpath, path) end status, headers, response = ::Rack::Response.new( diff --git a/middleman-core/lib/middleman-core/renderers/sass.rb b/middleman-core/lib/middleman-core/renderers/sass.rb index 9c7a237a..3baf2872 100644 --- a/middleman-core/lib/middleman-core/renderers/sass.rb +++ b/middleman-core/lib/middleman-core/renderers/sass.rb @@ -38,8 +38,13 @@ module Middleman class << self # Once registered def registered(app) + opts = { output_style: :nested } + opts[:line_comments] = false if ENV['TEST'] + # Default sass options - app.config.define_setting :sass, {}, 'Sass engine options' + app.config.define_setting :sass, opts, 'Sass engine options' + + app.config.define_setting :sass_assets_paths, [], 'Paths to extra SASS/SCSS files' # Tell Tilt to use it as well (for inline sass blocks) ::Tilt.register 'sass', SassPlusCSSFilenameTemplate @@ -50,6 +55,8 @@ module Middleman ::Tilt.prefer(ScssPlusCSSFilenameTemplate) ::Compass::ImportOnce.activate! + + require 'middleman-core/renderers/sass_functions' end alias_method :included, :registered @@ -88,14 +95,22 @@ module Middleman # Change Sass path, for url functions, to the build folder if we're building # @return [Hash] def sass_options - more_opts = { filename: eval_file, line: line, syntax: syntax } + ctx = ::Middleman::Renderers::Haml.last_haml_scope || @context - if @context.is_a?(::Middleman::TemplateContext) && file - location_of_sass_file = @context.source_dir + more_opts = { + load_paths: ctx.config[:sass_assets_paths], + filename: eval_file, + line: line, + syntax: syntax, + custom: { middleman_context: ctx.app } + } + + if ctx.is_a?(::Middleman::TemplateContext) && file + location_of_sass_file = ctx.source_dir parts = basename.split('.') parts.pop - more_opts[:css_filename] = File.join(location_of_sass_file, @context.config[:css_dir], parts.join('.')) + more_opts[:css_filename] = File.join(location_of_sass_file, ctx.config[:css_dir], parts.join('.')) end options.merge(more_opts) diff --git a/middleman-core/lib/middleman-core/renderers/sass_functions.rb b/middleman-core/lib/middleman-core/renderers/sass_functions.rb new file mode 100644 index 00000000..e7d955ac --- /dev/null +++ b/middleman-core/lib/middleman-core/renderers/sass_functions.rb @@ -0,0 +1,117 @@ +module Sprockets + module Sass + module Functions + + # Using Middleman::Util#asset_path, return the full path + # for the given +source+ as a Sass String. This supports keyword + # arguments that mirror the +options+. + # + # === Examples + # + # background: url(image-path("image.jpg")); // background: url("/assets/image.jpg"); + # background: url(image-path("image.jpg", $digest: true)); // background: url("/assets/image-27a8f1f96afd8d4c67a59eb9447f45bd.jpg"); + # + def image_path(source, options = {}) + p = ::Middleman::Util.asset_path(middleman_context, :images, source.value, map_options(options)) + ::Sass::Script::String.new p.to_s, :string + end + + # Using Middleman::Util#asset_path, return the url CSS + # for the given +source+ as a Sass String. This supports keyword + # arguments that mirror the +options+. + # + # === Examples + # + # background: image-url("image.jpg"); // background: url("/assets/image.jpg"); + # background: image-url("image.jpg", $digest: true); // background: url("/assets/image-27a8f1f96afd8d4c67a59eb9447f45bd.jpg"); + # + def image_url(source, options = {}, cache_buster = nil) + # Work with the Compass #image_url API + if options.respond_to? :value + case options.value + when true + return image_path source + else + options = {} + end + end + ::Sass::Script::String.new "url(#{image_path(source, options)})" + end + + # Using Middleman::Util#asset_path, return the full path + # for the given +source+ as a Sass String. This supports keyword + # arguments that mirror the +options+. + # + # === Examples + # + # src: url(font-path("font.ttf")); // src: url("/assets/font.ttf"); + # src: url(font-path("font.ttf", $digest: true)); // src: url("/assets/font-27a8f1f96afd8d4c67a59eb9447f45bd.ttf"); + # + def font_path(source, options = {}) + p = ::Middleman::Util.asset_path(middleman_context, :fonts, source.value, map_options(options)) + ::Sass::Script::String.new p.to_s, :string + end + + # Using Middleman::Util#asset_path, return the url CSS + # for the given +source+ as a Sass String. This supports keyword + # arguments that mirror the +options+. + # + # === Examples + # + # src: font-url("font.ttf"); // src: url("/assets/font.ttf"); + # src: font-url("image.jpg", $digest: true); // src: url("/assets/font-27a8f1f96afd8d4c67a59eb9447f45bd.ttf"); + # + def font_url(source, options = {}) + # Work with the Compass #font_url API + if options.respond_to? :value + case options.value + when true + return font_path source + else + options = {} + end + end + ::Sass::Script::String.new "url(#{font_path(source, options)})" + end + + protected + + # Returns a reference to Middleman's context through + # the importer. + def middleman_context # :nodoc: + options[:custom][:middleman_context] + end + + # Returns an options hash where the keys are symbolized + # and the values are unwrapped Sass literals. + def map_options(options = {}) # :nodoc: + ::Sass::Util.map_hash(options) do |key, value| + [key.to_sym, value.respond_to?(:value) ? value.value : value] + end + end + end + end +end + +module Sass::Script::Functions + include Sprockets::Sass::Functions + + # Hack to ensure previous API declarations (by Compass or whatever) + # don't take precedence. + [:asset_path, :asset_url, :image_path, :image_url, :font_path, :font_url, :asset_data_uri].each do |method| + defined?(@signatures) && @signatures.delete(method) + end + + declare :asset_path, [:source], :var_kwargs => true + declare :asset_path, [:source, :kind] + declare :asset_url, [:source], :var_kwargs => true + declare :asset_url, [:source, :kind] + declare :image_path, [:source], :var_kwargs => true + declare :image_url, [:source], :var_kwargs => true + declare :image_url, [:source, :only_path] + declare :image_url, [:source, :only_path, :cache_buster] + declare :font_path, [:source], :var_kwargs => true + declare :font_url, [:source], :var_kwargs => true + declare :font_url, [:source, :only_path] + declare :asset_data_uri, [:source] +end diff --git a/middleman-core/lib/middleman-core/renderers/slim.rb b/middleman-core/lib/middleman-core/renderers/slim.rb index 16bf2f25..46ecaa08 100644 --- a/middleman-core/lib/middleman-core/renderers/slim.rb +++ b/middleman-core/lib/middleman-core/renderers/slim.rb @@ -33,7 +33,7 @@ module Middleman app.after_configuration do context_hack = { - context: self + context: self.template_context_class.new(self) } ::Slim::Embedded::SassEngine.disable_option_validator! diff --git a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb index 52394f89..0009e67a 100644 --- a/middleman-core/lib/middleman-core/step_definitions/server_steps.rb +++ b/middleman-core/lib/middleman-core/step_definitions/server_steps.rb @@ -97,6 +97,14 @@ Then /^I should not see "([^\"]*)"$/ do |expected| @last_response.body.should_not include(expected) end +Then /^I should see content matching %r{(.*)}$/ do |expected| + @last_response.body.should match(expected) +end + +Then /^I should not see content matching %r{(.*)}$/ do |expected| + @last_response.body.should_not match(expected) +end + Then /^I should see "([^\"]*)" lines$/ do |lines| @last_response.body.chomp.split($/).length.should == lines.to_i end diff --git a/middleman-core/lib/middleman-core/template_renderer.rb b/middleman-core/lib/middleman-core/template_renderer.rb index a9f7c22c..1b47db05 100644 --- a/middleman-core/lib/middleman-core/template_renderer.rb +++ b/middleman-core/lib/middleman-core/template_renderer.rb @@ -37,6 +37,7 @@ module Middleman # Sandboxed class for template eval context = @app.template_context_class.new(@app, locs, opts) + # TODO: Only for HAML files context.init_haml_helpers if context.respond_to?(:init_haml_helpers) # Keep rendering template until we've used up all extensions. This diff --git a/middleman-core/lib/middleman-core/util.rb b/middleman-core/lib/middleman-core/util.rb index 03c06e05..80800ac2 100644 --- a/middleman-core/lib/middleman-core/util.rb +++ b/middleman-core/lib/middleman-core/util.rb @@ -135,6 +135,55 @@ module Middleman end end + # Get the path of a file of a given type + # + # @param [Symbol] kind The type of file + # @param [String] source The path to the file + # @param [Hash] options Data to pass through. + # @return [String] + def asset_path(app, kind, source, options={}) + return source if source.to_s.include?('//') || source.to_s.start_with?('data:') + + asset_folder = case kind + when :css then app.config[:css_dir] + when :js then app.config[:js_dir] + when :images then app.config[:images_dir] + when :fonts then app.config[:fonts_dir] + else kind.to_s + end + + source = source.to_s.tr(' ', '') + ignore_extension = (kind == :images || kind == :fonts) # don't append extension + source << ".#{kind}" unless ignore_extension || source.end_with?(".#{kind}") + asset_folder = '' if source.start_with?('/') # absolute path + + asset_url(app, source, asset_folder, options) + end + + # Get the URL of an asset given a type/prefix + # + # @param [String] path The path (such as "photo.jpg") + # @param [String] prefix The type prefix (such as "images") + # @param [Hash] options Data to pass through. + # @return [String] The fully qualified asset url + def asset_url(app, path, prefix='', options={}) + # Don't touch assets which already have a full path + if path.include?('//') or path.start_with?('data:') + path + else # rewrite paths to use their destination path + if resource = app.sitemap.find_resource_by_destination_path(url_for(app, path)) + resource.url + else + path = File.join(prefix, path) + if resource = app.sitemap.find_resource_by_path(path) + resource.url + else + File.join(app.config[:http_prefix], path) + end + end + end + end + # Given a source path (referenced either absolutely or relatively) # or a Resource, this will produce the nice URL configured for that # path, respecting :relative_links, directory indexes, etc. diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 070339ab..9da9f039 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -37,4 +37,14 @@ Gem::Specification.new do |s| # Automatic Image Sizes s.add_dependency('fastimage', ['~> 1.6.2']) + + # Minify CSS + s.add_dependency('sass', ['>= 3.3.4']) + + # Work around Sass performance + s.add_dependency('compass-import-once', ['~> 1.0.4']) + + # Minify JS + s.add_dependency('uglifier', ['~> 2.5']) + s.add_dependency('execjs', ['~> 2.0']) end diff --git a/middleman/middleman.gemspec b/middleman/middleman.gemspec index e0268027..045919b9 100644 --- a/middleman/middleman.gemspec +++ b/middleman/middleman.gemspec @@ -21,12 +21,8 @@ Gem::Specification.new do |s| s.add_dependency('middleman-core', Middleman::VERSION) s.add_dependency('middleman-cli', Middleman::VERSION) s.add_dependency('middleman-sprockets', '>= 3.1.2') + s.add_dependency('middleman-compass', '~> 4.0.0') s.add_dependency('haml', ['>= 4.0.5']) - s.add_dependency('sass', ['>= 3.3.4']) - s.add_dependency("compass-import-once", ["1.0.4"]) - s.add_dependency('compass', ['>= 1.0.0.alpha.19']) - s.add_dependency('uglifier', ['~> 2.5']) s.add_dependency('coffee-script', ['~> 2.2.0']) - s.add_dependency('execjs', ['~> 2.0']) s.add_dependency('kramdown', ['~> 1.2']) end