117616: Created documentation for the custom lint options

This commit is contained in:
Alexandre Vryghem
2024-09-26 10:40:07 +02:00
parent eb0572640b
commit 2d8fada3c4
20 changed files with 137 additions and 23 deletions

View File

@@ -9,6 +9,8 @@ _______
[Source code](../../../../lint/src/rules/html/no-disabled-attribute-on-button.ts) [Source code](../../../../lint/src/rules/html/no-disabled-attribute-on-button.ts)
### Examples ### Examples

View File

@@ -11,6 +11,8 @@ _______
[Source code](../../../../lint/src/rules/html/themed-component-usages.ts) [Source code](../../../../lint/src/rules/html/themed-component-usages.ts)
### Examples ### Examples

View File

@@ -7,6 +7,21 @@ _______
[Source code](../../../../lint/src/rules/ts/alias-imports.ts) [Source code](../../../../lint/src/rules/ts/alias-imports.ts)
### Options
#### `aliases`
A list of all the imports that you want to alias for clarity. Every alias should be declared in the following format:
```json
{
"package": "rxjs",
"imported": "of",
"local": "observableOf"
}
```
### Examples ### Examples

View File

@@ -11,6 +11,8 @@ _______
[Source code](../../../../lint/src/rules/ts/themed-component-classes.ts) [Source code](../../../../lint/src/rules/ts/themed-component-classes.ts)
### Examples ### Examples

View File

@@ -17,6 +17,8 @@ _______
[Source code](../../../../lint/src/rules/ts/themed-component-selectors.ts) [Source code](../../../../lint/src/rules/ts/themed-component-selectors.ts)
### Examples ### Examples

View File

@@ -15,6 +15,8 @@ _______
[Source code](../../../../lint/src/rules/ts/themed-component-usages.ts) [Source code](../../../../lint/src/rules/ts/themed-component-usages.ts)
### Examples ### Examples

View File

@@ -7,6 +7,14 @@ _______
[Source code](../../../../lint/src/rules/ts/themed-decorators.ts) [Source code](../../../../lint/src/rules/ts/themed-decorators.ts)
### Options
#### `decorators`
A mapping for all the existing themeable decorators, with the decorator name as the key and the index of the `theme` argument as the value.
### Examples ### Examples

View File

@@ -7,6 +7,8 @@ _______
[Source code](../../../../lint/src/rules/ts/themed-wrapper-no-input-defaults.ts) [Source code](../../../../lint/src/rules/ts/themed-wrapper-no-input-defaults.ts)
### Examples ### Examples

View File

@@ -7,6 +7,14 @@ _______
[Source code](../../../../lint/src/rules/ts/unique-decorators.ts) [Source code](../../../../lint/src/rules/ts/unique-decorators.ts)
### Options
#### `decorators`
The list of all the decorators for which you want to enforce this behavior.
### Examples ### Examples

View File

@@ -33,6 +33,7 @@ export const info = {
[Message.USE_DSBTN_DISABLED]: 'Buttons should use the `dsBtnDisabled` directive instead of the `disabled` attribute.', [Message.USE_DSBTN_DISABLED]: 'Buttons should use the `dsBtnDisabled` directive instead of the `disabled` attribute.',
}, },
}, },
optionDocs: [],
defaultOptions: [], defaultOptions: [],
} as DSpaceESLintRuleInfo; } as DSpaceESLintRuleInfo;

View File

@@ -45,6 +45,7 @@ The only exception to this rule are unit tests, where we may want to use the bas
[Message.WRONG_SELECTOR]: 'Themeable components should be used via their ThemedComponent wrapper\'s selector', [Message.WRONG_SELECTOR]: 'Themeable components should be used via their ThemedComponent wrapper\'s selector',
}, },
}, },
optionDocs: [],
defaultOptions: [], defaultOptions: [],
} as DSpaceESLintRuleInfo; } as DSpaceESLintRuleInfo;

View File

@@ -9,6 +9,7 @@ import { Scope } from '@typescript-eslint/utils/ts-eslint';
import { import {
DSpaceESLintRuleInfo, DSpaceESLintRuleInfo,
NamedTests, NamedTests,
OptionDoc,
} from '../../util/structure'; } from '../../util/structure';
export enum Message { export enum Message {
@@ -17,13 +18,21 @@ export enum Message {
MULTIPLE_ALIASES = 'multipleAliases', MULTIPLE_ALIASES = 'multipleAliases',
} }
interface AliasImportOptions {
aliases: AliasImportOption[];
}
interface AliasImportOption { interface AliasImportOption {
package: string; package: string;
imported: string; imported: string;
local: string; local: string;
} }
export const info: DSpaceESLintRuleInfo<[[AliasImportOption]]> = { interface AliasImportDocOptions {
aliases: OptionDoc;
}
export const info: DSpaceESLintRuleInfo<[AliasImportOptions], [AliasImportDocOptions]> = {
name: 'alias-imports', name: 'alias-imports',
meta: { meta: {
docs: { docs: {
@@ -36,8 +45,7 @@ export const info: DSpaceESLintRuleInfo<[[AliasImportOption]]> = {
}, },
fixable: 'code', fixable: 'code',
type: 'problem', type: 'problem',
schema: [ schema: {
{
type: 'array', type: 'array',
items: { items: {
type: 'object', type: 'object',
@@ -48,23 +56,39 @@ export const info: DSpaceESLintRuleInfo<[[AliasImportOption]]> = {
}, },
}, },
}, },
],
}, },
optionDocs: [
{
aliases: {
title: '`aliases`',
description: `A list of all the imports that you want to alias for clarity. Every alias should be declared in the following format:
\`\`\`json
{
"package": "rxjs",
"imported": "of",
"local": "observableOf"
}
\`\`\``,
},
},
],
defaultOptions: [ defaultOptions: [
[ {
aliases: [
{ {
package: 'rxjs', package: 'rxjs',
imported: 'of', imported: 'of',
local: 'observableOf', local: 'observableOf',
}, },
], ],
},
], ],
}; };
export const rule = ESLintUtils.RuleCreator.withoutDocs({ export const rule = ESLintUtils.RuleCreator.withoutDocs({
...info, ...info,
create(context: TSESLint.RuleContext<Message, unknown[]>, options: any) { create(context: TSESLint.RuleContext<Message, unknown[]>, options: any) {
return options[0].reduce((selectors: any, option: AliasImportOption) => { return (options[0] as AliasImportOptions).aliases.reduce((selectors: any, option: AliasImportOption) => {
selectors[`ImportDeclaration[source.value = "${option.package}"] > ImportSpecifier[imported.name = "${option.imported}"][local.name != "${option.local}"]`] = (node: TSESTree.ImportSpecifier) => handleUnaliasedImport(context, option, node); selectors[`ImportDeclaration[source.value = "${option.package}"] > ImportSpecifier[imported.name = "${option.imported}"][local.name != "${option.local}"]`] = (node: TSESTree.ImportSpecifier) => handleUnaliasedImport(context, option, node);
return selectors; return selectors;
}, {}); }, {});

View File

@@ -52,6 +52,7 @@ export const info = {
[Message.WRAPPER_IMPORTS_BASE]: 'Themed component wrapper classes must only import the base class', [Message.WRAPPER_IMPORTS_BASE]: 'Themed component wrapper classes must only import the base class',
}, },
}, },
optionDocs: [],
defaultOptions: [], defaultOptions: [],
} as DSpaceESLintRuleInfo; } as DSpaceESLintRuleInfo;

View File

@@ -53,6 +53,7 @@ Unit tests are exempt from this rule, because they may redefine components using
[Message.THEMED]: 'Theme override of themeable component should have a selector starting with \'ds-themed-\'', [Message.THEMED]: 'Theme override of themeable component should have a selector starting with \'ds-themed-\'',
}, },
}, },
optionDocs: [],
defaultOptions: [], defaultOptions: [],
} as DSpaceESLintRuleInfo; } as DSpaceESLintRuleInfo;

View File

@@ -63,6 +63,7 @@ There are a few exceptions where the base class can still be used:
[Message.BASE_IN_MODULE]: 'Base themeable components shouldn\'t be declared in modules', [Message.BASE_IN_MODULE]: 'Base themeable components shouldn\'t be declared in modules',
}, },
}, },
optionDocs: [],
defaultOptions: [], defaultOptions: [],
} as DSpaceESLintRuleInfo; } as DSpaceESLintRuleInfo;

View File

@@ -10,6 +10,7 @@ import { isTestFile } from '../../util/filter';
import { import {
DSpaceESLintRuleInfo, DSpaceESLintRuleInfo,
NamedTests, NamedTests,
OptionDoc,
} from '../../util/structure'; } from '../../util/structure';
import { getFileTheme } from '../../util/theme-support'; import { getFileTheme } from '../../util/theme-support';
@@ -23,7 +24,11 @@ interface ThemedDecoratorsOption {
decorators: { [name: string]: number }; decorators: { [name: string]: number };
} }
export const info: DSpaceESLintRuleInfo<[ThemedDecoratorsOption]> = { interface ThemedDecoratorsDocsOption {
decorators: OptionDoc;
}
export const info: DSpaceESLintRuleInfo<[ThemedDecoratorsOption], [ThemedDecoratorsDocsOption]> = {
name: 'themed-decorators', name: 'themed-decorators',
meta: { meta: {
docs: { docs: {
@@ -47,6 +52,14 @@ export const info: DSpaceESLintRuleInfo<[ThemedDecoratorsOption]> = {
}, },
], ],
}, },
optionDocs: [
{
decorators: {
title: '`decorators`',
description: 'A mapping for all the existing themeable decorators, with the decorator name as the key and the index of the `theme` argument as the value.',
},
},
],
defaultOptions: [ defaultOptions: [
{ {
decorators: { decorators: {

View File

@@ -26,6 +26,7 @@ export const info: DSpaceESLintRuleInfo = {
type: 'problem', type: 'problem',
schema: [], schema: [],
}, },
optionDocs: [],
defaultOptions: [], defaultOptions: [],
}; };

View File

@@ -9,6 +9,7 @@ import { isTestFile } from '../../util/filter';
import { import {
DSpaceESLintRuleInfo, DSpaceESLintRuleInfo,
NamedTests, NamedTests,
OptionDoc,
} from '../../util/structure'; } from '../../util/structure';
export enum Message { export enum Message {
@@ -17,7 +18,15 @@ export enum Message {
const decoratorCalls: Map<string, Set<string>> = new Map(); const decoratorCalls: Map<string, Set<string>> = new Map();
export const info: DSpaceESLintRuleInfo = { export interface UniqueDecoratorsOptions {
decorators: string[];
}
export interface UniqueDecoratorsDocOptions {
decorators: OptionDoc;
}
export const info: DSpaceESLintRuleInfo<[UniqueDecoratorsOptions], [UniqueDecoratorsDocOptions]> = {
name: 'unique-decorators', name: 'unique-decorators',
meta: { meta: {
docs: { docs: {
@@ -41,6 +50,14 @@ export const info: DSpaceESLintRuleInfo = {
}, },
], ],
}, },
optionDocs: [
{
decorators: {
title: '`decorators`',
description: 'The list of all the decorators for which you want to enforce this behavior.',
},
},
],
defaultOptions: [ defaultOptions: [
{ {
decorators: [ decorators: [

View File

@@ -17,12 +17,18 @@ export type Meta = RuleMetaData<string, unknown[]>;
export type Valid = ValidTestCase<unknown[]>; export type Valid = ValidTestCase<unknown[]>;
export type Invalid = InvalidTestCase<string, unknown[]>; export type Invalid = InvalidTestCase<string, unknown[]>;
export interface DSpaceESLintRuleInfo<T = unknown[]> { export interface DSpaceESLintRuleInfo<T = unknown[], D = unknown[]> {
name: string; name: string;
meta: Meta, meta: Meta,
optionDocs: D,
defaultOptions: T, defaultOptions: T,
} }
export interface OptionDoc {
title: string;
description: string;
}
export interface NamedTests { export interface NamedTests {
plugin: string; plugin: string;
valid: Valid[]; valid: Valid[];

View File

@@ -7,6 +7,11 @@ _______
[Source code](../../../../lint/src/rules/<%- plugin.name.replace('dspace-angular-', '') %>/<%- rule.name %>.ts) [Source code](../../../../lint/src/rules/<%- plugin.name.replace('dspace-angular-', '') %>/<%- rule.name %>.ts)
<% if (rule.optionDocs?.length > 0) { %>
### Options
<%- rule.optionDocs.map(optionDoc => Object.keys(optionDoc).map(option => '\n#### ' + optionDoc[option].title + '\n\n' + optionDoc[option].description)) %>
<% } %>
### Examples ### Examples
<% if (tests.valid) {%> <% if (tests.valid) {%>