Permalink
Browse files

complete rewrite, bump to v0.1.0

  • Loading branch information...
1 parent 820335d commit 688d87da0d720411f7324e10dfe8944a11862a1a @matthodan committed Dec 12, 2012
Showing with 1,069 additions and 343 deletions.
  1. +23 −11 README.md
  2. +1 −1 jekyll_asset_pipeline.gemspec
  3. +22 −10 lib/jekyll_asset_pipeline.rb
  4. +10 −0 lib/jekyll_asset_pipeline/asset.rb
  5. +0 −150 lib/jekyll_asset_pipeline/bundler.rb
  6. +17 −0 lib/jekyll_asset_pipeline/cache.rb
  7. +3 −1 lib/jekyll_asset_pipeline/compressor.rb
  8. +7 −6 lib/jekyll_asset_pipeline/converter.rb
  9. +0 −19 lib/jekyll_asset_pipeline/css_asset_tag.rb
  10. +5 −0 lib/jekyll_asset_pipeline/extensions/jekyll/static_asset_file.rb
  11. +1 −1 lib/jekyll_asset_pipeline/{asset_file.rb → extensions/jekyll/static_file_extensions.rb}
  12. +6 −0 lib/jekyll_asset_pipeline/extensions/liquid/asset_tag.rb
  13. +14 −0 lib/jekyll_asset_pipeline/extensions/liquid/asset_tags/css_asset_tag.rb
  14. +14 −0 lib/jekyll_asset_pipeline/extensions/liquid/asset_tags/javascript_asset_tag.rb
  15. +53 −0 lib/jekyll_asset_pipeline/extensions/liquid/liquid_block_extensions.rb
  16. +3 −3 lib/jekyll_asset_pipeline/{extendable.rb → extensions/ruby/subclass_tracking.rb}
  17. +0 −19 lib/jekyll_asset_pipeline/javascript_asset_tag.rb
  18. +165 −0 lib/jekyll_asset_pipeline/pipeline.rb
  19. +3 −1 lib/jekyll_asset_pipeline/template.rb
  20. +4 −4 lib/jekyll_asset_pipeline/templates/css_tag_template.rb
  21. +4 −4 lib/jekyll_asset_pipeline/templates/javascript_tag_template.rb
  22. +1 −1 lib/jekyll_asset_pipeline/version.rb
  23. +0 −13 spec/asset_file_spec.rb
  24. +40 −0 spec/asset_spec.rb
  25. +23 −0 spec/cache_spec.rb
  26. +36 −23 spec/compressor_spec.rb
  27. +48 −38 spec/converter_spec.rb
  28. +0 −17 spec/extendable_spec.rb
  29. +11 −0 spec/extensions/jekyll/static_asset_file_extensions_spec.rb
  30. +5 −0 spec/extensions/jekyll/static_asset_file_spec.rb
  31. +6 −0 spec/extensions/liquid/asset_tag_spec.rb
  32. +13 −0 spec/extensions/liquid/asset_tags/css_asset_tag_spec.rb
  33. +13 −0 spec/extensions/liquid/asset_tags/javascript_asset_tag_spec.rb
  34. +151 −0 spec/extensions/liquid/liquid_block_extensions_spec.rb
  35. +21 −0 spec/extensions/ruby/subclass_tracking_spec.rb
  36. +15 −1 spec/helper.rb
  37. +14 −0 spec/helpers/extensions/ruby/module.rb
  38. +182 −0 spec/pipeline_spec.rb
  39. +3 −0 spec/resources/source/_assets/bar.css
  40. +5 −0 spec/resources/source/_assets/bar.scss
  41. +3 −0 spec/resources/source/_assets/foo.css
  42. +5 −0 spec/resources/source/_assets/foo.scss
  43. +35 −0 spec/resources/source/_plugins/jekyll_asset_pipeline.rb
  44. +2 −0 spec/resources/source/css-manifest.yml
  45. +81 −19 spec/template_spec.rb
  46. +1 −1 spec/version_spec.rb
View
@@ -70,8 +70,10 @@ Jekyll Asset Pipeline is extremely easy to add to your Jekyll project and has no
5. Run the `jekyll` command to compile your site. You should see an output that includes the following Jekyll Asset Pipeline status messages.
``` bash
- Asset Pipeline: Compiling bundle... compiled 'global-md5hash.css'.
- Asset Pipeline: Compiling bundle... compiled 'global-md5hash.js'.
+ Asset Pipeline: Processing 'css_asset_tag' manifest 'global'
+ Asset Pipeline: Saved 'global-md5hash.css' to '_site/assets'
+ Asset Pipeline: Processing 'javascript_asset_tag' manifest 'global'
+ Asset Pipeline: Saved 'global-md5hash.js' to '_site/assets'
```
> *If you do not see these messages, check that you have __not__ set Jekyll's "safe" option to "true" in your site's "_config.yml". If the "safe" option is set to "true", Jekyll will not run plugins.*
@@ -92,11 +94,11 @@ In the following example, we will add a preprocessor that converts CoffeeScript
module JekyllAssetPipeline
class CoffeeScriptConverter < JekyllAssetPipeline::Converter
require 'coffee-script'
-
+
def self.filetype
'.coffee'
end
-
+
def convert
return CoffeeScript.compile(@content)
end
@@ -137,9 +139,14 @@ module JekyllAssetPipeline
end
end
```
-
> *Don't forget to install the "sass" gem before you run the `jekyll` command since the above SASS converter requires the "sass" library as a dependency.*
+### Successive Preprocessing
+
+If you would like to run an asset through multiple preprocessors successively, you can do so by naming your assets with nested file extensions. Nest the extensions in the order (right to left) that the asset should be processed. For example, `.css.scss.erb` would first be processed by an "erb" preprocessor then by a "scss" preprocessor before being rendered. This convention is very similar to the convention used by the [Ruby on Rails asset pipeline](http://guides.rubyonrails.org/asset_pipeline.html#preprocessing).
+
+> *Don't forget to define preprocessors for the extensions you use in your filenames, otherwise Jekyll Asset Pipeline will not process your asset.*
+
## Asset Compression
Asset compression allows us to decrease the size of our assets and increase the speed of our site. One of Jekyll Asset Pipeline's key strengths is that it works with __any__ compression library that has a ruby wrapper. Adding asset compression is straightforward, but requires a small amount of additional code.
@@ -243,25 +250,30 @@ That is it! Your asset pipeline used your template to generate an HTML "link" t
## Configuration
-Jekyll Asset Pipeline provides the following two configuration options that can be controlled by adding the following to the end of your project's "\_config.yml" file.
+Jekyll Asset Pipeline provides the following configuration options that can be controlled by adding the following to the end of your project's "\_config.yml" file.
``` yaml
asset_pipeline:
+ bundle: true # Default = true
compress: true # Default = true
output_path: assets # Default = assets
+ gzip: false # Default = false
```
> *If you don't have a "\_config.yml" file, consider reading the [configuration section](https://github.com/mojombo/jekyll/wiki/Configuration) of the Jekyll documentation.*
-
-> The "compress" setting tells Jekyll Asset Pipeline whether or not to compress the bundled assets. It is useful to set this setting to "false" while you are debugging your site's JavaScript. The "output\_path" setting defines where generated bundles should be saved within the "\_site" folder of your project.
+>
+> - The "bundle" setting controls whether Jekyll Asset Pipeline bundles the assets defined in each manifest. If "bundle" is set to false, each asset will be saved individually and individual html tags pointing to each unbundled asset will be produced when you compile your site. It is useful to set this to false while you are debugging your site.
+> - The "compress" setting tells Jekyll Asset Pipeline whether or not to compress the bundled assets. It is useful to set this setting to "false" while you are debugging your site.
+> - The "output\_path" setting defines where generated bundles should be saved within the "\_site" folder of your project.
+> - The "gzip" setting controls whether Jekyll Asset Pipeline saves gzipped versions of your assets alongside un-gzipped versions.
## Contribute
You can contribute to the Jekyll Asset Pipeline by submitting a pull request [via GitHub](https://github.com/matthodan/jekyll-asset-pipeline). I have identified the following areas for improvement:
-- __Tests, tests, tests.__ I'm embarrassed to say that I didn't write a single test while building Jekyll Asset Pipeline. This started as a hack for my blog and quickly grew into a library as I tweaked it to support my own needs.
-- __Handle remote assets.__ Right now, Jekyll Asset Pipeline does not provide any way to include remote assets in bundles unless you save them locally before generating your site. Moshen's [Jekyll Asset Bundler](https://github.com/moshen/jekyll-asset_bundler) allows you to include remote assets, which I thought was pretty interesting. That said, I think it is generally better to keep remote assets separate so that they load asynchronously.
-- __Successive preprocessing.__ Currently you can only preprocess a file once. It would be better if you could run an asset through multiple preprocessors before it gets compressed and bundled.
+- __Tests, tests, tests.__ I'm embarrassed to say that I didn't write a single test while building Jekyll Asset Pipeline. This started as a hack for my blog and quickly grew into a library as I tweaked it to support my own needs. **This project is now fully tested.**
+- __Handle remote assets.__ Right now, Jekyll Asset Pipeline does not provide any way to include remote assets in bundles unless you save them locally before generating your site. Moshen's [Jekyll Asset Bundler](https://github.com/moshen/jekyll-asset_bundler) allows you to include remote assets, which I thought was pretty interesting. That said, I think it is generally better to keep remote assets separate so that they load asynchronously. **After some thought, I've decided that this is not a priority. If you disagree, let me know.**
+- __Successive preprocessing.__ Currently you can only preprocess a file once. It would be better if you could run an asset through multiple preprocessors before it gets compressed and bundled. **As of v0.1.0, Jekyll Asset Pipeline now supports successive preprocessing.**
Feel free to message me on [Twitter](http://twitter.com/matthodan) or [Facebook](http://facebook.com/matthodan).
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
s.version = JekyllAssetPipeline::VERSION
s.date = Time.now
s.summary = 'A powerful asset pipeline for Jekyll that bundles, converts, and minifies CSS and JavaScript assets.'
- s.description = 'Jekyll Asset Pipeline adds asset preprocessing (CoffeeScript, Sass, Less, ERB, etc.), asset compression/minification (Yahoo YUI Compressor, Google Closure Compiler, etc.) to Jekyll. Jekyll Asset Pipeline can be extended to support any preprocessing or compression library.'
+ s.description = 'Adds asset preprocessing (CoffeeScript, Sass, Less, ERB, etc.), asset compression/minification/gzip (Yahoo YUI Compressor, Google Closure Compiler, etc.) to Jekyll.'
s.authors = ['Matt Hodan']
s.email = 'matthew.c.hodan@gmail.com'
s.homepage = 'http://www.matthodan.com/2012/11/22/jekyll-asset-pipeline.html'
@@ -3,31 +3,43 @@
require 'fileutils'
require 'time'
require 'yaml'
+require 'zlib'
# Third-party dependencies
require 'jekyll'
require 'liquid'
# Jekyll extensions
+require 'jekyll_asset_pipeline/extensions/jekyll/static_file_extensions'
+require 'jekyll_asset_pipeline/extensions/jekyll/static_asset_file'
+
+# Liquid extensions
+require 'jekyll_asset_pipeline/extensions/liquid/liquid_block_extensions'
+require 'jekyll_asset_pipeline/extensions/liquid/asset_tag'
+require 'jekyll_asset_pipeline/extensions/liquid/asset_tags/css_asset_tag'
+require 'jekyll_asset_pipeline/extensions/liquid/asset_tags/javascript_asset_tag'
+
+# Ruby extensions
+require 'jekyll_asset_pipeline/extensions/ruby/subclass_tracking'
+
+# Jekyll Asset Pipeline
require 'jekyll_asset_pipeline/version'
-require 'jekyll_asset_pipeline/extendable'
-require 'jekyll_asset_pipeline/asset_file'
-require 'jekyll_asset_pipeline/bundler'
-require 'jekyll_asset_pipeline/compressor'
+require 'jekyll_asset_pipeline/asset'
require 'jekyll_asset_pipeline/converter'
+require 'jekyll_asset_pipeline/compressor'
require 'jekyll_asset_pipeline/template'
require 'jekyll_asset_pipeline/templates/javascript_tag_template'
require 'jekyll_asset_pipeline/templates/css_tag_template'
-
-# Liquid extensions
-require 'jekyll_asset_pipeline/css_asset_tag'
-require 'jekyll_asset_pipeline/javascript_asset_tag'
+require 'jekyll_asset_pipeline/cache'
+require 'jekyll_asset_pipeline/pipeline'
module JekyllAssetPipeline
- # Default configuration settings for Jekyll Asset Bundler
+ # Default configuration settings for Jekyll Asset Pipeline
# Strings used for keys to play nice when merging with _config.yml
DEFAULTS = {
'output_path' => 'assets', # Destination for bundle file (within the '_site' directory)
- 'compress' => true # true = Compress assets, false = Leave assets uncompressed
+ 'bundle' => true, # true = Bundle assets, false = Leave assets unbundled
+ 'compress' => true, # true = Minify assets, false = Leave assets unminified
+ 'gzip' => false # true = Create gzip versions, false = Do not create gzip versions
}
end
@@ -0,0 +1,10 @@
+module JekyllAssetPipeline
+ class Asset
+ def initialize(content, filename)
+ @content = content
+ @filename = filename
+ end
+
+ attr_accessor :content, :filename, :output_path
+ end
+end
@@ -1,150 +0,0 @@
-module JekyllAssetPipeline
- class Bundler
- def initialize(site, prefix, manifest, type)
- @site = site
- @prefix = prefix
- @manifest = manifest
- @type = type
-
- # Initialize configuration hash
- overrides = @site.config['asset_pipeline']
- if overrides.is_a? Hash
- @config = JekyllAssetPipeline::DEFAULTS.merge(overrides)
- else
- @config = JekyllAssetPipeline::DEFAULTS
- end
-
- self.process
- end
-
- # Bundle assets into new file or fetch previously bundled file from cache
- def process
- @@cache ||= {}
-
- self.extract
- self.collect
- self.hashify
-
- if @@cache.has_key?(@hash)
- print "Asset Pipeline: Using cached bundle..."
- @file = @@cache[@hash]
-
- # Prevent Jekyll from cleaning up bundle file
- @site.static_files << JekyllAssetPipeline::AssetFile.new(@site, @site.dest, @config['output_path'], filename)
- puts " used '#{@prefix}-#{@hash[0, 6]}#{@type}'."
- else
- print "Asset Pipeline: Compiling bundle..."
-
- # Create directories if necessary
- path = "#{@site.dest}/#{@config['output_path']}"
- FileUtils::mkpath(path) unless File.directory?(path)
-
- # Create bundle file
- self.convert
- self.bundle
- self.compress if @config['compress']
-
- @file = File.new(File.join(@site.dest, @config['output_path'], filename), "w")
- @file.write(@bundled)
- @file.close
-
- # Prevent Jekyll from cleaning up bundle file
- @site.static_files << JekyllAssetPipeline::AssetFile.new(@site, @site.dest, @config['output_path'], filename)
-
- # Save generated file to cache
- @@cache[@hash] = @file
-
- puts " compiled '#{@prefix}-#{@hash[0, 6]}#{@type}'."
- end
- end
-
- # Extract asset paths from YAML manifest
- def extract
- begin
- @assets = YAML::load(@manifest)
- rescue Exception => e
- puts "Asset Pipeline: Failed to read YAML manifest."
- raise e
- end
- end
-
- # Collect assets from various sources
- def collect
- @assets.map! do |path|
- begin
- file = File.open(File.join(@site.source, path))
- rescue Exception => e
- puts "Asset Pipeline: Failed to open asset file."
- raise e
- end
- file
- end
- end
-
- # Generate a hash id based on asset file paths and last modified dates
- def hashify
- payload = @assets.map do |file|
- "#{file.path}-#{@config['compress'].to_s}-#{file.mtime.to_i.to_s}"
- end
- @hash = Digest::MD5.hexdigest(payload.join)
- end
-
- # Search for a Converter to use to convert a file based on the file extension
- def convert
- @assets.map! do |file|
- converter_klass = JekyllAssetPipeline::Converter.subclasses.select do |c|
- c.filetype == File.extname(file).downcase
- end.last
-
- converted = nil
- unless converter_klass.nil?
- converter = converter_klass.new(file)
- converted = converter.converted
- else
- converted = file.read
- end
- converted
- end
- end
-
- # Bundle all of the separate asset files into one big file
- def bundle
- @bundled = @assets.join("\n")
- end
-
- # Search for a Compressor to use to compress a file based on the output type
- def compress
- compressor_klass = JekyllAssetPipeline::Compressor.subclasses.select do |c|
- c.filetype == @type
- end.last
-
- unless compressor_klass.nil?
- compressor = compressor_klass.new(@bundled)
- @bundled = compressor.compressed
- end
- end
-
- # Return filename of bundle
- def filename
- "#{@prefix}-#{@hash}#{@type}"
- end
-
- # Return an HTML tag that points to the bundle file
- def html_tag
- path = @config['output_path']
-
- template_klass = JekyllAssetPipeline::Template.subclasses.select do |t|
- t.filetype == @type
- end.sort! { |a, b| b.priority <=> a.priority }.last
-
- template = nil
- unless template_klass.nil?
- template = template_klass.new(path, filename)
- @html_tag = template.html
- else
- # Return link to file if no template exists
- return "<a href='/#{path}/#{filename}'>AssetPipeline: No template available for '#{filename}'</a>"
- end
- end
- end
-end
@@ -0,0 +1,17 @@
+module JekyllAssetPipeline
+ class Cache
+ @@cache = {}
+
+ def self.add(key, value)
+ @@cache[key] = value
+ end
+
+ def self.has_key?(key)
+ @@cache.has_key?(key)
+ end
+
+ def self.get(key)
+ @@cache[key]
+ end
+ end
+end
@@ -1,5 +1,7 @@
module JekyllAssetPipeline
- class Compressor < JekyllAssetPipeline::Extendable
+ class Compressor
+ extend JekyllAssetPipeline::SubclassTracking
+
def initialize(content)
@content = content
begin
@@ -1,13 +1,14 @@
module JekyllAssetPipeline
- class Converter < JekyllAssetPipeline::Extendable
- def initialize(file)
- @file = file
- @content = file.read
- @type = File.extname(@file).downcase
+ class Converter
+ extend JekyllAssetPipeline::SubclassTracking
+
+ def initialize(asset)
+ @content = asset.content
+ @type = File.extname(asset.filename).downcase
begin
@converted = self.convert
rescue Exception => e
- puts "Failed to convert asset '#{@file.path}'."
+ puts "Failed to convert asset '#{asset.filename}'."
raise e
end
end
@@ -1,19 +0,0 @@
-module JekyllAssetPipeline
- class CssAssetTag < Liquid::Block
- def render(context)
- # Get YAML manifest from Liquid block
- manifest = @nodelist.first
- prefix = @markup.lstrip.rstrip
-
- # Compile bundle based on manifest
- site = context.registers[:site]
- bundle = JekyllAssetPipeline::Bundler.new(site, prefix, manifest, '.css')
-
- # Return HTML tag linked to bundle
- return bundle.html_tag
- end
- end
-
- # Register CssAssetTag tag with Liquid
- Liquid::Template.register_tag('css_asset_tag', JekyllAssetPipeline::CssAssetTag)
-end
@@ -0,0 +1,5 @@
+module JekyllAssetPipeline
+ class StaticAssetFile < ::Jekyll::StaticFile
+ include JekyllAssetPipeline::JekyllStaticFileExtensions
+ end
+end
@@ -1,5 +1,5 @@
module JekyllAssetPipeline
- class AssetFile < Jekyll::StaticFile
+ module JekyllStaticFileExtensions
# Override #write method since the asset file is dynamically created
def write(dest)
true
@@ -0,0 +1,6 @@
+module JekyllAssetPipeline
+ class AssetTag < ::Liquid::Block
+ extend JekyllAssetPipeline::LiquidBlockExtensions::ClassMethods
+ include JekyllAssetPipeline::LiquidBlockExtensions
+ end
+end
Oops, something went wrong.

0 comments on commit 688d87d

Please sign in to comment.