Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for async rules #2351

Merged
merged 2 commits into from Feb 19, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 36 additions & 3 deletions docs/developer-guide/plugins.md
Expand Up @@ -36,6 +36,39 @@ In order for your plugin rule to work with the [standard configuration format](.

`ruleFunction` should return a function that is essentially a little [PostCSS plugin](https://github.com/postcss/postcss/blob/master/docs/writing-a-plugin.md): it takes 2 arguments: the PostCSS Root (the parsed AST), and the PostCSS LazyResult. You'll have to [learn about the PostCSS API](https://github.com/postcss/postcss/blob/master/docs/api.md).

### Asynchronous rules

Rules with asynchronous PostCSS plugins are also possible you only need to return a Promise instance.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add some punctuation here:

Rules with asynchronous PostCSS plugins are also possible! All you need to do is return a Promise instance from your plugin function.


```js
// Abbreviated asynchronous example
var stylelint = require("stylelint")

var ruleName = "plugin/foo-bar-async"
var messages = stylelint.utils.ruleMessages(ruleName, {
expected: "Expected ...",
})

module.exports = stylelint.createPlugin(ruleName, function(primaryOption, secondaryOptionObject) {
return function(postcssRoot, postcssResult) {
var validOptions = stylelint.utils.validateOptions(postcssResult, ruleName, { .. })
if (!validOptions) { return }

return new Promise(function(resolve) {
// some async operation
setTimeout(function() {
// ... some logic ...
stylelint.utils.report({ .. })
resolve()
}, 1)
})
}
})

module.exports.ruleName = ruleName
module.exports.messages = messages
```

## `stylelint.utils`

stylelint exposes some utilities that are useful. *For details about the APIs of these functions, please look at comments in the source code and examples in the standard rules.*
Expand Down Expand Up @@ -82,9 +115,9 @@ function myPluginRule(primaryOption, secondaryOptions) {
root: root
}, (warning) => {
stylelint.utils.report({
message: myMessage,
ruleName: myRuleName,
result: result,
message: myMessage,
ruleName: myRuleName,
result: result,
node: warning.node,
line: warning.line,
column: warning.column,
Expand Down
30 changes: 30 additions & 0 deletions lib/__tests__/fixtures/plugin-async.js
@@ -0,0 +1,30 @@
"use strict"

const stylelint = require("../../")

const ruleName = "plugin/async"

const rule = enabled => (root, result) => {
const validOptions = stylelint.utils.validateOptions(result, ruleName, {
actual: enabled,
possible: [ true, false ],
})

if (!validOptions) {
return null
}

return new Promise((resolve) => {
setTimeout(() => {
stylelint.utils.report({
result,
ruleName,
message: "Async rule",
node: root,
})
resolve()
})
}, 1)
}

module.exports = stylelint.createPlugin(ruleName, rule)
12 changes: 12 additions & 0 deletions lib/__tests__/plugins.test.js
Expand Up @@ -199,6 +199,18 @@ it("plugin with primary option array within options array", () => {
})
})

it("plugin with async rule", () => {
const config = {
plugins: [path.join(__dirname, "fixtures/plugin-async")],
rules: {
"plugin/async": true,
},
}
return postcss().use(stylelint(config)).process("a {}").then(result => {
expect(result.warnings().length).toBe(1)
})
})

describe("loading a plugin from process.cwd", () => {
let actualCwd
let result
Expand Down
2 changes: 1 addition & 1 deletion lib/lintSource.js
Expand Up @@ -119,7 +119,7 @@ function lintPostcssResult(
postcssResult.stylelint.customMessages[ruleName] = _.get(secondaryOptions, "message")

const performRule = Promise.resolve().then(() => {
ruleFunction(primaryOption, secondaryOptions)(postcssRoot, postcssResult)
return ruleFunction(primaryOption, secondaryOptions)(postcssRoot, postcssResult)
})
performRules.push(performRule)
})
Expand Down