Appearance
Writing Rule Plugins
Plugins let you extend @lapidist/design-lint
with custom rules distributed as normal npm packages. A plugin exports an object with a rules
array containing one or more RuleModule
implementations.
Step-by-step
Create a new package
bashmkdir design-lint-plugin-example && cd design-lint-plugin-example npm init -y npm install @lapidist/design-lint
Author a rule
ts// rules/no-hardcoded-colors.ts import type { RuleModule } from '@lapidist/design-lint'; export const noHardcodedColors: RuleModule = { name: 'plugin/no-hardcoded-colors', meta: { description: 'disallow colors outside the design tokens' }, create(context) { const allowed = new Set(Object.values(context.tokens.colors || {})); return { onCSSDeclaration(decl) { if (!allowed.has(decl.value)) { context.report({ message: `Unexpected color ${decl.value}`, line: decl.line, column: decl.column, }); } }, }; }, };
This mirrors the built-in
token-colors
rule which checks CSS and string literals for non-token colors.Note: Rule names must be unique across all plugins. Duplicates will cause an engine error during plugin loading.
Export the plugin
ts// index.ts import { noHardcodedColors } from './rules/no-hardcoded-colors'; export const rules = [noHardcodedColors];
Use the plugin by listing it in
designlint.config.js
:jsmodule.exports = { plugins: ['@org/design-lint-plugin-example'], rules: { '@org/design-lint-plugin-example/no-hardcoded-colors': 'error', }, };
Publish the package to npm when ready:
bashnpm publish --access public
Troubleshooting
- Plugin not found: ensure the package is installed and referenced in the
plugins
array. - Invalid plugin shape: the default export must be an object like
{ rules: RuleModule[] }
. - Rule never runs: confirm the rule
name
matches the key used in the configuration.
API Reference
RuleModule
ts
interface RuleModule {
name: string;
meta: { description: string };
create(context: RuleContext): RuleListener;
}
RuleContext
ts
interface RuleContext {
report(msg): void;
tokens: DesignTokens;
options?: unknown;
filePath: string;
}
RuleListener
ts
interface RuleListener {
onNode?(node: ts.Node): void;
onCSSDeclaration?(decl: CSSDeclaration): void;
}
PluginModule
ts
interface PluginModule {
rules: RuleModule[];
}
For more examples, inspect the built-in rules such as component-usage
.