Created
March 15, 2012 02:36
-
-
Save yulanggong/2041387 to your computer and use it in GitHub Desktop.
Less compiler with --watch and --smartpath support
This file contains 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
/* | |
* Less compiler with --watch and --smartpath support | |
* | |
* Based on lessc of less 1.3.0 | |
* | |
* Added options: | |
* | |
* -w, --watch Watch files (include @import files) for changes and re-compile | |
* | |
* -m, --smartpath output css file like this: | |
* if a css folder exists | |
* folder/less/main.less -> folder/css/main.css | |
* if not | |
* folder/main.less -> folder/main.css | |
*/ | |
var path = require('path'), | |
fs = require('fs'), | |
sys = require('util'), | |
less = require('less'); | |
var options = { | |
compress: false, | |
yuicompress: false, | |
optimization: 1, | |
silent: false, | |
paths: [], | |
color: true, | |
smartpath: false, | |
watch: false, | |
strictImports: true | |
} | |
var args = process.argv.slice(1); | |
args = args.filter(function (arg) { | |
var match; | |
if (match = arg.match(/^-I(.+)$/)) { | |
options.paths.push(match[1]); | |
return false; | |
} | |
if (match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=([^\s]+))?$/i)) { arg = match[1] } | |
else { return arg } | |
switch (arg) { | |
case 'v': | |
case 'version': | |
sys.puts("lessc " + less.version.join('.') + " (LESS Compiler) [JavaScript]"); | |
process.exit(0); | |
case 'verbose': | |
options.verbose = true; | |
break; | |
case 's': | |
case 'silent': | |
options.silent = true; | |
break; | |
case 'strict-imports': | |
options.strictImports = true; | |
break; | |
case 'm' : | |
case 'smartpath' : | |
options.smartpath = true; | |
break; | |
case 'h': | |
case 'help': | |
sys.puts("usage: lessc source [destination]"); | |
process.exit(0); | |
case 'x': | |
case 'compress': | |
options.compress = true; | |
break; | |
case 'w': | |
case 'watch': | |
options.watch = true; | |
break; | |
case 'yui-compress': | |
options.yuicompress = true; | |
break; | |
case 'no-color': | |
options.color = false; | |
break; | |
case 'include-path': | |
options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':') | |
.map(function(p) { | |
if (p) { | |
return path.resolve(process.cwd(), p); | |
} | |
}); | |
break; | |
break; | |
case 'O0': options.optimization = 0; break; | |
case 'O1': options.optimization = 1; break; | |
case 'O2': options.optimization = 2; break; | |
} | |
}); | |
var input = args[1]; | |
if (input && input != '-') { | |
input = path.resolve(process.cwd(), input); | |
} | |
var output = args[2]; | |
if (output) { | |
output = path.resolve(process.cwd(), output); | |
} | |
var css, fd, tree, watchList = []; | |
if (! input) { | |
sys.puts("lessc: no input files"); | |
process.exit(1); | |
} | |
if (options.smartpath) { | |
var basename = path.basename(input, '.less'), | |
rootPath = path.resolve(input, '..','..'), | |
cssPath = path.resolve(rootPath, 'css'); | |
path.exists(cssPath, function (exists){ | |
if (exists) { | |
output = path.resolve(cssPath, basename + ".css"); | |
} else { | |
output = path.resolve(input, '..', basename + ".css"); | |
} | |
}); | |
} | |
var currentTime = function (){ | |
return (new Date()).toTimeString().substr(0,9); | |
} | |
var parseLessFile = function (e, data) { | |
if (e) { | |
sys.puts("lessc: " + e.message); | |
if (!options.watch) process.exit(1); | |
} | |
var parser = new (less.Parser)({ | |
paths: [path.dirname(input)].concat(options.paths), | |
optimization: options.optimization, | |
filename: input, | |
strictImports: options.strictImports | |
}); | |
parser.parse(data, function (err, tree) { | |
if (options.watch) { | |
if(!watchList.length) { | |
watchList.push(input); | |
setTimeout(function () { | |
watchLess(input); | |
},0); | |
} | |
for (i in parser.imports.files) { | |
var filename = path.resolve(input,"..", i); | |
if (watchList.indexOf(filename) == -1){ | |
watchList.push(filename); | |
(function (filename) { | |
setTimeout(function () { | |
watchLess(filename); | |
},0); | |
})(filename); | |
} | |
} | |
} | |
if (err) { | |
sys.puts('Error -- ' + currentTime()); | |
less.writeError(err, options); | |
if (!options.watch) process.exit(1); | |
} else { | |
try { | |
css = tree.toCSS({ | |
compress: options.compress, | |
yuicompress: options.yuicompress | |
}); | |
if (output) { | |
fd = fs.openSync(output, "w"); | |
fs.writeSync(fd, css, 0, "utf8"); | |
sys.puts(output + ' -- ' + currentTime()); | |
} else { | |
sys.print(css); | |
} | |
} catch (e) { | |
sys.puts('Error -- ' + currentTime()); | |
less.writeError(e, options); | |
if (!options.watch) process.exit(2); | |
} | |
} | |
}); | |
}; | |
var lastChange = 0; | |
var watchLess = function (filename){ | |
path.exists(filename,function (exists){ | |
if (exists) { | |
fs.watch(filename, function (event){ | |
if(event === "change"){ | |
var time = + new Date(); | |
if (time - lastChange > 100) { | |
fs.readFile(input, 'utf-8', parseLessFile); | |
} | |
lastChange = time; | |
} | |
}) | |
} else { | |
sys.puts('File not found: ' + filename); | |
} | |
}) | |
}; | |
if (input != '-') { | |
fs.readFile(input, 'utf-8', parseLessFile); | |
} else { | |
process.stdin.resume(); | |
process.stdin.setEncoding('utf8'); | |
var buffer = ''; | |
process.stdin.on('data', function(data) { | |
buffer += data; | |
}); | |
process.stdin.on('end', function() { | |
parseLessFile(false, buffer); | |
}); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment