rake-pipeline-web-filters-fork 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/.travis.yml +11 -0
- data/.yardopts +2 -0
- data/Gemfile +6 -0
- data/README.markdown +58 -0
- data/README.yard +25 -0
- data/Rakefile +10 -0
- data/lib/rake-pipeline-web-filters.rb +31 -0
- data/lib/rake-pipeline-web-filters/cache_buster_filter.rb +42 -0
- data/lib/rake-pipeline-web-filters/chained_filter.rb +116 -0
- data/lib/rake-pipeline-web-filters/coffee_script_filter.rb +41 -0
- data/lib/rake-pipeline-web-filters/filter_with_dependencies.rb +27 -0
- data/lib/rake-pipeline-web-filters/gzip_filter.rb +59 -0
- data/lib/rake-pipeline-web-filters/handlebars_filter.rb +62 -0
- data/lib/rake-pipeline-web-filters/helpers.rb +138 -0
- data/lib/rake-pipeline-web-filters/iife_filter.rb +38 -0
- data/lib/rake-pipeline-web-filters/jade_filter.rb +61 -0
- data/lib/rake-pipeline-web-filters/less_filter.rb +55 -0
- data/lib/rake-pipeline-web-filters/markdown_filter.rb +70 -0
- data/lib/rake-pipeline-web-filters/minispade_filter.rb +63 -0
- data/lib/rake-pipeline-web-filters/neuter_filter.rb +110 -0
- data/lib/rake-pipeline-web-filters/sass_filter.rb +87 -0
- data/lib/rake-pipeline-web-filters/stylus_filter.rb +59 -0
- data/lib/rake-pipeline-web-filters/tilt_filter.rb +70 -0
- data/lib/rake-pipeline-web-filters/uglify_filter.rb +82 -0
- data/lib/rake-pipeline-web-filters/version.rb +9 -0
- data/lib/rake-pipeline-web-filters/yui_css_filter.rb +70 -0
- data/lib/rake-pipeline-web-filters/yui_javascript_filter.rb +59 -0
- data/rake-pipeline-web-filters.gemspec +33 -0
- data/spec/cache_buster_filter_spec.rb +108 -0
- data/spec/chained_filter_spec.rb +79 -0
- data/spec/coffee_script_filter_spec.rb +113 -0
- data/spec/gzip_filter_spec.rb +52 -0
- data/spec/handlebars_filter_spec.rb +73 -0
- data/spec/helpers_spec.rb +146 -0
- data/spec/iife_filter_spec.rb +58 -0
- data/spec/jade_filter_spec.rb +92 -0
- data/spec/less_filter_spec.rb +62 -0
- data/spec/markdown_filter_spec.rb +89 -0
- data/spec/minispade_filter_spec.rb +82 -0
- data/spec/neuter_filter_spec.rb +216 -0
- data/spec/sass_filter_spec.rb +152 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/stylus_filter_spec.rb +72 -0
- data/spec/support/spec_helpers/file_utils.rb +33 -0
- data/spec/support/spec_helpers/filters.rb +37 -0
- data/spec/support/spec_helpers/input_helpers.rb +23 -0
- data/spec/support/spec_helpers/memory_file_wrapper.rb +38 -0
- data/spec/support/spec_helpers/memory_manifest.rb +19 -0
- data/spec/tilt_filter_spec.rb +82 -0
- data/spec/uglify_filter_spec.rb +128 -0
- data/spec/yui_css_filter_spec.rb +91 -0
- data/spec/yui_javascript_filter_spec.rb +71 -0
- metadata +308 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-cfs -r spec_helper.rb
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# Rake::Pipeline::Web::Filters [](http://travis-ci.org/wycats/rake-pipeline-web-filters)
|
2
|
+
|
3
|
+
This project contains a set of rake-pipeline filters for building web
|
4
|
+
apps.
|
5
|
+
|
6
|
+
It includes these filters:
|
7
|
+
|
8
|
+
* Cache Buster - Write a fingerprint into each file name
|
9
|
+
* Coffescript - Convert Coffeescript to Javascript
|
10
|
+
* GZip - Create gzip'd version of your files
|
11
|
+
* Handlebars - Process handlebars templates
|
12
|
+
* IIFE - Wrap source files in Immediately Invoked Function Expressions
|
13
|
+
* Jade - Process Jade templates
|
14
|
+
* LESS - Convert LESS to CSS
|
15
|
+
* Markdown - Convert Markdown to HTML
|
16
|
+
* Minispade - Wrap JS files in Minispade modules
|
17
|
+
* Neuter - Require files in a file and generate one single combined file
|
18
|
+
* SASS - Convert SASS to CSS
|
19
|
+
* Stylus - Convert Stylus to CSS
|
20
|
+
* Tilt - Use Tilt to process
|
21
|
+
* Uglify - Minify JS
|
22
|
+
* YUI CSS - Minify CSS
|
23
|
+
* YUI Javascript - Minify JS
|
24
|
+
|
25
|
+
Here's a quick example of a realistic project's Assetfile:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
# Assetfile
|
29
|
+
require 'rake-pipeline-web-filters'
|
30
|
+
|
31
|
+
output "site"
|
32
|
+
|
33
|
+
input "javascripts" do
|
34
|
+
match "**/*.coffee" do
|
35
|
+
coffee_script
|
36
|
+
end
|
37
|
+
|
38
|
+
match "**/*.js" do
|
39
|
+
minispade
|
40
|
+
concat "application.js"
|
41
|
+
uglify
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
input "stylesheets" do
|
46
|
+
match "**/*.sass" do
|
47
|
+
sass
|
48
|
+
end
|
49
|
+
|
50
|
+
match "**/*.css" do
|
51
|
+
concat "application.css"
|
52
|
+
yui_css
|
53
|
+
end
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
API documentation is hosted at
|
58
|
+
<a href="http://rubydoc.info/github/wycats/rake-pipeline-web-filters/master/file/README.yard">rubydoc.info</a>
|
data/README.yard
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
= Rake::Pipeline::Web::Filters
|
2
|
+
|
3
|
+
Rake::Pipeline::Web::Filters is a collection of filters for Rake::Pipeline
|
4
|
+
for creating pipelines to generate web content.
|
5
|
+
|
6
|
+
= Usage
|
7
|
+
|
8
|
+
In your +Assetfile+:
|
9
|
+
|
10
|
+
!!!ruby
|
11
|
+
require "rake-pipeline-web-filters"
|
12
|
+
|
13
|
+
input "assets"
|
14
|
+
output "public"
|
15
|
+
|
16
|
+
# Take all JS inputs and wrap each of them in code to
|
17
|
+
# register them with the Minispade module loader.
|
18
|
+
match "*.js" do
|
19
|
+
filter Rake::Pipeline::Web::Filters::MinispadeFilter
|
20
|
+
end
|
21
|
+
|
22
|
+
# Take all SCSS inputs and compile them with Sass
|
23
|
+
match "*.scss" do
|
24
|
+
filter Rake::Pipeline::Web::Filters::SassCompiler
|
25
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require "rake-pipeline"
|
2
|
+
|
3
|
+
module Rake
|
4
|
+
class Pipeline
|
5
|
+
module Web
|
6
|
+
module Filters
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
require "rake-pipeline-web-filters/version"
|
13
|
+
require "rake-pipeline-web-filters/cache_buster_filter"
|
14
|
+
require "rake-pipeline-web-filters/filter_with_dependencies"
|
15
|
+
require "rake-pipeline-web-filters/markdown_filter"
|
16
|
+
require "rake-pipeline-web-filters/minispade_filter"
|
17
|
+
require "rake-pipeline-web-filters/neuter_filter"
|
18
|
+
require "rake-pipeline-web-filters/sass_filter"
|
19
|
+
require "rake-pipeline-web-filters/stylus_filter"
|
20
|
+
require "rake-pipeline-web-filters/jade_filter"
|
21
|
+
require "rake-pipeline-web-filters/tilt_filter"
|
22
|
+
require "rake-pipeline-web-filters/coffee_script_filter"
|
23
|
+
require "rake-pipeline-web-filters/yui_javascript_filter"
|
24
|
+
require "rake-pipeline-web-filters/yui_css_filter"
|
25
|
+
require "rake-pipeline-web-filters/gzip_filter"
|
26
|
+
require "rake-pipeline-web-filters/uglify_filter"
|
27
|
+
require "rake-pipeline-web-filters/chained_filter"
|
28
|
+
require "rake-pipeline-web-filters/less_filter"
|
29
|
+
require "rake-pipeline-web-filters/handlebars_filter"
|
30
|
+
require "rake-pipeline-web-filters/iife_filter"
|
31
|
+
require "rake-pipeline-web-filters/helpers"
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Rake::Pipeline::Web::Filters
|
2
|
+
# A filter that inserts a cache-busting key into the outputted file name.
|
3
|
+
#
|
4
|
+
# @example
|
5
|
+
# !!!ruby
|
6
|
+
# Rake::Pipeline.build do
|
7
|
+
# input "app/assets"
|
8
|
+
# output "public"
|
9
|
+
#
|
10
|
+
# filter Rake::Pipeline::Web::Filters::CacheBusterFilter
|
11
|
+
# end
|
12
|
+
class CacheBusterFilter < Rake::Pipeline::Filter
|
13
|
+
|
14
|
+
# @return [Proc] the default cache key generator, which
|
15
|
+
# takes the MD5 hash of the input's file name and contents.
|
16
|
+
DEFAULT_KEY_GENERATOR = proc { |input|
|
17
|
+
require 'digest/md5'
|
18
|
+
Digest::MD5.new << input.path << input.read
|
19
|
+
}
|
20
|
+
|
21
|
+
# @param [Proc] key_generator a block to use as the Filter's method of
|
22
|
+
# turning input file wrappers into cache keys; defaults to
|
23
|
+
# +DEFAULT_KEY_GENERATOR+
|
24
|
+
def initialize(&key_generator)
|
25
|
+
key_generator ||= DEFAULT_KEY_GENERATOR
|
26
|
+
output_name_generator = proc { |path, file|
|
27
|
+
parts = path.split('.')
|
28
|
+
index_to_modify = parts.length > 1 ? -2 : -1
|
29
|
+
parts[index_to_modify] << "-#{key_generator.call(file)}"
|
30
|
+
parts.join('.')
|
31
|
+
}
|
32
|
+
super(&output_name_generator)
|
33
|
+
end
|
34
|
+
|
35
|
+
def generate_output(inputs, output)
|
36
|
+
inputs.each do |input|
|
37
|
+
output.write input.read
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Rake::Pipeline::Web::Filters
|
2
|
+
# Implement the FileWrapper API. Because filters are defined
|
3
|
+
# in terms of the FileWrapper API, we can implement an
|
4
|
+
# alternative that doesn't write to disk but still utilizes
|
5
|
+
# the same filter definitions.
|
6
|
+
class MemoryFileWrapper < Struct.new(:root, :path, :encoding, :body)
|
7
|
+
def with_encoding(new_encoding)
|
8
|
+
self.class.new(root, path, new_encoding, body)
|
9
|
+
end
|
10
|
+
|
11
|
+
def fullpath
|
12
|
+
File.join(root, path)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
self.body = ""
|
17
|
+
yield
|
18
|
+
end
|
19
|
+
|
20
|
+
alias read body
|
21
|
+
|
22
|
+
def write(contents)
|
23
|
+
self.body << contents
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# The purpose of ChainedFilter is to enable filters to
|
28
|
+
# be applied to files based upon their file extensions.
|
29
|
+
#
|
30
|
+
# Filters are applied repeatedly to files for each
|
31
|
+
# extension.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
#
|
35
|
+
# filter ChainedFilter, :types => {
|
36
|
+
# :erb => ErbFilter,
|
37
|
+
# :coffee => CoffeeFilter,
|
38
|
+
# :scss => ScssFilter
|
39
|
+
# }
|
40
|
+
#
|
41
|
+
# In this example, files with the extensions +erb+,
|
42
|
+
# +coffee+, and +scss+ will be processed using the
|
43
|
+
# specified filters. If a file has multiple extensions,
|
44
|
+
# all of the filters will be applied.
|
45
|
+
#
|
46
|
+
# For example, with the above filter specification,
|
47
|
+
# a file like +application.js.coffee.erb+ will first
|
48
|
+
# apply the +ErbFilter+, then the +CoffeeFilter+, and
|
49
|
+
# then output +application.js+.
|
50
|
+
#
|
51
|
+
# This filter is largely designed for use with the
|
52
|
+
# {ProjectHelpers#register register} helper, which
|
53
|
+
# will transparently add a ChainedFilter before each
|
54
|
+
# input block with the registered extensions.
|
55
|
+
class ChainedFilter < Rake::Pipeline::Filter
|
56
|
+
attr_reader :filters
|
57
|
+
|
58
|
+
# @param [Hash] options
|
59
|
+
# @option options [Hash] :types
|
60
|
+
# A hash of file extensions and their associated
|
61
|
+
# filters. See the class description for more
|
62
|
+
# information.
|
63
|
+
def initialize(options={}, &block)
|
64
|
+
@filters = options[:types]
|
65
|
+
|
66
|
+
keys = @filters.keys
|
67
|
+
pattern = keys.map { |key| "\\.#{key}" }.join("|")
|
68
|
+
@pattern = Regexp.new("(#{pattern})*$", "i")
|
69
|
+
|
70
|
+
block ||= proc do |input|
|
71
|
+
input.sub(@pattern, '')
|
72
|
+
end
|
73
|
+
|
74
|
+
super(&block)
|
75
|
+
end
|
76
|
+
|
77
|
+
# @private
|
78
|
+
#
|
79
|
+
# Implement +generate_output+
|
80
|
+
def generate_output(inputs, output)
|
81
|
+
inputs.each do |input|
|
82
|
+
output.write process_filters(input)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# @private
|
87
|
+
#
|
88
|
+
# Process an input file by applying the filter for each
|
89
|
+
# extension in the file.
|
90
|
+
def process_filters(input)
|
91
|
+
keys = input.path.match(@pattern)[0].scan(/(?<=\.)\w+/)
|
92
|
+
|
93
|
+
filters = keys.reverse_each.map do |key|
|
94
|
+
@filters[key.to_sym]
|
95
|
+
end
|
96
|
+
|
97
|
+
filters.each do |filter|
|
98
|
+
input = process_with_filter(input, filter)
|
99
|
+
end
|
100
|
+
|
101
|
+
input.read
|
102
|
+
end
|
103
|
+
|
104
|
+
# @private
|
105
|
+
#
|
106
|
+
# Process an individual file with a filter.
|
107
|
+
def process_with_filter(input, filter_class)
|
108
|
+
filter = filter_class.new
|
109
|
+
|
110
|
+
output = MemoryFileWrapper.new("/output", input.path, "UTF-8")
|
111
|
+
output.create { filter.generate_output([input], output) }
|
112
|
+
|
113
|
+
output
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Rake::Pipeline::Web::Filters
|
2
|
+
# A filter that compiles CoffeeScript to JavaScript.
|
3
|
+
class CoffeeScriptFilter < Rake::Pipeline::Filter
|
4
|
+
include Rake::Pipeline::Web::Filters::FilterWithDependencies
|
5
|
+
|
6
|
+
# @return [Hash] a hash of options to pass to CoffeeScript when
|
7
|
+
# rendering.
|
8
|
+
attr_reader :options
|
9
|
+
|
10
|
+
# By default, the CoffeeScriptFilter converts inputs
|
11
|
+
# with the extension +.coffee+ to +.js+.
|
12
|
+
#
|
13
|
+
# @param [Hash] options options to pass to the CoffeeScript
|
14
|
+
# compiler.
|
15
|
+
# @param [Proc] block the output name generator block
|
16
|
+
def initialize(options = {}, &block)
|
17
|
+
block ||= proc { |input| input.sub(/\.coffee$/, '.js') }
|
18
|
+
super(&block)
|
19
|
+
@options = options
|
20
|
+
end
|
21
|
+
|
22
|
+
# The body of the filter. Compile each input file into
|
23
|
+
# a CoffeeScript compiled output file.
|
24
|
+
#
|
25
|
+
# @param [Array] inputs an Array of FileWrapper objects.
|
26
|
+
# @param [FileWrapper] output a FileWrapper object
|
27
|
+
def generate_output(inputs, output)
|
28
|
+
inputs.each do |input|
|
29
|
+
begin
|
30
|
+
output.write CoffeeScript.compile(input, options)
|
31
|
+
rescue ExecJS::Error => error
|
32
|
+
raise error, "Error compiling #{input.path}. #{error.message}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def external_dependencies
|
38
|
+
[ "coffee-script" ]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rake::Pipeline::Web::Filters
|
2
|
+
# A mixin for filters that have dependencies on external
|
3
|
+
# libraries. Include this module in the filter class and
|
4
|
+
# declare a private `external_dependencies` method that
|
5
|
+
# returns an array of strings. Each one will be passed
|
6
|
+
# to `Kernel#require` when an instance of the filter
|
7
|
+
# is created.
|
8
|
+
module FilterWithDependencies
|
9
|
+
|
10
|
+
def initialize(*args, &block)
|
11
|
+
require_dependencies!
|
12
|
+
super(*args, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def require_dependencies!
|
18
|
+
external_dependencies.each do |d|
|
19
|
+
begin
|
20
|
+
require d
|
21
|
+
rescue LoadError => error
|
22
|
+
raise error, "#{self.class} requires #{d}, but it is not available."
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rake-pipeline-web-filters/filter_with_dependencies'
|
2
|
+
|
3
|
+
module Rake::Pipeline::Web::Filters
|
4
|
+
# A filter that gzips input files using zlib
|
5
|
+
#
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# !!!ruby
|
9
|
+
# Rake::Pipeline.build do
|
10
|
+
# input "app/assets", "**/*.js"
|
11
|
+
# output "public"
|
12
|
+
#
|
13
|
+
# # Compress each JS file under the app/assets
|
14
|
+
# # directory.
|
15
|
+
# filter Rake::Pipeline::Web::Filters::GzipFilter
|
16
|
+
# end
|
17
|
+
class GzipFilter < Rake::Pipeline::Filter
|
18
|
+
|
19
|
+
include Rake::Pipeline::Web::Filters::FilterWithDependencies
|
20
|
+
|
21
|
+
processes_binary_files
|
22
|
+
|
23
|
+
# @param [Proc] block a block to use as the Filter's
|
24
|
+
# {#output_name_generator}.
|
25
|
+
def initialize(&block)
|
26
|
+
block ||= proc { |input| input.sub(/\.(.*)$/, '.\1.gz') }
|
27
|
+
super(&block)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Implement the {#generate_output} method required by
|
31
|
+
# the {Filter} API. Compresses each input file with
|
32
|
+
# Zlib.GzipWriter.
|
33
|
+
#
|
34
|
+
# @param [Array<FileWrapper>] inputs an Array of
|
35
|
+
# {FileWrapper} objects representing the inputs to
|
36
|
+
# this filter.
|
37
|
+
# @param [FileWrapper] output a single {FileWrapper}
|
38
|
+
# object representing the output.
|
39
|
+
def generate_output(inputs, output)
|
40
|
+
inputs.each do |input|
|
41
|
+
# gzip input file to stream
|
42
|
+
fakefile = StringIO.new
|
43
|
+
gz = Zlib::GzipWriter.new(fakefile)
|
44
|
+
gz.write(input.read)
|
45
|
+
gz.close
|
46
|
+
|
47
|
+
# send gzipped contents to output
|
48
|
+
output.write fakefile.string
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def external_dependencies
|
55
|
+
[ 'stringio', 'zlib' ]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|