| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 | #!/usr/bin/env nodevar path = require('path'),    fs = require('../lib/less-node/fs'),    os = require('os'),    errno,    mkdirp;try {    errno = require('errno');} catch (err) {    errno = null;}var less = require('../lib/less-node'),    pluginLoader = new less.PluginLoader(less),    plugin,    plugins = [];var args = process.argv.slice(1);var silent = false,    verbose = false,    options = {    depends: false,    compress: false,    max_line_len: -1,    lint: false,    paths: [],    color: true,    strictImports: false,    insecure: false,    rootpath: '',    relativeUrls: false,    ieCompat: true,    strictMath: false,    strictUnits: false,    globalVars: null,    modifyVars: null,    urlArgs: '',    plugins: plugins};var sourceMapOptions = {};var continueProcessing = true,    currentErrorcode;// calling process.exit does not flush stdout always// so use this to set the exit codeprocess.on('exit', function() { process.reallyExit(currentErrorcode); });var checkArgFunc = function(arg, option) {    if (!option) {        console.log(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) {        console.log(" 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 parseVariableOption = function(option, variables) {    var parts = option.split('=', 2);    variables[parts[0]] = parts[1];};var warningMessages = "";var sourceMapFileInline = false;function printUsage() {    less.lesscHelper.printUsage();    pluginLoader.printUsage(plugins);    continueProcessing = false;}// self executing function so we can return(function() {    args = args.filter(function (arg) {        var match;        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':                verbose = true;                break;            case 's':            case 'silent':                silent = true;                break;            case 'l':            case 'lint':                options.lint = true;                break;            case 'strict-imports':                options.strictImports = true;                break;            case 'h':            case 'help':                printUsage();                break;            case 'x':            case 'compress':                options.compress = true;                break;            case 'insecure':                options.insecure = true;                break;            case 'M':            case 'depends':                options.depends = 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])) {                    options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':')                        .map(function(p) {                            if (p) {                                return path.resolve(process.cwd(), p);                            }                        });                }                break;            case 'line-numbers':                if (checkArgFunc(arg, match[2])) {                    options.dumpLineNumbers = match[2];                }                break;            case 'source-map':                options.sourceMap = true;                if (match[2]) {                    sourceMapOptions.sourceMapFullFilename = match[2];                }                break;            case 'source-map-rootpath':                if (checkArgFunc(arg, match[2])) {                    sourceMapOptions.sourceMapRootpath = match[2];                }                break;            case 'source-map-basepath':                if (checkArgFunc(arg, match[2])) {                    sourceMapOptions.sourceMapBasepath = match[2];                }                break;            case 'source-map-map-inline':                sourceMapFileInline = true;                options.sourceMap = true;                break;            case 'source-map-less-inline':                sourceMapOptions.outputSourceFiles = true;                break;            case 'source-map-url':                if (checkArgFunc(arg, match[2])) {                    sourceMapOptions.sourceMapURL = match[2];                }                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;            case "global-var":                if (checkArgFunc(arg, match[2])) {                    if (!options.globalVars) {                        options.globalVars = {};                    }                    parseVariableOption(match[2], options.globalVars);                }                break;            case "modify-var":                if (checkArgFunc(arg, match[2])) {                    if (!options.modifyVars) {                        options.modifyVars = {};                    }                    parseVariableOption(match[2], options.modifyVars);                }                break;            case 'url-args':                if (checkArgFunc(arg, match[2])) {                    options.urlArgs = match[2];                }                break;            case 'plugin':                var splitupArg = match[2].match(/^([^=]+)(=(.*))?/),                    name = splitupArg[1],                    pluginOptions = splitupArg[3];                plugin = pluginLoader.tryLoadPlugin(name, pluginOptions);                if (plugin) {                    plugins.push(plugin);                } else {                    console.log("Unable to load plugin " + name +                        " please make sure that it is installed under or at the same level as less");                    console.log();                    printUsage();                    currentErrorcode = 1;                }                break;            default:                plugin = pluginLoader.tryLoadPlugin("less-plugin-" + arg, match[2]);                if (plugin) {                    plugins.push(plugin);                } else {                    console.log("Unable to interpret argument " + arg +                        " - if it is a plugin (less-plugin-" + arg + "), make sure that it is installed under or at" +                        " the same level as less");                    console.log();                    printUsage();                    currentErrorcode = 1;                }                break;        }    });    if (!continueProcessing) {        return;    }    var input = args[1];    if (input && input != '-') {        input = path.resolve(process.cwd(), input);    }    var output = args[2];    var outputbase = args[2];    if (output) {        output = path.resolve(process.cwd(), output);        if (warningMessages) {            console.log(warningMessages);        }    }    if (options.sourceMap) {        sourceMapOptions.sourceMapInputFilename = input;        if (!sourceMapOptions.sourceMapFullFilename) {            if (!output && !sourceMapFileInline) {                console.log("the sourcemap option only has an optional filename if the css filename is given");                console.log("consider adding --source-map-map-inline which embeds the sourcemap into the css");                return;            }            // its in the same directory, so always just the basename            sourceMapOptions.sourceMapOutputFilename = path.basename(output);            sourceMapOptions.sourceMapFullFilename = output + ".map";            // its in the same directory, so always just the basename            sourceMapOptions.sourceMapFilename = path.basename(sourceMapOptions.sourceMapFullFilename);        } else if (options.sourceMap && !sourceMapFileInline) {            var mapFilename = path.resolve(process.cwd(), sourceMapOptions.sourceMapFullFilename),                mapDir = path.dirname(mapFilename),                outputDir = path.dirname(output);            // find the path from the map to the output file            sourceMapOptions.sourceMapOutputFilename = path.join(                path.relative(mapDir, outputDir), path.basename(output));            // make the sourcemap filename point to the sourcemap relative to the css file output directory            sourceMapOptions.sourceMapFilename = path.join(                path.relative(outputDir, mapDir), path.basename(sourceMapOptions.sourceMapFullFilename));        }    }    if (sourceMapOptions.sourceMapBasepath === undefined) {        sourceMapOptions.sourceMapBasepath = input ? path.dirname(input) : process.cwd();    }    if (sourceMapOptions.sourceMapRootpath === undefined) {        var pathToMap = path.dirname(sourceMapFileInline ? output : sourceMapOptions.sourceMapFullFilename),            pathToInput = path.dirname(sourceMapOptions.sourceMapInputFilename);        sourceMapOptions.sourceMapRootpath = path.relative(pathToMap, pathToInput);    }    if (! input) {        console.log("lessc: no input files");        console.log("");        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;        }        process.stdout.write(outputbase + ": ");    }    if (!sourceMapFileInline) {        var writeSourceMap = function(output, onDone) {            var filename = sourceMapOptions.sourceMapFullFilename;            ensureDirectory(filename);            fs.writeFile(filename, output, 'utf8', function (err) {                if (err) {                    var description = "Error: ";                    if (errno && errno.errno[err.errno]) {                        description += errno.errno[err.errno].description;                    } else {                        description += err.code + " " + err.message;                    }                    less.logger.error('lessc: failed to create file ' + filename);                    less.logger.error(description);                } else {                    less.logger.info('lessc: wrote ' + filename);                }                onDone();            });        };    }    var writeSourceMapIfNeeded = function(output, onDone) {        if (options.sourceMap && !sourceMapFileInline) {            writeSourceMap(output, onDone);        } else {            onDone();        }    };    var writeOutput = function(output, result, onSuccess) {        if (output) {            ensureDirectory(output);            fs.writeFile(output, result.css, {encoding: 'utf8'}, function (err) {                if (err) {                    var description = "Error: ";                    if (errno && errno.errno[err.errno]) {                        description += errno.errno[err.errno].description;                    } else {                        description += err.code + " " + err.message;                    }                    less.logger.error('lessc: failed to create file ' + output);                    less.logger.error(description);                } else {                    less.logger.info('lessc: wrote ' + output);                    onSuccess();                }            });        } else if (!options.depends) {            process.stdout.write(result.css);            onSuccess();        }    };    var logDependencies = function(options, result) {        if (options.depends) {            var depends = "";            for (var i = 0; i < result.imports.length; i++) {                depends += result.imports[i] + " ";            }            console.log(depends);        }    };    var parseLessFile = function (e, data) {        if (e) {            console.log("lessc: " + e.message);            currentErrorcode = 1;            return;        }        data = data.replace(/^\uFEFF/, '');        options.paths = [path.dirname(input)].concat(options.paths);        options.filename = input;        if (options.lint) {            options.sourceMap = false;        }        sourceMapOptions.sourceMapFileInline = sourceMapFileInline;        if (options.sourceMap) {            options.sourceMap = sourceMapOptions;        }        less.logger.addListener({            info: function(msg) {                if (verbose) {                    console.log(msg);                }            },            warn: function(msg) {                // do not show warning if outputting css to the console or the silent option is used                if (!silent && output) {                    console.warn(msg);                }            },            error: function(msg) {                console.log(msg);            }        });        less.render(data, options)            .then(function(result) {                if (!options.lint) {                    writeOutput(output, result, function() {                        writeSourceMapIfNeeded(result.map, function() {                            logDependencies(options, result);                        });                    });                }            },            function(err) {                less.writeError(err, options);                currentErrorcode = 1;            });    };    if (input != '-') {        fs.readFile(input, 'utf8', 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);        });    }})();
 |