UNPKG

capt

Version:

Command line tool for creating backbone.js applications with coffeescript

366 lines (297 loc) 10.6 kB
fs = require('fs') sys = require('sys') yaml = require("#{root}/lib/yaml") Path = require("path") Glob = require("glob") exec = require('child_process').exec _ = require("#{root}/lib/underscore") CoffeeScript = require 'coffee-script' eco = require "eco" LessParser = require('less').Parser sys.puts "Capt:" sys.puts " * Using coffeescript version #{CoffeeScript.VERSION}" String.prototype.capitalize = -> this.charAt(0).toUpperCase() + this.substring(1).toLowerCase() class Project constructor: (cwd) -> @cwd = cwd @root = cwd try @yaml = yaml.eval(fs.readFileSync(@configPath()) + "\n\n") catch e sys.puts " * [ERROR] Unable to parse config.yml" sys.puts " * [ERROR] #{e.message}" process.exit(-1) # Include these sections of the config.yml (eg nokia, android or web) @targets = [] name : -> @cwd.replace(/.+\//,'') language : -> 'coffee' # or 'js' configPath : -> Path.join(@cwd, "config.yml") getScriptPathFor: (path) -> if Path.extname(path) == '.eco' # Eco templates Path.join(Path.dirname(path), ".js", Path.basename(path, '.eco') + '.js') else if Path.extname(path) == '.json' # Fixtures Path.join(Path.dirname(path), ".js", Path.basename(path, '.json') + '.js') else if Path.extname(path) == '.xml' # Fixtures Path.join(Path.dirname(path), ".js", Path.basename(path, '.xml') + '.js') else if Path.extname(path) == '.coffee' # Coffeescript Path.join(Path.dirname(path), ".js", Path.basename(path, '.coffee') + '.js') else # Javascript path getScriptTagFor: (path) -> path = @getScriptPathFor(path) "<script src='#{path}' type='text/javascript'></script>" getStyleTagFor: (path) -> if Path.extname(path) == '.less' # LESS CSS compiler csspath = Path.join(Path.dirname(path), "." + Path.basename(path, '.less') + '.css') "<link href='#{csspath}' media='screen' rel='stylesheet' type='text/css' />" else "<link href='#{path}' media='screen' rel='stylesheet' type='text/css' />" bundleStylesheet : (filename) -> index = 0 inputs = for sheet in @getStylesheetDependencies() path = Path.join(@root, @getScriptPathFor(sheet)) inputs = inputs.join " " exec("cat #{inputs} > #{filename}") # createManifest : -> # [].concat( # @getDependencies('specs') # @getScriptDependencies() # @getStylesheetDependencies() # ) # bundleJavascript : (filename) -> index = 0 inputs = for script in @getScriptDependencies() path = Path.join(@root, @getScriptPathFor(script)) inputs = inputs.join " " # sys.puts inputs # sys.puts "java -jar #{root}/bin/compiler.jar #{inputs} --js_output_file #{filename}" # exec("java -jar #{root}/bin/compiler.jar --compilation_level WHITESPACE_ONLY #{inputs} --js_output_file #{filename}") # sys.puts("cat #{inputs} > #{filename}") exec("cat #{inputs} > #{filename}") getScriptDependencies : () -> [].concat( @getDependencies('javascripts') @getDependencies('templates') ) # # # scripts = _([]) # # @getDependencies('templates') # # for pathspec in @yaml.javascripts # for path in Glob(Path.join(@cwd, pathspec)) # path = path.replace(@cwd, '').replace(/^[.\/]+/,'/') # scripts.push path # # # # for target in @targets # # for pathspec in @yaml[target] # # for path in Glob(Path.join(@cwd, pathspec)) # # path = path.replace(@cwd, '') # # scripts.push path # # scripts.unique() getDependencies: (section) -> if !@yaml[section] if section == 'static' return ['/index.jst', '/spec/index.jst'] sys.puts "[WARNING] Unable to find section '#{section}' in config.yml" return [] result = _([]) for pathspec in @yaml[section] for path in Glob(Path.join(@cwd, pathspec), { sync : true }) path = path.replace(@cwd, '').replace(/^[.\/]+/,'') result.push path result.value() getStylesheetDependencies : -> result = _([]) for pathspec in @yaml.stylesheets for path in Glob(Path.join(@cwd, pathspec), { sync : true }) path = path.replace(@cwd, '').replace(/^[.\/]+/,'') result.push path result.unique() stylesheetIncludes : -> tags = for css in @getStylesheetDependencies() @getStyleTagFor css tags.join("\n ") specIncludes : -> tags = for script in @getScriptDependencies() @getScriptTagFor(Path.join("..", script)) for script in @getDependencies('specs') tags.push @getScriptTagFor(Path.join("..", script)) # for script in @getDependencies('fixtures') # tags.push @getScriptTagFor(Path.join("..", script)) tags.join("\n ") scriptIncludes : -> tags = for script in @getScriptDependencies() @getScriptTagFor script tags.join("\n ") compileFile : (file) -> extension = Path.extname(file) if extension == ".coffee" @_compileCoffee(file) else if extension == ".less" @_compileLess(file) else if extension == ".xml" @_compileXml(file) else if extension == ".json" @_compileJson(file) else if extension == ".eco" @_compileEco(file) else if extension == ".jst" @_compileJst(file) else # do nothing... getWatchables : -> [].concat( @getDependencies('static') @getDependencies('specs') # @getDependencies('fixtures') @getScriptDependencies() @getStylesheetDependencies() ) _compileLess : (file) -> parser = new LessParser { # Specify search paths for @import directives paths: ['.', 'public/stylesheets'], # Specify a filename, for better error messages filename: file } fs.readFile Path.join(@root, file), (err, code) => throw err if err path = Path.dirname(file) outpath = Path.join(path, "." + Path.basename(file, ".less") + ".css") try fs.mkdirSync Path.join(@root, path), 0755 catch e # .. ok .. parser.parse code.toString(), (e, css) => if e sys.puts " * Error compiling #{file}" sys.puts " #{e.message}" else sys.puts " * Compiled " + outpath fs.writeFileSync Path.join(@root, outpath), css.toCSS() # Compile xml fixtures # _compileXml : (file) -> # fs.readFile Path.join(@root, file), "utf-8", (err, code) => # throw err if err # # path = Path.join(Path.dirname(file), ".js") # outpath = Path.join(path, Path.basename(file, ".xml") + ".js") # # try # fs.mkdirSync Path.join(@root, path), 0755 # catch e # # .. ok .. # # templateName = [ # Path.dirname(file).split("/").pop().toLowerCase() # Path.basename(file, ".xml").capitalize() # ].join("") # # output = "if(!this.$fixtures){\n $fixtures={};\n};\n\n" + # "this.$fixtures.#{templateName}=$(\"" + # code.replace(/"/g,"\\\"").replace(/\n/g,"\\n") + # "\");" # # sys.puts " * Compiled " + outpath # fs.writeFileSync Path.join(@root, outpath), output # Compile json fixtures # _compileJson : (file) -> # fs.readFile Path.join(@root, file), "utf-8", (err, code) => # throw err if err # # path = Path.join(Path.dirname(file), ".js") # outpath = Path.join(path, Path.basename(file, ".json") + ".js") # # try # fs.mkdirSync Path.join(@root, path), 0755 # catch e # # .. ok .. # # templateName = [ # Path.dirname(file).split("/").pop().toLowerCase() # Path.basename(file, ".json").capitalize() # ].join("") # # output = "if(!this.$fixtures){\n $fixtures={};\n};\n\n" + # "this.$fixtures.#{templateName}=" + code.toString() + ";" # # sys.puts " * Compiled " + outpath # fs.writeFileSync Path.join(@root, outpath), output _compileCoffee : (file) -> fs.readFile Path.join(@root, file), (err, code) => throw err if err path = Path.join(Path.dirname(file), ".js") outpath = Path.join(path, Path.basename(file, ".coffee") + ".js") try fs.mkdirSync Path.join(@root, path), 0755 catch e # .. ok .. try output = CoffeeScript.compile(new String(code)) catch err sys.puts " * Error compiling #{file}" sys.puts err.message return sys.puts " * Compiled " + outpath fs.writeFileSync Path.join(@root, outpath), output _compileEco : (file) -> fs.readFile Path.join(@root, file), "utf-8", (err, code) => throw err if err path = Path.join(Path.dirname(file), ".js") outpath = Path.join(path, Path.basename(file, ".eco") + ".js") try fs.mkdirSync Path.join(@root, path), 0755 catch e # .. ok .. try output = eco.compile(new String(code)) catch err sys.puts " * Error compiling #{file}" sys.puts err.message return templateName = [ Path.dirname(file).split("/").pop().toLowerCase() Path.basename(file, ".eco").capitalize() ].join("") output = "this.$templates.#{templateName} = " + output output = "if(!this.$templates){\n $templates={};\n};\n\n" + output sys.puts " * Compiled " + outpath fs.writeFileSync Path.join(@root, outpath), output _compileJst : (file) -> fs.readFile Path.join(@root, file), (err, code) => throw err if err outpath = Path.join(Path.dirname(file), Path.basename(file, '.jst') + ".html") try output = _.template(new String(code), { project : this }) catch err sys.puts " * Error compiling #{file}" sys.puts err.message return sys.puts " * Compiled " + outpath fs.writeFileSync Path.join(@root, outpath), output build: -> for source in @getWatchables() @compileFile(source) watchAndBuild: -> watch = (source) => fs.watchFile Path.join(@root, source), {persistent: true, interval: 500}, (curr, prev) => return if curr.size is prev.size and curr.mtime.getTime() is prev.mtime.getTime() @compileFile(source) for source in @getWatchables() watch(source) @compileFile(source) exports.Project = Project