npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

stylelint-rule-creator

v5.1.0

Published

Create custom stylelint rules with less boilerplate.

Downloads

55,820

Readme

Stylelint Rule Creator

This is not an official stylelint package.

tests

Create custom stylelint rules with less boilerplate.

This package greatly reduces the complexity of creating custom stylelint rules. All that is needed is calling a single function to generate a testable and directly exportable rule to stylelint as a plugin. All the necessary types are also included to keep everything type safe.

There are two ways of creating a decreased-boilerplate rule with this package. Both export an object which can be directly exported as a Plugin for stylelint.

  • There's the opinionated DefaultRule created with createDefaultRule. DefaultRule is very easy to test, automatically generates tests based on those supplied to it, and is much more type safe.
  • There's the bare-bones Rule created with createRule. This is less opinionated than DefaultRule but requires more checking in the rule and setup for tests.

If possible, prefer using DefaultRule with createDefaultRule to have the best experience.

Installation

npm install stylelint-rule-creator

createDefaultRule Usage

This is the recommended way of creating a rule.

createDefaultRule creates a DefaultRule object which greatly reduces boilerplate needed for type checking and testing. Extra tests are automatically generated from the tests you supply. Stricter typing is enforced on DefaultRule and its tests.

DefaultRule requires that the rule is always enabled with a single option (no secondary options) which is either a boolean or an object, as seen in the following type:

boolean | {
    mode: DefaultOptionMode;
    fileExceptions?: string[];
    lineExceptions?: string[];
}

This type can easily be extended to add more properties to the object portion of that format (which is done in the example DefaultRule), like so:

import {DefaultRuleOptions} from 'stylelint-rule-creator';

type MyCustomRuleOptions = DefaultRuleOptions & {
    // note that all values must be either strings or numbers because this will come straight from a stylelint config file
    anotherProperty: string;
};

If more flexibility is needed, use the simpler createRule which is explained in a later section.

Create a DefaultRule like so:

import {DefaultRuleOptions, DefaultOptionMode, createDefaultRule} from 'stylelint-rule-creator';

const messages = {
    exampleMessage(input: string) {
        return `Example message with ${input}`;
    },
};

export const exampleDefaultRule = createDefaultRule<typeof messages, DefaultRuleOptions>({
    ruleName: 'my-plugin-name/my-rule-name',
    messages,
    defaultOptions: {
        mode: DefaultOptionMode.REQUIRE,
    },
    ruleCallback: (report, messages, {ruleOptions, root}) => {
        // whatever your rule does here

        // example:
        root.walkDecls((decl) => {
            if (decl.prop === 'visibility') {
                report({
                    message: messages.myMessageName(decl.value),
                    node: decl,
                    word: decl.value,
                });
            }
        });
    },
});

For more info, see the source code here, which is heavily documented.

See this file for an example using createDefaultRule.

DefaultRule Testing

Testing a DefaultRule (the output of createDefaultRule) is very simple and requires very little boilerplate.

import {testDefaultRule, DefaultOptionMode} from 'stylelint-rule-creator';

testDefaultRule({
    rule: yourRuleHere,
    pluginPath: 'path/to/plugin/file.js',
    tests: [
        {
            ruleOptions: {
                mode: DefaultOptionMode.REQUIRE,
            },
            description: 'top level description optional',
            accept: [
                {
                    code: 'whatever code here',
                    description:
                        'lower level description optional but should exist if top level description does not',
                },
            ],
            reject: [
                {
                    code: 'whatever code here',
                    description:
                        'lower level description optional but should exist if top level description does not',
                    message:
                        'message with rule name must be supplied for rejections (plugin-name/rule-name)',
                },
            ],
        },
        //... more tests
    ],
});

For more info, see the default rule test source code here, which is heavily documented.

See this file for example DefaultRule tests.

createRule Usage

This creates a basic Rule which can be directly exported to stylelint as a plugin just as the above DefaultRule can be. Rule is much simpler than DefaultRule and doesn't provide as many typing or testing benefits. It, however, makes less requirements on your input rule options. For example, this allows primary and secondary options (whereas DefaultRule requires all information to be in a singular primary option).

To create a Rule, use the following:

import {createRule} from 'stylelint-rule-creator';

export const myExampleRule = createRule({
    ruleName: 'my-plugin-name/my-rule-name',
    messages: {
        myMessageName: (messageInput: string) => `My message example: ${messageInput}`,
    },
    ruleCallback: (report, messages, {primaryOption, root}) => {
        // whatever your rule does here

        // example:
        if (!primaryOption) {
            // this needs to be checked because the basic createRule function doesn't do any option checking for us
            return;
        }

        root.walkDecls((decl) => {
            if (decl.prop === 'visibility') {
                report({
                    message: messages.myMessageName(decl.value),
                    node: decl,
                    word: decl.value,
                });
            }
        });
    },
});

See this file for an example using createRule.

Rule Testing

When not using createDefaultRule, testing is more verbose and requires more boilerplate.

This package exports the functionality of the stylelint-jest-rule-tester package to be used for these testing purposes.

Create testRule

In a central file somewhere, create your testRule function by calling getTestRuleFunction with a reference to your plugin's main file:

import {getTestRuleFunction} from 'stylelint-rule-creator';

export const testRule = getTestRuleFunction({
    // a plugin must be supplied so that stylelint can find the rule(s) you want to test
    linterOptions: {config: {plugins: ['./dist/index.js']}},
});

In this example, dist/index.js should be the file which is exporting your rules as its default export. See this plugin test file as an example of this.

Use testRule

Then, in your rule's test file, import and call testRule like so:

import {exampleRule} from './example.rule';
import {testRule} from '.';

testRule({
    ruleName: exampleRule.name,
    ruleOptions: [true],
    fix: false,
    accept: [
        {
            // this code should pass the rule
            code: 'div { color: blue }',
        },
    ],
    reject: [
        {
            // this code should fail the rule
            code: 'div { color: blue; visibility: hidden; }',
            message: exampleRule.messages.myMessageName('hidden'),
        },
    ],
});

See this file for example Rule tests.