123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- /* jshint rhino:true, unused: false */
- /* jscs:disable validateIndentation */
- /*global name:true, less, loadStyleSheet, os */
- function formatError(ctx, options) {
- options = options || {};
- var message = "";
- var extract = ctx.extract;
- var error = [];
- // var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str; };
- var stylize = function (str) { return str; };
- // only output a stack if it isn't a less error
- if (ctx.stack && !ctx.type) { return stylize(ctx.stack, 'red'); }
- if (!ctx.hasOwnProperty('index') || !extract) {
- return ctx.stack || ctx.message;
- }
- if (typeof extract[0] === 'string') {
- error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey'));
- }
- if (typeof extract[1] === 'string') {
- var errorTxt = ctx.line + ' ';
- if (extract[1]) {
- errorTxt += extract[1].slice(0, ctx.column) +
- stylize(stylize(stylize(extract[1][ctx.column], 'bold') +
- extract[1].slice(ctx.column + 1), 'red'), 'inverse');
- }
- error.push(errorTxt);
- }
- if (typeof extract[2] === 'string') {
- error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey'));
- }
- error = error.join('\n') + stylize('', 'reset') + '\n';
- message += stylize(ctx.type + 'Error: ' + ctx.message, 'red');
- if (ctx.filename) {
- message += stylize(' in ', 'red') + ctx.filename +
- stylize(' on line ' + ctx.line + ', column ' + (ctx.column + 1) + ':', 'grey');
- }
- message += '\n' + error;
- if (ctx.callLine) {
- message += stylize('from ', 'red') + (ctx.filename || '') + '/n';
- message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n';
- }
- return message;
- }
- function writeError(ctx, options) {
- options = options || {};
- if (options.silent) { return; }
- var message = formatError(ctx, options);
- throw new Error(message);
- }
- function loadStyleSheet(sheet, callback, reload, remaining) {
- var endOfPath = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\')),
- sheetName = name.slice(0, endOfPath + 1) + sheet.href,
- contents = sheet.contents || {},
- input = readFile(sheetName);
- input = input.replace(/^\xEF\xBB\xBF/, '');
- contents[sheetName] = input;
- var parser = new less.Parser({
- paths: [sheet.href.replace(/[\w\.-]+$/, '')],
- contents: contents
- });
- parser.parse(input, function (e, root) {
- if (e) {
- return writeError(e);
- }
- try {
- callback(e, root, input, sheet, { local: false, lastModified: 0, remaining: remaining }, sheetName);
- } catch(e) {
- writeError(e);
- }
- });
- }
- less.Parser.fileLoader = function (file, currentFileInfo, callback, env) {
- var href = file;
- if (currentFileInfo && currentFileInfo.currentDirectory && !/^\//.test(file)) {
- href = less.modules.path.join(currentFileInfo.currentDirectory, file);
- }
- var path = less.modules.path.dirname(href);
- var newFileInfo = {
- currentDirectory: path + '/',
- filename: href
- };
- if (currentFileInfo) {
- newFileInfo.entryPath = currentFileInfo.entryPath;
- newFileInfo.rootpath = currentFileInfo.rootpath;
- newFileInfo.rootFilename = currentFileInfo.rootFilename;
- newFileInfo.relativeUrls = currentFileInfo.relativeUrls;
- } else {
- newFileInfo.entryPath = path;
- newFileInfo.rootpath = less.rootpath || path;
- newFileInfo.rootFilename = href;
- newFileInfo.relativeUrls = env.relativeUrls;
- }
- var j = file.lastIndexOf('/');
- if (newFileInfo.relativeUrls && !/^(?:[a-z-]+:|\/)/.test(file) && j != -1) {
- var relativeSubDirectory = file.slice(0, j + 1);
- newFileInfo.rootpath = newFileInfo.rootpath + relativeSubDirectory; // append (sub|sup) directory path of imported file
- }
- newFileInfo.currentDirectory = path;
- newFileInfo.filename = href;
- var data = null;
- try {
- data = readFile(href);
- } catch (e) {
- callback({ type: 'File', message: "'" + less.modules.path.basename(href) + "' wasn't found" });
- return;
- }
- try {
- callback(null, data, href, newFileInfo, { lastModified: 0 });
- } catch (e) {
- callback(e, null, href);
- }
- };
- function writeFile(filename, content) {
- var fstream = new java.io.FileWriter(filename);
- var out = new java.io.BufferedWriter(fstream);
- out.write(content);
- out.close();
- }
- // Command line integration via Rhino
- (function (args) {
- var options = {
- depends: false,
- compress: false,
- cleancss: false,
- max_line_len: -1,
- silent: false,
- verbose: false,
- lint: false,
- paths: [],
- color: true,
- strictImports: false,
- rootpath: '',
- relativeUrls: false,
- ieCompat: true,
- strictMath: false,
- strictUnits: false
- };
- var continueProcessing = true,
- currentErrorcode;
- var checkArgFunc = function(arg, option) {
- if (!option) {
- print(arg + " option requires a parameter");
- continueProcessing = false;
- return false;
- }
- return true;
- };
- var checkBooleanArg = function(arg) {
- var onOff = /^((on|t|true|y|yes)|(off|f|false|n|no))$/i.exec(arg);
- if (!onOff) {
- print(" unable to parse " + arg + " as a boolean. use one of on/t/true/y/yes/off/f/false/n/no");
- continueProcessing = false;
- return false;
- }
- return Boolean(onOff[2]);
- };
- var warningMessages = "";
- var sourceMapFileInline = false;
- args = args.filter(function (arg) {
- var match = arg.match(/^-I(.+)$/);
- if (match) {
- options.paths.push(match[1]);
- return false;
- }
- match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=(.*))?$/i);
- if (match) {
- arg = match[1];
- }
- else {
- return arg;
- }
- switch (arg) {
- case 'v':
- case 'version':
- console.log("lessc " + less.version.join('.') + " (Less Compiler) [JavaScript]");
- continueProcessing = false;
- break;
- case 'verbose':
- options.verbose = true;
- break;
- case 's':
- case 'silent':
- options.silent = true;
- break;
- case 'l':
- case 'lint':
- options.lint = true;
- break;
- case 'strict-imports':
- options.strictImports = true;
- break;
- case 'h':
- case 'help':
- //TODO
- // require('../lib/less/lessc_helper').printUsage();
- continueProcessing = false;
- break;
- case 'x':
- case 'compress':
- options.compress = true;
- break;
- case 'M':
- case 'depends':
- options.depends = true;
- break;
- case 'yui-compress':
- warningMessages += "yui-compress option has been removed. assuming clean-css.";
- options.cleancss = true;
- break;
- case 'clean-css':
- options.cleancss = true;
- break;
- case 'max-line-len':
- if (checkArgFunc(arg, match[2])) {
- options.maxLineLen = parseInt(match[2], 10);
- if (options.maxLineLen <= 0) {
- options.maxLineLen = -1;
- }
- }
- break;
- case 'no-color':
- options.color = false;
- break;
- case 'no-ie-compat':
- options.ieCompat = false;
- break;
- case 'no-js':
- options.javascriptEnabled = false;
- break;
- case 'include-path':
- if (checkArgFunc(arg, match[2])) {
- // support for both ; and : path separators
- // even on windows when using absolute paths with drive letters (eg C:\path:D:\path)
- options.paths = match[2]
- .split(os.type().match(/Windows/) ? /:(?!\\)|;/ : ':')
- .map(function(p) {
- if (p) {
- // return path.resolve(process.cwd(), p);
- return p;
- }
- });
- }
- break;
- case 'line-numbers':
- if (checkArgFunc(arg, match[2])) {
- options.dumpLineNumbers = match[2];
- }
- break;
- case 'source-map':
- if (!match[2]) {
- options.sourceMap = true;
- } else {
- options.sourceMap = match[2];
- }
- break;
- case 'source-map-rootpath':
- if (checkArgFunc(arg, match[2])) {
- options.sourceMapRootpath = match[2];
- }
- break;
- case 'source-map-basepath':
- if (checkArgFunc(arg, match[2])) {
- options.sourceMapBasepath = match[2];
- }
- break;
- case 'source-map-map-inline':
- sourceMapFileInline = true;
- options.sourceMap = true;
- break;
- case 'source-map-less-inline':
- options.outputSourceFiles = true;
- break;
- case 'source-map-url':
- if (checkArgFunc(arg, match[2])) {
- options.sourceMapURL = match[2];
- }
- break;
- case 'source-map-output-map-file':
- if (checkArgFunc(arg, match[2])) {
- options.writeSourceMap = function(sourceMapContent) {
- writeFile(match[2], sourceMapContent);
- };
- }
- break;
- case 'rp':
- case 'rootpath':
- if (checkArgFunc(arg, match[2])) {
- options.rootpath = match[2].replace(/\\/g, '/');
- }
- break;
- case "ru":
- case "relative-urls":
- options.relativeUrls = true;
- break;
- case "sm":
- case "strict-math":
- if (checkArgFunc(arg, match[2])) {
- options.strictMath = checkBooleanArg(match[2]);
- }
- break;
- case "su":
- case "strict-units":
- if (checkArgFunc(arg, match[2])) {
- options.strictUnits = checkBooleanArg(match[2]);
- }
- break;
- default:
- console.log('invalid option ' + arg);
- continueProcessing = false;
- }
- });
- if (!continueProcessing) {
- return;
- }
- var name = args[0];
- if (name && name != '-') {
- // name = path.resolve(process.cwd(), name);
- }
- var output = args[1];
- var outputbase = args[1];
- if (output) {
- options.sourceMapOutputFilename = output;
- // output = path.resolve(process.cwd(), output);
- if (warningMessages) {
- console.log(warningMessages);
- }
- }
- // options.sourceMapBasepath = process.cwd();
- // options.sourceMapBasepath = '';
- if (options.sourceMap === true) {
- console.log("output: " + output);
- if (!output && !sourceMapFileInline) {
- console.log("the sourcemap option only has an optional filename if the css filename is given");
- return;
- }
- options.sourceMapFullFilename = options.sourceMapOutputFilename + ".map";
- options.sourceMap = less.modules.path.basename(options.sourceMapFullFilename);
- } else if (options.sourceMap) {
- options.sourceMapOutputFilename = options.sourceMap;
- }
- if (!name) {
- console.log("lessc: no inout files");
- console.log("");
- // TODO
- // require('../lib/less/lessc_helper').printUsage();
- currentErrorcode = 1;
- return;
- }
- // var ensureDirectory = function (filepath) {
- // var dir = path.dirname(filepath),
- // cmd,
- // existsSync = fs.existsSync || path.existsSync;
- // if (!existsSync(dir)) {
- // if (mkdirp === undefined) {
- // try {mkdirp = require('mkdirp');}
- // catch(e) { mkdirp = null; }
- // }
- // cmd = mkdirp && mkdirp.sync || fs.mkdirSync;
- // cmd(dir);
- // }
- // };
- if (options.depends) {
- if (!outputbase) {
- console.log("option --depends requires an output path to be specified");
- return;
- }
- console.log(outputbase + ": ");
- }
- if (!name) {
- console.log('No files present in the fileset');
- quit(1);
- }
- var input = null;
- try {
- input = readFile(name, 'utf-8');
- } catch (e) {
- console.log('lesscss: couldn\'t open file ' + name);
- quit(1);
- }
- options.filename = name;
- var result;
- try {
- var parser = new less.Parser(options);
- parser.parse(input, function (e, root) {
- if (e) {
- writeError(e, options);
- quit(1);
- } else {
- result = root.toCSS(options);
- if (output) {
- writeFile(output, result);
- console.log("Written to " + output);
- } else {
- print(result);
- }
- quit(0);
- }
- });
- }
- catch(e) {
- writeError(e, options);
- quit(1);
- }
- }(arguments));
|