├── test ├── config │ ├── assets-default.yml │ ├── assets-css.yml │ ├── assets-environment.yml │ ├── assets-sass.yml │ ├── assets-uglifier.yml │ ├── assets-erb.yml │ ├── assets-compression-disabled.yml │ ├── assets-no-rewrite-relative-paths.yml │ ├── assets-closure.yml │ ├── assets-no-java.yml │ ├── assets-broken.yml │ └── assets.yml ├── fixtures │ ├── src │ │ ├── nested │ │ │ ├── nested3.html.mustache │ │ │ ├── double_nested │ │ │ │ ├── double_nested.jst │ │ │ │ └── double_nested.html.mustache │ │ │ ├── nested1.jst │ │ │ ├── nested2.jst │ │ │ ├── nested2.js │ │ │ ├── nested1.js │ │ │ ├── nested1.css │ │ │ └── nested2.css │ │ ├── template1.jst │ │ ├── template2.jst │ │ ├── test2.js │ │ ├── test1.js │ │ ├── test1.scss │ │ ├── test1.css │ │ ├── test_fonts.css │ │ └── test2.css │ ├── jammed │ │ ├── css_test-scss.css │ │ ├── js_test-closure.js │ │ ├── js_test.js │ │ ├── js_test-uglifier.js │ │ ├── js_test_package_names.js │ │ ├── js_test-uncompressed.js │ │ ├── jst_test_diff_ext.js │ │ ├── css_test.css │ │ ├── css_test-sass.css │ │ ├── css_test-line-break.css │ │ ├── css_test-no-rewrite-relative-paths.css │ │ ├── jst_test.js │ │ ├── jst_test_diff_ext_and_nested.js │ │ ├── jst_test-custom-namespace.js │ │ ├── js_test_with_templates.js │ │ ├── css_test-uncompressed.css │ │ ├── jst_test_nested.js │ │ └── css_test-mhtml.css │ └── tags │ │ ├── css_plain_includes.html │ │ ├── js_individual_includes.html │ │ ├── css_individual_includes.html │ │ ├── css_print.html │ │ └── css_includes.html ├── public │ └── embed │ │ ├── DroidSansMono.eot │ │ ├── DroidSansMono.ttf │ │ ├── asterisk_orange.png │ │ └── asterisk_yellow.png ├── unit │ ├── test_sass_compressor.rb │ ├── test_uglifier.rb │ ├── test_closure_compressor.rb │ ├── test_compressor.rb │ ├── command_line_test.rb │ ├── test_in_the_wrong_directory.rb │ ├── test_jammit_controller.rb │ ├── test_jammit_helpers.rb │ ├── test_configuration.rb │ └── test_packager.rb └── test_helper.rb ├── doc ├── css │ ├── common.css │ ├── full_list.css │ └── style.css ├── frames.html ├── file_list.html ├── top-level-namespace.html ├── Jammit │ ├── Uglifier.html │ ├── Railtie.html │ ├── DeprecationError.html │ ├── OutputNotWritable.html │ ├── PackageNotFound.html │ ├── MissingConfiguration.html │ ├── Routes.html │ ├── JsminCompressor.html │ ├── CssminCompressor.html │ └── SassCompressor.html ├── class_list.html ├── js │ ├── full_list.js │ └── app.js ├── index.html └── _index.html ├── .yardopts ├── jammit-logo.png ├── lib ├── jammit │ ├── uglifier.rb │ ├── jsmin_compressor.rb │ ├── cssmin_compressor.rb │ ├── railtie.rb │ ├── jst.js │ ├── sass_compressor.rb │ ├── routes.rb │ ├── dependencies.rb │ ├── command_line.rb │ ├── controller.rb │ ├── helper.rb │ ├── packager.rb │ └── compressor.rb └── jammit.rb ├── .gitignore ├── bin └── jammit ├── Gemfile ├── rails └── routes.rb ├── assets.example.yml ├── README.md ├── Rakefile ├── LICENSE └── jammit.gemspec /test/config/assets-default.yml: -------------------------------------------------------------------------------- 1 | dummy: setting -------------------------------------------------------------------------------- /doc/css/common.css: -------------------------------------------------------------------------------- 1 | /* Override this file with custom rules */ -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --title Jammit 2 | -m textile 3 | --protected 4 | --private -------------------------------------------------------------------------------- /test/fixtures/src/nested/nested3.html.mustache: -------------------------------------------------------------------------------- 1 |

Goodbye, {{name}}

-------------------------------------------------------------------------------- /test/fixtures/src/nested/double_nested/double_nested.jst: -------------------------------------------------------------------------------- 1 |

<%= hello_world %>

-------------------------------------------------------------------------------- /jammit-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/documentcloud/Jammit/HEAD/jammit-logo.png -------------------------------------------------------------------------------- /test/fixtures/src/template1.jst: -------------------------------------------------------------------------------- 1 | <%= saying_something %> -------------------------------------------------------------------------------- /test/fixtures/src/nested/nested1.jst: -------------------------------------------------------------------------------- 1 | <%= saying_something %> -------------------------------------------------------------------------------- /lib/jammit/uglifier.rb: -------------------------------------------------------------------------------- 1 | class Jammit::Uglifier < ::Uglifier 2 | alias :compress :compile 3 | end -------------------------------------------------------------------------------- /test/fixtures/src/nested/double_nested/double_nested.html.mustache: -------------------------------------------------------------------------------- 1 |

Hello again, {{name}}!

-------------------------------------------------------------------------------- /test/fixtures/jammed/css_test-scss.css: -------------------------------------------------------------------------------- 1 | html{background:red}html body{background:lime}#thing{background:blue} 2 | -------------------------------------------------------------------------------- /test/fixtures/tags/css_plain_includes.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/jammed/js_test-closure.js: -------------------------------------------------------------------------------- 1 | console.log("hello, "+function(){return this.constructor.prototype}()); 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .yardoc 2 | *.gem 3 | example 4 | raws 5 | test/precache 6 | .ruby-version 7 | .DS_Store 8 | Gemfile.lock 9 | -------------------------------------------------------------------------------- /test/public/embed/DroidSansMono.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/documentcloud/Jammit/HEAD/test/public/embed/DroidSansMono.eot -------------------------------------------------------------------------------- /test/public/embed/DroidSansMono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/documentcloud/Jammit/HEAD/test/public/embed/DroidSansMono.ttf -------------------------------------------------------------------------------- /test/public/embed/asterisk_orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/documentcloud/Jammit/HEAD/test/public/embed/asterisk_orange.png -------------------------------------------------------------------------------- /test/public/embed/asterisk_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/documentcloud/Jammit/HEAD/test/public/embed/asterisk_yellow.png -------------------------------------------------------------------------------- /test/fixtures/src/template2.jst: -------------------------------------------------------------------------------- 1 | <% _([1,2,3]).each(function(num) { %> 2 |
  • 3 | <%= num %> 4 |
  • 5 | <% }) %> -------------------------------------------------------------------------------- /test/fixtures/src/nested/nested2.jst: -------------------------------------------------------------------------------- 1 | <% _([1,2,3]).each(function(num) { %> 2 |
  • 3 | <%= num %> 4 |
  • 5 | <% }) %> -------------------------------------------------------------------------------- /test/fixtures/src/test2.js: -------------------------------------------------------------------------------- 1 | var mandelay = { 2 | name : function() { return this.constructor.prototype; } 3 | }; 4 | 5 | myself.sayHi(mandelay.name()); -------------------------------------------------------------------------------- /test/fixtures/src/nested/nested2.js: -------------------------------------------------------------------------------- 1 | var mandelay = { 2 | name : function() { return this.constructor.prototype; } 3 | }; 4 | 5 | myself.sayHi(mandelay.name()); -------------------------------------------------------------------------------- /test/fixtures/src/test1.js: -------------------------------------------------------------------------------- 1 | var myself = { 2 | 3 | // An Introduction: 4 | sayHi : function(name) { 5 | console.log("hello, " + name); 6 | } 7 | 8 | }; -------------------------------------------------------------------------------- /test/config/assets-css.yml: -------------------------------------------------------------------------------- 1 | css_compressor: yui 2 | 3 | css_compressor_options: 4 | line_break: 0 5 | 6 | stylesheets: 7 | css_test: 8 | - fixtures/src/*.css 9 | -------------------------------------------------------------------------------- /test/fixtures/src/nested/nested1.js: -------------------------------------------------------------------------------- 1 | var myself = { 2 | 3 | // An Introduction: 4 | sayHi : function(name) { 5 | console.log("hello, " + name); 6 | } 7 | 8 | }; -------------------------------------------------------------------------------- /test/fixtures/jammed/js_test.js: -------------------------------------------------------------------------------- 1 | var myself={sayHi:function(a){console.log("hello, "+a)}};var mandelay={name:function(){return this.constructor.prototype}};myself.sayHi(mandelay.name()); -------------------------------------------------------------------------------- /test/fixtures/jammed/js_test-uglifier.js: -------------------------------------------------------------------------------- 1 | var myself={sayHi:function(n){console.log("hello, "+n)}},mandelay={name:function(){return this.constructor.prototype}};myself.sayHi(mandelay.name()); -------------------------------------------------------------------------------- /test/fixtures/jammed/js_test_package_names.js: -------------------------------------------------------------------------------- 1 | var myself={sayHi:function(a){console.log("hello, "+a)}};var mandelay={name:function(){return this.constructor.prototype}};myself.sayHi(mandelay.name()); -------------------------------------------------------------------------------- /test/fixtures/tags/js_individual_includes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /test/config/assets-environment.yml: -------------------------------------------------------------------------------- 1 | css_compressor: yui 2 | js_compressor: yui 3 | compress_assets: on 4 | gzip_assets: on 5 | 6 | development: 7 | compress_assets: off 8 | 9 | test: 10 | gzip_assets: off 11 | -------------------------------------------------------------------------------- /bin/jammit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -rrubygems 2 | require 'pathname' 3 | 4 | APP_ROOT = File.dirname(Pathname.new(__FILE__).realpath) 5 | require File.join(APP_ROOT, '../lib/jammit/command_line.rb') 6 | 7 | Jammit::CommandLine.new -------------------------------------------------------------------------------- /test/config/assets-sass.yml: -------------------------------------------------------------------------------- 1 | css_compressor: sass 2 | 3 | stylesheets: 4 | css_test: &css_test 5 | - fixtures/src/*.css 6 | scss_test: 7 | - fixtures/src/*.scss 8 | css_test_nested: 9 | - *css_test 10 | - fixtures/src/nested/*.css -------------------------------------------------------------------------------- /test/fixtures/src/nested/nested1.css: -------------------------------------------------------------------------------- 1 | #hello { 2 | color: white; 3 | background: blue; 4 | } 5 | #hello .world { 6 | border: 1px solid red; 7 | margin-left: 10px; 8 | margin-right: 10px; 9 | margin-bottom: 45px; 10 | margin-top: 45px; 11 | } -------------------------------------------------------------------------------- /test/fixtures/tags/css_individual_includes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /lib/jammit/jsmin_compressor.rb: -------------------------------------------------------------------------------- 1 | # Wraps JSMin compressor to use the same API as the rest of 2 | # Jammit's compressors. 3 | class Jammit::JsminCompressor 4 | def initialize(options = {}) 5 | end 6 | 7 | def compress(js) 8 | JSMin.minify(js) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /test/fixtures/src/test1.scss: -------------------------------------------------------------------------------- 1 | $primary: #FF0000; 2 | $secondary: #00FF00; 3 | 4 | html { 5 | background: $primary; 6 | 7 | body { 8 | background: $secondary; 9 | } 10 | } 11 | 12 | $primary: #0000FF; 13 | 14 | #thing { 15 | background: $primary; 16 | } 17 | -------------------------------------------------------------------------------- /test/fixtures/tags/css_print.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/fixtures/src/test1.css: -------------------------------------------------------------------------------- 1 | /* Üníc✪de */ 2 | #hello { 3 | color: white; 4 | background: blue; 5 | } 6 | #hello .world { 7 | border: 1px solid red; 8 | margin-left: 10px; 9 | margin-right: 10px; 10 | margin-bottom: 45px; 11 | margin-top: 45px; 12 | } -------------------------------------------------------------------------------- /test/fixtures/src/test_fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'DroidSansMonoRegular'; 3 | src: url('../../public/embed/DroidSansMono.eot'); 4 | src: local('Droid Sans Mono Regular'), local('DroidSansMono'), url('../../public/embed/DroidSansMono.ttf') format('truetype'); 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/tags/css_includes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/jammit/cssmin_compressor.rb: -------------------------------------------------------------------------------- 1 | # Wraps CSSMin compressor to use the same API as the rest of 2 | # Jammit's compressors. 3 | class Jammit::CssminCompressor 4 | def initialize(options = {}) 5 | end 6 | 7 | def compress(css) 8 | CSSMin.minify(css) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /test/config/assets-uglifier.yml: -------------------------------------------------------------------------------- 1 | javascript_compressor: uglifier 2 | css_compressor: yui 3 | embed_assets: on 4 | 5 | javascripts: 6 | js_test: 7 | - fixtures/src/*.js 8 | jst_test: 9 | - fixtures/src/*.jst 10 | 11 | stylesheets: 12 | css_test: 13 | - fixtures/src/*.css 14 | -------------------------------------------------------------------------------- /test/fixtures/jammed/js_test-uncompressed.js: -------------------------------------------------------------------------------- 1 | var myself = { 2 | 3 | // An Introduction: 4 | sayHi : function(name) { 5 | console.log("hello, " + name); 6 | } 7 | 8 | }; 9 | var mandelay = { 10 | name : function() { return this.constructor.prototype; } 11 | }; 12 | 13 | myself.sayHi(mandelay.name()); -------------------------------------------------------------------------------- /test/config/assets-erb.yml: -------------------------------------------------------------------------------- 1 | javascript_compressor: yui 2 | css_compressor: yui 3 | embed_assets: <%= ENV['RAILS_ENV'] == 'test' %> 4 | 5 | javascripts: 6 | js_test: 7 | - fixtures/src/*.js 8 | jst_test: 9 | - fixtures/src/*.jst 10 | 11 | stylesheets: 12 | css_test: 13 | - fixtures/src/*.css 14 | -------------------------------------------------------------------------------- /test/config/assets-compression-disabled.yml: -------------------------------------------------------------------------------- 1 | javascript_compressor: yui 2 | compress_assets: false 3 | gzip_assets: false 4 | embed_images: on 5 | 6 | javascripts: 7 | js_test: 8 | - fixtures/src/*.js 9 | jst_test: 10 | - fixtures/src/*.jst 11 | 12 | stylesheets: 13 | css_test: 14 | - fixtures/src/*.css 15 | -------------------------------------------------------------------------------- /test/config/assets-no-rewrite-relative-paths.yml: -------------------------------------------------------------------------------- 1 | javascript_compressor: yui 2 | css_compressor: yui 3 | embed_assets: on 4 | rewrite_relative_paths: off 5 | 6 | javascripts: 7 | js_test: 8 | - fixtures/src/*.js 9 | jst_test: 10 | - fixtures/src/*.jst 11 | 12 | stylesheets: 13 | css_test: 14 | - fixtures/src/*.css 15 | -------------------------------------------------------------------------------- /test/config/assets-closure.yml: -------------------------------------------------------------------------------- 1 | javascript_compressor: closure 2 | compressor_options: 3 | compilation_level: ADVANCED_OPTIMIZATIONS 4 | embed_assets: on 5 | 6 | javascripts: 7 | js_test: 8 | - fixtures/src/*.js 9 | jst_test: 10 | - fixtures/src/*.jst 11 | 12 | stylesheets: 13 | css_test: 14 | - fixtures/src/*.css 15 | -------------------------------------------------------------------------------- /test/config/assets-no-java.yml: -------------------------------------------------------------------------------- 1 | javascript_compressor: yui 2 | css_compressor: yui 3 | compressor_options: 4 | java: /nonexistent/java 5 | embed_assets: on 6 | 7 | javascripts: 8 | js_test: 9 | - fixtures/src/*.js 10 | jst_test: 11 | - fixtures/src/*.jst 12 | 13 | stylesheets: 14 | css_test: 15 | - fixtures/src/*.css 16 | -------------------------------------------------------------------------------- /test/config/assets-broken.yml: -------------------------------------------------------------------------------- 1 | javascript_compressor: undefined 2 | css_compressor: yui 3 | embed_assets: nope 4 | package_assets: 42 5 | package_path: /dev/null 6 | 7 | javascripts: 8 | js_test: 9 | - fixtures/src/*.js 10 | jst_test: 11 | - fixtures/src/*.jst 12 | 13 | stylesheets: 14 | css_test: 15 | - fixtures/src/*.css 16 | -------------------------------------------------------------------------------- /lib/jammit/railtie.rb: -------------------------------------------------------------------------------- 1 | # Rails 3 configuration via Railtie 2 | 3 | if defined?(Rails::Railtie) 4 | module Jammit 5 | class Railtie < Rails::Railtie 6 | 7 | initializer :jammit_routes do |app| 8 | # Add a Jammit route for the reloader. 9 | app.routes_reloader.paths << File.join(File.dirname(__FILE__), "..", "..", "rails", "routes.rb") 10 | end 11 | 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | 5 | group :development, :test do 6 | gem "rake", "~> 10.3" 7 | gem "rails", "~> 5.0" 8 | gem "cssmin", "~> 1.0" 9 | gem "jsmin", "~> 1.0" 10 | gem "yui-compressor", "~> 0.12" 11 | gem "closure-compiler", "~> 1.1" 12 | gem "uglifier", "~> 2.5" 13 | gem "sass", "~> 3.4" 14 | gem "pry" 15 | end 16 | 17 | group :development do 18 | gem "RedCloth", "~> 4.2" 19 | end 20 | -------------------------------------------------------------------------------- /lib/jammit/jst.js: -------------------------------------------------------------------------------- 1 | var template = function(str){var fn = new Function('obj', 'var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push(\''+str.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/<%=([\s\S]+?)%>/g,function(match,code){return "',"+code.replace(/\\'/g, "'")+",'";}).replace(/<%([\s\S]+?)%>/g,function(match,code){return "');"+code.replace(/\\'/g, "'").replace(/[\r\n\t]/g,' ')+"__p.push('";}).replace(/\r/g,'\\r').replace(/\n/g,'\\n').replace(/\t/g,'\\t')+"');}return __p.join('');");return fn;}; -------------------------------------------------------------------------------- /test/fixtures/src/test2.css: -------------------------------------------------------------------------------- 1 | #another { 2 | color: white; 3 | background: blue; 4 | } 5 | #css .file { 6 | border: 1px solid red; 7 | margin-left: 10px; 8 | margin-right: 10px; 9 | margin-bottom: 45px; 10 | margin-top: 45px; 11 | } 12 | #with_images { 13 | background: url(../../public/embed/asterisk_yellow.png); 14 | } 15 | #and_relative_paths { 16 | background: url(../../public/embed/asterisk_orange.png?1010101); 17 | } 18 | #and_real_urls { 19 | background: url(http://example.com/image.png); 20 | } -------------------------------------------------------------------------------- /test/fixtures/src/nested/nested2.css: -------------------------------------------------------------------------------- 1 | #another { 2 | color: white; 3 | background: blue; 4 | } 5 | #css .file { 6 | border: 1px solid red; 7 | margin-left: 10px; 8 | margin-right: 10px; 9 | margin-bottom: 45px; 10 | margin-top: 45px; 11 | } 12 | #with_images { 13 | background: url(../../public/embed/asterisk_yellow.png); 14 | } 15 | #and_relative_paths { 16 | background: url(../../public/embed/asterisk_orange.png?1010101); 17 | } 18 | #and_real_urls { 19 | background: url(http://example.com/image.png); 20 | } -------------------------------------------------------------------------------- /lib/jammit/sass_compressor.rb: -------------------------------------------------------------------------------- 1 | # Wraps sass' css compressor to use the same API as the rest of 2 | # Jammit's compressors. 3 | class Jammit::SassCompressor 4 | # Creates a new sass compressor. Jammit::SassCompressor doesn't use 5 | # any options, the +options+ parameter is there for API 6 | # compatibility. 7 | def initialize(options = {}) 8 | end 9 | 10 | # Compresses +css+ using sass' CSS parser, and returns the 11 | # compressed css. 12 | def compress(css) 13 | ::Sass::Engine.new(css, :syntax => :scss, :style => :compressed).render.strip 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /test/config/assets.yml: -------------------------------------------------------------------------------- 1 | javascript_compressor: yui 2 | css_compressor: yui 3 | embed_assets: on 4 | compress_assets: true 5 | 6 | javascripts: 7 | js_test: &js_test 8 | - fixtures/src/*.js 9 | js_test_with_templates: 10 | - fixtures/src/*.js 11 | - fixtures/src/*.jst 12 | js_test_nested: 13 | - *js_test 14 | - fixtures/src/nested/*.js 15 | jst_test: &jst_test 16 | - fixtures/src/*.jst 17 | jst_test_nested: 18 | - *jst_test 19 | - fixtures/src/nested/**/*.jst 20 | 21 | stylesheets: 22 | css_test: &css_test 23 | - fixtures/src/*.css 24 | css_test_nested: 25 | - *css_test 26 | - fixtures/src/nested/*.css 27 | -------------------------------------------------------------------------------- /test/fixtures/jammed/jst_test_diff_ext.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | window.JST = window.JST || {}; 3 | var template = function(str){var fn = new Function('obj', 'var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push(\''+str.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/<%=([\s\S]+?)%>/g,function(match,code){return "',"+code.replace(/\\'/g, "'")+",'";}).replace(/<%([\s\S]+?)%>/g,function(match,code){return "');"+code.replace(/\\'/g, "'").replace(/[\r\n\t]/g,' ')+"__p.push('";}).replace(/\r/g,'\\r').replace(/\n/g,'\\n').replace(/\t/g,'\\t')+"');}return __p.join('');");return fn;}; 4 | window.JST['template3'] = template('

    Hello, {{name}}

    '); 5 | })(); -------------------------------------------------------------------------------- /test/unit/test_sass_compressor.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SassCompressorTest < MiniTest::Test 4 | def test_css_compression 5 | Jammit.load_configuration('test/config/assets-sass.yml') 6 | 7 | packed = Compressor.new.compress_css(glob('test/fixtures/src/*.css')) 8 | 9 | assert_equal File.read('test/fixtures/jammed/css_test-sass.css'), packed 10 | end 11 | 12 | def test_scss_to_css 13 | Jammit.load_configuration('test/config/assets-sass.yml') 14 | 15 | packed = Compressor.new.compress_css(glob('test/fixtures/src/*.scss')) 16 | assert_equal File.read('test/fixtures/jammed/css_test-scss.css').strip, packed 17 | end 18 | 19 | end -------------------------------------------------------------------------------- /test/fixtures/jammed/css_test.css: -------------------------------------------------------------------------------- 1 | #hello{color:white;background:blue}#hello .world{border:1px solid red;margin-left:10px;margin-right:10px;margin-bottom:45px;margin-top:45px}#another{color:white;background:blue}#css .file{border:1px solid red;margin-left:10px;margin-right:10px;margin-bottom:45px;margin-top:45px}#with_images{background:url(../embed/asterisk_yellow.png?101)}#and_relative_paths{background:url(../embed/asterisk_orange.png?101)}#and_real_urls{background:url(http://example.com/image.png)}@font-face{font-family:'DroidSansMonoRegular';src:url(../embed/DroidSansMono.eot?101);src:local('Droid Sans Mono Regular'),local('DroidSansMono'),url(../embed/DroidSansMono.ttf?101) format('truetype')} -------------------------------------------------------------------------------- /test/fixtures/jammed/css_test-sass.css: -------------------------------------------------------------------------------- 1 | #hello{color:white;background:blue}#hello .world{border:1px solid red;margin-left:10px;margin-right:10px;margin-bottom:45px;margin-top:45px}#another{color:white;background:blue}#css .file{border:1px solid red;margin-left:10px;margin-right:10px;margin-bottom:45px;margin-top:45px}#with_images{background:url(../embed/asterisk_yellow.png?101)}#and_relative_paths{background:url(../embed/asterisk_orange.png?101)}#and_real_urls{background:url(http://example.com/image.png)}@font-face{font-family:'DroidSansMonoRegular';src:url(../embed/DroidSansMono.eot?101);src:local("Droid Sans Mono Regular"),local("DroidSansMono"),url(../embed/DroidSansMono.ttf?101) format("truetype")} -------------------------------------------------------------------------------- /lib/jammit/routes.rb: -------------------------------------------------------------------------------- 1 | module Jammit 2 | 3 | # Rails 2.x routing module. Rails 3.x routes are in rails/routes.rb. 4 | module Routes 5 | 6 | # Jammit uses a single route in order to slow down Rails' routing speed 7 | # by the absolute minimum. In your config/routes.rb file, call: 8 | # Jammit::Routes.draw(map) 9 | # Passing in the routing "map" object. 10 | def self.draw(map) 11 | map.jammit "/#{Jammit.package_path}/:package.:extension", { 12 | :controller => 'jammit', 13 | :action => 'package', 14 | :requirements => { 15 | # A hack to allow extension to include "." 16 | :extension => /.+/ 17 | } 18 | } 19 | end 20 | 21 | end 22 | 23 | end -------------------------------------------------------------------------------- /test/fixtures/jammed/css_test-line-break.css: -------------------------------------------------------------------------------- 1 | #hello{color:white;background:blue} 2 | #hello .world{border:1px solid red;margin-left:10px;margin-right:10px;margin-bottom:45px;margin-top:45px} 3 | #another{color:white;background:blue} 4 | #css .file{border:1px solid red;margin-left:10px;margin-right:10px;margin-bottom:45px;margin-top:45px} 5 | #with_images{background:url(../embed/asterisk_yellow.png?101)} 6 | #and_relative_paths{background:url(../embed/asterisk_orange.png?101)} 7 | #and_real_urls{background:url(http://example.com/image.png)} 8 | @font-face{font-family:'DroidSansMonoRegular';src:url(../embed/DroidSansMono.eot?101);src:local('Droid Sans Mono Regular'),local('DroidSansMono'),url(../embed/DroidSansMono.ttf?101) format('truetype')} -------------------------------------------------------------------------------- /rails/routes.rb: -------------------------------------------------------------------------------- 1 | if defined?(Rails::Application) 2 | major = Rails.version.split(".").first.to_i 3 | 4 | # Rails3 routes 5 | Rails.application.routes.draw do 6 | match "/#{Jammit.package_path}/:package.:extension", 7 | :to => 'jammit#package', :as => :jammit, :constraints => { 8 | # A hack to allow extension to include "." 9 | :extension => /.+/ 10 | } 11 | end if major == 3 12 | 13 | # Rails4 routes 14 | Rails.application.routes.draw do 15 | get "/#{Jammit.package_path}/:package.:extension", 16 | :to => 'jammit#package', :as => :jammit, :constraints => { 17 | # A hack to allow extension to include "." 18 | :extension => /.+/ 19 | } 20 | end if major >= 4 21 | end 22 | -------------------------------------------------------------------------------- /test/fixtures/jammed/css_test-no-rewrite-relative-paths.css: -------------------------------------------------------------------------------- 1 | #hello{color:white;background:blue}#hello .world{border:1px solid red;margin-left:10px;margin-right:10px;margin-bottom:45px;margin-top:45px}#another{color:white;background:blue}#css .file{border:1px solid red;margin-left:10px;margin-right:10px;margin-bottom:45px;margin-top:45px}#with_images{background:url(../../public/embed/asterisk_yellow.png?101)}#and_relative_paths{background:url(../../public/embed/asterisk_orange.png?101)}#and_real_urls{background:url(http://example.com/image.png)}@font-face{font-family:'DroidSansMonoRegular';src:url(../../public/embed/DroidSansMono.eot?101);src:local('Droid Sans Mono Regular'),local('DroidSansMono'),url(../../public/embed/DroidSansMono.ttf?101) format('truetype')} -------------------------------------------------------------------------------- /test/unit/test_uglifier.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class UglifierText < MiniTest::Test 4 | 5 | def setup 6 | Jammit.load_configuration('test/config/assets-uglifier.yml').reload! 7 | @compressor = Compressor.new 8 | end 9 | 10 | def teardown 11 | Jammit.load_configuration('test/config/assets.yml').reload! 12 | end 13 | 14 | def test_javascript_compression 15 | packed = @compressor.compress_js(glob('test/fixtures/src/*.js')) 16 | assert_equal packed, File.read('test/fixtures/jammed/js_test-uglifier.js') 17 | end 18 | 19 | def test_jst_compilation 20 | packed = @compressor.compile_jst(glob('test/fixtures/src/*.jst')) 21 | assert_equal packed, File.read('test/fixtures/jammed/jst_test.js') 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /test/unit/test_closure_compressor.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ClosureCompressorTest < MiniTest::Test 4 | 5 | def setup 6 | Jammit.load_configuration('test/config/assets-closure.yml').reload! 7 | @compressor = Compressor.new 8 | end 9 | 10 | def teardown 11 | Jammit.load_configuration('test/config/assets.yml').reload! 12 | end 13 | 14 | def test_javascript_compression 15 | packed = @compressor.compress_js(glob('test/fixtures/src/*.js')) 16 | assert_equal File.read('test/fixtures/jammed/js_test-closure.js'), packed 17 | end 18 | 19 | def test_jst_compilation 20 | packed = @compressor.compile_jst(glob('test/fixtures/src/*.jst')) 21 | assert_equal File.read('test/fixtures/jammed/jst_test.js'), packed 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /test/fixtures/jammed/jst_test.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | window.JST = window.JST || {}; 3 | var template = function(str){var fn = new Function('obj', 'var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push(\''+str.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/<%=([\s\S]+?)%>/g,function(match,code){return "',"+code.replace(/\\'/g, "'")+",'";}).replace(/<%([\s\S]+?)%>/g,function(match,code){return "');"+code.replace(/\\'/g, "'").replace(/[\r\n\t]/g,' ')+"__p.push('";}).replace(/\r/g,'\\r').replace(/\n/g,'\\n').replace(/\t/g,'\\t')+"');}return __p.join('');");return fn;}; 4 | window.JST['template1'] = template('<%= saying_something %>'); 5 | window.JST['template2'] = template('<% _([1,2,3]).each(function(num) { %>\n
  • \n <%= num %>\n
  • \n<% }) %>'); 6 | })(); -------------------------------------------------------------------------------- /assets.example.yml: -------------------------------------------------------------------------------- 1 | package_assets: on 2 | embed_assets: on 3 | template_function: _.template 4 | package_path: packages 5 | javascript_compressor: closure 6 | compressor_options: 7 | compilation_level: ADVANCED_OPTIMIZATIONS 8 | 9 | javascripts: 10 | workspace: 11 | - public/javascripts/vendor/*.js 12 | - public/javascripts/application.js 13 | - public/javascripts/lib/bindable.js 14 | - public/javascripts/lib/set.js 15 | - public/javascripts/lib/*.js 16 | - public/javascripts/**/*.js 17 | - app/views/workspace/*.jst 18 | 19 | stylesheets: 20 | common: 21 | - public/stylesheets/vendor/reset.css 22 | - public/stylesheets/ui/*.css 23 | workspace: 24 | - public/stylesheets/pages/workspace.css 25 | empty: 26 | - public/stylesheets/pages/empty.css 27 | 28 | -------------------------------------------------------------------------------- /test/fixtures/jammed/jst_test_diff_ext_and_nested.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | window.JST = window.JST || {}; 3 | var template = function(str){var fn = new Function('obj', 'var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push(\''+str.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/<%=([\s\S]+?)%>/g,function(match,code){return "',"+code.replace(/\\'/g, "'")+",'";}).replace(/<%([\s\S]+?)%>/g,function(match,code){return "');"+code.replace(/\\'/g, "'").replace(/[\r\n\t]/g,' ')+"__p.push('";}).replace(/\r/g,'\\r').replace(/\n/g,'\\n').replace(/\t/g,'\\t')+"');}return __p.join('');");return fn;}; 4 | window.JST['nested/double_nested/double_nested'] = template('

    Hello again, {{name}}!

    '); 5 | window.JST['nested/nested3'] = template('

    Goodbye, {{name}}

    '); 6 | window.JST['template3'] = template('

    Hello, {{name}}

    '); 7 | })(); -------------------------------------------------------------------------------- /test/fixtures/jammed/jst_test-custom-namespace.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | custom_namespace = custom_namespace || {}; 3 | var template = function(str){var fn = new Function('obj', 'var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push(\''+str.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/<%=([\s\S]+?)%>/g,function(match,code){return "',"+code.replace(/\\'/g, "'")+",'";}).replace(/<%([\s\S]+?)%>/g,function(match,code){return "');"+code.replace(/\\'/g, "'").replace(/[\r\n\t]/g,' ')+"__p.push('";}).replace(/\r/g,'\\r').replace(/\n/g,'\\n').replace(/\t/g,'\\t')+"');}return __p.join('');");return fn;}; 4 | custom_namespace['template1'] = template('<%= saying_something %>'); 5 | custom_namespace['template2'] = template('<% _([1,2,3]).each(function(num) { %>\n
  • \n <%= num %>\n
  • \n<% }) %>'); 6 | })(); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | _ _ __ __ __ __ ___ _____ 2 | _ | |/_\ | \/ | \/ |_ _|_ _| 3 | | || / _ \| |\/| | |\/| || | | | 4 | \__/_/ \_\_| |_|_| |_|___| |_| 5 | 6 | Jammit is an industrial-strength asset packaging library for Rails, providing both the CSS and JavaScript concatenation and compression that you'd expect, as well as ahead-of-time gzipping, built-in JavaScript template support, and optional Data-URI / MHTML image embedding. 7 | 8 | - For documentation, usage, and examples, see: http://documentcloud.github.com/jammit/ 9 | - To suggest a feature or report a bug: http://github.com/documentcloud/jammit/issues/ 10 | - For internal source docs, see: http://documentcloud.github.com/jammit/doc/ 11 | 12 | ## Installation 13 | 14 | `gem install jammit` 15 | 16 | ## License 17 | 18 | Jammit is released under the MIT license (see the LICENSE file). 19 | -------------------------------------------------------------------------------- /test/fixtures/jammed/js_test_with_templates.js: -------------------------------------------------------------------------------- 1 | var myself={sayHi:function(a){console.log("hello, "+a)}};var mandelay={name:function(){return this.constructor.prototype}};myself.sayHi(mandelay.name());(function(){window.JST=window.JST||{};var a=function(c){var b=new Function("obj","var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+c.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(/<%=([\s\S]+?)%>/g,function(d,e){return"',"+e.replace(/\\'/g,"'")+",'"}).replace(/<%([\s\S]+?)%>/g,function(d,e){return"');"+e.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');");return b};window.JST.template1=a('<%= saying_something %>');window.JST.template2=a('<% _([1,2,3]).each(function(num) { %>\n
  • \n <%= num %>\n
  • \n<% }) %>')})(); -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | desc 'Run all tests' 4 | task :test, [:path] do |task, args| 5 | ENV['RAILS_ENV'] = 'test' 6 | $LOAD_PATH.unshift(File.expand_path('test')) 7 | if args[:path] 8 | require_relative args[:path] 9 | else 10 | Dir['test/*/**/test_*.rb'].each {|test| require "./#{test}" } 11 | end 12 | end 13 | 14 | desc 'Generate YARD Documentation' 15 | task :doc do 16 | sh "mv README.md TEMPREADME" 17 | sh "rm -rf doc" 18 | sh "yardoc" 19 | sh "mv TEMPREADME README.md" 20 | end 21 | 22 | namespace :gem do 23 | 24 | desc 'Build and install the jammit gem' 25 | task :install do 26 | sh "gem build jammit.gemspec" 27 | sh "gem install #{Dir['*.gem'].join(' ')} --local --no-ri --no-rdoc" 28 | end 29 | 30 | desc 'Uninstall the jammit gem' 31 | task :uninstall do 32 | sh "gem uninstall -x jammit" 33 | end 34 | 35 | end 36 | 37 | task :default => :test 38 | -------------------------------------------------------------------------------- /doc/frames.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Jammit 8 | 9 | 20 | 26 | 27 | -------------------------------------------------------------------------------- /test/unit/test_compressor.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class CompressorTest < MiniTest::Test 4 | 5 | def setup 6 | Jammit.load_configuration('test/config/assets.yml') 7 | @compressor = Compressor.new 8 | end 9 | 10 | def test_javascript_compression 11 | packed = @compressor.compress_js(glob('test/fixtures/src/*.js')) 12 | expected = File.read('test/fixtures/jammed/js_test.js') 13 | assert packed == expected, "packed: #{packed}\nexpected: #{expected}" 14 | end 15 | 16 | def test_css_compression 17 | packed = @compressor.compress_css(glob('test/fixtures/src/*.css')) 18 | expected = File.read('test/fixtures/jammed/css_test.css') 19 | assert packed == expected, "packed: #{packed}\nexpected: #{expected}" 20 | end 21 | 22 | def test_jst_compilation 23 | packed = @compressor.compile_jst(glob('test/fixtures/src/*.jst')) 24 | expected = File.read('test/fixtures/jammed/jst_test.js') 25 | assert packed == expected, "packed: #{packed}\nexpected: #{expected}" 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /test/fixtures/jammed/css_test-uncompressed.css: -------------------------------------------------------------------------------- 1 | /* Üníc✪de */ 2 | #hello { 3 | color: white; 4 | background: blue; 5 | } 6 | #hello .world { 7 | border: 1px solid red; 8 | margin-left: 10px; 9 | margin-right: 10px; 10 | margin-bottom: 45px; 11 | margin-top: 45px; 12 | } 13 | #another { 14 | color: white; 15 | background: blue; 16 | } 17 | #css .file { 18 | border: 1px solid red; 19 | margin-left: 10px; 20 | margin-right: 10px; 21 | margin-bottom: 45px; 22 | margin-top: 45px; 23 | } 24 | #with_images { 25 | background: url(../embed/asterisk_yellow.png?101); 26 | } 27 | #and_relative_paths { 28 | background: url(../embed/asterisk_orange.png?101); 29 | } 30 | #and_real_urls { 31 | background: url(http://example.com/image.png); 32 | } 33 | @font-face { 34 | font-family: 'DroidSansMonoRegular'; 35 | src: url(../embed/DroidSansMono.eot?101); 36 | src: local('Droid Sans Mono Regular'), local('DroidSansMono'), url(../embed/DroidSansMono.ttf?101) format('truetype'); 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2011 Jeremy Ashkenas, DocumentCloud 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /test/fixtures/jammed/jst_test_nested.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | window.JST = window.JST || {}; 3 | var template = function(str){var fn = new Function('obj', 'var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push(\''+str.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/<%=([\s\S]+?)%>/g,function(match,code){return "',"+code.replace(/\\'/g, "'")+",'";}).replace(/<%([\s\S]+?)%>/g,function(match,code){return "');"+code.replace(/\\'/g, "'").replace(/[\r\n\t]/g,' ')+"__p.push('";}).replace(/\r/g,'\\r').replace(/\n/g,'\\n').replace(/\t/g,'\\t')+"');}return __p.join('');");return fn;}; 4 | window.JST['nested/double_nested/double_nested'] = template('

    <%= hello_world %>

    '); 5 | window.JST['nested/nested1'] = template('<%= saying_something %>'); 6 | window.JST['nested/nested2'] = template('<% _([1,2,3]).each(function(num) { %>\n
  • \n <%= num %>\n
  • \n<% }) %>'); 7 | window.JST['template1'] = template('<%= saying_something %>'); 8 | window.JST['template2'] = template('<% _([1,2,3]).each(function(num) { %>\n
  • \n <%= num %>\n
  • \n<% }) %>'); 9 | })(); -------------------------------------------------------------------------------- /jammit.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = 'jammit' 3 | s.version = '0.7.1' # Keep version in sync with jammit.rb 4 | s.license = 'MIT' 5 | s.date = '2015-10-28' 6 | 7 | s.homepage = "http://documentcloud.github.com/jammit/" 8 | s.summary = "Industrial-strength asset packaging for Rails." 9 | s.description = <<-EOS 10 | Jammit is an industrial-strength asset packaging library for Rails, 11 | providing both the CSS and JavaScript concatenation and compression that 12 | you'd expect, as well as YUI Compressor and Closure Compiler compatibility, 13 | ahead-of-time gzipping, built-in JavaScript template support, and optional 14 | Data-URI / MHTML image embedding. 15 | EOS 16 | 17 | s.authors = ['Jeremy Ashkenas', 'Ted Han', 'Justin Reese'] 18 | s.email = ['opensource@documentcloud.org'] 19 | 20 | s.require_paths = ['lib'] 21 | s.executables = ['jammit'] 22 | 23 | s.extra_rdoc_files = ['README.md'] 24 | s.rdoc_options << '--title' << 'Jammit' << 25 | '--exclude' << 'test' << 26 | '--main' << 'README.md' << 27 | '--all' 28 | 29 | s.add_dependency 'cssmin', ['~> 1.0'] 30 | s.add_dependency 'jsmin', ['~> 1.0'] 31 | 32 | s.files = Dir['lib/**/*', 'bin/*', 'rails/*', 'jammit.gemspec', 'LICENSE', 'README.md'] 33 | end 34 | -------------------------------------------------------------------------------- /lib/jammit/dependencies.rb: -------------------------------------------------------------------------------- 1 | # Standard Library Dependencies: 2 | require 'uri' 3 | require 'erb' 4 | require 'zlib' 5 | require 'yaml' 6 | require 'base64' 7 | require 'pathname' 8 | require 'fileutils' 9 | 10 | # Try Uglifier. 11 | begin 12 | require 'uglifier' 13 | require 'jammit/uglifier' 14 | rescue LoadError 15 | Jammit.javascript_compressors.delete :uglifier 16 | end 17 | 18 | # Try YUI 19 | begin 20 | require 'yui/compressor' 21 | rescue LoadError 22 | Jammit.javascript_compressors.delete :yui 23 | Jammit.css_compressors.delete :yui 24 | end 25 | 26 | # Try Closure. 27 | begin 28 | require 'closure-compiler' 29 | rescue LoadError 30 | Jammit.javascript_compressors.delete :closure 31 | end 32 | 33 | # Try Sass 34 | begin 35 | require 'sass' 36 | require 'jammit/sass_compressor' 37 | rescue LoadError 38 | Jammit.css_compressors.delete :sass 39 | end 40 | 41 | # Load initial configuration before the rest of Jammit. 42 | Jammit.load_configuration(Jammit::DEFAULT_CONFIG_PATH, true) if defined?(Rails) 43 | 44 | # Jammit Core: 45 | require 'jsmin' 46 | require 'cssmin' 47 | require 'jammit/jsmin_compressor' 48 | require 'jammit/cssmin_compressor' 49 | require 'jammit/compressor' 50 | require 'jammit/packager' 51 | 52 | # Jammit Rails Integration: 53 | if defined?(Rails) 54 | require 'jammit/controller' 55 | require 'jammit/helper' 56 | require 'jammit/railtie' 57 | require 'jammit/routes' 58 | end 59 | 60 | -------------------------------------------------------------------------------- /test/unit/command_line_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'zlib' 3 | 4 | class CommandLineTest < MiniTest::Test 5 | 6 | def teardown 7 | begin 8 | FileUtils.rm_r('test/precache') 9 | rescue Errno::ENOENT 10 | end 11 | end 12 | 13 | def test_version_and_help_can_run 14 | assert system('bin/jammit -v') && system('bin/jammit -h') 15 | end 16 | 17 | def test_jammit_precaching 18 | system('bin/jammit -c test/config/assets.yml -o test/precache -u http://www.example.com') 19 | assert PRECACHED_FILES == glob('test/precache/*') 20 | assert Zlib::GzipReader.open('test/precache/css_test-datauri.css.gz') {|f| f.read } == File.read('test/fixtures/jammed/css_test-datauri.css') 21 | assert Zlib::GzipReader.open('test/precache/jst_test.js.gz') {|f| f.read } == File.read('test/fixtures/jammed/jst_test.js') 22 | assert Zlib::GzipReader.open('test/precache/js_test_with_templates.js.gz') {|f| f.read } == File.read('test/fixtures/jammed/js_test_with_templates.js') 23 | end 24 | 25 | def test_lazy_precaching 26 | system('bin/jammit -c test/config/assets.yml -o test/precache -u http://www.example.com') 27 | assert PRECACHED_FILES == glob('test/precache/*') 28 | mtime = File.mtime(PRECACHED_FILES.first) 29 | system('bin/jammit -c test/config/assets.yml -o test/precache -u http://www.example.com') 30 | assert File.mtime(PRECACHED_FILES.first) == mtime 31 | system('bin/jammit -c test/config/assets.yml -o test/precache -u http://www.example.com --force') 32 | assert File.mtime(PRECACHED_FILES.first) > mtime 33 | end 34 | 35 | end 36 | -------------------------------------------------------------------------------- /test/unit/test_in_the_wrong_directory.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class WrongDirectoryTest < MiniTest::Test 4 | 5 | def setup 6 | Jammit.load_configuration('test/config/assets.yml').reload! 7 | @original_dir ||= File.expand_path(Dir.pwd) 8 | Dir.chdir('/') 9 | end 10 | 11 | def teardown 12 | Dir.chdir(@original_dir) 13 | end 14 | 15 | def test_fetching_lists_of_individual_urls 16 | urls = Jammit.packager.individual_urls(:css_test, :css) 17 | assert urls == ['/fixtures/src/test1.css', '/fixtures/src/test2.css', '/fixtures/src/test_fonts.css'] 18 | urls = Jammit.packager.individual_urls(:js_test, :js) 19 | assert urls == ['/fixtures/src/test1.js', '/fixtures/src/test2.js'] 20 | end 21 | 22 | def test_packaging_stylesheets 23 | css = Jammit.packager.pack_stylesheets(:css_test) 24 | assert css == File.read("#{ASSET_ROOT}/fixtures/jammed/css_test.css") 25 | css = Jammit.packager.pack_stylesheets(:css_test, :datauri) 26 | assert css == File.read("#{ASSET_ROOT}/fixtures/jammed/css_test-datauri.css") 27 | css = Jammit.packager.pack_stylesheets(:css_test, :mhtml, 'http://www.example.com') 28 | assert css == File.open("#{ASSET_ROOT}/fixtures/jammed/css_test-mhtml.css", 'rb') {|f| f.read } 29 | end 30 | 31 | def test_packaging_javascripts 32 | js = Jammit.packager.pack_javascripts(:js_test) 33 | assert js == File.read("#{ASSET_ROOT}/fixtures/jammed/js_test.js") 34 | end 35 | 36 | def test_packaging_templates 37 | jst = Jammit.packager.pack_templates(:jst_test) 38 | assert jst == File.read("#{ASSET_ROOT}/fixtures/jammed/jst_test.js") 39 | end 40 | 41 | end 42 | -------------------------------------------------------------------------------- /test/unit/test_jammit_controller.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'active_support' 3 | require 'action_pack' 4 | require 'action_controller' 5 | require 'action_controller/base' 6 | require 'action_controller/test_case' 7 | require 'jammit/controller' 8 | require 'jammit/routes' 9 | require 'action_dispatch' 10 | 11 | class JammitController 12 | def self.controller_path 13 | "jammit" 14 | end 15 | # Tests needs this defined otherwise it will call 16 | # the parent ActionController::UrlFor#url_options 17 | # That method doesn't work since it depends on 18 | # Rail's boot process defining the routes 19 | def url_options 20 | {} 21 | end 22 | end 23 | 24 | class JammitControllerTest < ActionController::TestCase 25 | 26 | def setup 27 | Jammit.load_configuration('test/config/assets.yml') 28 | 29 | # Perform the routing setup that Rails needs to test the controller 30 | @routes = ::ActionDispatch::Routing::RouteSet.new 31 | @routes.draw do 32 | get "/package/:package.:extension", to: 'jammit#package', as: :jammit, 33 | constraints: { extension: /.+/ } 34 | end 35 | end 36 | 37 | def test_package_with_jst 38 | get(:package, params: {package: 'jst_test', extension: 'jst'}) 39 | assert_equal( File.read("#{ASSET_ROOT}/fixtures/jammed/jst_test.js"), @response.body ) 40 | assert_match( /text\/javascript/, @response.headers['Content-Type'] ) 41 | end 42 | 43 | def test_package_with_jst_mixed 44 | get(:package, params: {package: 'js_test_with_templates', extension: 'jst'}) 45 | assert_equal( File.read("#{ASSET_ROOT}/fixtures/jammed/jst_test.js"), @response.body ) 46 | assert_match( /text\/javascript/, @response.headers['Content-Type'] ) 47 | end 48 | 49 | end 50 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | Encoding.default_external = 'ascii' if defined? Encoding 2 | 3 | require 'pry' 4 | require 'logger' 5 | 6 | ASSET_ROOT = File.expand_path(File.dirname(__FILE__)) 7 | 8 | devnull = RUBY_PLATFORM =~ /mswin|mingw|bccwin|wince|emx/ ? 'nul' : '/dev/null' 9 | ENV['RAILS_ENV'] ||= "test" 10 | ENV["RAILS_ASSET_ID"] = "101" 11 | 12 | require './lib/jammit' 13 | Jammit.load_configuration(Jammit::DEFAULT_CONFIG_PATH) 14 | 15 | def glob(g) 16 | Dir.glob(g).sort 17 | end 18 | 19 | require 'minitest/autorun' 20 | 21 | 22 | class MiniTest::Test 23 | 24 | PRECACHED_FILES = %w( 25 | test/precache/css_test-datauri.css 26 | test/precache/css_test-datauri.css.gz 27 | test/precache/css_test-mhtml.css 28 | test/precache/css_test-mhtml.css.gz 29 | test/precache/css_test.css 30 | test/precache/css_test.css.gz 31 | test/precache/css_test_nested-datauri.css 32 | test/precache/css_test_nested-datauri.css.gz 33 | test/precache/css_test_nested-mhtml.css 34 | test/precache/css_test_nested-mhtml.css.gz 35 | test/precache/css_test_nested.css 36 | test/precache/css_test_nested.css.gz 37 | test/precache/js_test.js 38 | test/precache/js_test.js.gz 39 | test/precache/js_test_nested.js 40 | test/precache/js_test_nested.js.gz 41 | test/precache/js_test_with_templates.js 42 | test/precache/js_test_with_templates.js.gz 43 | test/precache/jst_test.js 44 | test/precache/jst_test.js.gz 45 | test/precache/jst_test_nested.js 46 | test/precache/jst_test_nested.js.gz 47 | ) 48 | 49 | PRECACHED_SOURCES = %w( 50 | test/precache/css_test-datauri.css 51 | test/precache/css_test-mhtml.css 52 | test/precache/css_test.css 53 | test/precache/js_test.js 54 | test/precache/jst_test.js 55 | ) 56 | 57 | include Jammit 58 | 59 | end 60 | -------------------------------------------------------------------------------- /doc/file_list.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | File List 19 | 20 | 21 | 22 | 32 |
    33 |

    File List

    34 | 49 | 50 | 51 | 55 |
    56 | 57 | 58 | -------------------------------------------------------------------------------- /doc/top-level-namespace.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Top Level Namespace 8 | 9 | — Jammit 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 63 | 64 | 65 | 66 |

    Top Level Namespace 67 | 68 | 69 | 70 |

    71 | 72 |
    73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 |
    82 |
    83 | 84 |

    Defined Under Namespace

    85 |

    86 | 87 | 88 | Modules: Jammit 89 | 90 | 91 | 92 | 93 |

    94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |
    104 | 105 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /test/unit/test_jammit_helpers.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'action_pack' 3 | require 'action_view' 4 | require 'action_view/base' 5 | require 'action_controller' 6 | require 'action_controller/base' 7 | require 'action_view/test_case' 8 | require 'jammit/controller' 9 | require 'jammit/helper' 10 | 11 | class ActionController::Base 12 | cattr_accessor :asset_host 13 | end 14 | 15 | class JammitHelpersTest < ActionView::TestCase 16 | include ActionView::Helpers::AssetTagHelper 17 | include Jammit::Helper 18 | 19 | # Rails 3.0 compatibility. 20 | if defined?(ActionController::Configuration) 21 | include ActionController::Configuration 22 | extend ActionController::Configuration::ClassMethods 23 | def initialize(*args) 24 | super 25 | @config = ActiveSupport::OrderedOptions.new 26 | @config.merge! ActionView::DEFAULT_CONFIG 27 | end 28 | end 29 | 30 | def params 31 | @debug ? {:debug_assets => true} : {} 32 | end 33 | 34 | def setup 35 | Rails.env = "pretend_this_isnt_test" 36 | Jammit.load_configuration('test/config/assets.yml').reload! 37 | end 38 | 39 | def test_include_stylesheets 40 | File.write('test/fixtures/tags/css_includes.html', include_stylesheets(:css_test) ) 41 | assert_equal File.read('test/fixtures/tags/css_includes.html'), include_stylesheets(:css_test) 42 | end 43 | 44 | def test_include_stylesheets_with_options 45 | assert_equal File.read('test/fixtures/tags/css_print.html'), include_stylesheets(:css_test, :media => 'print') 46 | end 47 | 48 | def test_include_stylesheets_forcing_embed_assets_off 49 | assert_equal File.read('test/fixtures/tags/css_plain_includes.html'), include_stylesheets(:css_test, :embed_assets => false) 50 | end 51 | 52 | def test_include_javascripts 53 | assert_equal '', include_javascripts(:js_test) 54 | end 55 | 56 | def test_include_templates 57 | assert_equal '', include_javascripts(:jst_test) 58 | end 59 | 60 | def test_individual_assets_in_development 61 | Jammit.instance_variable_set(:@package_assets, false) 62 | asset = File.read('test/fixtures/tags/css_individual_includes.html') 63 | assert_equal asset, include_stylesheets(:css_test) 64 | asset = File.read('test/fixtures/tags/js_individual_includes.html') 65 | assert_equal asset, include_javascripts(:js_test_with_templates) 66 | ensure 67 | Jammit.reload! 68 | end 69 | 70 | def test_individual_assets_while_debugging 71 | @debug = true 72 | asset = File.read('test/fixtures/tags/css_individual_includes.html') 73 | assert_equal asset, include_stylesheets(:css_test) 74 | asset = File.read('test/fixtures/tags/js_individual_includes.html') 75 | assert_equal asset, include_javascripts(:js_test_with_templates) 76 | @debug = false 77 | end 78 | 79 | end 80 | -------------------------------------------------------------------------------- /test/fixtures/jammed/css_test-mhtml.css: -------------------------------------------------------------------------------- 1 | /* 2 | Content-Type: multipart/related; boundary="MHTML_MARK" 3 | 4 | --MHTML_MARK 5 | Content-Location: 2-asterisk_orange.png 6 | Content-Type: image/png 7 | Content-Transfer-Encoding: base64 8 | 9 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAKKSURBVDjLpZNdSBRRGIbnzOzubSxBRReBYhTRDziQQlKxbmoKItp0YVRUsBB2UVQsWdkfilHaj6GuZqEkhJaSf6knISqUYIgooogWS2uRwjFd25yZ3Xn7NlKS3bzp4jDMzHne73zPfCMAEP5nzbux6gU5UifwsE+AWSMos89DVczz4xpD8ArjkxUsMW4AwZ7InSWwetJh8Vzo1YzPviNYjfTmQL8rY+KSqI1fFJWYAKrsjjSvgPV4F/DsAGbqFyF0nSVOX2Xu0M3lwKMdCHdlgGDtW5kox23BqGFes2UdBeyD2ZYKgn1Tlcynt6YAPB/TDUkg2PNPB9H1s4pxozWZTlIIgjX9XipVL0CoaW0U9sVINGsF2ahm8l/9OkmWZg3shNWXC/TnwnzgwtdSUR27IDpn942cluSPxZIsRGXpt5eCTINg7Y9pNdy1DejbDjzMhNm+BQSrgXMS/1wi+UdOSQiUOeH32rgwc4PxSH8eMFSECC+A2Z0Ns5PAgXygNxPoTqdrFoz2dMy0bKLTuCk0B6HmjXh3hALINCdZCFYyTFaIKn0mTqa50baZNmZQgAvG/TSMlkjqp5MSHz4h+T8ct+HtYRteFdl5jMTxctFJsjSrLw/hDtfvEL01DQSrBDsXnMToIphPN66H0ZGJL2ckf7ApGejJglazCu+P2XwLBpDp8smG1dS/gonalSDTHjLtm7q1AehyIXA5AS8P2r1xAwhWvtcm0Bjn08Rlg0xrBDvJtHukdBnQuRU6SXxzdDGG9jpiJ3HsvKgEzkpasDEZE3VrMFwszVV6fciuTjWmYLQ8CYN7HNrTQocStwUynUiyWkgWJ9Nzf90Lj115vt/BB3c7vE8KHfNE/gKM7aCNx0eNYwAAAABJRU5ErkJggg== 10 | --MHTML_MARK 11 | Content-Location: 1-asterisk_yellow.png 12 | Content-Type: image/png 13 | Content-Transfer-Encoding: base64 14 | 15 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAJ5SURBVDjLpZPNS1RhFMaff2EWLWo5tGnRaqCFRBAM0cZFwVSQpVHNQAWVMQwaSSZWtimLiKnsO5lEjKzs4y1zRK3oItfMj1FnnJkaUtNrjo45H3eejpCKNa5anMX73vs855zfOS9I4n9i2SHbCpvph8q8A9PNcCzcz76EM9EETj+DmmqENaeBiJ3mRyuzQy5mwyVMKqiFbzNN0MxgKZOd2zj5GMZE/ZL5ooHZAntGW89s7Bw5Ws25llWcfQHrzHPYE/51ZOQ0M4Fiitj4UQdbzhZSb+FJ63ZypJqp7p0UsTf+FN6kvoMMl3GmNY9jj+BckcF8/HoFldLzpZIqxhthJPVdkr2cifdb5sXefyAKLFvyzVJJAssisIxstILZ0DEyeJzpHifHfNBGamFZ+C9yC7bhG7BBxCrZZqWQpoiNP6S1TMBFDh4gA0VMdxfy+0NosftQX+8gGKkBY741HLoGhbnXUOZwKTn+gGa4nOlBN9MDxdJzCTmwj+wvEKPDTPUc5Zx+kOk+NxmqZOJTIXsviYGQVgKLAos/n0CbbIAS0ir1eY9kF4O+3UzpBYzehhaugQpdR3DwKth7EeyqEoO/oYzXwyKwDDN0ipme/VKFi0l9L8M3oYW8SwxWnIKI1XT7Vqb6i/ntLoLTHdulhROcUJsZuJJjCsvEPpyf8m8io5U0VB6FtFNIe6da84XFEcYaNrDzLDw5DUZ9cEwqm6zxGWYGPBTShogtQtoerV0rLA5JKy5+ubya7SdzbKKMyRG7ByPeIfvebKfAWszUdQFavKOI0bqNbCuF4XfneAvzIaStQrpOxEpIL746rQKOD2VQbSXwtLiXg/wNTNvAOhsl8oEAAAAASUVORK5CYII= 16 | 17 | --MHTML_MARK-- 18 | */ 19 | #hello{color:white;background:blue}#hello .world{border:1px solid red;margin-left:10px;margin-right:10px;margin-bottom:45px;margin-top:45px}#another{color:white;background:blue}#css .file{border:1px solid red;margin-left:10px;margin-right:10px;margin-bottom:45px;margin-top:45px}#with_images{background:url(mhtml:http://www.example.com!1-asterisk_yellow.png)}#and_relative_paths{background:url(mhtml:http://www.example.com!2-asterisk_orange.png)}#and_real_urls{background:url(http://example.com/image.png)}@font-face{font-family:'DroidSansMonoRegular';src:url(../embed/DroidSansMono.eot?101);src:local('Droid Sans Mono Regular'),local('DroidSansMono'),url(../embed/DroidSansMono.ttf?101) format('truetype')} -------------------------------------------------------------------------------- /lib/jammit/command_line.rb: -------------------------------------------------------------------------------- 1 | require 'optparse' 2 | require File.expand_path(File.dirname(__FILE__) + '/../jammit') 3 | 4 | module Jammit 5 | 6 | # The @CommandLine@ is able to compress, pre-package, and pre-gzip all the 7 | # assets specified in the configuration file, in order to avoid an initial 8 | # round of slow requests after a fresh deployment. 9 | class CommandLine 10 | 11 | BANNER = <<-EOS 12 | 13 | Usage: jammit OPTIONS 14 | 15 | Run jammit inside a Rails application to compresses all JS, CSS, 16 | and JST according to config/assets.yml, saving the packaged 17 | files and corresponding gzipped versions. 18 | 19 | If you're using "embed_assets", and you wish to precompile the 20 | MHTML stylesheet variants, you must specify the "base-url". 21 | 22 | Options: 23 | EOS 24 | 25 | # The @Jammit::CommandLine@ runs from the contents of @ARGV@. 26 | def initialize 27 | parse_options 28 | ensure_configuration_file 29 | Jammit.package!(@options) 30 | end 31 | 32 | 33 | private 34 | 35 | # Make sure that we have a readable configuration file. The @jammit@ 36 | # command can't run without one. 37 | def ensure_configuration_file 38 | config = @options[:config_paths] 39 | return true if File.exists?(config) && File.readable?(config) 40 | puts "Could not find the asset configuration file \"#{config}\"" 41 | exit(1) 42 | end 43 | 44 | # Uses @OptionParser@ to grab the options: *--output*, *--config*, and 45 | # *--base-url*... 46 | def parse_options 47 | @options = { 48 | :config_paths => Jammit::DEFAULT_CONFIG_PATH, 49 | :output_folder => nil, 50 | :base_url => nil, 51 | :force => false 52 | } 53 | @option_parser = OptionParser.new do |opts| 54 | opts.on('-o', '--output PATH', 'output folder for packages (default: "public/assets")') do |output_folder| 55 | @options[:output_folder] = output_folder 56 | end 57 | opts.on('-c', '--config PATH', 'path to assets.yml (default: "config/assets.yml")') do |config_path| 58 | @options[:config_paths] = config_path 59 | end 60 | opts.on('-u', '--base-url URL', 'base URL for MHTML (ex: "http://example.com")') do |base_url| 61 | @options[:base_url] = base_url 62 | end 63 | opts.on('-f', '--force', 'force a rebuild of all assets') do |force| 64 | @options[:force] = force 65 | end 66 | opts.on('-p', '--packages LIST', 'list of packages to build (ex: "core,ui", default: all)') do |package_names| 67 | @options[:package_names] = package_names.split(/,\s*/).map {|n| n.to_sym } 68 | end 69 | opts.on('-P', '--public-root PATH', 'path to public assets (default: "public")') do |public_root| 70 | puts "Option for PUBLIC_ROOT" 71 | @options[:public_root] = public_root 72 | end 73 | opts.on_tail('-v', '--version', 'display Jammit version') do 74 | puts "Jammit version #{Jammit::VERSION}" 75 | exit 76 | end 77 | end 78 | @option_parser.banner = BANNER 79 | @option_parser.parse!(ARGV) 80 | end 81 | 82 | end 83 | 84 | end -------------------------------------------------------------------------------- /doc/Jammit/Uglifier.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Class: Jammit::Uglifier 8 | 9 | — Jammit 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 63 | 64 | 65 | 66 |

    Class: Jammit::Uglifier 67 | 68 | 69 | 70 |

    71 | 72 |
    73 | 74 |
    Inherits:
    75 |
    76 | Uglifier 77 | 78 |
      79 |
    • Object
    • 80 | 81 | 82 | 83 | 84 | 85 |
    86 | show all 87 | 88 |
    89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
    Defined in:
    99 |
    lib/jammit/uglifier.rb
    100 | 101 |
    102 |
    103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
    115 | 116 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /doc/Jammit/Railtie.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Class: Jammit::Railtie 8 | 9 | — Jammit 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 63 | 64 | 65 | 66 |

    Class: Jammit::Railtie 67 | 68 | 69 | 70 |

    71 | 72 |
    73 | 74 |
    Inherits:
    75 |
    76 | Rails::Railtie 77 | 78 |
      79 |
    • Object
    • 80 | 81 | 82 | 83 | 84 | 85 |
    86 | show all 87 | 88 |
    89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
    Defined in:
    99 |
    lib/jammit/railtie.rb
    100 | 101 |
    102 |
    103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
    115 | 116 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /doc/Jammit/DeprecationError.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Exception: Jammit::DeprecationError 8 | 9 | — Jammit 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 63 | 64 | 65 | 66 |

    Exception: Jammit::DeprecationError 67 | 68 | 69 | 70 |

    71 | 72 |
    73 | 74 |
    Inherits:
    75 |
    76 | StandardError 77 | 78 |
      79 |
    • Object
    • 80 | 81 | 82 | 83 | 84 | 85 |
    86 | show all 87 | 88 |
    89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
    Defined in:
    99 |
    lib/jammit.rb
    100 | 101 |
    102 |
    103 | 104 |

    Overview

    105 |
    106 |

    Jammit raises a DeprecationError if you try to use an outdated feature.

    107 | 108 |
    109 |
    110 |
    111 | 112 | 113 |
    114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 |
    124 | 125 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /doc/Jammit/OutputNotWritable.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Exception: Jammit::OutputNotWritable 8 | 9 | — Jammit 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 63 | 64 | 65 | 66 |

    Exception: Jammit::OutputNotWritable 67 | 68 | 69 | 70 |

    71 | 72 |
    73 | 74 |
    Inherits:
    75 |
    76 | StandardError 77 | 78 |
      79 |
    • Object
    • 80 | 81 | 82 | 83 | 84 | 85 |
    86 | show all 87 | 88 |
    89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
    Defined in:
    99 |
    lib/jammit.rb
    100 | 101 |
    102 |
    103 | 104 |

    Overview

    105 |
    106 |

    Jammit raises an OutputNotWritable exception if the output directory for 107 | cached packages is locked.

    108 | 109 |
    110 |
    111 |
    112 | 113 | 114 |
    115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 |
    125 | 126 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /doc/Jammit/PackageNotFound.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Exception: Jammit::PackageNotFound 8 | 9 | — Jammit 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 63 | 64 | 65 | 66 |

    Exception: Jammit::PackageNotFound 67 | 68 | 69 | 70 |

    71 | 72 |
    73 | 74 |
    Inherits:
    75 |
    76 | NameError 77 | 78 |
      79 |
    • Object
    • 80 | 81 | 82 | 83 | 84 | 85 |
    86 | show all 87 | 88 |
    89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
    Defined in:
    99 |
    lib/jammit.rb
    100 | 101 |
    102 |
    103 | 104 |

    Overview

    105 |
    106 |

    Jammit raises a PackageNotFound exception when a non-existent package is 107 | requested by a browser — rendering a 404.

    108 | 109 |
    110 |
    111 |
    112 | 113 | 114 |
    115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 |
    125 | 126 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /doc/Jammit/MissingConfiguration.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Exception: Jammit::MissingConfiguration 8 | 9 | — Jammit 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 63 | 64 | 65 | 66 |

    Exception: Jammit::MissingConfiguration 67 | 68 | 69 | 70 |

    71 | 72 |
    73 | 74 |
    Inherits:
    75 |
    76 | NameError 77 | 78 |
      79 |
    • Object
    • 80 | 81 | 82 | 83 | 84 | 85 |
    86 | show all 87 | 88 |
    89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 |
    Defined in:
    99 |
    lib/jammit.rb
    100 | 101 |
    102 |
    103 | 104 |

    Overview

    105 |
    106 |

    Jammit raises a MissingConfiguration exception when you try to load the 107 | configuration of an assets.yml file that doesn’t exist, or are missing 108 | a piece of required configuration.

    109 | 110 |
    111 |
    112 |
    113 | 114 | 115 |
    116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 |
    126 | 127 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /test/unit/test_configuration.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class BrokenConfigurationTest < Minitest::Test 4 | 5 | def setup 6 | Jammit.load_configuration('test/config/assets-broken.yml').reload! 7 | @compressor = Compressor.new 8 | end 9 | 10 | def test_loading_a_nonexistent_file 11 | assert_raises(MissingConfiguration) do 12 | Jammit.load_configuration('nonexistent/assets.yml') 13 | end 14 | end 15 | end 16 | 17 | class ConfigurationTest < MiniTest::Test 18 | def test_default_booleans 19 | Jammit.load_configuration('test/config/assets-default.yml') 20 | # Default false 21 | assert !Jammit.embed_assets 22 | assert !Jammit.mhtml_enabled 23 | # Default true 24 | assert Jammit.compress_assets 25 | assert Jammit.rewrite_relative_paths 26 | assert Jammit.gzip_assets 27 | assert Jammit.allow_debugging 28 | end 29 | 30 | 31 | def test_disabled_compression 32 | Jammit.load_configuration('test/config/assets-compression-disabled.yml') 33 | assert !Jammit.compress_assets 34 | assert !Jammit.gzip_assets 35 | @compressor = Compressor.new 36 | # Should not compress js. 37 | packed = @compressor.compress_js(glob('test/fixtures/src/*.js')) 38 | assert_equal File.read('test/fixtures/jammed/js_test-uncompressed.js'), packed 39 | # Nothing should change with jst. 40 | packed = @compressor.compile_jst(glob('test/fixtures/src/*.jst')) 41 | assert_equal File.read('test/fixtures/jammed/jst_test.js'), packed 42 | packed = @compressor.compress_css(glob('test/fixtures/src/*.css')) 43 | assert_equal packed, File.read('test/fixtures/jammed/css_test-uncompressed.css', { encoding: 'UTF-8'}) 44 | end 45 | 46 | def test_css_compression 47 | Jammit.load_configuration('test/config/assets-css.yml').reload! 48 | assert Jammit.compress_assets 49 | assert Jammit.gzip_assets 50 | packed = Compressor.new.compress_css(glob('test/fixtures/src/*.css')) 51 | assert_equal packed, File.read('test/fixtures/jammed/css_test-line-break.css') 52 | end 53 | 54 | def test_erb_configuration 55 | Jammit.load_configuration('test/config/assets-erb.yml') 56 | assert Jammit.compress_assets 57 | packed = Compressor.new.compress_css(glob('test/fixtures/src/*.css')) 58 | assert_equal packed, File.read('test/fixtures/jammed/css_test.css') 59 | end 60 | 61 | def test_css_configuration 62 | Jammit.load_configuration('test/config/assets.yml').reload! 63 | packed = Compressor.new.compress_css(glob('test/fixtures/src/*.css')) 64 | assert_equal packed, File.read('test/fixtures/jammed/css_test.css') 65 | end 66 | 67 | def test_javascript_compression 68 | Jammit.load_configuration('test/config/assets.yml') 69 | packed = Compressor.new.compress_js(glob('test/fixtures/src/*.js')) 70 | assert_equal packed, File.read('test/fixtures/jammed/js_test.js') 71 | end 72 | 73 | def test_jst_compilation 74 | Jammit.load_configuration('test/config/assets.yml') 75 | packed = Compressor.new.compile_jst(glob('test/fixtures/src/*.jst')) 76 | assert_equal packed, File.read('test/fixtures/jammed/jst_test.js') 77 | end 78 | 79 | def test_environment_specific_configuration 80 | Rails.env = 'development' 81 | Jammit.load_configuration('test/config/assets-environment.yml') 82 | 83 | assert !Jammit.compress_assets # Should override with environment specific configuration 84 | assert Jammit.gzip_assets # but keep the general configuration 85 | 86 | Rails.env = 'test' 87 | end 88 | 89 | def test_no_rewrite_relative_paths 90 | Jammit.load_configuration('test/config/assets-no-rewrite-relative-paths.yml') 91 | assert !Jammit.rewrite_relative_paths 92 | packed = Compressor.new.compress_css(glob('test/fixtures/src/*.css')) 93 | assert_equal packed, File.read('test/fixtures/jammed/css_test-no-rewrite-relative-paths.css') 94 | end 95 | 96 | end 97 | -------------------------------------------------------------------------------- /lib/jammit/controller.rb: -------------------------------------------------------------------------------- 1 | require 'rails' 2 | require 'action_controller' 3 | 4 | module Jammit 5 | 6 | # The JammitController is added to your Rails application when the Gem is 7 | # loaded. It takes responsibility for /assets, and dynamically packages any 8 | # missing or uncached asset packages. 9 | class Controller < ActionController::Base 10 | 11 | VALID_FORMATS = [:css, :js] 12 | 13 | SUFFIX_STRIPPER = /-(datauri|mhtml)\Z/ 14 | 15 | NOT_FOUND_PATH = "#{Jammit.public_root}/404.html" 16 | 17 | # The "package" action receives all requests for asset packages that haven't 18 | # yet been cached. The package will be built, cached, and gzipped. 19 | def package 20 | parse_request 21 | template_ext = Jammit.template_extension.to_sym 22 | case @extension 23 | when :js 24 | render :js => (@contents = Jammit.packager.pack_javascripts(@package)) 25 | when template_ext 26 | render :js => (@contents = Jammit.packager.pack_templates(@package)) 27 | when :css 28 | render :text => generate_stylesheets, :content_type => 'text/css' 29 | end 30 | cache_package if perform_caching && (@extension != template_ext) 31 | rescue Jammit::PackageNotFound 32 | package_not_found 33 | end 34 | 35 | 36 | private 37 | 38 | # Tells the Jammit::Packager to cache and gzip an asset package. We can't 39 | # just use the built-in "cache_page" because we need to ensure that 40 | # the timestamp that ends up in the MHTML is also on the cached file. 41 | def cache_package 42 | dir = File.join(page_cache_directory, Jammit.package_path) 43 | Jammit.packager.cache(@package, @extension, @contents, dir, @variant, @mtime) 44 | end 45 | 46 | # Generate the complete, timestamped, MHTML url -- if we're rendering a 47 | # dynamic MHTML package, we'll need to put one URL in the response, and a 48 | # different one into the cached package. 49 | def prefix_url(path) 50 | host = request.port == 80 ? request.host : request.host_with_port 51 | "#{request.protocol}#{host}#{path}" 52 | end 53 | 54 | # If we're generating MHTML/CSS, return a stylesheet with the absolute 55 | # request URL to the client, and cache a version with the timestamped cache 56 | # URL swapped in. 57 | def generate_stylesheets 58 | return @contents = Jammit.packager.pack_stylesheets(@package, @variant) unless @variant == :mhtml 59 | @mtime = Time.now 60 | request_url = prefix_url(request.fullpath) 61 | cached_url = prefix_url(Jammit.asset_url(@package, @extension, @variant, @mtime)) 62 | css = Jammit.packager.pack_stylesheets(@package, @variant, request_url) 63 | @contents = css.gsub(request_url, cached_url) if perform_caching 64 | css 65 | end 66 | 67 | # Extracts the package name, extension (:css, :js), and variant (:datauri, 68 | # :mhtml) from the incoming URL. 69 | def parse_request 70 | pack = params[:package] 71 | @extension = params[:extension].to_sym 72 | raise PackageNotFound unless (VALID_FORMATS + [Jammit.template_extension.to_sym]).include?(@extension) 73 | if Jammit.embed_assets 74 | suffix_match = pack.match(SUFFIX_STRIPPER) 75 | @variant = Jammit.embed_assets && suffix_match && suffix_match[1].to_sym 76 | pack.sub!(SUFFIX_STRIPPER, '') 77 | end 78 | @package = pack.to_sym 79 | end 80 | 81 | # Render the 404 page, if one exists, for any packages that don't. 82 | def package_not_found 83 | return render(:file => NOT_FOUND_PATH, :status => 404) if File.exists?(NOT_FOUND_PATH) 84 | render :text => "

    404: \"#{@package}\" asset package not found.

    ", :status => 404 85 | end 86 | 87 | end 88 | 89 | end 90 | 91 | # Make the Jammit::Controller available to Rails as a top-level controller. 92 | ::JammitController = Jammit::Controller 93 | 94 | if defined?(Rails) && Rails.env.development? 95 | ActionController::Base.class_eval do 96 | append_before_action { Jammit.reload! } 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /lib/jammit/helper.rb: -------------------------------------------------------------------------------- 1 | module Jammit 2 | 3 | # The Jammit::Helper module, which is made available to every view, provides 4 | # helpers for writing out HTML tags for asset packages. In development you 5 | # get the ordered list of source files -- in any other environment, a link 6 | # to the cached packages. 7 | module Helper 8 | 9 | DATA_URI_START = "" unless defined?(DATA_URI_START) 10 | DATA_URI_END = "" unless defined?(DATA_URI_END) 11 | MHTML_START = "" unless defined?(MHTML_END) 13 | 14 | # If embed_assets is turned on, writes out links to the Data-URI and MHTML 15 | # versions of the stylesheet package, otherwise the package is regular 16 | # compressed CSS, and in development the stylesheet URLs are passed verbatim. 17 | def include_stylesheets(*packages) 18 | options = packages.extract_options! 19 | return html_safe(individual_stylesheets(packages, options)) unless should_package? 20 | disabled = (options.delete(:embed_assets) == false) || (options.delete(:embed_images) == false) 21 | return html_safe(packaged_stylesheets(packages, options)) if disabled || !Jammit.embed_assets 22 | return html_safe(embedded_image_stylesheets(packages, options)) 23 | end 24 | 25 | # Writes out the URL to the bundled and compressed javascript package, 26 | # except in development, where it references the individual scripts. 27 | def include_javascripts(*packages) 28 | options = packages.extract_options! 29 | options.merge!(:extname=>false) 30 | html_safe packages.map {|pack| 31 | should_package? ? Jammit.asset_url(pack, :js) : Jammit.packager.individual_urls(pack.to_sym, :js) 32 | }.flatten.map {|pack| 33 | "" 34 | }.join("\n") 35 | end 36 | 37 | # Writes out the URL to the concatenated and compiled JST file -- we always 38 | # have to pre-process it, even in development. 39 | def include_templates(*packages) 40 | raise DeprecationError, "Jammit 0.5+ no longer supports separate packages for templates.\nYou can include your JST alongside your JS, and use include_javascripts." 41 | end 42 | 43 | 44 | private 45 | 46 | def should_package? 47 | Jammit.package_assets && !(Jammit.allow_debugging && params[:debug_assets]) 48 | end 49 | 50 | def html_safe(string) 51 | string.respond_to?(:html_safe) ? string.html_safe : string 52 | end 53 | 54 | # HTML tags, in order, for all of the individual stylesheets. 55 | def individual_stylesheets(packages, options) 56 | tags_with_options(packages, options) {|p| Jammit.packager.individual_urls(p.to_sym, :css) } 57 | end 58 | 59 | # HTML tags for the stylesheet packages. 60 | def packaged_stylesheets(packages, options) 61 | tags_with_options(packages, options) {|p| Jammit.asset_url(p, :css) } 62 | end 63 | 64 | # HTML tags for the 'datauri', and 'mhtml' versions of the packaged 65 | # stylesheets, using conditional comments to load the correct variant. 66 | def embedded_image_stylesheets(packages, options) 67 | datauri_tags = tags_with_options(packages, options) {|p| Jammit.asset_url(p, :css, :datauri) } 68 | ie_tags = Jammit.mhtml_enabled ? 69 | tags_with_options(packages, options) {|p| Jammit.asset_url(p, :css, :mhtml) } : 70 | packaged_stylesheets(packages, options) 71 | [DATA_URI_START, datauri_tags, DATA_URI_END, MHTML_START, ie_tags, MHTML_END].join("\n") 72 | end 73 | 74 | # Generate the stylesheet tags for a batch of packages, with options, by 75 | # yielding each package to a block. 76 | def tags_with_options(packages, options) 77 | packages.dup.map {|package| 78 | yield package 79 | }.flatten.map {|package| 80 | stylesheet_link_tag package, options 81 | }.join("\n") 82 | end 83 | 84 | end 85 | 86 | end 87 | 88 | # Include the Jammit asset helpers in all views, a-la ApplicationHelper. 89 | ::ActionView::Base.send(:include, Jammit::Helper) 90 | -------------------------------------------------------------------------------- /doc/class_list.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Class List 19 | 20 | 21 | 22 | 32 |
    33 |

    Class List

    34 | 49 | 50 | 51 | 56 |
    57 | 58 | 59 | -------------------------------------------------------------------------------- /doc/css/full_list.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; 4 | font-size: 13px; 5 | height: 101%; 6 | overflow-x: hidden; 7 | } 8 | 9 | h1 { padding: 12px 10px; padding-bottom: 0; margin: 0; font-size: 1.4em; } 10 | .clear { clear: both; } 11 | #search { position: absolute; right: 5px; top: 9px; padding-left: 24px; } 12 | #content.insearch #search, #content.insearch #noresults { background: url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAAPr6+pKSkoiIiO7u7sjIyNjY2J6engAAAI6OjsbGxjIyMlJSUuzs7KamppSUlPLy8oKCghwcHLKysqSkpJqamvT09Pj4+KioqM7OzkRERAwMDGBgYN7e3ujo6Ly8vCoqKjY2NkZGRtTU1MTExDw8PE5OTj4+PkhISNDQ0MrKylpaWrS0tOrq6nBwcKysrLi4uLq6ul5eXlxcXGJiYoaGhuDg4H5+fvz8/KKiohgYGCwsLFZWVgQEBFBQUMzMzDg4OFhYWBoaGvDw8NbW1pycnOLi4ubm5kBAQKqqqiQkJCAgIK6urnJyckpKSjQ0NGpqatLS0sDAwCYmJnx8fEJCQlRUVAoKCggICLCwsOTk5ExMTPb29ra2tmZmZmhoaNzc3KCgoBISEiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCAAAACwAAAAAEAAQAAAHaIAAgoMgIiYlg4kACxIaACEJCSiKggYMCRselwkpghGJBJEcFgsjJyoAGBmfggcNEx0flBiKDhQFlIoCCA+5lAORFb4AJIihCRbDxQAFChAXw9HSqb60iREZ1omqrIPdJCTe0SWI09GBACH5BAkIAAAALAAAAAAQABAAAAdrgACCgwc0NTeDiYozCQkvOTo9GTmDKy8aFy+NOBA7CTswgywJDTIuEjYFIY0JNYMtKTEFiRU8Pjwygy4ws4owPyCKwsMAJSTEgiQlgsbIAMrO0dKDGMTViREZ14kYGRGK38nHguHEJcvTyIEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDAggPg4iJAAMJCRUAJRIqiRGCBI0WQEEJJkWDERkYAAUKEBc4Po1GiKKJHkJDNEeKig4URLS0ICImJZAkuQAhjSi/wQyNKcGDCyMnk8u5rYrTgqDVghgZlYjcACTA1sslvtHRgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCQARAtOUoQRGRiFD0kJUYWZhUhKT1OLhR8wBaaFBzQ1NwAlkIszCQkvsbOHL7Y4q4IuEjaqq0ZQD5+GEEsJTDCMmIUhtgk1lo6QFUwJVDKLiYJNUd6/hoEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4uen4ICCA+IkIsDCQkVACWmhwSpFqAABQoQF6ALTkWFnYMrVlhWvIKTlSAiJiVVPqlGhJkhqShHV1lCW4cMqSkAR1ofiwsjJyqGgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCSMhREZGIYYGY2ElYebi56fhyWQniSKAKKfpaCLFlAPhl0gXYNGEwkhGYREUywag1wJwSkHNDU3D0kJYIMZQwk8MjPBLx9eXwuETVEyAC/BOKsuEjYFhoEAIfkECQgAAAAsAAAAABAAEAAAB2eAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4ueICImip6CIQkJKJ4kigynKaqKCyMnKqSEK05StgAGQRxPYZaENqccFgIID4KXmQBhXFkzDgOnFYLNgltaSAAEpxa7BQoQF4aBACH5BAkIAAAALAAAAAAQABAAAAdogACCg4SFggJiPUqCJSWGgkZjCUwZACQkgxGEXAmdT4UYGZqCGWQ+IjKGGIUwPzGPhAc0NTewhDOdL7Ykji+dOLuOLhI2BbaFETICx4MlQitdqoUsCQ2vhKGjglNfU0SWmILaj43M5oEAOwAAAAAAAAAAAA==) no-repeat center left; } 13 | #full_list { padding: 0; list-style: none; margin-left: 0; } 14 | #full_list ul { padding: 0; } 15 | #full_list li { padding: 5px; padding-left: 12px; margin: 0; font-size: 1.1em; list-style: none; } 16 | #noresults { padding: 7px 12px; } 17 | #content.insearch #noresults { margin-left: 7px; } 18 | ul.collapsed ul, ul.collapsed li { display: none; } 19 | ul.collapsed.search_uncollapsed { display: block; } 20 | ul.collapsed.search_uncollapsed li { display: list-item; } 21 | li a.toggle { cursor: default; position: relative; left: -5px; top: 4px; text-indent: -999px; width: 10px; height: 9px; margin-left: -10px; display: block; float: left; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdEVYdENyZWF0aW9uIFRpbWUAMy8xNC8wOeNZPpQAAAE2SURBVDiNrZTBccIwEEXfelIAHUA6CZ24BGaWO+FuzZAK4k6gg5QAdGAq+Bxs2Yqx7BzyL7Llp/VfzZeQhCTc/ezuGzKKnKSzpCxXJM8fwNXda3df5RZETlIt6YUzSQDs93sl8w3wBZxCCE10GM1OcWbWjB2mWgEH4Mfdyxm3PSepBHibgQE2wLe7r4HjEidpnXMYdQPKEMJcsZ4zs2POYQOcaPfwMVOo58zsAdMt18BuoVDPxUJRacELbXv3hUIX2vYmOUvi8C8ydz/ThjXrqKqqLbDIAdsCKBd+Wo7GWa7o9qzOQHVVVXeAbs+yHHCH4aTsaCOQqunmUy1yBUAXkdMIfMlgF5EXLo2OpV/c/Up7jG4hhHcYLgWzAZXUc2b2ixsfvc/RmNNfOXD3Q/oeL9axJE1yT9IOoUu6MGUkAAAAAElFTkSuQmCC) no-repeat bottom left; } 22 | li.collapsed a.toggle { opacity: 0.5; cursor: default; background-position: top left; } 23 | li { color: #888; cursor: pointer; } 24 | li.deprecated { text-decoration: line-through; font-style: italic; } 25 | li.r1 { background: #f0f0f0; } 26 | li.r2 { background: #fafafa; } 27 | li:hover { background: #ddd; } 28 | li small:before { content: "("; } 29 | li small:after { content: ")"; } 30 | li small.search_info { display: none; } 31 | a:link, a:visited { text-decoration: none; color: #05a; } 32 | li.clicked { background: #05a; color: #ccc; } 33 | li.clicked a:link, li.clicked a:visited { color: #eee; } 34 | li.clicked a.toggle { opacity: 0.5; background-position: bottom right; } 35 | li.collapsed.clicked a.toggle { background-position: top right; } 36 | #search input { border: 1px solid #bbb; -moz-border-radius: 3px; -webkit-border-radius: 3px; } 37 | #nav { margin-left: 10px; font-size: 0.9em; display: none; color: #aaa; } 38 | #nav a:link, #nav a:visited { color: #358; } 39 | #nav a:hover { background: transparent; color: #5af; } 40 | .frames #nav span:after { content: ' | '; } 41 | .frames #nav span:last-child:after { content: ''; } 42 | 43 | .frames #content h1 { margin-top: 0; } 44 | .frames li { white-space: nowrap; cursor: normal; } 45 | .frames li small { display: block; font-size: 0.8em; } 46 | .frames li small:before { content: ""; } 47 | .frames li small:after { content: ""; } 48 | .frames li small.search_info { display: none; } 49 | .frames #search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #888; padding-left: 0; padding-right: 24px; } 50 | .frames #content.insearch #search { background-position: center right; } 51 | .frames #search input { width: 110px; } 52 | .frames #nav { display: block; } 53 | 54 | #full_list.insearch li { display: none; } 55 | #full_list.insearch li.found { display: list-item; padding-left: 10px; } 56 | #full_list.insearch li a.toggle { display: none; } 57 | #full_list.insearch li small.search_info { display: block; } 58 | -------------------------------------------------------------------------------- /doc/js/full_list.js: -------------------------------------------------------------------------------- 1 | var inSearch = null; 2 | var searchIndex = 0; 3 | var searchCache = []; 4 | var searchString = ''; 5 | var regexSearchString = ''; 6 | var caseSensitiveMatch = false; 7 | var ignoreKeyCodeMin = 8; 8 | var ignoreKeyCodeMax = 46; 9 | var commandKey = 91; 10 | 11 | RegExp.escape = function(text) { 12 | return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 13 | } 14 | 15 | function fullListSearch() { 16 | // generate cache 17 | searchCache = []; 18 | $('#full_list li').each(function() { 19 | var link = $(this).find('.object_link a'); 20 | if (link.length === 0) return; 21 | var fullName = link.attr('title').split(' ')[0]; 22 | searchCache.push({name:link.text(), fullName:fullName, node:$(this), link:link}); 23 | }); 24 | 25 | $('#search input').keyup(function(event) { 26 | if ((event.keyCode > ignoreKeyCodeMin && event.keyCode < ignoreKeyCodeMax) 27 | || event.keyCode == commandKey) 28 | return; 29 | searchString = this.value; 30 | caseSensitiveMatch = searchString.match(/[A-Z]/) != null; 31 | regexSearchString = RegExp.escape(searchString); 32 | if (caseSensitiveMatch) { 33 | regexSearchString += "|" + 34 | $.map(searchString.split(''), function(e) { return RegExp.escape(e); }). 35 | join('.+?'); 36 | } 37 | if (searchString === "") { 38 | clearTimeout(inSearch); 39 | inSearch = null; 40 | $('ul .search_uncollapsed').removeClass('search_uncollapsed'); 41 | $('#full_list, #content').removeClass('insearch'); 42 | $('#full_list li').removeClass('found').each(function() { 43 | 44 | var link = $(this).find('.object_link a'); 45 | if (link.length > 0) link.text(link.text()); 46 | }); 47 | if (clicked) { 48 | clicked.parents('ul').each(function() { 49 | $(this).removeClass('collapsed').prev().removeClass('collapsed'); 50 | }); 51 | } 52 | highlight(); 53 | } 54 | else { 55 | if (inSearch) clearTimeout(inSearch); 56 | searchIndex = 0; 57 | lastRowClass = ''; 58 | $('#full_list, #content').addClass('insearch'); 59 | $('#noresults').text(''); 60 | searchItem(); 61 | } 62 | }); 63 | 64 | $('#search input').focus(); 65 | $('#full_list').after("
    "); 66 | } 67 | 68 | var lastRowClass = ''; 69 | function searchItem() { 70 | for (var i = 0; i < searchCache.length / 50; i++) { 71 | var item = searchCache[searchIndex]; 72 | var searchName = (searchString.indexOf('::') != -1 ? item.fullName : item.name); 73 | var matchString = regexSearchString; 74 | var matchRegexp = new RegExp(matchString, caseSensitiveMatch ? "" : "i"); 75 | if (searchName.match(matchRegexp) == null) { 76 | item.node.removeClass('found'); 77 | } 78 | else { 79 | item.node.css('padding-left', '10px').addClass('found'); 80 | item.node.parents().addClass('search_uncollapsed'); 81 | item.node.removeClass(lastRowClass).addClass(lastRowClass == 'r1' ? 'r2' : 'r1'); 82 | lastRowClass = item.node.hasClass('r1') ? 'r1' : 'r2'; 83 | item.link.html(item.name.replace(matchRegexp, "$&")); 84 | } 85 | 86 | if (searchCache.length === searchIndex + 1) { 87 | searchDone(); 88 | return; 89 | } 90 | else { 91 | searchIndex++; 92 | } 93 | } 94 | inSearch = setTimeout('searchItem()', 0); 95 | } 96 | 97 | function searchDone() { 98 | highlight(true); 99 | if ($('#full_list li:visible').size() === 0) { 100 | $('#noresults').text('No results were found.').hide().fadeIn(); 101 | } 102 | else { 103 | $('#noresults').text(''); 104 | } 105 | $('#content').removeClass('insearch'); 106 | clearTimeout(inSearch); 107 | inSearch = null; 108 | } 109 | 110 | clicked = null; 111 | function linkList() { 112 | $('#full_list li, #full_list li a:last').click(function(evt) { 113 | if ($(this).hasClass('toggle')) return true; 114 | if (this.tagName.toLowerCase() == "li") { 115 | if ($(this).find('.object_link a').length === 0) { 116 | $(this).children('a.toggle').click(); 117 | return false; 118 | } 119 | var toggle = $(this).children('a.toggle'); 120 | if (toggle.size() > 0 && evt.pageX < toggle.offset().left) { 121 | toggle.click(); 122 | return false; 123 | } 124 | } 125 | if (clicked) clicked.removeClass('clicked'); 126 | var win; 127 | try { 128 | win = window.top.frames.main ? window.top.frames.main : window.parent; 129 | } catch (e) { win = window.parent; } 130 | if (this.tagName.toLowerCase() == "a") { 131 | clicked = $(this).parents('li').addClass('clicked'); 132 | win.location = this.href; 133 | } 134 | else { 135 | clicked = $(this).addClass('clicked'); 136 | win.location = $(this).find('a:last').attr('href'); 137 | } 138 | return false; 139 | }); 140 | } 141 | 142 | function collapse() { 143 | if (!$('#full_list').hasClass('class')) return; 144 | $('#full_list.class a.toggle').click(function() { 145 | $(this).parent().toggleClass('collapsed').next().toggleClass('collapsed'); 146 | highlight(); 147 | return false; 148 | }); 149 | $('#full_list.class ul').each(function() { 150 | $(this).addClass('collapsed').prev().addClass('collapsed'); 151 | }); 152 | $('#full_list.class').children().removeClass('collapsed'); 153 | highlight(); 154 | } 155 | 156 | function highlight(no_padding) { 157 | var n = 1; 158 | $('#full_list li:visible').each(function() { 159 | var next = n == 1 ? 2 : 1; 160 | $(this).removeClass("r" + next).addClass("r" + n); 161 | if (!no_padding && $('#full_list').hasClass('class')) { 162 | $(this).css('padding-left', (10 + $(this).parents('ul').size() * 15) + 'px'); 163 | } 164 | n = next; 165 | }); 166 | } 167 | 168 | function escapeShortcut() { 169 | $(document).keydown(function(evt) { 170 | if (evt.which == 27) { 171 | $('#search_frame', window.top.document).slideUp(100); 172 | $('#search a', window.top.document).removeClass('active inactive'); 173 | $(window.top).focus(); 174 | } 175 | }); 176 | } 177 | 178 | $(escapeShortcut); 179 | $(fullListSearch); 180 | $(linkList); 181 | $(collapse); 182 | -------------------------------------------------------------------------------- /test/unit/test_packager.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'zlib' 3 | 4 | class PackagerTest < MiniTest::Test 5 | def setup 6 | Jammit.load_configuration('test/config/assets.yml').reload! 7 | end 8 | 9 | def teardown 10 | Jammit.set_template_namespace(nil) 11 | Jammit.set_template_extension(nil) 12 | begin 13 | FileUtils.rm_r('test/precache') 14 | rescue Errno::ENOENT 15 | end 16 | end 17 | 18 | def test_fetching_lists_of_individual_urls 19 | urls = Jammit.packager.individual_urls(:css_test, :css) 20 | assert urls == ['/fixtures/src/test1.css', '/fixtures/src/test2.css', '/fixtures/src/test_fonts.css'] 21 | urls = Jammit.packager.individual_urls(:js_test, :js) 22 | assert urls == ['/fixtures/src/test1.js', '/fixtures/src/test2.js'] 23 | urls = Jammit.packager.individual_urls(:js_test_with_templates, :js) 24 | assert urls == ['/fixtures/src/test1.js', '/fixtures/src/test2.js', '/assets/js_test_with_templates.jst'] 25 | end 26 | 27 | def test_fetching_lists_of_nested_urls 28 | urls = Jammit.packager.individual_urls(:css_test_nested, :css) 29 | assert urls == ['/fixtures/src/test1.css', '/fixtures/src/test2.css', '/fixtures/src/test_fonts.css', '/fixtures/src/nested/nested1.css', '/fixtures/src/nested/nested2.css'] 30 | urls = Jammit.packager.individual_urls(:js_test_nested, :js) 31 | assert urls == ['/fixtures/src/test1.js', '/fixtures/src/test2.js', '/fixtures/src/nested/nested1.js', '/fixtures/src/nested/nested2.js'] 32 | urls = Jammit.packager.individual_urls(:jst_test_nested, :js) 33 | assert urls == ['/assets/jst_test_nested.jst'] 34 | end 35 | 36 | def test_packaging_stylesheets 37 | css = Jammit.packager.pack_stylesheets(:css_test) 38 | assert css == File.read('test/fixtures/jammed/css_test.css') 39 | css = Jammit.packager.pack_stylesheets(:css_test, :datauri) 40 | assert css == File.read('test/fixtures/jammed/css_test-datauri.css') 41 | css = Jammit.packager.pack_stylesheets(:css_test, :mhtml, 'http://www.example.com') 42 | assert css == File.open('test/fixtures/jammed/css_test-mhtml.css', 'rb') {|f| f.read } 43 | end 44 | 45 | def test_packaging_javascripts 46 | js = Jammit.packager.pack_javascripts(:js_test) 47 | assert js == File.read('test/fixtures/jammed/js_test.js') 48 | js = Jammit.packager.pack_javascripts(:js_test_with_templates) 49 | assert js == File.read('test/fixtures/jammed/js_test_with_templates.js') 50 | end 51 | 52 | def test_packaging_templates 53 | jst = Jammit.packager.pack_templates(:jst_test) 54 | assert jst == File.read('test/fixtures/jammed/jst_test.js') 55 | end 56 | 57 | def test_packaging_templates_when_mixed_with_javascript 58 | # If you mix in JS with the JST, it shouldn't change the JST output. 59 | jst = Jammit.packager.pack_templates(:js_test_with_templates) 60 | assert jst == File.read('test/fixtures/jammed/jst_test.js') 61 | end 62 | 63 | def test_packaging_templates_with_custom_namespace 64 | Jammit.set_template_namespace('custom_namespace') 65 | jst = Jammit.packager.pack_templates(:jst_test) 66 | assert jst == File.read('test/fixtures/jammed/jst_test-custom-namespace.js') 67 | end 68 | 69 | def test_packaging_templates_nested 70 | jst = Jammit.packager.pack_templates(:jst_test_nested) 71 | assert jst == File.read('test/fixtures/jammed/jst_test_nested.js') 72 | end 73 | 74 | def test_package_caching 75 | css = Jammit.packager.pack_stylesheets(:css_test, :mhtml, 'http://www.example.com') 76 | mtime = Time.now 77 | Jammit.packager.cache(:css_test, :css, css, 'test/public', :mhtml, mtime) 78 | canonical = File.open('test/fixtures/jammed/css_test-mhtml.css', 'rb') {|f| f.read } 79 | assert File.open('test/public/css_test-mhtml.css', 'rb') {|f| f.read } == canonical 80 | assert Zlib::GzipReader.open('test/public/css_test-mhtml.css.gz') {|f| f.read } == canonical 81 | FileUtils.rm(['test/public/css_test-mhtml.css', 'test/public/css_test-mhtml.css.gz']) 82 | end 83 | 84 | def test_precache_all 85 | Jammit.load_configuration('test/config/assets.yml').reload! 86 | Jammit.packager.precache_all('test/precache', 'http://www.example.com') 87 | assert PRECACHED_FILES == glob('test/precache/*') 88 | assert Zlib::GzipReader.open('test/precache/css_test-datauri.css.gz') {|f| f.read } == File.read('test/fixtures/jammed/css_test-datauri.css') 89 | end 90 | 91 | def test_precache_no_gzip 92 | Jammit.load_configuration('test/config/assets-compression-disabled.yml').reload! 93 | Jammit.packager.precache_all('test/precache', 'http://www.example.com') 94 | assert PRECACHED_SOURCES == glob('test/precache/*') 95 | Jammit.load_configuration('test/config/assets.yml').reload! 96 | end 97 | 98 | def test_precache_regenerates_css_variants 99 | Jammit.load_configuration('test/config/assets-compression-disabled.yml').reload! 100 | Jammit.packager.precache_all('test/precache', 'http://www.example.com') 101 | assert_equal PRECACHED_SOURCES, glob('test/precache/*') 102 | 103 | File.unlink("test/precache/css_test-mhtml.css") 104 | File.unlink("test/precache/css_test-datauri.css") 105 | 106 | Jammit.packager.precache_all('test/precache', 'http://www.example.com') 107 | assert_equal PRECACHED_SOURCES, glob('test/precache/*') 108 | end 109 | 110 | def test_exceptions_for_unwritable_directories 111 | return unless File.exists?('text/fixtures/unwritable') 112 | assert_raises(OutputNotWritable) do 113 | Jammit.packager.precache_all('test/fixtures/unwritable') 114 | end 115 | end 116 | 117 | def test_package_helper 118 | FileUtils.rm_rf("test/public/assets/*") 119 | Jammit.package! :config_file => "test/config/assets.yml", :base_url => "http://example.com/" 120 | assert File.exists?("test/public/assets/js_test.js") 121 | assert File.exists?("test/public/assets/css_test.css") 122 | FileUtils.rm_rf("test/public/assets") 123 | end 124 | 125 | def test_packaging_javascripts_with_package_names 126 | FileUtils.rm_rf("test/public/assets/*") 127 | Jammit.package! :config_file => "test/config/assets.yml", :package_names => [:js_test] 128 | assert File.exists?("test/public/assets/js_test.js") 129 | assert File.read('test/public/assets/js_test.js') == File.read('test/fixtures/jammed/js_test_package_names.js') 130 | FileUtils.rm_rf("test/public/assets") 131 | end 132 | 133 | end 134 | -------------------------------------------------------------------------------- /doc/Jammit/Routes.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Module: Jammit::Routes 8 | 9 | — Jammit 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 63 | 64 | 65 | 66 |

    Module: Jammit::Routes 67 | 68 | 69 | 70 |

    71 | 72 |
    73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 |
    Defined in:
    82 |
    lib/jammit/routes.rb
    83 | 84 |
    85 |
    86 | 87 |

    Overview

    88 |
    89 |

    Rails 2.x routing module. Rails 3.x routes are in rails/routes.rb.

    90 | 91 |
    92 |
    93 |
    94 | 95 | 96 |
    97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 |

    105 | Class Method Summary 106 | (collapse) 107 |

    108 | 109 | 134 | 135 | 136 | 137 | 138 |
    139 |

    Class Method Details

    140 | 141 | 142 |
    143 |

    144 | 145 | + (Object) draw(map) 146 | 147 | 148 | 149 | 150 | 151 |

    152 |
    153 |

    Jammit uses a single route in order to slow down Rails’ routing speed 154 | by the absolute minimum. In your config/routes.rb file, call: 155 | Jammit::Routes.draw(map) 156 | Passing in the routing “map” object.

    157 | 158 |
    159 |
    160 |
    161 | 162 | 163 |
    164 | 165 | 180 | 194 | 195 |
    166 |
    167 | 
    168 | 
    169 | 10
    170 | 11
    171 | 12
    172 | 13
    173 | 14
    174 | 15
    175 | 16
    176 | 17
    177 | 18
    178 | 19
    179 |
    181 |
    # File 'lib/jammit/routes.rb', line 10
    182 | 
    183 | def self.draw(map)
    184 |   map.jammit "/#{Jammit.package_path}/:package.:extension", {
    185 |     :controller => 'jammit',
    186 |     :action => 'package',
    187 |     :requirements => {
    188 |       # A hack to allow extension to include "."
    189 |       :extension => /.+/
    190 |     }
    191 |   }
    192 | end
    193 |
    196 |
    197 | 198 |
    199 | 200 |
    201 | 202 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /doc/Jammit/JsminCompressor.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Class: Jammit::JsminCompressor 8 | 9 | — Jammit 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 63 | 64 | 65 | 66 |

    Class: Jammit::JsminCompressor 67 | 68 | 69 | 70 |

    71 | 72 |
    73 | 74 |
    Inherits:
    75 |
    76 | Object 77 | 78 |
      79 |
    • Object
    • 80 | 81 | 82 | 83 |
    84 | show all 85 | 86 |
    87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 |
    Defined in:
    97 |
    lib/jammit/jsmin_compressor.rb
    98 | 99 |
    100 |
    101 | 102 |

    Overview

    103 |
    104 |

    Wraps JSMin compressor to use the same API as the rest of 105 | Jammit’s compressors.

    106 | 107 |
    108 |
    109 |
    110 | 111 | 112 |
    113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 |

    121 | Instance Method Summary 122 | (collapse) 123 |

    124 | 125 | 174 | 175 | 176 |
    177 |

    Constructor Details

    178 | 179 |
    180 |

    181 | 182 | - (JsminCompressor) initialize(options = {}) 183 | 184 | 185 | 186 | 187 | 188 |

    189 |
    190 |

    Returns a new instance of JsminCompressor

    191 | 192 |
    193 |
    194 |
    195 | 196 | 197 |
    198 | 199 | 206 | 212 | 213 |
    200 |
    201 | 
    202 | 
    203 | 4
    204 | 5
    205 |
    207 |
    # File 'lib/jammit/jsmin_compressor.rb', line 4
    208 | 
    209 | def initialize(options = {})
    210 | end
    211 |
    214 |
    215 | 216 |
    217 | 218 | 219 |
    220 |

    Instance Method Details

    221 | 222 | 223 |
    224 |

    225 | 226 | - (Object) compress(js) 227 | 228 | 229 | 230 | 231 | 232 |

    233 | 234 | 242 | 249 | 250 |
    235 |
    236 | 
    237 | 
    238 | 7
    239 | 8
    240 | 9
    241 |
    243 |
    # File 'lib/jammit/jsmin_compressor.rb', line 7
    244 | 
    245 | def compress(js)
    246 |   JSMin.minify(js)
    247 | end
    248 |
    251 |
    252 | 253 |
    254 | 255 |
    256 | 257 | 262 | 263 | 264 | -------------------------------------------------------------------------------- /doc/Jammit/CssminCompressor.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | Class: Jammit::CssminCompressor 8 | 9 | — Jammit 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 63 | 64 | 65 | 66 |

    Class: Jammit::CssminCompressor 67 | 68 | 69 | 70 |

    71 | 72 |
    73 | 74 |
    Inherits:
    75 |
    76 | Object 77 | 78 |
      79 |
    • Object
    • 80 | 81 | 82 | 83 |
    84 | show all 85 | 86 |
    87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 |
    Defined in:
    97 |
    lib/jammit/cssmin_compressor.rb
    98 | 99 |
    100 |
    101 | 102 |

    Overview

    103 |
    104 |

    Wraps CSSMin compressor to use the same API as the rest of 105 | Jammit’s compressors.

    106 | 107 |
    108 |
    109 |
    110 | 111 | 112 |
    113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 |

    121 | Instance Method Summary 122 | (collapse) 123 |

    124 | 125 | 174 | 175 | 176 |
    177 |

    Constructor Details

    178 | 179 |
    180 |

    181 | 182 | - (CssminCompressor) initialize(options = {}) 183 | 184 | 185 | 186 | 187 | 188 |

    189 |
    190 |

    Returns a new instance of CssminCompressor

    191 | 192 |
    193 |
    194 |
    195 | 196 | 197 |
    198 | 199 | 206 | 212 | 213 |
    200 |
    201 | 
    202 | 
    203 | 4
    204 | 5
    205 |
    207 |
    # File 'lib/jammit/cssmin_compressor.rb', line 4
    208 | 
    209 | def initialize(options = {})
    210 | end
    211 |
    214 |
    215 | 216 |
    217 | 218 | 219 |
    220 |

    Instance Method Details

    221 | 222 | 223 |
    224 |

    225 | 226 | - (Object) compress(css) 227 | 228 | 229 | 230 | 231 | 232 |

    233 | 234 | 242 | 249 | 250 |
    235 |
    236 | 
    237 | 
    238 | 7
    239 | 8
    240 | 9
    241 |
    243 |
    # File 'lib/jammit/cssmin_compressor.rb', line 7
    244 | 
    245 | def compress(css)
    246 |   CSSMin.minify(css)
    247 | end
    248 |
    251 |
    252 | 253 |
    254 | 255 |
    256 | 257 | 262 | 263 | 264 | -------------------------------------------------------------------------------- /doc/js/app.js: -------------------------------------------------------------------------------- 1 | function createSourceLinks() { 2 | $('.method_details_list .source_code'). 3 | before("[View source]"); 4 | $('.toggleSource').toggle(function() { 5 | $(this).parent().nextAll('.source_code').slideDown(100); 6 | $(this).text("Hide source"); 7 | }, 8 | function() { 9 | $(this).parent().nextAll('.source_code').slideUp(100); 10 | $(this).text("View source"); 11 | }); 12 | } 13 | 14 | function createDefineLinks() { 15 | var tHeight = 0; 16 | $('.defines').after(" more..."); 17 | $('.toggleDefines').toggle(function() { 18 | tHeight = $(this).parent().prev().height(); 19 | $(this).prev().show(); 20 | $(this).parent().prev().height($(this).parent().height()); 21 | $(this).text("(less)"); 22 | }, 23 | function() { 24 | $(this).prev().hide(); 25 | $(this).parent().prev().height(tHeight); 26 | $(this).text("more..."); 27 | }); 28 | } 29 | 30 | function createFullTreeLinks() { 31 | var tHeight = 0; 32 | $('.inheritanceTree').toggle(function() { 33 | tHeight = $(this).parent().prev().height(); 34 | $(this).parent().toggleClass('showAll'); 35 | $(this).text("(hide)"); 36 | $(this).parent().prev().height($(this).parent().height()); 37 | }, 38 | function() { 39 | $(this).parent().toggleClass('showAll'); 40 | $(this).parent().prev().height(tHeight); 41 | $(this).text("show all"); 42 | }); 43 | } 44 | 45 | function fixBoxInfoHeights() { 46 | $('dl.box dd.r1, dl.box dd.r2').each(function() { 47 | $(this).prev().height($(this).height()); 48 | }); 49 | } 50 | 51 | function searchFrameLinks() { 52 | $('.full_list_link').click(function() { 53 | toggleSearchFrame(this, $(this).attr('href')); 54 | return false; 55 | }); 56 | } 57 | 58 | function toggleSearchFrame(id, link) { 59 | var frame = $('#search_frame'); 60 | $('#search a').removeClass('active').addClass('inactive'); 61 | if (frame.attr('src') == link && frame.css('display') != "none") { 62 | frame.slideUp(100); 63 | $('#search a').removeClass('active inactive'); 64 | } 65 | else { 66 | $(id).addClass('active').removeClass('inactive'); 67 | frame.attr('src', link).slideDown(100); 68 | } 69 | } 70 | 71 | function linkSummaries() { 72 | $('.summary_signature').click(function() { 73 | document.location = $(this).find('a').attr('href'); 74 | }); 75 | } 76 | 77 | function framesInit() { 78 | if (hasFrames) { 79 | document.body.className = 'frames'; 80 | $('#menu .noframes a').attr('href', document.location); 81 | try { 82 | window.top.document.title = $('html head title').text(); 83 | } catch(error) { 84 | // some browsers will not allow this when serving from file:// 85 | // but we don't want to stop the world. 86 | } 87 | } 88 | else { 89 | $('#menu .noframes a').text('frames').attr('href', framesUrl); 90 | } 91 | } 92 | 93 | function keyboardShortcuts() { 94 | if (window.top.frames.main) return; 95 | $(document).keypress(function(evt) { 96 | if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) return; 97 | if (typeof evt.target !== "undefined" && 98 | (evt.target.nodeName == "INPUT" || 99 | evt.target.nodeName == "TEXTAREA")) return; 100 | switch (evt.charCode) { 101 | case 67: case 99: $('#class_list_link').click(); break; // 'c' 102 | case 77: case 109: $('#method_list_link').click(); break; // 'm' 103 | case 70: case 102: $('#file_list_link').click(); break; // 'f' 104 | default: break; 105 | } 106 | }); 107 | } 108 | 109 | function summaryToggle() { 110 | $('.summary_toggle').click(function() { 111 | if (localStorage) { 112 | localStorage.summaryCollapsed = $(this).text(); 113 | } 114 | $('.summary_toggle').each(function() { 115 | $(this).text($(this).text() == "collapse" ? "expand" : "collapse"); 116 | var next = $(this).parent().parent().nextAll('ul.summary').first(); 117 | if (next.hasClass('compact')) { 118 | next.toggle(); 119 | next.nextAll('ul.summary').first().toggle(); 120 | } 121 | else if (next.hasClass('summary')) { 122 | var list = $('