kungfusheep / SublimeLinter-contrib-stylelint

this repo is no longer maintained - please see https://github.com/SublimeLinter/SublimeLinter-stylelint
MIT License
116 stars 19 forks source link

Pass args to CLI #15

Open backflip opened 8 years ago

backflip commented 8 years ago

I might be wrong, but in order to use a custom syntax, e.g., we probably have to expose more arguments to the CLI than just the file path:

var args = process.argv;
// Remove the paths for the node binary and the linter script, add the one for stylelint
args.splice(0, 2, cliLocation);

var child_process = require("child_process");
var lint = child_process.spawnSync("node", args);

This allows me to add "args": ["--syntax", "scss"], to the linter config in SublimeLinter.sublime-settings.

chris-pearce commented 8 years ago

I tried making that change to the stylelint_wrapper.js file but no dice, here's the entire contents of that file + my SublimeLinter.sublime-settings file:

var fs = require("fs");

/// we're keeping this project-specific.
var CLI_JS_LOCATION = "/node_modules/stylelint/dist/cli.js";
var PACKAGE_JSON = "/node_modules/stylelint/package.json";

/// get the config location, if it's been provided.
var configPath, prjPath, cliLocation, useOld = false;
var index = process.argv.indexOf("--config");
if (index > -1) {

    configPath = prjPath = process.argv[index + 1];

    /// choose a platform specific separator
    var sep = prjPath.indexOf("/") > -1 ? "/" : "\\";

    /// set the working directory to the config location - this is necessary because 'plugins' and 'extends' are relative.
    process.chdir(prjPath.slice(0, prjPath.lastIndexOf(sep)));

    /// now try to use the node_modules folder from the project folder (we're saying the project folder is where the config is...)
    /// we'll add a bunch of paths for require to check.
    while (prjPath.indexOf(sep) > -1) {
        prjPath = prjPath.slice(0, prjPath.lastIndexOf(sep));

        /// look for the stylelint CLI on the way whilst we're here. we'll either need this or the require paths
        if(!cliLocation && fs.existsSync(prjPath + CLI_JS_LOCATION)){

            /// check the version number. old versions of stylelint had the cli.js file but it didn't work.
            var json = JSON.parse(fs.readFileSync(prjPath + PACKAGE_JSON));
            var ver = Number(json.version.split(".")[0]);
            if(ver >= 2){

                cliLocation = prjPath + CLI_JS_LOCATION;
                break;
            }
            else {
                /// we've found a stylelint instance but it's an older version,
                ///  so make sure this is the one that is used and not the global instance.
                useOld = true;
            }
        }

        require.main.paths.splice(0, 0, prjPath + "/node_modules");
    }

    /// if we cannot locate a local stylelint CLI, try to look for it on npm global
    if(!cliLocation && !useOld) {
        var npmPath = require("child_process").execSync("npm root -g").toString()
            .trim().replace("/node_modules", "");

        if(fs.existsSync(npmPath + CLI_JS_LOCATION)) {
            cliLocation = npmPath + CLI_JS_LOCATION;
        }
    }
}

/// we want to support the latest stylelint and use the CLI, but also want to support the pre-CLI version.
/// using the CLI gets around a bunch of things, like needing the "postcss-scss" module. plus a lot of work went into it!
if(cliLocation){
    /// See:
    /// https://github.com/kungfusheep/SublimeLinter-contrib-stylelint/issues/15 will fail when SublimeLinter-contrib-stylelint is updated
    var args = process.argv;
    // Remove the paths for the node binary and the linter script, add the one
    // for stylelint
    args.splice(0, 2, cliLocation);
    var child_process = require("child_process");
    var lint = child_process.spawnSync("node", args);
    ///console.log("Args here:", args);

    /// use the CLI, we found it earlier on.

    ///var child_process = require("child_process");
    ///var lint = child_process.spawnSync("node", [cliLocation, process.argv[2] ]);
    /// re-route the stdout to ours
    console.log(String(lint.stdout) + String(lint.stderr));
}
else {
    /// old stylelint versions.

    var postcss = require("postcss");
    var stylelint = require("stylelint");
    var reporter = postcss.plugin("reporter", require("./reporter/lib/reporter"));

    /// css to be processed
    var fileName = process.argv[2];
    var css = fs.readFileSync(fileName, "utf8");

    /// load the config json
    var config = configPath ? JSON.parse(fs.readFileSync(configPath)) : {};

    /// start the linting process.
    postcss([
            stylelint(config), reporter()
        ])
        .process(css, {
            from: fileName
        })
        .then()
        .catch(function(err) {
            console.error(err.stack)
        })
}
{
    "user": {
        "debug": true,
        "delay": 0.25,
        "error_color": "D02000",
        "gutter_theme": "Packages/SublimeLinter/gutter-themes/Default/Default.gutter-theme",
        "gutter_theme_excludes": [],
        "lint_mode": "background",
        "linters": {
            "eslint": {
                "@disable": false,
                "args": [],
                "excludes": []
            },
            "stylelint": {
                "@disable": false,
                "args": [
                    "--syntax",
                    "scss"
                ],
                "excludes": []
            }
        },
        "mark_style": "fill",
        "no_column_highlights_line": false,
        "passive_warnings": false,
        "paths": {
            "*": [],
            "linux": [],
            "osx": [],
            "windows": []
        },
        "python_paths": {
            "linux": [],
            "osx": [],
            "windows": []
        },
        "rc_search_limit": 3,
        "shell_timeout": 10,
        "show_errors_on_save": false,
        "show_marks_in_minimap": true,
        "syntax_map": {
            "html (django)": "html",
            "html (rails)": "html",
            "html 5": "html",
            "javascript (babel)": "javascript",
            "magicpython": "python",
            "php": "html",
            "python django": "python",
            "pythonimproved": "python"
        },
        "warning_color": "FFA500",
        "wrap_find": true
    }
}
oskarrough commented 8 years ago

@backflip your solution works for me. That the SCSS syntax in user preferences of the linter. But shouldn't it be able to defer the syntax from the .stylelintrc?

{
  "extends": "stylelint-config-suitcss",
  "syntax": "scss"
}
narehart commented 8 years ago

With the default code the linter only ever passes the file location to stylelint. The following fixes that:

if(cliLocation){
    /// use the CLI, we found it earlier on.
    var file = process.argv[2];
    var args = process.argv.concat([]);
    args.splice(0, 2);
    var child_process = require("child_process");
    var lint = child_process.spawnSync("node", [cliLocation, file].concat(args));
    /// re-route the stdout to ours
    console.log(String(lint.stdout) + String(lint.stderr));
}
iamhollow commented 8 years ago

Would it be a good idea to determine the syntax depending on the file extension? As a default, this way you wouldn't be required to configure stylelint for it to parse the files intelligently.

var fs = require("fs");
var path = require("path");

...

if(cliLocation){
    /// use the CLI, we found it earlier on.
    var file = process.argv[2];
    var syntax = ['--syntax', path.extname(file).substr(1)];

    var child_process = require("child_process");
    var lint = child_process.spawnSync("node", [cliLocation, file].concat(syntax));
    /// re-route the stdout to ours
    console.log(String(lint.stdout) + String(lint.stderr));
}
emlama commented 8 years ago

+1 on this. We use Sass in our org and this would be great.

Also, as far as I can tell, you can't set the syntax in the stylelint config file. It's not mentioned in their documentation and putting this in the config doesn't seem to change out the stylelint sublime plugin behaves.