├── test ├── fixtures │ ├── asset_pack_app │ │ ├── assets │ │ │ ├── js │ │ │ │ └── myapp.js │ │ │ ├── javascripts │ │ │ │ ├── coffee.coffee │ │ │ │ ├── other.js │ │ │ │ └── app.js │ │ │ ├── css │ │ │ │ └── meow.css │ │ │ └── stylesheets │ │ │ │ ├── app.css │ │ │ │ └── default.scss │ │ └── asset_pack_app.rb │ └── sprockets_app │ │ ├── assets │ │ ├── other │ │ │ └── other.css │ │ ├── javascripts │ │ │ ├── unrequired.js │ │ │ ├── app.js │ │ │ ├── coffee.js.coffee │ │ │ ├── application.js │ │ │ └── second_js_file.js │ │ ├── stylesheets │ │ │ ├── boot.scss │ │ │ ├── require_bootstrap.css │ │ │ ├── second_file.css │ │ │ ├── application.css │ │ │ └── sass.scss │ │ └── images │ │ │ └── glass.png │ │ └── sprockets_app.rb ├── pipelines │ ├── sprockets │ │ ├── test_js.rb │ │ ├── test_bootstrap.rb │ │ └── test_compiler.rb │ └── asset_pack │ │ └── test_packages.rb ├── test_compiler.rb ├── helpers │ ├── mini_shoulda.rb │ └── helper.rb ├── test_other.rb ├── test_asset_tag.rb ├── test_compression.rb ├── test_css.rb ├── test_js.rb └── test_images.rb ├── .gitignore ├── Gemfile ├── lib ├── padrino-pipeline │ ├── version.rb │ ├── compilers │ │ ├── asset_pack.rb │ │ └── sprockets.rb │ ├── tasks.rb │ ├── ext │ │ ├── asset-pack │ │ │ └── helpers.rb │ │ └── padrino-helpers │ │ │ └── asset_tag_helper.rb │ ├── tasks │ │ └── pipeline_tasks.rb │ ├── pipelines │ │ ├── asset_pack.rb │ │ └── sprockets.rb │ └── configuration.rb └── padrino-pipeline.rb ├── .travis.yml ├── Rakefile ├── LICENSE.txt ├── padrino-pipeline.gemspec └── README.md /test/fixtures/asset_pack_app/assets/js/myapp.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | .sass-cache 3 | pkg/* 4 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/other/other.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | -------------------------------------------------------------------------------- /test/fixtures/asset_pack_app/assets/javascripts/coffee.coffee: -------------------------------------------------------------------------------- 1 | @coffee = true -------------------------------------------------------------------------------- /test/fixtures/asset_pack_app/assets/css/meow.css: -------------------------------------------------------------------------------- 1 | .meow { 2 | left: 0px; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/javascripts/unrequired.js: -------------------------------------------------------------------------------- 1 | var unrequired; 2 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/stylesheets/boot.scss: -------------------------------------------------------------------------------- 1 | @import "bootstrap" 2 | -------------------------------------------------------------------------------- /test/fixtures/asset_pack_app/assets/javascripts/other.js: -------------------------------------------------------------------------------- 1 | var otherFileVar = true; 2 | -------------------------------------------------------------------------------- /test/fixtures/asset_pack_app/assets/stylesheets/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/stylesheets/require_bootstrap.css: -------------------------------------------------------------------------------- 1 | //= require bootstrap 2 | -------------------------------------------------------------------------------- /test/fixtures/asset_pack_app/assets/stylesheets/default.scss: -------------------------------------------------------------------------------- 1 | .content { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/stylesheets/second_file.css: -------------------------------------------------------------------------------- 1 | .home { 2 | display: none; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/javascripts/app.js: -------------------------------------------------------------------------------- 1 | //= require second_js_file 2 | //= require coffee 3 | -------------------------------------------------------------------------------- /test/fixtures/asset_pack_app/assets/javascripts/app.js: -------------------------------------------------------------------------------- 1 | var mainApp = true; 2 | function test() { 3 | 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/javascripts/coffee.js.coffee: -------------------------------------------------------------------------------- 1 | cf = 'yes' 2 | coffee_method -> 3 | true; 4 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | //= require second_file 2 | //= require sass 3 | -------------------------------------------------------------------------------- /lib/padrino-pipeline/version.rb: -------------------------------------------------------------------------------- 1 | module Padrino 2 | module Pipeline 3 | VERSION = '0.4.0' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | //= require second_js_file 2 | //= require coffee 3 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/stylesheets/sass.scss: -------------------------------------------------------------------------------- 1 | body { 2 | .div { 3 | display: none; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/javascripts/second_js_file.js: -------------------------------------------------------------------------------- 1 | var in_second_file; 2 | function in_second_file(){} 3 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/assets/images/glass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ujifgc/padrino-pipeline/master/test/fixtures/sprockets_app/assets/images/glass.png -------------------------------------------------------------------------------- /lib/padrino-pipeline/compilers/asset_pack.rb: -------------------------------------------------------------------------------- 1 | module Padrino 2 | module Pipeline 3 | module Compiler 4 | class AssetPack 5 | 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | lang: ruby 2 | before_install: gem install bundler --pre 3 | install: 4 | - gem update --system 5 | - bundle update 6 | rvm: 7 | - 1.9.3 8 | - 2.0.0 9 | - 2.1.0 10 | - jruby-19mode 11 | branches: 12 | only: 13 | - master 14 | -------------------------------------------------------------------------------- /lib/padrino-pipeline/tasks.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require 'padrino-core/tasks' 3 | ## 4 | # Allows tasks to be added to the client Padrino application 5 | if defined? Padrino::Tasks 6 | Padrino::Tasks.files.concat(Dir["#{File.dirname(__FILE__)}/tasks/**/*.rb"]) 7 | end 8 | rescue LoadError 9 | end 10 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | RAKE_ROOT = __FILE__ 3 | 4 | require 'rubygems' unless defined?(Gem) 5 | require 'rake' 6 | require 'rake/testtask' 7 | require 'bundler/gem_tasks' 8 | Rake::TestTask.new(:test) do |test| 9 | test.libs << 'test' 10 | test.test_files = Dir['test/**/test_*.rb'] 11 | test.verbose = true 12 | end 13 | 14 | task :default => :test 15 | -------------------------------------------------------------------------------- /lib/padrino-pipeline/ext/asset-pack/helpers.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require 'sinatra/assetpack/helpers.rb' 3 | 4 | module Sinatra 5 | module AssetPack 6 | module Helpers 7 | 8 | alias_method :original_image_path, :image_path 9 | def image_path(source) 10 | resolve_path(:images, source) 11 | end 12 | 13 | end 14 | end 15 | end 16 | 17 | rescue LoadError 18 | 19 | end 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/fixtures/sprockets_app/sprockets_app.rb: -------------------------------------------------------------------------------- 1 | require 'padrino-core' 2 | require 'padrino-pipeline' 3 | 4 | class AssetsAppSprockets < Padrino::Application 5 | register Padrino::Pipeline 6 | 7 | configure do 8 | set :logging, false 9 | set :padrino_logging, false 10 | end 11 | 12 | configure_assets do |assets| 13 | assets.pipeline = Padrino::Pipeline::Sprockets 14 | end 15 | 16 | 17 | end 18 | 19 | Padrino.load! 20 | -------------------------------------------------------------------------------- /test/pipelines/sprockets/test_js.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../../helpers/helper') 2 | require File.expand_path(File.dirname(__FILE__) + '/../../fixtures/sprockets_app/sprockets_app') 3 | 4 | 5 | describe :sprockets_javascript do 6 | let(:app) { AssetsAppSprockets } 7 | context 'for //= require' do 8 | it 'picks up require statements' do 9 | get '/assets/javascripts/app.js' 10 | assert_match 'var in_second_file;', last_response.body 11 | end 12 | end 13 | 14 | end 15 | -------------------------------------------------------------------------------- /test/test_compiler.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/helpers/helper') 2 | 3 | describe :configuration do 4 | it 'can find the correct compiler' do 5 | class SomeApp < Padrino::Application; end 6 | config = Padrino::Pipeline::Configuration.new(SomeApp) 7 | 8 | config.pipeline = Padrino::Pipeline::Sprockets.new(SomeApp, config) 9 | assert_equal Padrino::Pipeline::Compiler::Sprockets, config.send(:match_compiler) 10 | 11 | config.pipeline = Padrino::Pipeline::AssetPack.new(SomeApp, config) 12 | assert_equal Padrino::Pipeline::Compiler::AssetPack, config.send(:match_compiler) 13 | 14 | # config.pipeline = nil 15 | # assert_equal nil, config.send(:match_compiler) 16 | end 17 | 18 | end 19 | -------------------------------------------------------------------------------- /lib/padrino-pipeline.rb: -------------------------------------------------------------------------------- 1 | require 'padrino-pipeline/pipelines/sprockets' 2 | require 'padrino-pipeline/pipelines/asset_pack' 3 | require 'padrino-pipeline/compilers/sprockets' 4 | require 'padrino-pipeline/compilers/asset_pack' 5 | 6 | require 'padrino-pipeline/ext/padrino-helpers/asset_tag_helper' 7 | require 'padrino-pipeline/ext/asset-pack/helpers.rb' 8 | require 'padrino-pipeline/configuration' 9 | 10 | module Padrino 11 | ## 12 | # Add public api docs here 13 | module Pipeline 14 | 15 | def configure_assets(&block) 16 | config = Padrino::Pipeline::Configuration.new(self) 17 | yield config if block_given? 18 | config.pipeline = config.pipeline.new(self, config) 19 | set :pipeline, config 20 | end 21 | 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /test/pipelines/asset_pack/test_packages.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../../helpers/helper') 2 | require File.expand_path(File.dirname(__FILE__) + '/../../fixtures/asset_pack_app/asset_pack_app') 3 | 4 | describe :asset_pack_packages do 5 | context :custom_package do 6 | let(:app) { CustomPackagesAppDev } 7 | 8 | it 'can serve a js asset pack' do 9 | get '/assets/javascripts/app.js' 10 | assert_equal 200, last_response.status 11 | assert_match 'mainApp', last_response.body 12 | end 13 | 14 | it 'can serve a css asset pack' do 15 | get '/assets/stylesheets/app.css' 16 | assert_equal 200, last_response.status 17 | assert_match 'body', last_response.body 18 | end 19 | 20 | it 'can get application.js' do 21 | get '/assets/javascripts/application.js' 22 | assert_equal 200, last_response.status 23 | end 24 | 25 | it 'can get application.css' do 26 | get '/assets/stylesheets/application.css' 27 | assert_equal 200, last_response.status 28 | end 29 | 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Padrino 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /lib/padrino-pipeline/tasks/pipeline_tasks.rb: -------------------------------------------------------------------------------- 1 | namespace :pipeline do 2 | def load_apps 3 | require File.expand_path('config/boot.rb', Rake.application.original_dir) 4 | end 5 | 6 | def send_to_pipeline(method, *args) 7 | Padrino.mounted_apps.each do |mounted_app| 8 | app = mounted_app.app_obj 9 | app.pipeline.send(method, *args) if app.pipeline? 10 | end 11 | end 12 | 13 | desc "Compile all assets" 14 | task :compile => [:compile_js, :compile_css] 15 | 16 | desc "Clean all assets" 17 | task :clean => [:clean_js, :clean_css] 18 | 19 | desc "Compile javascript assets" 20 | task :compile_js do 21 | load_apps 22 | send_to_pipeline(:compile, :js) 23 | end 24 | 25 | desc "Compile CSS assets" 26 | task :compile_css do 27 | load_apps 28 | send_to_pipeline(:compile, :css) 29 | end 30 | 31 | desc "Clean javascipt assets" 32 | task :clean_js do 33 | load_apps 34 | send_to_pipeline(:clean, :js) 35 | end 36 | 37 | desc "Clean CSS assets" 38 | task :clean_css do 39 | load_apps 40 | send_to_pipeline(:clean, :css) 41 | end 42 | 43 | end 44 | -------------------------------------------------------------------------------- /test/helpers/mini_shoulda.rb: -------------------------------------------------------------------------------- 1 | gem 'minitest' 2 | require 'minitest/autorun' 3 | require 'minitest/spec' 4 | 5 | begin 6 | require 'ruby-debug' 7 | rescue LoadError; end 8 | 9 | class MiniTest::Spec 10 | class << self 11 | alias :setup :before unless defined?(Rails) 12 | alias :teardown :after unless defined?(Rails) 13 | alias :should :it 14 | alias :context :describe 15 | def should_eventually(desc) 16 | it("should eventually #{desc}") { skip("Should eventually #{desc}") } 17 | end 18 | end 19 | alias :assert_no_match :refute_match 20 | alias :assert_not_nil :refute_nil 21 | alias :assert_not_equal :refute_equal 22 | end 23 | 24 | class ColoredIO 25 | def initialize(io) 26 | @io = io 27 | end 28 | 29 | def print(o) 30 | case o 31 | when "." then @io.send(:print, o.green) 32 | when "E" then @io.send(:print, o.red) 33 | when "F" then @io.send(:print, o.yellow) 34 | when "S" then @io.send(:print, o.magenta) 35 | else @io.send(:print, o) 36 | end 37 | end 38 | 39 | def puts(*o) 40 | super 41 | end 42 | end 43 | 44 | #MiniTest::Unit.output = ColoredIO.new(MiniTest::Unit.output) 45 | -------------------------------------------------------------------------------- /test/fixtures/asset_pack_app/asset_pack_app.rb: -------------------------------------------------------------------------------- 1 | require 'padrino-core' 2 | require 'padrino-pipeline' 3 | 4 | class BaseApp < Sinatra::Base 5 | register Padrino::Pipeline 6 | 7 | configure do 8 | set :logging, false 9 | set :padrino_logging, false 10 | set :root, File.dirname(__FILE__) 11 | end 12 | 13 | end 14 | 15 | class AssetsAppAssetPack < BaseApp 16 | configure_assets do |config| 17 | config.pipeline = Padrino::Pipeline::AssetPack 18 | end 19 | end 20 | 21 | class AssetsAppAssetPackCustom < BaseApp 22 | configure_assets do |config| 23 | config.pipeline = Padrino::Pipeline::AssetPack 24 | config.js_prefix = '/meow/javascripts' 25 | config.js_assets = 'assets/js' 26 | 27 | config.css_prefix = '/meow/stylesheets' 28 | config.css_assets = 'assets/css' 29 | end 30 | end 31 | 32 | class CustomPackagesAppDev < BaseApp 33 | configure_assets do |config| 34 | config.pipeline = Padrino::Pipeline::AssetPack 35 | 36 | config.packages << [:js, :application, '/assets/javascripts/application.js', ['/assets/javascripts/*']] 37 | config.packages << [:css, :application, '/assets/stylesheets/application.css', ['/assets/stylesheets/*']] 38 | 39 | end 40 | 41 | end 42 | 43 | Padrino.load! 44 | -------------------------------------------------------------------------------- /test/test_other.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/helpers/helper') 2 | 3 | shared_examples_for :pipeline do 4 | describe 'non-default options' do 5 | let(:app) { rack_app } 6 | before do 7 | @assets_location = "#{fixture_path('asset_pack_app')}/assets/javascripts" 8 | end 9 | 10 | it 'knows that assets should be served' do 11 | pipeline = @pipeline 12 | mock_app do 13 | register Padrino::Pipeline 14 | configure_assets {|c| c.pipeline = pipeline} 15 | end 16 | 17 | assert_equal true, @app.serve_assets? 18 | end 19 | 20 | it 'can set a general prefix for all asset types' do 21 | assets_location = @assets_location 22 | pipeline = @pipeline 23 | mock_app do 24 | register Padrino::Pipeline 25 | configure_assets do |assets| 26 | assets.pipeline = pipeline 27 | assets.js_assets = assets_location 28 | assets.prefix = '/trunk' 29 | end 30 | end 31 | 32 | get '/trunk/assets/javascripts/app.js' 33 | assert_equal 200, last_response.status 34 | end 35 | end 36 | end 37 | 38 | 39 | describe Padrino::Pipeline::Sprockets do 40 | before { @pipeline = Padrino::Pipeline::Sprockets } 41 | it_behaves_like :pipeline 42 | end 43 | 44 | describe Padrino::Pipeline::AssetPack do 45 | before { @pipeline = Padrino::Pipeline::AssetPack} 46 | it_behaves_like :pipeline 47 | end 48 | -------------------------------------------------------------------------------- /test/pipelines/sprockets/test_bootstrap.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../../helpers/helper') 2 | require File.expand_path(File.dirname(__FILE__) + '/../../fixtures/sprockets_app/sprockets_app') 3 | 4 | require 'bootstrap-sass' 5 | 6 | describe :sprockets_javascript do 7 | let(:app) { rack_app } 8 | 9 | before do 10 | asset_path = "#{fixture_path('sprockets_app')}/assets" 11 | public_path = "#{fixture_path('sprockets_app')}/public" 12 | mock_app do 13 | register Padrino::Pipeline 14 | register Padrino::Helpers 15 | 16 | configure_assets do |assets| 17 | assets.pipeline = Padrino::Pipeline::Sprockets 18 | assets.js_assets = [ "#{asset_path}/javascripts", Bootstrap.javascripts_path ] 19 | assets.css_assets = [ "#{asset_path}/stylesheets", Bootstrap.stylesheets_path ] 20 | assets.compiled_output = "#{public_path}" 21 | end 22 | 23 | end 24 | end 25 | 26 | context 'javascript' do 27 | it 'can get a javascript file from the bootstrap gem' do 28 | get '/assets/javascripts/bootstrap.js' 29 | assert_match "getbootstrap\.com", last_response.body 30 | end 31 | end 32 | 33 | context 'css' do 34 | it 'finds the example bootstrap gems assets' do 35 | get '/assets/stylesheets/boot.css' 36 | assert_match "normalize\.css", last_response.body 37 | end 38 | 39 | it 'finds the example bootstrap gem with a require directive' do 40 | get '/assets/stylesheets/require_bootstrap.css' 41 | assert_match "normalize\.css", last_response.body 42 | end 43 | end 44 | 45 | end 46 | -------------------------------------------------------------------------------- /test/helpers/helper.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', '..')) 2 | $:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', '..','lib')) 3 | 4 | require 'rack/test' 5 | require 'padrino-helpers' 6 | require 'padrino-pipeline/ext/padrino-helpers/asset_tag_helper' 7 | require File.expand_path(File.dirname(__FILE__) + '/mini_shoulda') 8 | require File.expand_path(File.dirname(__FILE__) + '/../fixtures/sprockets_app/sprockets_app') 9 | 10 | class MiniTest::Spec 11 | include Rack::Test::Methods 12 | 13 | def mock_app(base=Padrino::Application, &block) 14 | @app = Sinatra.new(base, &block) 15 | @app.set :logging, false 16 | @app.set :padrino_logging, false 17 | end 18 | 19 | def rack_app 20 | Rack::Lint.new(@app) 21 | end 22 | 23 | def fixture_path(fixture) 24 | test_path = File.expand_path(File.dirname(__FILE__) + '/..') 25 | "#{test_path}/fixtures/#{fixture}" 26 | end 27 | end 28 | 29 | MiniTest::Spec.class_eval do 30 | def self.shared_examples 31 | @shared_examples ||= {} 32 | end 33 | end 34 | 35 | module MiniTest::Spec::SharedExamples 36 | def shared_examples_for(desc, &block) 37 | MiniTest::Spec.shared_examples[desc] = block 38 | end 39 | 40 | def it_behaves_like(desc) 41 | self.instance_eval do 42 | MiniTest::Spec.shared_examples[desc].call 43 | end 44 | end 45 | end 46 | 47 | Object.class_eval { include(MiniTest::Spec::SharedExamples) } 48 | 49 | # Asserts that a file matches the pattern 50 | def assert_match_in_file(pattern, file) 51 | assert File.exist?(file), "File '#{file}' does not exist!" 52 | assert_match pattern, File.read(file) 53 | end 54 | -------------------------------------------------------------------------------- /test/test_asset_tag.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/helpers/helper') 2 | 3 | shared_examples_for :pipeline do 4 | describe :asset_tags do 5 | 6 | context 'asset tags for #js #css #image' do 7 | let(:app) { rack_app } 8 | before :each do 9 | assets_location = "#{fixture_path('sprockets_app')}/assets/javascripts" 10 | pipeline = @pipeline 11 | mock_app do 12 | register Padrino::Pipeline 13 | register Padrino::Helpers 14 | configure_assets do |assets| 15 | assets.pipeline = pipeline 16 | assets.js_assets = [assets_location] 17 | end 18 | get('/js') { render :erb, "<%= javascript_include_tag 'app.js' %>" } 19 | get('/css') { render :erb, "<%= stylesheet_link_tag 'app.css' %>" } 20 | get('/image') { render :erb, "<%= image_tag 'image.png' %>" } 21 | end 22 | end 23 | 24 | it 'can use the default javascript_include_tag to resolve JS asset' do 25 | get '/js' 26 | assert_match '/assets/javascripts/app.js', last_response.body 27 | end 28 | 29 | it 'can use the default stylesheet_link_tag to resolve css asset' do 30 | get '/css' 31 | assert_match '/assets/stylesheets/app.css', last_response.body 32 | end 33 | 34 | it 'can use the default image_tag to resolve img asset' do 35 | get '/image' 36 | assert_match '/assets/images/image.png', last_response.body 37 | end 38 | 39 | end 40 | end 41 | end 42 | 43 | describe Padrino::Pipeline::Sprockets do 44 | before { @pipeline = Padrino::Pipeline::Sprockets } 45 | it_behaves_like :pipeline 46 | end 47 | 48 | describe Padrino::Pipeline::AssetPack do 49 | before { @pipeline = Padrino::Pipeline::AssetPack} 50 | it_behaves_like :pipeline 51 | end 52 | -------------------------------------------------------------------------------- /padrino-pipeline.gemspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env gem build 2 | # encoding: utf-8 3 | 4 | require File.expand_path("../lib/padrino-pipeline/version.rb", __FILE__) 5 | require File.expand_path("../lib/padrino-pipeline/tasks.rb", __FILE__) 6 | 7 | Gem::Specification.new do |s| 8 | s.name = "padrino-pipeline" 9 | s.rubyforge_project = "padrino-pipeline" 10 | s.authors = ["Sumeet Singh"] 11 | s.email = "ortuna@gmail.com" 12 | s.summary = "The Padrino asset management system" 13 | s.homepage = "http://www.padrinorb.com" 14 | s.description = "The Padrino asset management system allowing frictionless serving of assets" 15 | s.required_rubygems_version = ">= 1.3.6" 16 | s.version = Padrino::Pipeline::VERSION 17 | s.date = Time.now.strftime("%Y-%m-%d") 18 | 19 | s.extra_rdoc_files = Dir["*.rdoc"] 20 | s.files = `git ls-files`.split("\n") | Dir.glob("{lib}/**/*") 21 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 22 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 23 | s.require_paths = ["lib"] 24 | s.rdoc_options = ["--charset=UTF-8"] 25 | 26 | 27 | s.add_dependency("padrino-core", ">= 0.11") 28 | s.add_dependency("padrino-helpers", ">= 0.11") 29 | 30 | s.add_development_dependency("nokogiri", RUBY_VERSION < "1.9" ? "~> 1.5.10" : "~> 1.6") 31 | 32 | s.add_development_dependency("rake") 33 | s.add_development_dependency("rack-test", ">= 0.5.0") 34 | s.add_development_dependency("minitest") 35 | s.add_development_dependency("bootstrap-sass", "~> 3.1") 36 | 37 | s.add_development_dependency("coffee-script", "~> 2.2") 38 | s.add_development_dependency("sass", "~> 3.0") 39 | s.add_development_dependency("uglifier", "~> 2.1") 40 | 41 | s.add_development_dependency("sprockets", "~> 2.11") 42 | s.add_development_dependency("sinatra-assetpack", "~> 0.3") 43 | end 44 | -------------------------------------------------------------------------------- /lib/padrino-pipeline/pipelines/asset_pack.rb: -------------------------------------------------------------------------------- 1 | module Padrino 2 | module Pipeline 3 | class AssetPack 4 | 5 | def initialize(app, config) 6 | require_libraries 7 | @app = app 8 | @config = config 9 | setup_enviroment 10 | setup_pipeline 11 | end 12 | 13 | def packages 14 | @config.packages || [] 15 | end 16 | 17 | private 18 | 19 | def require_libraries 20 | require 'sinatra/assetpack' 21 | rescue LoadError 22 | message = 'Please, add `gem "sinatra-assetpack", "~> 0.3"` to your app Gemfile' 23 | defined?(logger) ? logger.error(message) : warn(message) 24 | raise 25 | end 26 | 27 | def setup_enviroment 28 | @app.set :serve_assets, true 29 | @app.register Sinatra::AssetPack 30 | end 31 | 32 | def setup_pipeline 33 | js_prefix, css_prefix, image_prefix = @config.js_prefix, @config.css_prefix, @config.image_prefix 34 | js_assets, css_assets, image_assets = @config.js_assets, @config.css_assets, @config.image_assets 35 | packages = self.packages 36 | compression_enabled = @config.serve_compressed? 37 | 38 | @app.assets do 39 | def mount_asset(prefix, assets) 40 | [*assets].flatten.each do |asset| 41 | serve(prefix, :from => asset) if File.exists? asset 42 | end 43 | end 44 | 45 | mount_asset(js_prefix, js_assets) 46 | mount_asset(css_prefix, css_assets) 47 | mount_asset(image_prefix, image_assets) 48 | 49 | packages.each { |package| send(package.shift, *package) } 50 | if compression_enabled 51 | js_compression :jsmin 52 | css_compression :sass 53 | end 54 | end 55 | end 56 | 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/padrino-pipeline/configuration.rb: -------------------------------------------------------------------------------- 1 | module Padrino 2 | module Pipeline 3 | class Configuration 4 | 5 | attr_accessor :pipeline, :packages, :prefix 6 | attr_accessor :css_prefix, :js_prefix, :image_prefix 7 | attr_accessor :css_assets, :js_assets, :image_assets 8 | attr_accessor :js_compiled_output, :css_compiled_output, :compiled_output 9 | attr_accessor :js_compiled_asset, :css_compiled_asset 10 | attr_accessor :enable_compression, :app 11 | 12 | def initialize(app) 13 | @app = app 14 | @packages = [] 15 | @image_prefix = '/assets/images' 16 | @js_prefix = '/assets/javascripts' 17 | @css_prefix = '/assets/stylesheets' 18 | 19 | @image_assets = "#{app_root}/assets/images" 20 | @js_assets = "#{app_root}/assets/javascripts" 21 | @css_assets = "#{app_root}/assets/stylesheets" 22 | 23 | @compiled_output = "#{app_root}/public" 24 | @js_compiled_output = "javascripts" 25 | @css_compiled_output = "stylesheets" 26 | 27 | @js_compiled_asset = 'application.js' 28 | @css_compiled_asset = 'application.css' 29 | end 30 | 31 | def compile(*args) 32 | asset_compiler.compile(*args) 33 | end 34 | 35 | def clean(*args) 36 | asset_compiler.clean(*args) 37 | end 38 | 39 | def app_root 40 | @app.settings.root 41 | end 42 | 43 | def image_prefix 44 | "#{prefix || ''}#{@image_prefix}" 45 | end 46 | 47 | def js_prefix 48 | "#{prefix || ''}#{@js_prefix}" 49 | end 50 | 51 | def css_prefix 52 | "#{prefix || ''}#{@css_prefix}" 53 | end 54 | 55 | def serve_compressed? 56 | env = (defined?(PADRINO_ENV) && PADRINO_ENV) || \ 57 | (defined?(RACK_ENV) && RACK_ENV) || \ 58 | (defined?(RAKE_ENV) && RAKE_ENV) 59 | enable_compression || env == "production" 60 | end 61 | 62 | def asset_compiler 63 | @asset_compiler ||= match_compiler.new(self) 64 | end 65 | 66 | private 67 | def pipeline_class 68 | @pipeline.class.name 69 | end 70 | 71 | def match_compiler 72 | pipeline_type = pipeline_class.split('::').last 73 | "Padrino::Pipeline::Compiler::#{pipeline_type}".constantize 74 | end 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /lib/padrino-pipeline/compilers/sprockets.rb: -------------------------------------------------------------------------------- 1 | module Padrino 2 | module Pipeline 3 | module Compiler 4 | class Sprockets 5 | def initialize(config) 6 | @config = config 7 | end 8 | 9 | def compile(type) 10 | create_directory(@config.compiled_output) 11 | create_directory("#{@config.compiled_output}/#{@config.js_compiled_output}") 12 | create_directory("#{@config.compiled_output}/#{@config.css_compiled_output}") 13 | return unless @config.app 14 | case type 15 | when :js then compile_js 16 | when :css then compile_css 17 | else 18 | throw RuntimeError, "Can not compile #{type} asset" 19 | end 20 | end 21 | 22 | def clean(type) 23 | case type 24 | when :js then clean_js 25 | when :css then clean_css 26 | else 27 | throw RuntimeError, "Can not compile #{type} asset" 28 | end 29 | end 30 | 31 | def js_output_path(file_name = '') 32 | output_path(@config.js_compiled_output).join(file_name) 33 | end 34 | 35 | def css_output_path(file_name = '') 36 | output_path(@config.css_compiled_output).join(file_name) 37 | end 38 | 39 | private 40 | def assets 41 | @config.app.assets 42 | end 43 | 44 | def output_path(directory_name) 45 | output_path = Pathname.new(@config.compiled_output).join(directory_name) 46 | end 47 | 48 | def compile_css 49 | compile_assets(:css, ['css', 'css.gz']) 50 | end 51 | 52 | def compile_js 53 | compile_assets(:js, ['js', 'js.gz']) 54 | end 55 | 56 | def clean_css 57 | clean_assets(:css, ['css', 'css.gz']) 58 | end 59 | 60 | def clean_js 61 | clean_assets(:js, ['js', 'js.gz']) 62 | end 63 | 64 | def compile_assets(type, extensions = []) 65 | asset = assets[@config.send("#{type.to_s}_compiled_asset")] 66 | extensions.each do |ext| 67 | output_path = self.send("#{type.to_s}_output_path", "application-#{asset.digest}.#{ext}") 68 | asset.write_to output_path 69 | end 70 | end 71 | 72 | def clean_assets(type, extensions = []) 73 | extensions.each do |ext| 74 | FileUtils.rm Dir.glob(self.send("#{type.to_s}_output_path") + "application-*.#{ext}") 75 | end 76 | end 77 | 78 | def create_directory(path) 79 | FileUtils.mkdir_p(path) 80 | end 81 | end 82 | end 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /test/test_compression.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/helpers/helper') 2 | 3 | def reset_consts 4 | Object.send(:remove_const, :PADRINO_ENV) if defined? PADRINO_ENV 5 | Object.send(:remove_const, :RACK_ENV) if defined? RACK_ENV 6 | Object.send(:remove_const, :RAKE_ENV) if defined? RAKE_ENV 7 | end 8 | 9 | def silence_warnings 10 | @warn_level = $VERBOSE 11 | $VERBOSE = nil 12 | end 13 | 14 | def unsilence_warnings 15 | $VERBOSE = @warn_level 16 | end 17 | 18 | def in_env(env) 19 | silence_warnings 20 | reset_consts 21 | %w(PADRINO_ENV RACK_ENV RAKE_ENV).each do |const| 22 | Object.const_set(const, env) 23 | yield 24 | end 25 | unsilence_warnings 26 | end 27 | 28 | 29 | shared_examples_for :pipeline do 30 | describe :asset_compression do 31 | let(:app) { rack_app } 32 | before do 33 | assets_location = "#{fixture_path('asset_pack_app')}/assets/" 34 | pipeline = @pipeline 35 | mock_app do 36 | register Padrino::Pipeline 37 | configure_assets do |config| 38 | config.pipeline = pipeline 39 | config.css_assets = "#{assets_location}/stylesheets" 40 | config.js_assets = "#{assets_location}/javascripts" 41 | end 42 | end 43 | end 44 | 45 | it 'should not compress css in development mode' do 46 | in_env "development" do 47 | get '/assets/stylesheets/app.css' 48 | assert_match "body {\n", last_response.body 49 | end 50 | end 51 | 52 | it 'should not compress js in development mode' do 53 | in_env "development" do 54 | get '/assets/javascripts/app.js' 55 | assert_match "function test() {\n", last_response.body 56 | end 57 | end 58 | 59 | end 60 | end 61 | 62 | describe :default_compression do 63 | before do 64 | class SomeApp < Padrino::Application; end 65 | @config = Padrino::Pipeline::Configuration.new(SomeApp) 66 | end 67 | 68 | it 'serve_compressed? is false for test' do 69 | in_env "test" do 70 | refute @config.serve_compressed? 71 | end 72 | end 73 | 74 | it 'serve_compressed? is false for development' do 75 | in_env "development" do 76 | refute @config.serve_compressed? 77 | end 78 | end 79 | 80 | it 'serve_compressed? is true for production' do 81 | in_env "production" do 82 | assert @config.serve_compressed? 83 | end 84 | end 85 | end 86 | 87 | describe Padrino::Pipeline::Sprockets do 88 | before { @pipeline = Padrino::Pipeline::Sprockets } 89 | it_behaves_like :pipeline 90 | end 91 | 92 | describe Padrino::Pipeline::AssetPack do 93 | before { @pipeline = Padrino::Pipeline::AssetPack } 94 | it_behaves_like :pipeline 95 | end 96 | -------------------------------------------------------------------------------- /lib/padrino-pipeline/pipelines/sprockets.rb: -------------------------------------------------------------------------------- 1 | module Padrino 2 | module Pipeline 3 | class Sprockets 4 | 5 | def initialize(app, config) 6 | require_libraries 7 | @app = app 8 | @config = config 9 | setup_enviroment 10 | setup_sprockets 11 | end 12 | 13 | private 14 | 15 | REQUIRED_LIBRARIES = %w[sprockets uglifier] 16 | 17 | def require_libraries 18 | REQUIRED_LIBRARIES.each { |package| require package } 19 | rescue LoadError 20 | message = REQUIRED_LIBRARIES.inject("Please, add these to your app Gemfile:\n") do |all, package| 21 | all << "gem '#{package}'\n" 22 | end 23 | defined?(logger) ? logger.error(message) : warn(message) 24 | raise 25 | end 26 | 27 | def paths 28 | js_assets = @config.js_assets.kind_of?(Array) ? @config.js_assets : [@config.js_assets] 29 | css_assets = @config.css_assets.kind_of?(Array) ? @config.css_assets : [@config.css_assets] 30 | image_assets = @config.image_assets.kind_of?(Array) ? @config.image_assets : [@config.image_assets] 31 | js_assets + css_assets + image_assets 32 | end 33 | 34 | def setup_sprockets 35 | paths.each { |path| @app.settings.assets.append_path path } 36 | mount_js_assets @config.js_prefix 37 | mount_css_assets @config.css_prefix 38 | mount_image_assets @config.image_prefix 39 | end 40 | 41 | def setup_enviroment 42 | @app.set :serve_assets, true 43 | @app.set :assets, ::Sprockets::Environment.new 44 | if @config.serve_compressed? 45 | @app.settings.assets.js_compressor = Uglifier.new(:mangle => true) 46 | @app.settings.assets.css_compressor = :sass 47 | end 48 | @app.settings.assets.context_class.class_eval do 49 | def asset_path(path, options = {}) 50 | path 51 | end 52 | end 53 | end 54 | 55 | def mount_image_assets(prefix) 56 | mount_assets(:prefix => prefix) 57 | end 58 | 59 | def mount_js_assets(prefix) 60 | mount_assets(:prefix => prefix, 61 | :extension => "js", 62 | :content_type => "application/javascript") 63 | end 64 | 65 | def mount_css_assets(prefix) 66 | mount_assets(:prefix => prefix, 67 | :extension => "css", 68 | :content_type => "text/css") 69 | end 70 | 71 | def mount_assets(options = {}) 72 | prefix = options[:prefix] 73 | extension = options[:extension] 74 | content_type = options[:content_type] 75 | @app.get "#{prefix}/:path.:ext" do |path, ext| 76 | return not_found if (extension && ext != extension) 77 | content_type(content_type || Rack::Mime::MIME_TYPES[".#{ext}"]) 78 | settings.assets["#{path}.#{ext}"] || not_found 79 | end 80 | end 81 | 82 | end 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /lib/padrino-pipeline/ext/padrino-helpers/asset_tag_helper.rb: -------------------------------------------------------------------------------- 1 | require 'padrino-helpers' 2 | 3 | module Padrino 4 | module Helpers 5 | module AssetTagHelpers 6 | 7 | def pipeline_asset_folder_name(kind) 8 | pipeline = settings.pipeline 9 | case kind 10 | when :css then pipeline.css_prefix 11 | when :js then pipeline.js_prefix 12 | when :images then pipeline.image_prefix 13 | else kind.to_s 14 | end 15 | end 16 | 17 | alias_method :original_asset_folder_name, :asset_folder_name 18 | alias_method :asset_folder_name, :pipeline_asset_folder_name 19 | 20 | alias_method :original_javascript_include_tag, :javascript_include_tag 21 | def javascript_include_tag(*sources) 22 | options = sources.extract_options!.symbolize_keys 23 | options.reverse_merge!(:type => 'text/javascript') 24 | sources.flatten.map { |source| 25 | content_tag(:script, nil, options.reverse_merge(:src => resolve_js_path(source))) 26 | }.join("\n").html_safe 27 | end 28 | 29 | alias_method :original_stylesheet_link_tag, :stylesheet_link_tag 30 | def stylesheet_link_tag(*sources) 31 | options = sources.extract_options!.symbolize_keys 32 | options.reverse_merge!(:media => 'screen', :rel => 'stylesheet', :type => 'text/css') 33 | sources.flatten.map { |source| 34 | tag(:link, options.reverse_merge(:href => asset_path(:css, resolve_css_path(source)))) 35 | }.join("\n").html_safe 36 | end 37 | 38 | private 39 | def resolve_css_path(source) 40 | resolve_path(:css, source) 41 | end 42 | 43 | def resolve_js_path(source) 44 | resolve_path(:js, source) 45 | end 46 | 47 | def resolve_path(type, source) 48 | digested_source = digested_source(source) 49 | digested_source_path = digested_source_path(type, digested_source) 50 | File.exists?(digested_source_path) ? asset_path(type, digested_source) : asset_path(type, source) 51 | end 52 | 53 | ## 54 | # Get the full path of the digested_source 55 | def digested_source_path(type, digested_source) 56 | #hackzor 57 | settings.pipeline.asset_compiler.send("#{type.to_s}_output_path", digested_source) 58 | rescue 59 | '' 60 | end 61 | 62 | ## 63 | # Add the hex digest to the source path 64 | def digested_source(source) 65 | digest = asset_digest(source) 66 | parts = source.split('.') 67 | (parts[0...parts.count-1]).join('.') << "-#{digest}.#{parts.last}" 68 | end 69 | 70 | ## 71 | # Get the hex digest for a particular asset 72 | def asset_digest(source) 73 | return '' unless defined? settings 74 | return '' unless settings.respond_to?(:assets) 75 | return '' unless settings.assets.respond_to?(:[]) 76 | settings.assets[source] && settings.assets[source].digest 77 | end 78 | 79 | end #AssetTagHelpers 80 | end #Helpers 81 | end #Padrino 82 | -------------------------------------------------------------------------------- /test/test_css.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/helpers/helper') 2 | 3 | shared_examples_for :pipeline do 4 | describe 'default options' do 5 | let(:app) { rack_app } 6 | before do 7 | pipeline = @pipeline 8 | app_root = fixture_path('asset_pack_app') 9 | base = Padrino::Application 10 | base = Sinatra::Base if @pipeline == Padrino::Pipeline::AssetPack 11 | mock_app(base) do 12 | set :root, app_root 13 | register Padrino::Pipeline 14 | configure_assets{ |c| c.pipeline = pipeline } 15 | end 16 | end 17 | 18 | it 'can get a stylesheet file' do 19 | get '/assets/stylesheets/app.css' 20 | assert_equal 200, last_response.status 21 | end 22 | 23 | it 'makes sure that sass is compiled' do 24 | get '/assets/stylesheets/default.css' 25 | assert_equal 200, last_response.status 26 | assert_match ".content", last_response.body 27 | end 28 | 29 | it 'can not get a file other than .css' do 30 | get '/assets/stylesheets/default.scss' 31 | assert_equal 404, last_response.status 32 | end 33 | 34 | it 'gives 404 for unknown files' do 35 | get '/assets/stylesheets/omg.css' 36 | assert_equal 404, last_response.status 37 | end 38 | end 39 | 40 | 41 | describe 'custom options' do 42 | let(:app) { rack_app } 43 | before do 44 | @assets_location = "#{fixture_path('asset_pack_app')}/assets/stylesheets" 45 | end 46 | 47 | it 'get CSS asset from a custom location' do 48 | assets_location = @assets_location 49 | pipeline = @pipeline 50 | mock_app do 51 | register Padrino::Pipeline 52 | configure_assets do |assets| 53 | assets.pipeline = pipeline 54 | assets.css_assets = assets_location 55 | end 56 | end 57 | 58 | get '/assets/stylesheets/app.css' 59 | assert_equal 200, last_response.status 60 | end 61 | 62 | it 'get CSS asset from custom location(Array)' do 63 | assets_location = @assets_location 64 | pipeline = @pipeline 65 | mock_app do 66 | register Padrino::Pipeline 67 | configure_assets do |assets| 68 | assets.pipeline = pipeline 69 | assets.css_assets = ['some/unknown/source', assets_location] 70 | assets.css_prefix = '/custom/location' 71 | end 72 | end 73 | get '/custom/location/app.css' 74 | assert_equal 200, last_response.status 75 | end 76 | 77 | it 'get CSS asset form custom URI' do 78 | assets_location = @assets_location 79 | pipeline = @pipeline 80 | mock_app do 81 | register Padrino::Pipeline 82 | configure_assets do |assets| 83 | assets.pipeline = pipeline 84 | assets.css_assets = assets_location 85 | assets.css_prefix = '/custom/location' 86 | end 87 | end#mock-app 88 | get '/custom/location/app.css' 89 | assert_equal 200, last_response.status 90 | end 91 | end 92 | end 93 | 94 | describe Padrino::Pipeline::Sprockets do 95 | before { @pipeline = Padrino::Pipeline::Sprockets } 96 | it_behaves_like :pipeline 97 | end 98 | 99 | describe Padrino::Pipeline::AssetPack do 100 | before { @pipeline = Padrino::Pipeline::AssetPack} 101 | it_behaves_like :pipeline 102 | end 103 | 104 | 105 | -------------------------------------------------------------------------------- /test/test_js.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/helpers/helper') 2 | 3 | shared_examples_for :pipeline do 4 | describe 'default options' do 5 | let(:app) { rack_app } 6 | before do 7 | pipeline = @pipeline 8 | app_root = fixture_path('asset_pack_app') 9 | base = Padrino::Application 10 | base = Sinatra::Base if @pipeline == Padrino::Pipeline::AssetPack 11 | mock_app(base) do 12 | set :root, app_root 13 | register Padrino::Pipeline 14 | configure_assets{ |c| c.pipeline = pipeline } 15 | end 16 | end 17 | 18 | it 'GET a basic JS file' do 19 | get '/assets/javascripts/app.js' 20 | assert_equal 200, last_response.status 21 | assert_match 'var mainApp', last_response.body 22 | end 23 | 24 | it 'GET a coffee script file' do 25 | get '/assets/javascripts/coffee.js' 26 | assert_equal 200, last_response.status 27 | assert_match 'coffee', last_response.body 28 | end 29 | 30 | it 'is the right content type' do 31 | get '/assets/javascripts/app.js' 32 | assert_match 'application/javascript', last_response.content_type 33 | end 34 | 35 | it 'can not get a file other than .js' do 36 | get '/assets/javscripts/coffee.coffee' 37 | assert_equal 404, last_response.status 38 | end 39 | 40 | 41 | it 'gives 404 for unknown JS file' do 42 | get '/assets/javascripts/doesnotexist.js' 43 | assert_equal 404, last_response.status 44 | end 45 | end 46 | 47 | 48 | describe 'custom options' do 49 | let(:app) { rack_app } 50 | before do 51 | @assets_location = "#{fixture_path('asset_pack_app')}/assets/javascripts" 52 | end 53 | 54 | it 'get JS asset from a custom location' do 55 | assets_location = @assets_location 56 | pipeline = @pipeline 57 | mock_app do 58 | register Padrino::Pipeline 59 | configure_assets do |assets| 60 | assets.pipeline = pipeline 61 | assets.js_assets = assets_location 62 | end 63 | end 64 | 65 | get '/assets/javascripts/app.js' 66 | assert_equal 200, last_response.status 67 | end 68 | 69 | it 'get JS asset from custom location(Array)' do 70 | assets_location = @assets_location 71 | pipeline = @pipeline 72 | mock_app do 73 | register Padrino::Pipeline 74 | configure_assets do |assets| 75 | assets.pipeline = pipeline 76 | assets.js_assets = ['some/unknown/source', assets_location] 77 | assets.js_prefix = '/custom/location' 78 | end 79 | end 80 | get '/custom/location/app.js' 81 | assert_equal 200, last_response.status 82 | end 83 | 84 | it 'get JS asset form custom URI' do 85 | assets_location = @assets_location 86 | pipeline = @pipeline 87 | mock_app do 88 | register Padrino::Pipeline 89 | configure_assets do |assets| 90 | assets.pipeline = pipeline 91 | assets.js_assets = assets_location 92 | assets.js_prefix = '/custom/location' 93 | end 94 | end#mock-app 95 | get '/custom/location/app.js' 96 | assert_equal 200, last_response.status 97 | end 98 | end 99 | end 100 | 101 | describe Padrino::Pipeline::Sprockets do 102 | before { @pipeline = Padrino::Pipeline::Sprockets } 103 | it_behaves_like :pipeline 104 | end 105 | 106 | describe Padrino::Pipeline::AssetPack do 107 | before { @pipeline = Padrino::Pipeline::AssetPack} 108 | it_behaves_like :pipeline 109 | end 110 | 111 | 112 | -------------------------------------------------------------------------------- /test/test_images.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/helpers/helper') 2 | 3 | shared_examples_for :pipeline do 4 | describe 'default options' do 5 | let(:app) { rack_app } 6 | before do 7 | pipeline = @pipeline 8 | app_root = fixture_path('sprockets_app') 9 | base = Padrino::Application 10 | base = Sinatra::Base if @pipeline == Padrino::Pipeline::AssetPack 11 | mock_app(base) do 12 | set :root, app_root 13 | register Padrino::Pipeline 14 | configure_assets{ |c| c.pipeline = pipeline } 15 | end 16 | 17 | end 18 | 19 | it 'can get an image' do 20 | get '/assets/images/glass.png' 21 | assert_equal 200, last_response.status 22 | end 23 | 24 | it 'should have the right content type' do 25 | get '/assets/images/glass.png' 26 | assert_equal 'image/png', last_response.content_type 27 | end 28 | 29 | it 'gives 404 for unkown image files' do 30 | get '/assets/images/unkown.png' 31 | assert_equal 404, last_response.status 32 | end 33 | end 34 | 35 | describe 'custom options' do 36 | let(:app) { rack_app } 37 | before do 38 | @assets_location = "#{fixture_path('sprockets_app')}/assets/images" 39 | end 40 | 41 | it 'get image asset from a custom location' do 42 | assets_location = @assets_location 43 | pipeline = @pipeline 44 | mock_app do 45 | register Padrino::Pipeline 46 | configure_assets do |assets| 47 | assets.pipeline = pipeline 48 | assets.image_assets = assets_location 49 | end 50 | end 51 | 52 | get '/assets/images/glass.png' 53 | assert_equal 200, last_response.status 54 | end 55 | 56 | it 'get image asset from a custom location(Array)' do 57 | assets_location = @assets_location 58 | pipeline = @pipeline 59 | mock_app do 60 | register Padrino::Pipeline 61 | configure_assets do |assets| 62 | assets.pipeline = pipeline 63 | assets.image_assets = ['some/unkown/place', assets_location] 64 | end 65 | end 66 | 67 | get '/assets/images/glass.png' 68 | assert_equal 200, last_response.status 69 | end 70 | 71 | it 'get image asset form custom URI' do 72 | assets_location = @assets_location 73 | pipeline = @pipeline 74 | mock_app do 75 | register Padrino::Pipeline 76 | configure_assets do |assets| 77 | assets.pipeline = pipeline 78 | assets.image_assets = assets_location 79 | assets.image_prefix = '/custom/location' 80 | end 81 | end#mock-app 82 | get '/custom/location/glass.png' 83 | assert_equal 200, last_response.status 84 | end 85 | 86 | it 'get image asset form custom prefix' do 87 | assets_location = @assets_location 88 | pipeline = @pipeline 89 | mock_app do 90 | register Padrino::Pipeline 91 | configure_assets do |assets| 92 | assets.pipeline = pipeline 93 | assets.image_assets = assets_location 94 | assets.prefix = '/custom' 95 | end 96 | end#mock-app 97 | get '/custom/assets/images/glass.png' 98 | assert_equal 200, last_response.status 99 | end 100 | 101 | end 102 | end 103 | 104 | describe Padrino::Pipeline::Sprockets do 105 | before { @pipeline = Padrino::Pipeline::Sprockets } 106 | it_behaves_like :pipeline 107 | end 108 | 109 | describe Padrino::Pipeline::AssetPack do 110 | before { @pipeline = Padrino::Pipeline::AssetPack} 111 | it_behaves_like :pipeline 112 | end 113 | 114 | 115 | -------------------------------------------------------------------------------- /test/pipelines/sprockets/test_compiler.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/../../helpers/helper') 2 | require 'ostruct' 3 | require 'bootstrap-sass' 4 | 5 | describe Padrino::Pipeline::Compiler::Sprockets do 6 | before do 7 | @asset_path = "#{fixture_path('sprockets_app')}/assets" 8 | @public_path = "#{fixture_path('sprockets_app')}/public" 9 | end 10 | 11 | after do 12 | FileUtils.rm_rf @public_path 13 | end 14 | 15 | it 'creates a directory to put compiled assets' do 16 | config = OpenStruct.new(compiled_output: @public_path) 17 | compiler = Padrino::Pipeline::Compiler::Sprockets.new(config) 18 | 19 | compiler.compile(:js) 20 | assert_equal true, File.exists?(@public_path) 21 | end 22 | 23 | it 'raises exception on incorrect compile type' do 24 | skip 25 | config = OpenStruct.new( compiled_output: @public_path) 26 | compiler = Padrino::Pipeline::Compiler::Sprockets.new(config) 27 | 28 | assert_throws(RuntimeError) { compiler.compile(:somehting) } 29 | end 30 | 31 | it 'creates the correct directory for javascripts' do 32 | config_hash = { compiled_output: @public_path, js_compiled_output: 'javascripts' } 33 | config = OpenStruct.new(config_hash) 34 | compiler = Padrino::Pipeline::Compiler::Sprockets.new(config).compile(:js) 35 | assert_equal true, File.exists?("#{@public_path}/javascripts") 36 | 37 | config_hash = { compiled_output: @public_path, js_compiled_output: 'javascripts-compiled' } 38 | config = OpenStruct.new(config_hash) 39 | compiler = Padrino::Pipeline::Compiler::Sprockets.new(config).compile(:js) 40 | assert_equal true, File.exists?("#{@public_path}/javascripts-compiled") 41 | end 42 | 43 | it 'creates the correct directory for stylesheets' do 44 | config_hash = { compiled_output: @public_path, css_compiled_output: 'stylesheets' } 45 | config = OpenStruct.new(config_hash) 46 | compiler = Padrino::Pipeline::Compiler::Sprockets.new(config).compile(:css) 47 | assert_equal true, File.exists?("#{@public_path}/stylesheets") 48 | 49 | config_hash = { compiled_output: @public_path, css_compiled_output: 'stylesheets-compiled' } 50 | config = OpenStruct.new(config_hash) 51 | compiler = Padrino::Pipeline::Compiler::Sprockets.new(config).compile(:js) 52 | assert_equal true, File.exists?("#{@public_path}/stylesheets-compiled") 53 | end 54 | 55 | describe 'Custom compiler settings' do 56 | let(:app) { rack_app } 57 | before do 58 | asset_path, public_path = @asset_path, @public_path 59 | mock_app do 60 | register Padrino::Pipeline 61 | register Padrino::Helpers 62 | 63 | configure_assets do |assets| 64 | assets.pipeline = Padrino::Pipeline::Sprockets 65 | assets.js_assets = "#{asset_path}/javascripts" 66 | assets.css_assets = "#{asset_path}/stylesheets" 67 | assets.compiled_output = "#{public_path}" 68 | end 69 | 70 | get('/js') { render :erb, "<%= javascript_include_tag 'application.js' %>" } 71 | get('/css') { render :erb, "<%= stylesheet_link_tag 'application.css' %>" } 72 | end 73 | end 74 | 75 | after { FileUtils.rm_rf "#{@public_path}/javascripts" } 76 | 77 | context 'asset_tags' do 78 | it 'should return javascript with the correct digest' do 79 | @app.pipeline.compile :js 80 | 81 | digest = @app.assets['application.js'].digest 82 | get '/js' 83 | assert_match "/assets/javascripts/application-#{digest}.js", last_response.body 84 | end 85 | 86 | it 'should return stylesheet with the correct digest' do 87 | @app.pipeline.compile :css 88 | digest = @app.assets['application.css'].digest 89 | get '/css' 90 | assert_match "/assets/stylesheets/application-#{digest}.css", last_response.body 91 | end 92 | end 93 | 94 | context 'javascripts' do 95 | it 'should compile application.js and application.js.gz' do 96 | @app.pipeline.compile :js 97 | 98 | digest = @app.assets['application.js'].digest 99 | assert_equal true, File.exists?("#{@public_path}/javascripts/application-#{digest}.js") 100 | assert_equal true, File.exists?("#{@public_path}/javascripts/application-#{digest}.js.gz") 101 | end 102 | 103 | it 'should compile files included in the manifest' do 104 | @app.pipeline.compile :js 105 | 106 | digest = @app.assets['application.js'].digest 107 | assert_match_in_file 'function in_second_file()', "#{@public_path}/javascripts/application-#{digest}.js" 108 | assert_match_in_file 'coffee_method', "#{@public_path}/javascripts/application-#{digest}.js" 109 | end 110 | end 111 | 112 | context 'stylesheets' do 113 | it 'should compile application.css and application.css.gz' do 114 | @app.pipeline.compile :css 115 | 116 | digest = @app.assets['application.css'].digest 117 | assert_equal true, File.exists?("#{@public_path}/stylesheets/application-#{digest}.css") 118 | assert_equal true, File.exists?("#{@public_path}/stylesheets/application-#{digest}.css.gz") 119 | end 120 | 121 | it 'should compile files included in the manifest' do 122 | @app.pipeline.compile :css 123 | 124 | digest = @app.assets['application.css'].digest 125 | assert_match_in_file '.home', "#{@public_path}/stylesheets/application-#{digest}.css" 126 | assert_match_in_file '.div', "#{@public_path}/stylesheets/application-#{digest}.css" 127 | end 128 | 129 | end 130 | end 131 | end 132 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Padrino Pipeline 2 | 3 | Padrino Pipeline is a gem for [Padrino](http://www.padrinorb.com). It provides a unified way to use several different asset management systems. 4 | 5 | [![Build Status](https://travis-ci.org/Ortuna/padrino-pipeline.png?branch=master)](https://travis-ci.org/Ortuna/padrino-pipeline) 6 | [![Code Climate](https://codeclimate.com/github/Ortuna/padrino-pipeline.png)](https://codeclimate.com/github/Ortuna/padrino-pipeline) 7 | [![Dependency Status](https://gemnasium.com/Ortuna/padrino-pipeline.png)](https://gemnasium.com/Ortuna/padrino-pipeline) 8 | 9 | 10 | ## Supported Pipelines 11 | 12 | - [sprockets](https://github.com/sstephenson/sprockets) 13 | - [sinatra-assetpack](https://github.com/rstacruz/sinatra-assetpack) 14 | 15 | ## Simple Usage 16 | 17 | ### Gemfile 18 | Add to your Gemfile: 19 | ```ruby 20 | gem 'padrino-pipeline' 21 | ``` 22 | 23 | These examples examples setup a pipeline with defaulted options(see default options): 24 | 25 | ### Sprockets pipeline 26 | ```ruby 27 | module Example 28 | class App < Padrino::Application 29 | register Padrino::Pipeline 30 | configure_assets do |config| 31 | config.pipeline = Padrino::Pipeline::Sprockets 32 | end 33 | end 34 | end 35 | ``` 36 | 37 | ### Sinatra AssetPack pipeline 38 | ```ruby 39 | module Example 40 | class App < Padrino::Application 41 | register Padrino::Pipeline 42 | configure_assets do |config| 43 | config.pipeline = Padrino::Pipeline::AssetPack 44 | end 45 | end 46 | end 47 | ``` 48 | 49 | ## Options 50 | Certain options can be configured to change the behavior of the pipelines. 51 | These options should be used within the configure_assets block. 52 | 53 | for example: 54 | ```ruby 55 | module Example 56 | class App < Padrino::Application 57 | register Padrino::Pipeline 58 | configure_assets do |config| 59 | config.pipeline = Padrino::Pipeline::AssetPack 60 | config.css_prefix = '/xyz' 61 | end 62 | end 63 | end 64 | ``` 65 | 66 | 67 | ## Pipeline 68 | ```ruby 69 | module Example 70 | class App < Padrino::Application 71 | register Padrino::Pipeline 72 | configure_assets do |config| 73 | config.pipeline = Padrino::Pipeline::AssetPack 74 | end 75 | end 76 | end 77 | ``` 78 | 79 | `config.pipeline = Padrino::Pipeline::AssetPack` 80 | `config.pipeline = Padrino::Pipeline::Sprockets` 81 | 82 | ## Assets URI(mounting location) String 83 | 84 | ###css_prefix 85 | ```ruby 86 | module Example 87 | class App < Padrino::Application 88 | register Padrino::Pipeline 89 | configure_assets do |config| 90 | config.pipeline = Padrino::Pipeline::Sprockets 91 | config.css_prefix = '/my_custom_location' 92 | end 93 | end 94 | end 95 | ``` 96 | `/my_custom_location` will be the location css assets are served 97 | e.g. `/my_custom_location/application.css` 98 | 99 | ###js_prefix 100 | ```ruby 101 | module Example 102 | class App < Padrino::Application 103 | register Padrino::Pipeline 104 | configure_assets do |config| 105 | config.pipeline = Padrino::Pipeline::Sprockets 106 | config.js_prefix = '/js' 107 | end 108 | end 109 | end 110 | ``` 111 | `/js` will be the location css assets are served 112 | e.g. `/js/application.js` 113 | 114 | ## Asset location(path to files) String/Array 115 | ###css_assets 116 | ```ruby 117 | module Example 118 | class App < Padrino::Application 119 | register Padrino::Pipeline 120 | configure_assets do |config| 121 | config.pipeline = Padrino::Pipeline::Sprockets 122 | config.css_assets = '/path/to/stylesheets' 123 | end 124 | end 125 | end 126 | ``` 127 | `/path/to/stylesheets` will be served at the css_prefix(default: /assets/stylesheets) 128 | 129 | ###js_assets 130 | ```ruby 131 | module Example 132 | class App < Padrino::Application 133 | register Padrino::Pipeline 134 | configure_assets do |config| 135 | config.pipeline = Padrino::Pipeline::Sprockets 136 | config.js_assets = '/path/to/javascripts' 137 | end 138 | end 139 | end 140 | ``` 141 | `/path/to/javascripts` will be served at the js_prefix(default: /assets/javascripts) 142 | 143 | ## Prefix prepend this prefix before all assets 144 | ###prefix 145 | ```ruby 146 | module Example 147 | class App < Padrino::Application 148 | register Padrino::Pipeline 149 | configure_assets do |config| 150 | config.pipeline = Padrino::Pipeline::Sprockets 151 | config.prefix = '/public' 152 | end 153 | end 154 | end 155 | ``` 156 | prefixes `/public` to all asset URLs. Above example will serve assets from: 157 | - `/public/assets/stylesheets/application.css` 158 | # => `http://localhost:3000/public/assets/stylesheets/application.css` 159 | - `/public/assets/javascripts/application.js` 160 | # => `http://localhost:3000/public/assets/javascripts/application.js` 161 | 162 | ## Default option values 163 | 164 | TODO 165 | 166 | ## compile asset rake tasks 167 | 168 | Add `require 'padrino-pipeline/tasks'` to your Rakefile. 169 | 170 | ## Sprocket compiled assets 171 | 172 | `javascript_include_tag` & `stylesheet_link_tag` have been patched to include the hex digest of compiled assets. 173 | if the assets do not exist a fresh copy will be served via the normal asset URL. 174 | e.g. `application-12abc456xyz.js` vs `application.js` 175 | 176 | ## Asset pack packages 177 | 178 | ```ruby 179 | module Example 180 | class App < Padrino::Application 181 | register Padrino::Pipeline 182 | configure_assets do |config| 183 | config.pipeline = Padrino::Pipeline::AssetPack 184 | config.packages << [:js, :application, '/assets/javascripts/application.js', ['/assets/javascripts/*.js']] 185 | end 186 | end 187 | end 188 | ``` 189 | 190 | Will serve /assets/javascripts/application.js as a bundle 191 | 192 | ## Sprocket directive require/include/require tree 193 | 194 | TODO 195 | --------------------------------------------------------------------------------