Socket
Socket
Sign inDemoInstall

stylelint

Package Overview
Dependencies
Maintainers
3
Versions
238
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

stylelint - npm Package Compare versions

Comparing version 1.2.1 to 2.0.0

dist/rules/function-comma-newline-after/index.js

15

CHANGELOG.md

@@ -0,1 +1,16 @@

# 2.0.0
* Added: CLI.
* Added: standalone Node API.
* Added: quiet mode to CLI and Node API.
* Added: support for formatters, including custom ones, to CLI and Node API.
* Added: `string` and `json` formatters.
* Added: support for using `.stylelintrc` JSON file.
* Added: support for extending existing configs using the `extends` property.
* Added: support for SCSS syntax parsing to CLI and Node API.
* Added: `function-comma-newline-after` rule.
* Added: `function-comma-newline-before` rule.
* Added: `"always-single-line"` and `"never-single-line"` options to `function-comma-space-after` rule.
* Added: `"always-single-line"` and `"never-single-line"` options to `function-comma-space-before` rule.
# 1.2.1

@@ -2,0 +17,0 @@

29

dist/cli.js

@@ -27,3 +27,3 @@ #!/usr/bin/env node

f: "string",
q: "false"
q: false
},

@@ -35,5 +35,6 @@ alias: {

};
var syntaxOptions = ["scss"];
var meowOptions = {
help: ["Usage", " stylelint [input] [options]", "", "By default, stylelint will look for a .stylelintrc file in JSON format,", "using rc to look in various places (cf. https://github.com/dominictarr/rc#standards).", "Alternately, you can specify a configuration file via --config.", "", "Input", " File glob(s) (passed to node-glob).", " You can also pass no input and use stdin.", "", "Options", " --config Path to a JSON configuration file.", " --version Get the currently installed version of stylelint.", " --custom-formatter Path to a JS file exporting a custom formatting function", " -f, --formatter Specify a formatter: \"json\" or \"string\". Default is \"string\".", " -q, --quiet Only register warnings for rules with a severity of 2 (ignore level 1)"],
help: ["Usage", " stylelint [input] [options]", "", "By default, stylelint will look for a .stylelintrc file in JSON format,", "using rc to look in various places (cf. https://github.com/dominictarr/rc#standards).", "Alternately, you can specify a configuration file via --config.", "", "Input", " File glob(s) (passed to node-glob).", " You can also pass no input and use stdin.", "", "Options", " --config Path to a JSON configuration file.", " --version Get the currently installed version of stylelint.", " --custom-formatter Path to a JS file exporting a custom formatting function", " -f, --formatter Specify a formatter: \"json\" or \"string\". Default is \"string\".", " -q, --quiet Only register warnings for rules with a severity of 2 (ignore level 1)", " -s, --syntax Specify a non-standard syntax that should be used to ", " parse source stylesheets. Options: \"scss\""],
pkg: "../package.json"

@@ -46,19 +47,25 @@ };

var configBase = {
var optionsBase = {
formatter: formatter,
config: {
quiet: cli.flags.quiet
}
configOverrides: {}
};
var configReady = cli.input.length ? Promise.resolve((0, _lodash.assign)({}, configBase, {
if (cli.flags.quiet) {
optionsBase.configOverrides.quiet = cli.flags.quiet;
}
if (cli.flags.s && (0, _lodash.includes)(syntaxOptions, cli.flags.s)) {
optionsBase.syntax = cli.flags.s;
}
var optionsReady = cli.input.length ? Promise.resolve((0, _lodash.assign)({}, optionsBase, {
files: cli.input
})) : (0, _getStdin2["default"])().then(function (stdin) {
return Promise.resolve((0, _lodash.assign)({}, configBase, {
css: stdin
return Promise.resolve((0, _lodash.assign)({}, optionsBase, {
code: stdin
}));
});
configReady.then(function (config) {
(0, _standalone2["default"])(config).then(function (_ref) {
optionsReady.then(function (options) {
(0, _standalone2["default"])(options).then(function (_ref) {
var output = _ref.output;

@@ -65,0 +72,0 @@ var errored = _ref.errored;

@@ -16,7 +16,9 @@ "use strict";

exports["default"] = function (root, result) {
result.disabledRanges = [];
result.stylelint = result.stylelint || {};
var disabledRanges = result.stylelint.disabledRanges = [];
var withinDisabledRange = false;
result.root.walkComments(function (comment) {
root.walkComments(function (comment) {
var text = comment.text;

@@ -61,3 +63,3 @@

result.disabledRanges.push(rangeObj);
disabledRanges.push(rangeObj);
}

@@ -67,3 +69,3 @@

// Add an `end` prop to the last range
result.disabledRanges[result.disabledRanges.length - 1].end = node.source.end.line;
disabledRanges[disabledRanges.length - 1].end = node.source.end.line;
}

@@ -70,0 +72,0 @@ };

@@ -10,2 +10,4 @@ "use strict";

validateOptions: require("./utils/validateOptions")
};
};
module.exports.lint = require("./standalone");

@@ -13,2 +13,18 @@ "use strict";

var _rc = require("rc");
var _rc2 = _interopRequireDefault(_rc);
var _path = require("path");
var _path2 = _interopRequireDefault(_path);
var _resolveFrom = require("resolve-from");
var _resolveFrom2 = _interopRequireDefault(_resolveFrom);
var _lodash = require("lodash");
var _utils = require("./utils");
var _rules = require("./rules");

@@ -22,25 +38,49 @@

exports["default"] = _postcss2["default"].plugin("stylelint", function (settings) {
exports["default"] = _postcss2["default"].plugin("stylelint", function () {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
return function (root, result) {
if (!settings) {
return;
// result.stylelint is the namespace for passing stylelint-related
// configuration and data across sub-plugins via the PostCSS Result
result.stylelint = result.stylelint || {};
result.stylelint.ruleSeverities = {};
var initialConfig = options.hasOwnProperty("config") ? options.config : options;
if ((0, _lodash.isEmpty)(initialConfig)) {
initialConfig = (0, _rc2["default"])("stylelint");
}
if (!settings.rules) {
return;
var configBasedir = options.configBasedir || _path2["default"].dirname(initialConfig.config);
var config = extendConfig(initialConfig, configBasedir);
if (config.plugins) {
Object.keys(config.plugins).forEach(function (pluginName) {
_rules2["default"][pluginName] = require(modulePath(config.plugins[pluginName], configBasedir));
});
}
if (settings.plugins) {
addPluginsToDefinitions(settings.plugins, _rules2["default"]);
if (options.configOverrides) {
(0, _lodash.merge)(config, options.configOverrides);
}
// First check for disabled ranges
if (!config) {
throw (0, _utils.configurationError)("No configuration provided");
}
if (!config.rules) {
throw (0, _utils.configurationError)("No rules found within configuration");
}
// Register details about the configuration
result.stylelint.quiet = config.quiet;
// First check for disabled ranges, adding them to the result object
(0, _disableRanges2["default"])(root, result);
Object.keys(settings.rules).forEach(function (ruleName) {
Object.keys(config.rules).forEach(function (ruleName) {
if (!_rules2["default"][ruleName]) {
throw new Error("Undefined rule " + ruleName);
throw (0, _utils.configurationError)("Undefined rule " + ruleName);
}
// If severity is 0, run nothing
var ruleSettings = settings.rules[ruleName];
var ruleSettings = config.rules[ruleName];
var ruleSeverity = Array.isArray(ruleSettings) ? ruleSettings[0] : ruleSettings;

@@ -51,3 +91,6 @@ if (ruleSeverity === 0) {

// Otherwise, run the rule with the primary and secondary options
// Log the rule's severity
result.stylelint.ruleSeverities[ruleName] = ruleSeverity;
// Run the rule with the primary and secondary options
_rules2["default"][ruleName](ruleSettings[1], ruleSettings[2])(root, result);

@@ -58,11 +101,24 @@ });

function addPluginsToDefinitions(plugins, definitions) {
Object.keys(plugins).forEach(function (name) {
if (typeof plugins[name] !== "function") {
addPluginsToDefinitions(plugins[name], definitions);
return;
}
definitions[name] = plugins[name];
});
function extendConfig(config, configBasedir) {
if (!config["extends"]) {
return config;
}
return [].concat(config["extends"]).reduce(function (mergedConfig, extendingConfigLookup) {
var extendingConfigPath = modulePath(extendingConfigLookup, configBasedir || process.cwd());
// Now we must recursively extend the extending config
var extendingConfig = extendConfig(require(extendingConfigPath), _path2["default"].dirname(extendingConfigPath));
return (0, _lodash.merge)({}, extendingConfig, mergedConfig);
}, (0, _lodash.cloneDeep)(config));
}
function modulePath(lookup, basedir) {
try {
return (0, _resolveFrom2["default"])(basedir, lookup);
} catch (e) {
throw (0, _utils.configurationError)("Could not find \"" + lookup + "\". " + "Do you need a `configBasedir`?");
}
}
module.exports = exports["default"];

@@ -19,2 +19,8 @@ "use strict";

return "Unexpected whitespace after \",\"";
},
expectedAfterSingleLine: function expectedAfterSingleLine() {
return "Expected single space after \",\" in a single-line list";
},
rejectedAfterSingleLine: function rejectedAfterSingleLine() {
return "Unexpected whitespace after \",\" in a single-line list";
}

@@ -30,3 +36,3 @@ });

actual: expectation,
possible: ["always", "never"]
possible: ["always", "never", "always-single-line", "never-single-line"]
});

@@ -33,0 +39,0 @@ if (!validOptions) {

@@ -20,2 +20,8 @@ "use strict";

return "Unexpected whitespace before \",\"";
},
expectedBeforeSingleLine: function expectedBeforeSingleLine() {
return "Expected single space before \",\" in a single-line list";
},
rejectedBeforeSingleLine: function rejectedBeforeSingleLine() {
return "Unexpected whitespace before \",\" in a single-line list";
}

@@ -31,3 +37,3 @@ });

actual: expectation,
possible: ["always", "never"]
possible: ["always", "never", "always-single-line", "never-single-line"]
});

@@ -34,0 +40,0 @@ if (!validOptions) {

@@ -129,2 +129,10 @@ "use strict";

var _functionCommaNewlineAfter = require("./function-comma-newline-after");
var _functionCommaNewlineAfter2 = _interopRequireDefault(_functionCommaNewlineAfter);
var _functionCommaNewlineBefore = require("./function-comma-newline-before");
var _functionCommaNewlineBefore2 = _interopRequireDefault(_functionCommaNewlineBefore);
var _functionCommaSpaceAfter = require("./function-comma-space-after");

@@ -389,2 +397,4 @@

"function-calc-no-unspaced-operator": _functionCalcNoUnspacedOperator2["default"],
"function-comma-newline-after": _functionCommaNewlineAfter2["default"],
"function-comma-newline-before": _functionCommaNewlineBefore2["default"],
"function-comma-space-after": _functionCommaSpaceAfter2["default"],

@@ -391,0 +401,0 @@ "function-comma-space-before": _functionCommaSpaceBefore2["default"],

@@ -63,4 +63,2 @@ "use strict";

// console.log(JSON.stringify(rule.toString()))
var beforeBrace = (0, _utils.cssStatementStringBeforeBlock)(rule);

@@ -67,0 +65,0 @@ var lineCheckStr = rule.toString().slice(beforeBrace.length);

@@ -59,3 +59,2 @@ "use strict";

decimalNumberMatches.forEach(function (match) {
console.log(match);
if (match.sub[1].length <= precision) {

@@ -62,0 +61,0 @@ return;

@@ -25,2 +25,6 @@ "use strict";

var _postcssScss = require("postcss-scss");
var _postcssScss2 = _interopRequireDefault(_postcssScss);
var _plugin = require("./plugin");

@@ -38,10 +42,12 @@

var files = _ref.files;
var css = _ref.css;
var code = _ref.code;
var config = _ref.config;
var configBasedir = _ref.configBasedir;
var configOverrides = _ref.configOverrides;
var syntax = _ref.syntax;
var _ref$formatter = _ref.formatter;
var formatter = _ref$formatter === undefined ? "json" : _ref$formatter;
if (!files && !css || files && css) {
throw new Error("You must pass stylelint a `files` glob or a `css` string, though not both");
if (!files && !code || files && code) {
throw new Error("You must pass stylelint a `files` glob or a `code` string, though not both");
}

@@ -56,3 +62,3 @@

var inputReady = files ? (0, _globby2["default"])(files) : Promise.resolve(css);
var inputReady = files ? (0, _globby2["default"])(files) : Promise.resolve(code);
inputReady.then(function (input) {

@@ -84,11 +90,11 @@ var q = (0, _queueAsync2["default"])();

function lintFile(filepath, cb) {
_fs2["default"].readFile(filepath, "utf8", function (err, css) {
_fs2["default"].readFile(filepath, "utf8", function (err, code) {
if (err) {
reject(err);
}
lint(css, filepath, cb);
lint(code, filepath, cb);
});
}
function lint(css, filepath, cb) {
function lint(code, filepath, cb) {
var processOptions = {};

@@ -98,3 +104,6 @@ if (filepath) {

}
(0, _postcss2["default"])().use((0, _plugin2["default"])({ config: config, configBasedir: configBasedir })).process(css, processOptions).then(function (postcssResult) {
if (syntax === "scss") {
processOptions.syntax = _postcssScss2["default"];
}
(0, _postcss2["default"])().use((0, _plugin2["default"])({ config: config, configBasedir: configBasedir, configOverrides: configOverrides })).process(code, processOptions).then(function (postcssResult) {
var source = !postcssResult.root.source ? undefined : postcssResult.root.source.input.file || postcssResult.root.source.input.id;

@@ -101,0 +110,0 @@

@@ -13,2 +13,6 @@ "use strict";

var _configurationError = require("./configurationError");
var _configurationError2 = _interopRequireDefault(_configurationError);
var _cssFunctionArguments = require("./cssFunctionArguments");

@@ -92,2 +96,3 @@

blurComments: _blurComments2["default"],
configurationError: _configurationError2["default"],
cssFunctionArguments: _cssFunctionArguments2["default"],

@@ -94,0 +99,0 @@ cssStatementBlockString: _cssStatementBlockString2["default"],

@@ -35,5 +35,11 @@ /**

result.stylelint = result.stylelint || {};
if (result.stylelint.quiet && result.stylelint.ruleSeverities[ruleName] !== 2) {
return;
}
var startLine = line ? line : node.source && node.source.start.line;
if (result.disabledRanges) {
if (result.stylelint.disabledRanges) {
var _iteratorNormalCompletion = true;

@@ -44,3 +50,3 @@ var _didIteratorError = false;

try {
for (var _iterator = result.disabledRanges[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
for (var _iterator = result.stylelint.disabledRanges[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var range = _step.value;

@@ -72,12 +78,24 @@

var warningOpts = node ? { node: node } : {};
var severity = result.stylelint.ruleSeverities ? result.stylelint.ruleSeverities[ruleName] : 0;
if (!result.stylelint.stylelintError && severity === 2) {
result.stylelint.stylelintError = true;
}
var warningProperties = {
severity: severity,
rule: ruleName
};
if (node) {
warningProperties.node = node;
}
if (index) {
warningOpts.index = index;
warningProperties.index = index;
}
if (word) {
warningOpts.word = word;
warningProperties.word = word;
}
result.warn(message, warningOpts);
result.warn(message, warningProperties);
};
module.exports = exports["default"];

@@ -19,2 +19,6 @@ "use strict";

var _configurationError = require("./configurationError");
var _configurationError2 = _interopRequireDefault(_configurationError);
/**

@@ -123,3 +127,3 @@ * Create a whitespaceChecker, which exposes the following functions:

default:
throw new Error("Unknown expectation \"" + expectation + "\"");
throw (0, _configurationError2["default"])("Unknown expectation \"" + expectation + "\"");
}

@@ -175,3 +179,3 @@ }

default:
throw new Error("Unknown expectation \"" + expectation + "\"");
throw (0, _configurationError2["default"])("Unknown expectation \"" + expectation + "\"");
}

@@ -178,0 +182,0 @@ }

{
"name": "stylelint",
"version": "1.2.1",
"version": "2.0.0",
"description": "Modern CSS linter",

@@ -23,2 +23,3 @@ "keywords": [

"main": "dist/index.js",
"bin": "dist/cli.js",
"files": [

@@ -34,5 +35,13 @@ "dist",

"execall": "^1.0.0",
"get-stdin": "^5.0.0",
"globby": "^3.0.1",
"lodash": "^3.10.1",
"meow": "^3.3.0",
"postcss": "^5.0.4",
"postcss-selector-parser": "^1.2.0"
"postcss-reporter": "^1.3.0",
"postcss-scss": "^0.1.3",
"postcss-selector-parser": "^1.2.0",
"queue-async": "^1.0.7",
"rc": "^1.1.1",
"resolve-from": "^1.0.1"
},

@@ -42,3 +51,4 @@ "devDependencies": {

"babel-tape-runner": "^1.2.0",
"eslint": "^1.3.1",
"chalk": "^1.1.1",
"eslint": "^1.4.1",
"eslint-config-stylelint": "^0.1.0",

@@ -50,3 +60,4 @@ "sinon": "^1.16.1",

"scripts": {
"prepublish": "babel src --out-dir dist",
"build": "babel src --out-dir dist",
"prepublish": "npm run build",
"lint": "eslint . --ignore-path .gitignore",

@@ -53,0 +64,0 @@ "tape": "babel-tape-runner \"src/**/__tests__/*.js\"",

@@ -18,200 +18,19 @@ # stylelint [![NPM version](http://img.shields.io/npm/v/stylelint.svg)](https://www.npmjs.org/package/stylelint) [![Travis Build Status](https://img.shields.io/travis/stylelint/stylelint/master.svg?label=unix%20build)](https://travis-ci.org/stylelint/stylelint) [![AppVeyor Build Status](https://img.shields.io/appveyor/ci/MoOx/stylelint/master.svg?label=windows%20build)](https://ci.appveyor.com/project/MoOx/stylelint) [![Join the chat at https://gitter.im/stylelint/stylelint](https://img.shields.io/badge/gitter%20-join%20chat%20%E2%9E%9E-1dce73.svg)](https://gitter.im/stylelint/stylelint)

## Installation
## Quick start
```console
$ npm install stylelint
```
With stylelint, it's easy to start linting your CSS to enforce your preferred conventions:
* _PostCSS `5.x` or `4.x` compatibility_ - versions `1.0.0+` of the linter are compatible with PostCSS `5.0.2+`. Whereas, versions `0.8.0 and below` are compatible with PostCSS `4.x`.
* _Use a reporter_ - this plugin registers warnings via PostCSS. Therefore, you'll want to use it with a PostCSS runner that prints warnings (e.g. [`gulp-postcss`](https://github.com/postcss/gulp-postcss)) or another PostCSS plugin that prints warnings (e.g. [`postcss-reporter`](https://github.com/postcss/postcss-reporter)).
1. Install stylelint: `npm install stylelint`.
2. Learn about [some rules](/docs/user-guide/rules.md). No rules are turned on by default, so you only have to learn about the rules you want to enforce; and you can start small, growing your config over time as you have a chance to explore more of the rules.
3. Create your [configuration](/docs/user-guide/configuration.md), probably as a `.stylelintrc` file.
4. Decide whether to use the [CLI](/docs/user-guide/cli.md), [Node API](/docs/user-guide/node-api.md), or [PostCSS plugin](/docs/user-guide/postcss-plugin.md).
5. Lint!
## Usage
## Guides
You must, for now, use the linter as a [PostCSS plugin](https://github.com/postcss/postcss#usage). You can either use a PostCSS runner -- such as [`gulp-postcss`](https://github.com/postcss/gulp-postcss), [`grunt-postcss`](https://github.com/nDmitry/grunt-postcss) and [`postcss-loader`](https://github.com/postcss/postcss-loader) -- or you can use the PostCSS JS API directly.
You'll find more detailed information on using the linter and tailoring it to your needs in our guides:
The linter also _expects a config_. You can either craft your own config or use a [pre-written one](#shareable-configs).
* [User guide](docs/user-guide.md) - Usage, configuration and complementary tools.
* [Developer guide](docs/developer-guide.md) - Contributing to stylelint and writing your own plugins & formatters.
An example of using [`gulp-postcss`](https://github.com/postcss/gulp-postcss) and crafting your own config:
```js
gulp.task("css", function () {
var postcss = require("gulp-postcss")
var stylelint = require("stylelint")
var reporter = require("postcss-reporter")
return gulp.src("src/**/*.css")
.pipe(postcss([
stylelint({ // an example config that has four rules
"rules": {
"color-no-invalid-hex": 2,
"declaration-colon-space-before": [2, "never"],
"indentation": [2, "tab"],
"number-leading-zero": [2, "always"]
}
}),
reporter({
clearMessages: true,
})
]))
})
```
An example of using the JS API and the [`stylelint-config-suitcss`](https://github.com/stylelint/stylelint-config-suitcss) config:
```js
var fs = require("fs")
var postcss = require("postcss")
var stylelint = require("stylelint")
var configSuitcss = require("stylelint-config-suitcss")
var reporter = require("postcss-reporter")
// css to be processed
var css = fs.readFileSync("input.css", "utf8")
postcss([
stylelint(configSuitcss), // using the pre-written SuitCSS config
reporter(),
])
.process(css, { from: "input.css" })
.then()
.catch(err => console.error(err.stack))
```
### With CSS processors
The linter supports current and future CSS syntax. This includes all standard CSS but also special features that use standard CSS syntactic structures, e.g. special at-rules, special properties, and special functions. Some CSS-*like* language extensions -- features that use non-standard syntactic structures -- are, as such, supported; however, since there are infinite processing possibilities, the linter cannot support everything.
You can run the linter before or after your css processors. Depending on which processors you use, each approach has caveats:
1. *Before*: Some plugins might enable a syntax that isn't compatible with the linter.
2. *After*: Some plugins might generate CSS that is invalid against your linter config, causing warnings that do not correspond to your original stylesheets.
*In both cases you can either turn off the incompatible linter rule, or stop using the incompatible plugin.* You could also approach plugin authors and request alternate formatting options that will make their plugin compatible with stylelint.
### Configuring rules
[Rules](docs/rules.md) are built into the linter and focus on _standard_ CSS. They are configured within the `rules` key of the config. The [user guide](docs/user-guide.md) contains details of how rules are named and how certain ones should be configured in unison.
#### Turning rules on and off
Like [ESLint](http://eslint.org/docs/user-guide/configuring#configuring-rules), each rule can be turned off or on:
* `0` - turn the rule off.
* ~~`1` - turn the rule on as a warning (does not affect exit code).~~
* `2` - turn the rule on ~~as an error (exit code is 1 when triggered)~~.
Severities are not yet implemented. _See issue [#26](https://github.com/stylelint/stylelint/issues/26) for more details._
An example of turning one rule off and another on:
```js
{
"rules": {
"rule-no-single-line": 0, // turn rule off
"declaration-no-important": 2, // turn rule on
}
}
```
Rules can be temporarily turned off by using special comments in your CSS. For example, you can either turn all the rules off:
```css
/* stylelint-disable */
a {}
/* stylelint-enable */
```
Or you can turn off individual rules:
```css
/* stylelint-disable selector-no-id, declaration-no-important */
#id {
color: pink !important;
}
/* stylelint-enable */
```
#### Configuring options
Only the `*-no-*` rules don't expect options. All the other rules must be explicitly configured as _there are no default values_.
An example of explicitly configuring the options for three rules:
```js
{
"rules": {
"indentation": [2, "tab", {
except: ["value"],
}],
"declaration-colon-space-before": [2, "never"],
"number-leading-zero": [2, "always"],
}
}
```
#### Shareable configs
If you prefer to enforce a third-party styleguide (rather than craft your own config), you can use:
* [SuitCSS shareable config](https://github.com/stylelint/stylelint-config-suitcss)
You can also extend a shareable config file, starting with what's there and making your own modifications and additions:
```js
var assign = require("lodash.assign")
var configSuitcss = require("stylelint-config-suitcss")
// change indentation to tabs and turn off the number-leading-zero rule
var myConfig = {
"rules": {
"indentation": [2, "tab"],
"number-leading-zero": 0,
}
}
// merge the configs together
var config = {
rules: assign(configSuitcss.rules, myConfig.rules)
}
```
### Plugin rules
[Plugins](docs/plugins.md) are userland rules that support _non-standard_ CSS features. To use one, add a `"plugins"` property to your config. The key is the rule's name; the value is the rule function itself. Then, within the `"rules"` object, your can add settings for your plugin rule just like any standard rule.
```js
var myConfig = {
plugins: {
"special-rule": require("special-rule"),
},
rules: {
// ...
"special-rule": [ 2, "everything" ],
// ...
},
}
```
## Complementary tools
The linter works well with:
### Editor plugins
* [linter-stylelint](https://github.com/1000ch/linter-stylelint) - An Atom Linter plugin for stylelint.
* [SublimeLinter-contrib-stylelint](https://github.com/kungfusheep/SublimeLinter-contrib-stylelint) - A Sublime Text plugin for stylelint.
### Other linters & formatters
* [cssfmt](https://github.com/morishitter/cssfmt) - A tool that automatically formats CSS and SCSS source code.
* [postcss-bem-linter](https://github.com/postcss/postcss-bem-linter) - A BEM linter for CSS.
* [stylehacks](https://github.com/ben-eb/stylehacks) - Detect/remove browser hacks from CSS files.
## Requirements
* node@0.12 or io.js@2
* node@0.10 with [babel-node](http://babeljs.io/docs/usage/cli/#babel-node)
## [Changelog](CHANGELOG.md)

@@ -218,0 +37,0 @@

@@ -9,7 +9,9 @@ import { compact } from "lodash"

export default function (root, result) {
result.disabledRanges = []
result.stylelint = result.stylelint || {}
const disabledRanges = result.stylelint.disabledRanges = []
let withinDisabledRange = false
result.root.walkComments(comment => {
root.walkComments(comment => {
const { text } = comment

@@ -51,3 +53,3 @@

result.disabledRanges.push(rangeObj)
disabledRanges.push(rangeObj)
}

@@ -57,4 +59,4 @@

// Add an `end` prop to the last range
result.disabledRanges[result.disabledRanges.length - 1].end = node.source.end.line
disabledRanges[disabledRanges.length - 1].end = node.source.end.line
}
}

@@ -9,1 +9,3 @@ module.exports = require("./plugin")

}
module.exports.lint = require("./standalone")
import postcss from "postcss"
import rc from "rc"
import path from "path"
import resolveFrom from "resolve-from"
import { merge, cloneDeep, isEmpty } from "lodash"
import { configurationError } from "./utils"
import ruleDefinitions from "./rules"
import disableRanges from "./disableRanges"
export default postcss.plugin("stylelint", settings => {
export default postcss.plugin("stylelint", (options = {}) => {
return (root, result) => {
if (!settings) { return }
if (!settings.rules) { return }
// result.stylelint is the namespace for passing stylelint-related
// configuration and data across sub-plugins via the PostCSS Result
result.stylelint = result.stylelint || {}
result.stylelint.ruleSeverities = {}
if (settings.plugins) {
addPluginsToDefinitions(settings.plugins, ruleDefinitions)
let initialConfig = options.hasOwnProperty("config") ? options.config : options
if (isEmpty(initialConfig)) {
initialConfig = rc("stylelint")
}
// First check for disabled ranges
const configBasedir = options.configBasedir || path.dirname(initialConfig.config)
const config = extendConfig(initialConfig, configBasedir)
if (config.plugins) {
Object.keys(config.plugins).forEach(pluginName => {
ruleDefinitions[pluginName] = require(modulePath(config.plugins[pluginName], configBasedir))
})
}
if (options.configOverrides) {
merge(config, options.configOverrides)
}
if (!config) {
throw configurationError("No configuration provided")
}
if (!config.rules) {
throw configurationError("No rules found within configuration")
}
// Register details about the configuration
result.stylelint.quiet = config.quiet
// First check for disabled ranges, adding them to the result object
disableRanges(root, result)
Object.keys(settings.rules).forEach(ruleName => {
Object.keys(config.rules).forEach(ruleName => {
if (!ruleDefinitions[ruleName]) {
throw new Error(
`Undefined rule ${ruleName}`
)
throw configurationError(`Undefined rule ${ruleName}`)
}
// If severity is 0, run nothing
const ruleSettings = settings.rules[ruleName]
const ruleSettings = config.rules[ruleName]
const ruleSeverity = (Array.isArray(ruleSettings))
? ruleSettings[0]
: ruleSettings
if (ruleSeverity === 0) { return }
if (ruleSeverity === 0) {
return
}
// Otherwise, run the rule with the primary and secondary options
// Log the rule's severity
result.stylelint.ruleSeverities[ruleName] = ruleSeverity
// Run the rule with the primary and secondary options
ruleDefinitions[ruleName](ruleSettings[1], ruleSettings[2])(root, result)

@@ -37,10 +71,24 @@ })

function addPluginsToDefinitions(plugins, definitions) {
Object.keys(plugins).forEach(name => {
if (typeof plugins[name] !== "function") {
addPluginsToDefinitions(plugins[name], definitions)
return
}
definitions[name] = plugins[name]
})
function extendConfig(config, configBasedir) {
if (!config.extends) { return config }
return [].concat(config.extends).reduce((mergedConfig, extendingConfigLookup) => {
let extendingConfigPath = modulePath(extendingConfigLookup, configBasedir || process.cwd())
// Now we must recursively extend the extending config
let extendingConfig = extendConfig(require(extendingConfigPath), path.dirname(extendingConfigPath))
return merge({}, extendingConfig, mergedConfig)
}, cloneDeep(config))
}
function modulePath(lookup, basedir) {
try {
return resolveFrom(basedir, lookup)
} catch (e) {
throw configurationError(
`Could not find "${lookup}". ` +
`Do you need a \`configBasedir\`?`
)
}
}

@@ -14,2 +14,4 @@ import {

rejectedAfter: () => `Unexpected whitespace after ","`,
expectedAfterSingleLine: () => `Expected single space after "," in a single-line list`,
rejectedAfterSingleLine: () => `Unexpected whitespace after "," in a single-line list`,
})

@@ -25,2 +27,4 @@

"never",
"always-single-line",
"never-single-line",
],

@@ -27,0 +31,0 @@ })

@@ -13,3 +13,3 @@ # function-comma-space-after

`string`: `"always"|"never"`
`string`: `"always"|"never"|"always-single-line"|"never-single-line"`

@@ -63,1 +63,63 @@ ### `"always"`

```
### `"always-single-line"`
There *must always* be a single space after the commas in single-line functions.
The following patterns are considered warnings:
```css
a { transform: translate(1,1) }
```
```css
a { transform: translate(1 ,1) }
```
The following patterns are *not* considered warnings:
```css
a { transform: translate(1, 1) }
```
```css
a { transform: translate(1 , 1) }
```
```css
a {
transform: translate(1
,1)
}
```
### `"never-single-line"`
There *must never* be whitepace after the commas in single-line functions.
The following patterns are considered warnings:
```css
a { transform: translate(1, 1) }
```
```css
a { transform: translate(1 , 1) }
```
The following patterns are *not* considered warnings:
```css
a { transform: translate(1,1) }
```
```css
a { transform: translate(1 ,1) }
```
```css
a {
transform: translate(1
, 1)
}
```

@@ -13,2 +13,4 @@ import {

rejectedBefore: () => `Unexpected whitespace before ","`,
expectedBeforeSingleLine: () => `Expected single space before "," in a single-line list`,
rejectedBeforeSingleLine: () => `Unexpected whitespace before "," in a single-line list`,
})

@@ -24,2 +26,4 @@

"never",
"always-single-line",
"never-single-line",
],

@@ -26,0 +30,0 @@ })

@@ -13,3 +13,3 @@ # function-comma-space-before

`string`: `"always"|"never"`
`string`: `"always"|"never"|"always-single-line"|"never-single-line"`

@@ -63,1 +63,63 @@ ### `"always"`

```
### `"always-single-line"`
There *must always* be a single space before the commas in single-line functions.
The following patterns are considered warnings:
```css
a { transform: translate(1,1) }
```
```css
a { transform: translate(1, 1) }
```
The following patterns are *not* considered warnings:
```css
a { transform: translate(1 ,1) }
```
```css
a { transform: translate(1 , 1) }
```
```css
a {
transform: translate(1,
1)
}
```
### `"never-single-line"`
There *must never* be whitepace before the commas in single-line functions.
The following patterns are considered warnings:
```css
a { transform: translate(1 ,1) }
```
```css
a { transform: translate(1 , 1) }
```
The following patterns are *not* considered warnings:
```css
a { transform: translate(1,1) }
```
```css
a { transform: translate(1, 1) }
```
```css
a {
transform: translate(1 ,
1)
}
```

@@ -31,2 +31,4 @@ import atRuleEmptyLineBefore from "./at-rule-empty-line-before"

import functionCalcNoUnspacedOperator from "./function-calc-no-unspaced-operator"
import functionCommaNewlineAfter from "./function-comma-newline-after"
import functionCommaNewlineBefore from "./function-comma-newline-before"
import functionCommaSpaceAfter from "./function-comma-space-after"

@@ -121,2 +123,4 @@ import functionCommaSpaceBefore from "./function-comma-space-before"

"function-calc-no-unspaced-operator": functionCalcNoUnspacedOperator,
"function-comma-newline-after": functionCommaNewlineAfter,
"function-comma-newline-before": functionCommaNewlineBefore,
"function-comma-space-after": functionCommaSpaceAfter,

@@ -123,0 +127,0 @@ "function-comma-space-before": functionCommaSpaceBefore,

@@ -48,4 +48,2 @@ import {

// console.log(JSON.stringify(rule.toString()))
const beforeBrace = cssStatementStringBeforeBlock(rule)

@@ -52,0 +50,0 @@ const lineCheckStr = rule.toString().slice(beforeBrace.length)

@@ -45,3 +45,2 @@ import { isNumber } from "lodash"

decimalNumberMatches.forEach(match => {
console.log(match)
if (match.sub[1].length <= precision) { return }

@@ -48,0 +47,0 @@ report({

import blurComments from "./blurComments"
import configurationError from "./configurationError"
import cssFunctionArguments from "./cssFunctionArguments"

@@ -24,2 +25,3 @@ import cssStatementBlockString from "./cssStatementBlockString"

blurComments,
configurationError,
cssFunctionArguments,

@@ -26,0 +28,0 @@ cssStatementBlockString,

@@ -21,3 +21,8 @@ /**

export default function ({ ruleName, result, message, line, node, index, word }) {
result.stylelint = result.stylelint || {}
if (result.stylelint.quiet && result.stylelint.ruleSeverities[ruleName] !== 2) {
return
}
const startLine = (line)

@@ -27,4 +32,4 @@ ? line

if (result.disabledRanges) {
for (let range of result.disabledRanges) {
if (result.stylelint.disabledRanges) {
for (let range of result.stylelint.disabledRanges) {
if (

@@ -40,10 +45,16 @@ // If the violation is within a disabledRange,

const warningOpts = (node) ? { node } : {}
if (index) {
warningOpts.index = index
const severity = (result.stylelint.ruleSeverities) ? result.stylelint.ruleSeverities[ruleName] : 0
if (!result.stylelint.stylelintError && severity === 2) {
result.stylelint.stylelintError = true
}
if (word) {
warningOpts.word = word
const warningProperties = {
severity,
rule: ruleName,
}
result.warn(message, warningOpts)
if (node) { warningProperties.node = node }
if (index) { warningProperties.index = index }
if (word) { warningProperties.word = word }
result.warn(message, warningProperties)
}
import { assign } from "lodash"
import isWhitespace from "./isWhitespace"
import isSingleLineString from "./isSingleLineString"
import configurationError from "./configurationError"

@@ -97,3 +98,3 @@ /**

default:
throw new Error(`Unknown expectation "${expectation}"`)
throw configurationError(`Unknown expectation "${expectation}"`)
}

@@ -134,3 +135,3 @@ }

default:
throw new Error(`Unknown expectation "${expectation}"`)
throw configurationError(`Unknown expectation "${expectation}"`)
}

@@ -137,0 +138,0 @@ }

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc