├── 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 |
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 | Class: Jammit::Uglifier
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | - Inherits:
75 | -
76 | Uglifier
77 |
78 |
79 | - Object
80 |
81 | - Uglifier
82 |
83 | - Jammit::Uglifier
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 | Class: Jammit::Railtie
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | - Inherits:
75 | -
76 | Rails::Railtie
77 |
78 |
79 | - Object
80 |
81 | - Rails::Railtie
82 |
83 | - Jammit::Railtie
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 | Exception: Jammit::DeprecationError
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | - Inherits:
75 | -
76 | StandardError
77 |
78 |
79 | - Object
80 |
81 | - StandardError
82 |
83 | - Jammit::DeprecationError
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 | Exception: Jammit::OutputNotWritable
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | - Inherits:
75 | -
76 | StandardError
77 |
78 |
79 | - Object
80 |
81 | - StandardError
82 |
83 | - Jammit::OutputNotWritable
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 | Exception: Jammit::PackageNotFound
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | - Inherits:
75 | -
76 | NameError
77 |
78 |
79 | - Object
80 |
81 | - NameError
82 |
83 | - Jammit::PackageNotFound
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 | Exception: Jammit::MissingConfiguration
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | - Inherits:
75 | -
76 | NameError
77 |
78 |
79 | - Object
80 |
81 | - NameError
82 |
83 | - Jammit::MissingConfiguration
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 => "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 |
110 |
111 | -
112 |
113 |
114 | + (Object) draw(map)
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
Jammit uses a single route in order to slow down Rails’ routing speed by the absolute minimum.
129 |
130 |
131 |
132 |
133 |
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 |
166 |
167 |
168 |
169 | 10
170 | 11
171 | 12
172 | 13
173 | 14
174 | 15
175 | 16
176 | 17
177 | 18
178 | 19
179 | |
180 |
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 | :extension => /.+/
190 | }
191 | }
192 | end
193 | |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
207 |
208 |
209 |
--------------------------------------------------------------------------------
/doc/Jammit/JsminCompressor.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 | Class: Jammit::JsminCompressor
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | - Inherits:
75 | -
76 | Object
77 |
78 |
79 | - Object
80 |
81 | - Jammit::JsminCompressor
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 |
126 |
127 | -
128 |
129 |
130 | - (Object) compress(js)
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | -
150 |
151 |
152 | - (JsminCompressor) initialize(options = {})
153 |
154 |
155 |
156 |
157 |
158 |
159 | constructor
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
A new instance of JsminCompressor.
169 |
170 |
171 |
172 |
173 |
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 |
200 |
201 |
202 |
203 | 4
204 | 5
205 | |
206 |
207 | # File 'lib/jammit/jsmin_compressor.rb', line 4
208 |
209 | def initialize(options = {})
210 | end
211 | |
212 |
213 |
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 |
235 |
236 |
237 |
238 | 7
239 | 8
240 | 9
241 | |
242 |
243 | # File 'lib/jammit/jsmin_compressor.rb', line 7
244 |
245 | def compress(js)
246 | JSMin.minify(js)
247 | end
248 | |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
262 |
263 |
264 |
--------------------------------------------------------------------------------
/doc/Jammit/CssminCompressor.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 | Class: Jammit::CssminCompressor
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | - Inherits:
75 | -
76 | Object
77 |
78 |
79 | - Object
80 |
81 | - Jammit::CssminCompressor
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 |
126 |
127 | -
128 |
129 |
130 | - (Object) compress(css)
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | -
150 |
151 |
152 | - (CssminCompressor) initialize(options = {})
153 |
154 |
155 |
156 |
157 |
158 |
159 | constructor
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
A new instance of CssminCompressor.
169 |
170 |
171 |
172 |
173 |
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 |
200 |
201 |
202 |
203 | 4
204 | 5
205 | |
206 |
207 | # File 'lib/jammit/cssmin_compressor.rb', line 4
208 |
209 | def initialize(options = {})
210 | end
211 | |
212 |
213 |
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 |
235 |
236 |
237 |
238 | 7
239 | 8
240 | 9
241 | |
242 |
243 | # File 'lib/jammit/cssmin_compressor.rb', line 7
244 |
245 | def compress(css)
246 | CSSMin.minify(css)
247 | end
248 | |
249 |
250 |
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("Class: Jammit::SassCompressor
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | - Inherits:
75 | -
76 | Object
77 |
78 |
79 | - Object
80 |
81 | - Jammit::SassCompressor
82 |
83 |
84 | show all
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | - Defined in:
97 | - lib/jammit/sass_compressor.rb
98 |
99 |
100 |
101 |
102 |
Overview
103 |
104 |
Wraps sass’ css 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 |
126 |
127 | -
128 |
129 |
130 | - (Object) compress(css)
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
Compresses css using sass’ CSS parser, and returns the compressed css.
145 |
146 |
147 |
148 |
149 | -
150 |
151 |
152 | - (SassCompressor) initialize(options = {})
153 |
154 |
155 |
156 |
157 |
158 |
159 | constructor
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
Creates a new sass compressor.
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
Constructor Details
178 |
179 |
180 |
181 |
182 | - (SassCompressor) initialize(options = {})
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
Creates a new sass compressor. Jammit::SassCompressor doesn’t use
191 | any options, the options parameter is there for API
192 | compatibility.
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 | 7
206 | 8
207 | |
208 |
209 | # File 'lib/jammit/sass_compressor.rb', line 7
210 |
211 | def initialize(options = {})
212 | end
213 | |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
Instance Method Details
223 |
224 |
225 |
226 |
227 |
228 | - (Object) compress(css)
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
Compresses css using sass’ CSS parser, and returns the
237 | compressed css.
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 | 12
251 | 13
252 | 14
253 | |
254 |
255 | # File 'lib/jammit/sass_compressor.rb', line 12
256 |
257 | def compress(css)
258 | ::Sass::Engine.new(css, :syntax => :scss, :style => :compressed).render.strip
259 | end
260 | |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
274 |
275 |
276 |
--------------------------------------------------------------------------------
/lib/jammit/packager.rb:
--------------------------------------------------------------------------------
1 | module Jammit
2 |
3 | # The Jammit::Packager resolves the configuration file into lists of real
4 | # assets that get merged into individual asset packages. Given the compiled
5 | # contents of an asset package, the Packager knows how to cache that package
6 | # with the correct timestamps.
7 | class Packager
8 |
9 | # Set force to false to allow packages to only be rebuilt when their source
10 | # files have changed since the last time their package was built.
11 | attr_accessor :force, :package_names
12 |
13 | # Creating a new Packager will rebuild the list of assets from the
14 | # Jammit.configuration. When assets.yml is being changed on the fly,
15 | # create a new Packager.
16 | def initialize
17 | @force = false
18 | @package_names = nil
19 | @config = {
20 | :css => (Jammit.configuration[:stylesheets] || {}),
21 | :js => (Jammit.configuration[:javascripts] || {})
22 | }
23 | @packages = {
24 | :css => create_packages(@config[:css]),
25 | :js => create_packages(@config[:js])
26 | }
27 | end
28 |
29 | # Ask the packager to precache all defined assets, along with their gzip'd
30 | # versions. In order to prebuild the MHTML stylesheets, we need to know the
31 | # base_url, because IE only supports MHTML with absolute references.
32 | # Unless forced, will only rebuild assets whose source files have been
33 | # changed since their last package build.
34 | def precache_all(output_dir=nil, base_url=nil)
35 | output_dir ||= File.join(Jammit.public_root, Jammit.package_path)
36 | cacheable(:js, output_dir).each {|p| cache(p, 'js', pack_javascripts(p), output_dir) }
37 | cacheable(:css, output_dir).each do |p|
38 | cache(p, 'css', pack_stylesheets(p), output_dir)
39 | if Jammit.embed_assets
40 | cache(p, 'css', pack_stylesheets(p, :datauri), output_dir, :datauri)
41 | if Jammit.mhtml_enabled
42 | raise MissingConfiguration, "A --base-url option is required in order to generate MHTML." unless base_url
43 | mtime = latest_mtime package_for(p, :css)[:paths]
44 | asset_url = "#{base_url}#{Jammit.asset_url(p, :css, :mhtml, mtime)}"
45 | cache(p, 'css', pack_stylesheets(p, :mhtml, asset_url), output_dir, :mhtml, mtime)
46 | end
47 | end
48 | end
49 | end
50 |
51 | # Caches a single prebuilt asset package and gzips it at the highest
52 | # compression level. Ensures that the modification time of both both
53 | # variants is identical, for web server caching modules, as well as MHTML.
54 | def cache(package, extension, contents, output_dir, suffix=nil, mtime=nil)
55 | FileUtils.mkdir_p(output_dir) unless File.exists?(output_dir)
56 | raise OutputNotWritable, "Jammit doesn't have permission to write to \"#{output_dir}\"" unless File.writable?(output_dir)
57 | mtime ||= latest_mtime package_for(package, extension.to_sym)[:paths]
58 | files = []
59 | files << file_name = File.join(output_dir, Jammit.filename(package, extension, suffix))
60 | File.open(file_name, 'wb+') {|f| f.write(contents) }
61 | if Jammit.gzip_assets
62 | files << zip_name = "#{file_name}.gz"
63 | Zlib::GzipWriter.open(zip_name, Zlib::BEST_COMPRESSION) {|f| f.write(contents) }
64 | end
65 | File.utime(mtime, mtime, *files)
66 | end
67 |
68 | # Get the list of individual assets for a package.
69 | def individual_urls(package, extension)
70 | package_for(package, extension)[:urls]
71 | end
72 |
73 | def compressor
74 | @compressor ||= Compressor.new
75 | end
76 |
77 | # Return the compressed contents of a stylesheet package.
78 | def pack_stylesheets(package, variant=nil, asset_url=nil)
79 | compressor.compress_css(package_for(package, :css)[:paths], variant, asset_url)
80 | end
81 |
82 | # Return the compressed contents of a javascript package.
83 | def pack_javascripts(package)
84 | compressor.compress_js(package_for(package, :js)[:paths])
85 | end
86 |
87 | # Return the compiled contents of a JST package.
88 | def pack_templates(package)
89 | compressor.compile_jst(package_for(package, :js)[:paths])
90 | end
91 |
92 |
93 | private
94 |
95 | # Look up a package asset list by name, raising an exception if the
96 | # package has gone missing.
97 | def package_for(package, extension)
98 | pack = @packages[extension] && @packages[extension][package]
99 | pack || not_found(package, extension)
100 | end
101 |
102 | # Absolute globs are absolute -- relative globs are relative to ASSET_ROOT.
103 | # Print a warning if no files were found that match the glob.
104 | def glob_files(glob)
105 | absolute =
106 | paths = if Pathname.new(glob).absolute?
107 | Dir[glob].sort
108 | else
109 | search_paths = (Jammit.asset_roots).map{ |path| File.join(path, glob) }
110 | Dir[*search_paths].sort
111 | end
112 | Jammit.warn("No assets match '#{glob}'") if paths.empty?
113 | paths
114 | end
115 |
116 | # In Rails, the difference between a path and an asset URL is "public".
117 | def path_to_url
118 | prefix = Jammit.asset_roots.map{ |path| Regexp.escape(path) }.uniq.join("|")
119 | @path_to_url ||= /\A(#{prefix})(\/?#{Regexp.escape(Jammit.public_root.sub(/#{prefix}/, ''))})?/
120 | end
121 |
122 | # Get the latest mtime of a list of files (plus the config path).
123 | def latest_mtime(paths=[])
124 | paths += Jammit.config_paths
125 | paths.map {|p| File.mtime(p) }.max || Time.now
126 | end
127 |
128 | # Return a list of all of the packages that should be cached. If "force" is
129 | # true, this is all of them -- otherwise only the packages that are missing
130 | # or whose source files have changed since the last package build.
131 | def cacheable(extension, output_dir)
132 | names = @packages[extension].keys
133 | names = names.select {|n| @package_names.include? n } if @package_names
134 | config_mtime = latest_mtime
135 | return names if @force
136 | return names.select do |name|
137 | pack = package_for(name, extension)
138 | cached = [Jammit.filename(name, extension)]
139 | if extension == :css
140 | cached.push Jammit.filename(name, extension, :datauri) if Jammit.embed_assets
141 | cached.push Jammit.filename(name, extension, :mhtml) if Jammit.mhtml_enabled
142 | end
143 | cached.map! {|file| File.join(output_dir, file) }
144 | if cached.any? {|file| !File.exists?(file) }
145 | true
146 | else
147 | since = cached.map {|file| File.mtime(file) }.min
148 | config_mtime > since || pack[:paths].any? {|src| File.mtime(src) > since }
149 | end
150 | end
151 | end
152 |
153 | # Compiles the list of assets that goes into each package. Runs an
154 | # ordered list of Dir.globs, taking the merged unique result.
155 | # If there are JST files in this package we need to add an extra
156 | # path for when package_assets is off (e.g. in a dev environment).
157 | # This package (e.g. /assets/package-name.jst) will never exist as
158 | # an actual file but will be dynamically generated by Jammit on
159 | # every request.
160 | def create_packages(config)
161 | packages = {}
162 | return packages if !config
163 | config.each do |name, globs|
164 | globs ||= []
165 | packages[name] = {}
166 | paths = globs.flatten.uniq.map {|glob| glob_files(glob) }.flatten.uniq
167 | packages[name][:paths] = paths
168 | if !paths.grep(Jammit.template_extension_matcher).empty?
169 | packages[name][:urls] = paths.grep(JS_EXTENSION).map {|path| path.sub(path_to_url, '') }
170 | packages[name][:urls] += [Jammit.asset_url(name, Jammit.template_extension)]
171 | else
172 | packages[name][:urls] = paths.map {|path| path.sub(path_to_url, '') }
173 | end
174 | end
175 | packages
176 | end
177 |
178 | # Raise a PackageNotFound exception for missing packages...
179 | def not_found(package, extension)
180 | raise PackageNotFound, "assets.yml does not contain a \"#{package}\" #{extension.to_s.upcase} package"
181 | end
182 |
183 | end
184 |
185 | end
186 |
--------------------------------------------------------------------------------
/doc/index.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |