Skip to content

Commit

Permalink
Fix plugins.md document and createPlugin type definition
Browse files Browse the repository at this point in the history
  • Loading branch information
ybiquitous committed Aug 13, 2022
1 parent 4772851 commit 121a34f
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 71 deletions.
112 changes: 56 additions & 56 deletions docs/developer-guide/plugins.md
Expand Up @@ -26,33 +26,32 @@ const meta = {
// deprecated: true,
};

module.exports = stylelint.createPlugin(
ruleName,
(primaryOption, secondaryOptionObject) => {
return (postcssRoot, postcssResult) => {
const validOptions = stylelint.utils.validateOptions(
postcssResult,
ruleName,
{
/* .. */
}
);

if (!validOptions) {
return;
const ruleFunction = (primaryOption, secondaryOptionObject) => {
return (postcssRoot, postcssResult) => {
const validOptions = stylelint.utils.validateOptions(
postcssResult,
ruleName,
{
/* .. */
}
);

// ... some logic ...
stylelint.utils.report({
/* .. */
});
};
}
);
if (!validOptions) {
return;
}

// ... some logic ...
stylelint.utils.report({
/* .. */
});
};
};

module.exports.ruleName = ruleName;
module.exports.messages = messages;
module.exports.meta = meta;
ruleFunction.ruleName = ruleName;
ruleFunction.messages = messages;
ruleFunction.meta = meta;

module.exports = stylelint.createPlugin(ruleName, ruleFunction);
```

Your plugin's rule name must be namespaced, e.g. `your-namespace/your-rule-name`, to ensure it never clashes with the built-in rules. If your plugin provides only a single rule or you can't think of a good namespace, you can use `plugin/my-rule`. _You should document your plugin's rule name (and namespace) because users need to use them in their config._
Expand Down Expand Up @@ -89,39 +88,38 @@ const meta = {
/* .. */
};

module.exports = stylelint.createPlugin(
ruleName,
(primaryOption, secondaryOptionObject) => {
return (postcssRoot, postcssResult) => {
const validOptions = stylelint.utils.validateOptions(
postcssResult,
ruleName,
{
/* .. */
}
);

if (!validOptions) {
return;
const ruleFunction = (primaryOption, secondaryOptionObject) => {
return (postcssRoot, postcssResult) => {
const validOptions = stylelint.utils.validateOptions(
postcssResult,
ruleName,
{
/* .. */
}
);

return new Promise((resolve) => {
// some async operation
setTimeout(() => {
// ... some logic ...
stylelint.utils.report({
/* .. */
});
resolve();
}, 1);
});
};
}
);
if (!validOptions) {
return;
}

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

ruleFunction.ruleName = ruleName;
ruleFunction.messages = messages;
ruleFunction.meta = meta;

module.exports.ruleName = ruleName;
module.exports.messages = messages;
module.exports.meta = meta;
module.exports = stylelint.createPlugin(ruleName, ruleFunction);
```

## Testing
Expand All @@ -132,7 +130,9 @@ For example:

```js
// index.test.js
const { messages, ruleName } = require(".");
const {
rule: { ruleName, messages }
} = require(".");

testRule({
plugins: ["./index.js"],
Expand All @@ -153,7 +153,7 @@ testRule({
{
code: ".myClass {}",
fixed: ".my-class {}",
message: messages.expected(),
message: messages.expected,
line: 1,
column: 1,
endLine: 1,
Expand Down
16 changes: 13 additions & 3 deletions lib/__tests__/fixtures/plugin-warn-about-foo.js
Expand Up @@ -4,11 +4,15 @@ const stylelint = require('../..');

const ruleName = 'plugin/warn-about-foo';

const warnAboutFooMessages = stylelint.utils.ruleMessages('plugin/warn-about-foo', {
const warnAboutFooMessages = stylelint.utils.ruleMessages(ruleName, {
found: 'found .foo',
});

module.exports = stylelint.createPlugin(ruleName, (expectation) => {
const meta = {
url: 'https://github.com/stylelint/stylelint-foo-plugin/warn-about-foo',
};

const warnAboutFoo = (expectation) => {
return (root, result) => {
root.walkRules((rule) => {
if (rule.selector === '.foo' && expectation === 'always') {
Expand All @@ -21,4 +25,10 @@ module.exports = stylelint.createPlugin(ruleName, (expectation) => {
}
});
};
});
};

warnAboutFoo.ruleName = ruleName;
warnAboutFoo.messages = warnAboutFooMessages;
warnAboutFoo.meta = meta;

module.exports = stylelint.createPlugin(ruleName, warnAboutFoo);
13 changes: 13 additions & 0 deletions lib/__tests__/plugins.test.js
Expand Up @@ -67,6 +67,19 @@ it('another plugin runs', async () => {
expect(result.warnings()[0].text).toBe('Unexpected empty block (block-no-empty)');
});

it('plugin with rule metadata', async () => {
const result = await processorRelative.process(cssWithFoo, { from: undefined });

expect(result.stylelint).toHaveProperty('ruleMetadata', {
'plugin/warn-about-foo': {
url: 'https://github.com/stylelint/stylelint-foo-plugin/warn-about-foo',
},
'block-no-empty': {
url: expect.stringMatching(/block-no-empty/),
},
});
});

it('plugin with absolute path and no configBasedir', async () => {
const result = await processorAbsolute.process(cssWithFoo, { from: undefined });

Expand Down
12 changes: 3 additions & 9 deletions lib/createPlugin.js
@@ -1,17 +1,11 @@
'use strict';

/** @typedef {import('stylelint').Rule} StylelintRule */

/**
* @param {string} ruleName
* @param {StylelintRule} rule
* @returns {{ruleName: string, rule: StylelintRule}}
* @type {typeof import('stylelint').createPlugin}
*/
function createPlugin(ruleName, rule) {
module.exports = function createPlugin(ruleName, rule) {
return {
ruleName,
rule,
};
}

module.exports = /** @type {typeof import('stylelint').createPlugin} */ (createPlugin);
};
4 changes: 2 additions & 2 deletions types/stylelint/index.d.ts
Expand Up @@ -188,7 +188,7 @@ declare module 'stylelint' {
meta?: RuleMeta;
};

export type Plugin<P = any, S = any> = RuleBase<P, S>;
export type Plugin = RuleBase;

export type CodeProcessor = (code: string, file: string | undefined) => string;

Expand Down Expand Up @@ -440,7 +440,7 @@ declare module 'stylelint' {
/**
* Creates a Stylelint plugin.
*/
createPlugin: (ruleName: string, plugin: Plugin) => { ruleName: string; rule: Rule };
createPlugin: (ruleName: string, rule: Rule) => { ruleName: string; rule: Rule };
/**
* Internal use only. Do not use or rely on this method. It may
* change at any time.
Expand Down
10 changes: 9 additions & 1 deletion types/stylelint/type-test.ts
Expand Up @@ -12,6 +12,8 @@ import type {
LintResult,
LinterResult,
Plugin,
Rule,
RuleMeta,
Warning,
} from 'stylelint';
import stylelint from 'stylelint';
Expand Down Expand Up @@ -84,6 +86,7 @@ const messages = stylelint.utils.ruleMessages(ruleName, {
warning: (reason) => `This is not allowed because ${reason}`,
withNarrowedParam: (mixinName: string) => `Mixin not allowed: ${mixinName}`,
});
const meta: RuleMeta = { url: '...' };
const problemMessage: string = messages.problem;
const problemFunc: (...reason: string[]) => string = messages.warning;

Expand Down Expand Up @@ -115,7 +118,12 @@ const testPlugin: Plugin = (options) => {
};
};

stylelint.createPlugin(ruleName, testPlugin);
(testPlugin as Rule).ruleName = ruleName;
(testPlugin as Rule).messages = messages;
(testPlugin as Rule).primaryOptionArray = true;
(testPlugin as Rule).meta = meta;

stylelint.createPlugin(ruleName, testPlugin as Rule);

messages.withNarrowedParam('should work');

Expand Down

0 comments on commit 121a34f

Please sign in to comment.