Skip to content

Instantly share code, notes, and snippets.

@wookiehangover
Created November 5, 2011 06:47
Show Gist options
  • Save wookiehangover/1341203 to your computer and use it in GitHub Desktop.
Save wookiehangover/1341203 to your computer and use it in GitHub Desktop.
c2 build script
fs = require 'fs'
{exec} = require 'child_process'
util = require 'util'
uglify = require 'uglify-js'
uglifycss = require 'uglifycss'
growl = require 'growl'
tmpl = require 'jquery-tmpl-jst'
findit = require 'findit'
coffee_src_dir = 'app'
js_src_dir = 'public/js'
coffee_output = "#{coffee_src_dir}/app.coffee"
js_output = "#{js_src_dir}/app.js"
prodCoffeeOpts = "--output #{js_src_dir} --compile #{coffee_output}"
coffeeCompile = (options = "", file) ->
util.log "Compiling #{file}"
exec "coffee #{options} --compile #{file}", (err, stdout, stderr) ->
handleError(err) if err
displayNotification "Compiled #{file}"
displayNotification = (message = '') ->
options =
title: 'CoffeeScript'
image: 'lib/bear-sharktopus.jpeg'
growl.notify message, options
handleError = (error) ->
util.log "\t-----> #{error}"
displayNotification error
uglyStick = ( file, minfile, no_squeeze ) ->
jsp = uglify.parser
pro = uglify.uglify
fs.readFile file, 'utf8', (err, fileContents) ->
#console.log(fileContents)
ast = jsp.parse fileContents # parse code and get the initial AST
ast = pro.ast_mangle ast # get a new AST with mangled names
ast = pro.ast_squeeze ast unless no_squeeze
final_code = pro.gen_code ast # compressed code here
fs.writeFile minfile, final_code
#fs.unlink file, (err) -> handleError(err) if err
message = "Uglified #{minfile}"
console.log message
displayNotification message
###
Build Task
###
task 'build', 'Build production and test CoffeeScript', ->
invoke 'catpile'
invoke 'css'
invoke 'dependencies'
invoke 'templates'
###
CSS
###
css = [
'public/css/base.css'
'public/css/jquery-ui.selectmenu.css'
'public/css/style.css'
]
task 'css', 'concat and minify css', ->
output = uglifycss.processFiles( css )
handler = (err) ->
handleError(err) if err
util.log 'public/css/c2.min.css written'
fs.writeFile 'public/css/c2.min.css', output, 'utf8', handler
###
Dependencies
###
dependencies =
libs: [
'libs/underscore-min'
'libs/backbone-0.5.3'
'libs/jquery-ui-1.8.16.custom.min'
]
plugins: [
'libs/plugins/jquery-ui.selectmenu'
'libs/plugins/jquery.tmpl'
'libs/plugins/jquery.cookie'
'libs/plugins/jquery.strength'
'libs/plugins/jquery.tipsy'
'libs/plugins/jquery.quicksearch'
'libs/plugins/jquery.ba-postmessage'
'libs/plugins/password_strength'
'libs/plugins/ql_cache'
'libs/plugins/region_constants'
]
task 'dependencies', 'build all dependencies for prod', ->
for name, group of dependencies then do (name, group) ->
output = []
remaining = group.length
if !remaining
throw new Error('No files in group')
for file, i in group then do (file, i) ->
fs.readFile "public/js/#{file}.js", 'utf8', (err, data) ->
output[i] = data
console.log "Dependency: #{name}: [#{i + 1}] #{file}.js"
process( output, name ) if --remaining is 0
process = ( data, nm )->
dir = "#{js_src_dir}/src"
filename = "#{dir}/#{nm}.js"
fs.writeFile filename, data.join('\n\n'), 'utf8', (err) ->
handleError(err) if err
console.log "Dependency: #{filename} written"
uglyStick( filename, "#{dir}/#{nm}.min.js" )
###
Templates
###
templates_dir = 'app/templates'
task 'templates', 'Pre compile jQuery Templates', ->
dir = "#{js_src_dir}/src"
tmpl.build templates_dir, ( data ) ->
tmpl.process data, dir, ->
uglyStick( "#{dir}/templates.js", "#{dir}/templates.min.js", true)
###
Application
###
catpile_files = [
'lib/init'
'lib/helpers'
'lib/*'
'models/*'
'collections/*'
'controllers/base_controller'
'controllers/*'
'controllers/application_controller'
'c2'
]
task 'catpile', 'Build a single JavaScript file from prod coffeescript files', ->
console.log "Building #{js_output}"
appContents = []
remaining = catpile_files.length
processFile = ( file, index ) ->
fs.readFile "#{coffee_src_dir}/#{file}", 'utf8', (err, fileContents) ->
handleError(err) if err
appContents.push(fileContents)
console.log "[#{remaining}] #{file}"
if --remaining is 0
writeFile()
traverse = ( dir, sub_dir, index ) ->
remaining += dir.length - 1
for file_or_directory in dir then do (file_or_directory) ->
path = sub_dir + '/' + file_or_directory
stats = fs.statSync( coffee_src_dir + '/' + path )
if stats.isFile() and catpile_files.indexOf( path.replace('.coffee','') ) < 0
processFile( path, index )
else if stats.isDirectory()
traverse( fs.readdirSync(coffee_src_dir + '/' +path), path, index )
writeFile = ->
fs.writeFile coffee_output, appContents.join('\n\n'), 'utf8', (err) ->
handleError(err) if err
exec "coffee #{prodCoffeeOpts}", (err, stdout, stderr) ->
handleError(err) if err
message = "Compiled #{js_output}"
console.log message
displayNotification message
fs.unlink coffee_output, (err) -> handleError(err) if err
uglyStick js_output, "public/js/src/app.min.js"
for file, index in catpile_files then do (file, index) ->
if /\/\*/.test(file)
sub_dir = file.replace('/*', '')
sub_dir_files = fs.readdirSync( coffee_src_dir + '/' + sub_dir )
remaining -= 1
traverse( sub_dir_files, sub_dir, index )
else
processFile( file + '.coffee', index)
###
Watchers
###
task 'watch', 'Watch production and test CoffeeScript', ->
invoke 'watch:templates'
invoke 'watch:coffee'
task 'watch:coffee', 'Watch prod source files and build changes', ->
invoke 'catpile'
files = findit.sync(coffee_src_dir)
for file in files then do (file) ->
stat = fs.statSync( file )
if stat.isDirectory()
return
fs.watchFile file, (curr, prev) ->
if +curr.mtime isnt +prev.mtime
invoke 'catpile'
task 'watch:templates', '', ->
invoke 'templates'
files = findit.sync(templates_dir)
for file in files then do (file) ->
stat = fs.statSync( file )
if stat.isDirectory()
return
fs.watchFile file, (curr, prev) ->
if +curr.mtime isnt +prev.mtime
invoke 'templates'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment