haml-coffee
Version:
Haml templates where you can write inline CoffeeScript.
232 lines (207 loc) • 8 kB
text/coffeescript
CoffeeScript = require 'coffee-script'
CoffeeMaker = require './coffee-maker'
fs = require 'fs'
path = require 'path'
walkdir = require 'walkdir'
red = '\u001b[31m'
green = '\u001b[32m'
reset = '\u001b[0m'
optimist = require('optimist')
.usage('Usage: $0')
.options('i',
alias : 'input'
describe : 'Either a file or a directory name to be compiled'
)
.options('o',
alias : 'output'
describe : 'Set the output filename'
)
.options('n',
alias : 'namespace'
describe : 'Set a custom template namespace'
default : 'window.HAML'
)
.options('t',
alias : 'template'
describe : 'Set a custom template name'
)
.options('b',
alias : 'basename'
boolean : true
default : false
describe : 'Ignore file path when generate the template name'
)
.options('f',
alias : 'format'
default : 'html5'
describe : 'Set HTML output format, either `xhtml`, `html4` or `html5`'
)
.options('u',
alias : 'uglify'
boolean : true
default : false
describe : 'Do not properly indent or format the HTML output'
)
.options('e',
alias : 'extend'
boolean : true
default : false
describe : 'Extend the template scope with the context'
)
.options('p',
alias : 'placement'
default : 'global'
describe : 'Where to place the template function; one of: global, amd'
)
.options('d',
alias : 'dependencies'
default : "{ hc: 'hamlcoffee' }"
describe : 'The global template amd module dependencies'
)
.options('preserve',
default : 'pre,textarea'
describe : 'Set a comma separated list of HTML tags to preserve'
)
.options('autoclose',
default : 'meta,img,link,br,hr,input,area,param,col,base'
describe : 'Set a comma separated list of self-closed HTML tags'
)
.options('hyphenate-data-attrs',
boolean : true
describe : 'Convert underscores to hyphens for data attribute keys'
)
.options('disable-html-attribute-escaping',
boolean : true
default : true
describe : 'Disable any HTML attribute escaping'
)
.options('disable-html-escaping',
boolean : true
describe : 'Disable any HTML escaping'
)
.options('disable-clean-value',
boolean : true
describe : 'Disable any CoffeeScript code value cleaning'
)
.options('custom-html-escape',
default : ''
describe : 'Set the custom HTML escaping function name'
)
.options('custom-preserve',
default : ''
describe : 'Set the custom preserve whitespace function name'
)
.options('custom-find-and-preserve',
default : ''
describe : 'Set the custom find and preserve whitespace function name'
)
.options('custom-clean-value',
default : ''
describe : 'Set the custom code value clean function name'
)
.options('custom-surround',
default : ''
describe : 'Set the custom surround function name'
)
.options('custom-succeed',
default : ''
describe : 'Set the custom succeed function name'
)
.options('custom-precede',
default : ''
describe : 'Set the custom precede function name'
)
.options('custom-reference',
default : ''
describe : 'Set the custom object reference function name'
)
# Main function to run from console. This can either compile a single Haml Coffee template,
# compile a directory of Haml Coffee templates into several JavaScript templates or a directory
# of Haml Coffee templates into one JavaScript template.
#
exports.run = ->
argv = optimist.argv
throw new Error("Unknown template format '#{ argv.f }'") if ['xhtml', 'html4', 'html5'].indexOf(argv.f) is -1
inputFilename = argv.i
templateName = argv.t
namespace = argv.n
dependencies = {}
try
dependencies = CoffeeScript.eval(argv.d)
catch err
console.error " #{ red }[Haml Coffee] Invalid dependencies:#{ reset } %s (%s)", argv.d, err
compilerOptions =
placement : argv.p
dependencies : dependencies
format : argv.f
uglify : argv.u
extendScope : argv.e
preserveTags : argv.preserve
escapeHtml : not argv['disable-html-escaping']
escapeAttributes : not argv['disable-html-attribute-escaping']
cleanValue : not argv['disable-clean-value']
hyphenateDataAttrs : argv['hyphenate-data-attrs']
customHtmlEscape : argv['custom-html-escape']
customCleanValue : argv['custom-clean-value']
customFindAndPreserve : argv['custom-find-and-preserve']
customPreserve : argv['custom-preserve']
customSurround : argv['custom-surround']
customSucceed : argv['custom-succeed']
customPrecede : argv['custom-precede']
customReference : argv['custom-reference']
basename : argv['basename']
if inputFilename
fs.stat inputFilename, (err, stat) ->
unless err
# Compile a single Haml CoffeeScript template
unless stat.isDirectory()
outputFilename = argv.o || "#{ argv.i.match(/([^\.]+)(\.html)?\.haml[c]?$/)?[1] }.jst"
console.error " #{ green }[Haml Coffee] Compiling file#{ reset } %s to %s", inputFilename, outputFilename
fs.writeFileSync outputFilename, CoffeeMaker.compileFile(inputFilename, compilerOptions, namespace, templateName)
process.exit 0
# Compile a directory of Haml CoffeeScript files
else
if templateName
console.error " #{ red }[Haml Coffee] You can\'t compile all Haml templates in a directory and give a single template name!#{ reset }"
process.exit 1
console.log " #{ green }[Haml Coffee] Compiling directory#{ reset } %s", inputFilename
# Removing a trailing slash
baseDir = inputFilename.replace(/\/$/, '')
# When an output filename is given, all templates will be concatenated
compound = ''
# Loop through all Haml files and compile them
for filename in walkdir.sync baseDir
# walkdir sometimes returns absolute paths
if filename.substring(0, 1) is '/'
filename = path.relative(process.cwd(), filename)
if filename.match /([^\.]+)(\.html)?\.haml[c]?$/
# Combine all files into a single output
if argv.o
console.log " #{ green }[Haml Coffee] Compiling file#{ reset } %s", filename
compound += CoffeeMaker.compileFile(filename, compilerOptions, namespace)
# Compile and write each file on its own
else
outputFilename = "#{ filename.match(/([^\.]+)(\.html)?\.haml[c]?$/)?[1] }.jst"
console.log " #{ green }[Haml Coffee] Compiling file#{ reset } %s to %s", inputFilename, outputFilename
fs.writeFileSync outputFilename, CoffeeMaker.compileFile(filename, compilerOptions, namespace)
# Write concatenated output
if argv.o
console.log " #{ green }[Haml Coffee] Writing all templates to#{ reset } %s", argv.o
fs.writeFileSync argv.o, compound
process.exit 0
else
console.error " #{ red }[Haml Coffee] Error compiling file#{ reset } %s: %s", argv.i, err
process.exit 1
else if argv.help
console.log optimist.help()
# Read from stdin and write result to stdout
else
if require('tty').isatty(process.stdin)
console.log 'Please enter template source code and press Ctrl-D to generate:\n'
source = ''
process.stdin.resume()
process.stdin.setEncoding 'utf8'
process.stdin.on 'data', (chunk) -> source += chunk
process.stdin.on 'end', ->
console.log '\n'
process.stdout.write CoffeeMaker.compile(source, (templateName || 'test'), namespace, compilerOptions)