Created
May 16, 2012 17:55
-
-
Save robharper/2712617 to your computer and use it in GitHub Desktop.
Using rake-pipeline and a modified 'Neuter' filter for JS library development
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "rake-pipeline-web-filters" | |
require "neuter_plus_filter" | |
input 'src' do | |
output 'build' | |
match '**/main.js' do | |
filter(Rake::Pipeline::Web::ExtraFilters::NeuterPlusFilter, | |
# Possibly depend on JS files within same or subdirectories | |
:additional_dependencies => proc { |input| | |
Dir.glob(File.join(File.dirname(input.fullpath),'**','*.js')) | |
}, | |
# Append .js to module names to resolve filenames | |
:path_transform => proc { |path, input| | |
path + '.js' | |
}, | |
# Output eval'd strings when in development mode | |
:string_code => development? | |
) do |filename| | |
# Use the directory name that contains the main.js for the output filename | |
filename.gsub('/main.js', '.js') | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# This is an extension of the neuter filter by Peter Wagenet | |
# https://github.com/wycats/rake-pipeline-web-filters/blob/master/lib/rake-pipeline-web-filters/neuter_filter.rb | |
# | |
# It adds the capability to optionally output eval'd string representations of the code (plus @sourceURL annoations) | |
# instead of the raw code itself. This makes it possible to output a development version of a neutered library that | |
# is functionally identical but makes debugging in a webkit/Firefox browser much cleaner by breaking out source files. | |
# | |
module Rake::Pipeline::Web::ExtraFilters | |
class NeuterBatch | |
def initialize(config={}, known_files) | |
@config = config | |
@known_files = known_files | |
@required = [] | |
end | |
def file_wrapper(klass, *args) | |
file = klass.new(*args) | |
file.extend NeuterWrapper | |
file.batch(self) | |
file | |
end | |
def required(req) | |
unless @known_files.include?(req) | |
warn "Included '#{req}', which is not listed in :additional_dependencies. The pipeline may not invalidate properly." | |
end | |
@required << req | |
end | |
def required?(req) | |
@required.include?(req) | |
end | |
def strip_requires(source) | |
requires = [] | |
regexp = @config[:require_regexp] || %r{^\s*require\(['"]([^'"]*)['"]\);?\s*} | |
# FIXME: This $1 may not be reliable with other regexps | |
source.gsub!(regexp){ requires << $1; '' } | |
requires | |
end | |
def transform_path(path, input) | |
@config[:path_transform] ? @config[:path_transform].call(path, input) : path | |
end | |
def output_source(filename, source) | |
code = @config[:closure_wrap] ? "(function() {\n#{source}\n})();\n\n" : source | |
# TODO Allow a proc for customizing sourceURL paths | |
@config[:string_code] ? "eval( #{ "#{code}\n\n//@ sourceURL=#{filename.sub(Dir.pwd, '')}".to_json } );" : code | |
end | |
def filename_comment(input) | |
@config[:filename_comment] ? @config[:filename_comment].call(input) + "\n" : "" | |
end | |
end | |
module NeuterWrapper | |
def batch(batch) | |
@batch = batch | |
@batch.required(fullpath) | |
end | |
def read | |
source = super | |
required_files = @batch.strip_requires(source).map do |req| | |
req_path = @batch.transform_path(req, self) | |
if req_path && !@batch.required?(File.expand_path(req_path, root)) | |
@batch.file_wrapper(self.class, root, req_path, encoding).read | |
else | |
nil | |
end | |
end.compact | |
file = @batch.filename_comment(self) + @batch.output_source(self.fullpath, source) | |
(required_files << file).join("\n\n") | |
end | |
end | |
# A filter that takes files with requires and collapses them into a single | |
# file without requires. Optionally include the required code as eval'd strings | |
# for handy debugging in webkit/FF. | |
class NeuterPlusFilter < Rake::Pipeline::ConcatFilter | |
def initialize(string=nil, config={}, &block) | |
if string.is_a?(Hash) | |
config = string | |
string = nil | |
end | |
@config = config | |
super(string, &block) | |
end | |
def generate_output(inputs, output) | |
inputs.each do |input| | |
known_files = [input.fullpath] + additional_dependencies(input) | |
batch = NeuterBatch.new(@config, known_files) | |
file = batch.file_wrapper(file_wrapper_class, input.root, input.path, input.encoding) | |
output.write file.read | |
end | |
end | |
def additional_dependencies(input) | |
method = @config[:additional_dependencies] | |
method ? method.call(input).map{|p| File.expand_path(p, input.root) } : [] | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment