@db-ux/core-eslint-plugin 0.0.0 → 4.4.2-eslint-plugin-28ea614
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -0
- package/README.md +754 -0
- package/build/index.d.ts +99 -0
- package/build/index.js +79 -0
- package/build/rules/accordion/no-nested-accordion.d.ts +5 -0
- package/build/rules/accordion/no-nested-accordion.js +37 -0
- package/build/rules/badge/badge-corner-placement-rules.d.ts +5 -0
- package/build/rules/badge/badge-corner-placement-rules.js +76 -0
- package/build/rules/badge/badge-no-inline-in-interactive.d.ts +5 -0
- package/build/rules/badge/badge-no-inline-in-interactive.js +67 -0
- package/build/rules/button/button-no-text-requires-tooltip.d.ts +5 -0
- package/build/rules/button/button-no-text-requires-tooltip.js +59 -0
- package/build/rules/button/button-single-icon-attribute.d.ts +5 -0
- package/build/rules/button/button-single-icon-attribute.js +35 -0
- package/build/rules/button/button-type-required.d.ts +5 -0
- package/build/rules/button/button-type-required.js +45 -0
- package/build/rules/close-button/close-button-text-required.d.ts +5 -0
- package/build/rules/close-button/close-button-text-required.js +40 -0
- package/build/rules/content/text-or-children-required.d.ts +5 -0
- package/build/rules/content/text-or-children-required.js +49 -0
- package/build/rules/form/form-label-required.d.ts +5 -0
- package/build/rules/form/form-label-required.js +47 -0
- package/build/rules/form/form-validation-message-required.d.ts +5 -0
- package/build/rules/form/form-validation-message-required.js +93 -0
- package/build/rules/header/header-burger-menu-label-required.d.ts +5 -0
- package/build/rules/header/header-burger-menu-label-required.js +32 -0
- package/build/rules/icon/prefer-icon-attribute.d.ts +5 -0
- package/build/rules/icon/prefer-icon-attribute.js +67 -0
- package/build/rules/input/input-file-type-validation.d.ts +5 -0
- package/build/rules/input/input-file-type-validation.js +52 -0
- package/build/rules/input/input-type-required.d.ts +5 -0
- package/build/rules/input/input-type-required.js +40 -0
- package/build/rules/link/link-external-security.d.ts +5 -0
- package/build/rules/link/link-external-security.js +50 -0
- package/build/rules/navigation/navigation-item-back-button-text-required.d.ts +5 -0
- package/build/rules/navigation/navigation-item-back-button-text-required.js +32 -0
- package/build/rules/select/custom-select-tags-remove-text-required.d.ts +5 -0
- package/build/rules/select/custom-select-tags-remove-text-required.js +35 -0
- package/build/rules/select/select-requires-options.d.ts +5 -0
- package/build/rules/select/select-requires-options.js +44 -0
- package/build/rules/tag/tag-removable-remove-button-required.d.ts +5 -0
- package/build/rules/tag/tag-removable-remove-button-required.js +35 -0
- package/build/rules/tooltip/no-interactive-tooltip-content.d.ts +5 -0
- package/build/rules/tooltip/no-interactive-tooltip-content.js +47 -0
- package/build/rules/tooltip/tooltip-requires-interactive-parent.d.ts +5 -0
- package/build/rules/tooltip/tooltip-requires-interactive-parent.js +47 -0
- package/build/shared/utils.d.ts +5 -0
- package/build/shared/utils.js +61 -0
- package/package.json +32 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getAttributeValue, isDBComponent } from '../../shared/utils.js';
|
|
3
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/db-ux-design-system/core-web/blob/main/packages/eslint-plugin/README.md#${name}`);
|
|
4
|
+
const FORM_COMPONENTS = [
|
|
5
|
+
'DBInput',
|
|
6
|
+
'DBTextarea',
|
|
7
|
+
'DBSelect',
|
|
8
|
+
'DBCustomSelect',
|
|
9
|
+
'DBCheckbox',
|
|
10
|
+
'DBRadio',
|
|
11
|
+
'DBSwitch'
|
|
12
|
+
];
|
|
13
|
+
const COMPONENTS_WITH_CHILDREN_LABEL = ['DBCheckbox', 'DBRadio', 'DBSwitch'];
|
|
14
|
+
export default createRule({
|
|
15
|
+
name: 'form-label-required',
|
|
16
|
+
meta: {
|
|
17
|
+
type: 'problem',
|
|
18
|
+
docs: {
|
|
19
|
+
description: 'Ensure form components have a label attribute for accessibility'
|
|
20
|
+
},
|
|
21
|
+
messages: {
|
|
22
|
+
missingLabel: '{{component}} must have a label attribute for accessibility'
|
|
23
|
+
},
|
|
24
|
+
schema: []
|
|
25
|
+
},
|
|
26
|
+
defaultOptions: [],
|
|
27
|
+
create(context) {
|
|
28
|
+
return {
|
|
29
|
+
JSXElement(node) {
|
|
30
|
+
const openingElement = node.openingElement;
|
|
31
|
+
const component = FORM_COMPONENTS.find((comp) => isDBComponent(openingElement, comp));
|
|
32
|
+
if (!component)
|
|
33
|
+
return;
|
|
34
|
+
const label = getAttributeValue(openingElement, 'label');
|
|
35
|
+
const hasChildren = node.children.some((child) => child.type === 'JSXText' && child.value.trim() !== '');
|
|
36
|
+
const canUseChildren = COMPONENTS_WITH_CHILDREN_LABEL.includes(component);
|
|
37
|
+
if (!label && !(canUseChildren && hasChildren)) {
|
|
38
|
+
context.report({
|
|
39
|
+
node: openingElement,
|
|
40
|
+
messageId: 'missingLabel',
|
|
41
|
+
data: { component }
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getAttributeValue, isDBComponent } from '../../shared/utils.js';
|
|
3
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/db-ux-design-system/core-web/blob/main/packages/eslint-plugin/README.md#${name}`);
|
|
4
|
+
const FORM_COMPONENTS = [
|
|
5
|
+
'DBInput',
|
|
6
|
+
'DBTextarea',
|
|
7
|
+
'DBSelect',
|
|
8
|
+
'DBCustomSelect',
|
|
9
|
+
'DBCheckbox'
|
|
10
|
+
];
|
|
11
|
+
export default createRule({
|
|
12
|
+
name: 'form-validation-message-required',
|
|
13
|
+
meta: {
|
|
14
|
+
type: 'problem',
|
|
15
|
+
docs: {
|
|
16
|
+
description: 'Ensure form components with validation have invalidMessage'
|
|
17
|
+
},
|
|
18
|
+
messages: {
|
|
19
|
+
missingInvalidMessage: '{{component}} with {{attribute}} must have invalidMessage attribute'
|
|
20
|
+
},
|
|
21
|
+
schema: []
|
|
22
|
+
},
|
|
23
|
+
defaultOptions: [],
|
|
24
|
+
create(context) {
|
|
25
|
+
return {
|
|
26
|
+
JSXElement(node) {
|
|
27
|
+
const component = FORM_COMPONENTS.find((comp) => isDBComponent(node.openingElement, comp));
|
|
28
|
+
if (!component)
|
|
29
|
+
return;
|
|
30
|
+
const invalidMessage = getAttributeValue(node.openingElement, 'invalidMessage');
|
|
31
|
+
if (invalidMessage)
|
|
32
|
+
return;
|
|
33
|
+
const required = getAttributeValue(node.openingElement, 'required');
|
|
34
|
+
if (required) {
|
|
35
|
+
context.report({
|
|
36
|
+
node: node.openingElement,
|
|
37
|
+
messageId: 'missingInvalidMessage',
|
|
38
|
+
data: { component, attribute: 'required' }
|
|
39
|
+
});
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (component === 'DBInput' || component === 'DBTextarea') {
|
|
43
|
+
const maxLength = getAttributeValue(node.openingElement, 'maxLength');
|
|
44
|
+
const minLength = getAttributeValue(node.openingElement, 'minLength');
|
|
45
|
+
if (maxLength) {
|
|
46
|
+
context.report({
|
|
47
|
+
node: node.openingElement,
|
|
48
|
+
messageId: 'missingInvalidMessage',
|
|
49
|
+
data: { component, attribute: 'maxLength' }
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (minLength) {
|
|
54
|
+
context.report({
|
|
55
|
+
node: node.openingElement,
|
|
56
|
+
messageId: 'missingInvalidMessage',
|
|
57
|
+
data: { component, attribute: 'minLength' }
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (component === 'DBInput') {
|
|
63
|
+
const min = getAttributeValue(node.openingElement, 'min');
|
|
64
|
+
const max = getAttributeValue(node.openingElement, 'max');
|
|
65
|
+
const pattern = getAttributeValue(node.openingElement, 'pattern');
|
|
66
|
+
if (min) {
|
|
67
|
+
context.report({
|
|
68
|
+
node: node.openingElement,
|
|
69
|
+
messageId: 'missingInvalidMessage',
|
|
70
|
+
data: { component, attribute: 'min' }
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (max) {
|
|
75
|
+
context.report({
|
|
76
|
+
node: node.openingElement,
|
|
77
|
+
messageId: 'missingInvalidMessage',
|
|
78
|
+
data: { component, attribute: 'max' }
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (pattern) {
|
|
83
|
+
context.report({
|
|
84
|
+
node: node.openingElement,
|
|
85
|
+
messageId: 'missingInvalidMessage',
|
|
86
|
+
data: { component, attribute: 'pattern' }
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getAttributeValue, isDBComponent } from '../../shared/utils.js';
|
|
3
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/db-ux-design-system/core-web/blob/main/packages/eslint-plugin/README.md#${name}`);
|
|
4
|
+
export default createRule({
|
|
5
|
+
name: 'header-burger-menu-label-required',
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Ensure DBHeader has burgerMenuLabel for accessibility'
|
|
10
|
+
},
|
|
11
|
+
messages: {
|
|
12
|
+
missingBurgerMenuLabel: 'DBHeader must have burgerMenuLabel attribute for accessibility'
|
|
13
|
+
},
|
|
14
|
+
schema: []
|
|
15
|
+
},
|
|
16
|
+
defaultOptions: [],
|
|
17
|
+
create(context) {
|
|
18
|
+
return {
|
|
19
|
+
JSXElement(node) {
|
|
20
|
+
if (!isDBComponent(node.openingElement, 'DBHeader'))
|
|
21
|
+
return;
|
|
22
|
+
const burgerMenuLabel = getAttributeValue(node.openingElement, 'burgerMenuLabel');
|
|
23
|
+
if (!burgerMenuLabel) {
|
|
24
|
+
context.report({
|
|
25
|
+
node: node.openingElement,
|
|
26
|
+
messageId: 'missingBurgerMenuLabel'
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getAttributeValue, isDBComponent } from '../../shared/utils.js';
|
|
3
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/db-ux-design-system/core-web/blob/main/packages/eslint-plugin/README.md#${name}`);
|
|
4
|
+
const COMPONENTS_WITH_ICON_ATTR = [
|
|
5
|
+
'DBInput',
|
|
6
|
+
'DBBrand',
|
|
7
|
+
'DBButton',
|
|
8
|
+
'DBCustomSelectListItem',
|
|
9
|
+
'DBCustomSelect',
|
|
10
|
+
'DBInfotext',
|
|
11
|
+
'DBLink',
|
|
12
|
+
'DBNavigationItem',
|
|
13
|
+
'DBNotification',
|
|
14
|
+
'DBSelect',
|
|
15
|
+
'DBSwitch',
|
|
16
|
+
'DBTabItem',
|
|
17
|
+
'DBTag'
|
|
18
|
+
];
|
|
19
|
+
export default createRule({
|
|
20
|
+
name: 'prefer-icon-attribute',
|
|
21
|
+
meta: {
|
|
22
|
+
type: 'suggestion',
|
|
23
|
+
docs: {
|
|
24
|
+
description: 'Prefer icon attribute over DBIcon child component'
|
|
25
|
+
},
|
|
26
|
+
fixable: 'code',
|
|
27
|
+
messages: {
|
|
28
|
+
preferAttribute: 'Use icon attribute instead of DBIcon child in {{component}}'
|
|
29
|
+
},
|
|
30
|
+
schema: []
|
|
31
|
+
},
|
|
32
|
+
defaultOptions: [],
|
|
33
|
+
create(context) {
|
|
34
|
+
return {
|
|
35
|
+
JSXElement(node) {
|
|
36
|
+
const openingElement = node.openingElement;
|
|
37
|
+
const component = COMPONENTS_WITH_ICON_ATTR.find((comp) => isDBComponent(openingElement, comp));
|
|
38
|
+
if (!component)
|
|
39
|
+
return;
|
|
40
|
+
const iconChild = node.children.find((child) => child.type === 'JSXElement' &&
|
|
41
|
+
isDBComponent(child.openingElement, 'DBIcon'));
|
|
42
|
+
if (iconChild) {
|
|
43
|
+
const iconValue = getAttributeValue(iconChild.openingElement, 'icon');
|
|
44
|
+
context.report({
|
|
45
|
+
node: iconChild,
|
|
46
|
+
messageId: 'preferAttribute',
|
|
47
|
+
data: { component },
|
|
48
|
+
fix(fixer) {
|
|
49
|
+
if (!iconValue || typeof iconValue !== 'string')
|
|
50
|
+
return null;
|
|
51
|
+
const fixes = [];
|
|
52
|
+
// Remove DBIcon child
|
|
53
|
+
fixes.push(fixer.remove(iconChild));
|
|
54
|
+
// Add icon attribute to parent
|
|
55
|
+
const lastAttr = openingElement.attributes[openingElement.attributes.length - 1];
|
|
56
|
+
const insertPos = lastAttr
|
|
57
|
+
? lastAttr.range[1]
|
|
58
|
+
: openingElement.name.range[1];
|
|
59
|
+
fixes.push(fixer.insertTextAfterRange([insertPos, insertPos], ` icon="${iconValue}"`));
|
|
60
|
+
return fixes;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getAttributeValue, isDBComponent } from '../../shared/utils.js';
|
|
3
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/db-ux-design-system/core-web/blob/main/packages/eslint-plugin/README.md#${name}`);
|
|
4
|
+
export default createRule({
|
|
5
|
+
name: 'input-file-type-validation',
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Ensure DBInput file type has accept and validate file-only attributes'
|
|
10
|
+
},
|
|
11
|
+
messages: {
|
|
12
|
+
missingAccept: 'DBInput with type="file" should have accept attribute',
|
|
13
|
+
invalidMultiple: 'DBInput multiple attribute is only valid for type="file"',
|
|
14
|
+
invalidAccept: 'DBInput accept attribute is only valid for type="file"'
|
|
15
|
+
},
|
|
16
|
+
schema: []
|
|
17
|
+
},
|
|
18
|
+
defaultOptions: [],
|
|
19
|
+
create(context) {
|
|
20
|
+
return {
|
|
21
|
+
JSXElement(node) {
|
|
22
|
+
if (!isDBComponent(node.openingElement, 'DBInput'))
|
|
23
|
+
return;
|
|
24
|
+
const type = getAttributeValue(node.openingElement, 'type');
|
|
25
|
+
const accept = getAttributeValue(node.openingElement, 'accept');
|
|
26
|
+
const multiple = getAttributeValue(node.openingElement, 'multiple');
|
|
27
|
+
if (type === 'file') {
|
|
28
|
+
if (!accept) {
|
|
29
|
+
context.report({
|
|
30
|
+
node: node.openingElement,
|
|
31
|
+
messageId: 'missingAccept'
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
if (multiple) {
|
|
37
|
+
context.report({
|
|
38
|
+
node: node.openingElement,
|
|
39
|
+
messageId: 'invalidMultiple'
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
if (accept) {
|
|
43
|
+
context.report({
|
|
44
|
+
node: node.openingElement,
|
|
45
|
+
messageId: 'invalidAccept'
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getAttributeValue, isDBComponent } from '../../shared/utils.js';
|
|
3
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/db-ux-design-system/core-web/blob/main/packages/eslint-plugin/README.md#${name}`);
|
|
4
|
+
export default createRule({
|
|
5
|
+
name: 'input-type-required',
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'suggestion',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Ensure DBInput has type attribute for better developer experience'
|
|
10
|
+
},
|
|
11
|
+
fixable: 'code',
|
|
12
|
+
messages: {
|
|
13
|
+
missingType: 'DBInput should have type attribute for better developer experience'
|
|
14
|
+
},
|
|
15
|
+
schema: []
|
|
16
|
+
},
|
|
17
|
+
defaultOptions: [],
|
|
18
|
+
create(context) {
|
|
19
|
+
return {
|
|
20
|
+
JSXElement(node) {
|
|
21
|
+
if (!isDBComponent(node.openingElement, 'DBInput'))
|
|
22
|
+
return;
|
|
23
|
+
const type = getAttributeValue(node.openingElement, 'type');
|
|
24
|
+
if (!type) {
|
|
25
|
+
context.report({
|
|
26
|
+
node: node.openingElement,
|
|
27
|
+
messageId: 'missingType',
|
|
28
|
+
fix(fixer) {
|
|
29
|
+
const lastAttr = node.openingElement.attributes[node.openingElement.attributes.length - 1];
|
|
30
|
+
const insertPos = lastAttr
|
|
31
|
+
? lastAttr.range[1]
|
|
32
|
+
: node.openingElement.name.range[1];
|
|
33
|
+
return fixer.insertTextAfterRange([insertPos, insertPos], ' type="text"');
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getAttributeValue, isDBComponent } from '../../shared/utils.js';
|
|
3
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/db-ux-design-system/core-web/blob/main/packages/eslint-plugin/README.md#${name}`);
|
|
4
|
+
export default createRule({
|
|
5
|
+
name: 'link-external-security',
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Ensure external links have proper security attributes'
|
|
10
|
+
},
|
|
11
|
+
messages: {
|
|
12
|
+
missingTargetBlank: 'DBLink with content="external" should have target="_blank"',
|
|
13
|
+
missingReferrerPolicy: 'DBLink with content="external" should have referrerPolicy attribute',
|
|
14
|
+
missingContentExternal: 'DBLink with target="_blank" should have content="external"'
|
|
15
|
+
},
|
|
16
|
+
schema: []
|
|
17
|
+
},
|
|
18
|
+
defaultOptions: [],
|
|
19
|
+
create(context) {
|
|
20
|
+
return {
|
|
21
|
+
JSXElement(node) {
|
|
22
|
+
if (!isDBComponent(node.openingElement, 'DBLink'))
|
|
23
|
+
return;
|
|
24
|
+
const content = getAttributeValue(node.openingElement, 'content');
|
|
25
|
+
const target = getAttributeValue(node.openingElement, 'target');
|
|
26
|
+
const referrerPolicy = getAttributeValue(node.openingElement, 'referrerPolicy');
|
|
27
|
+
if (content === 'external') {
|
|
28
|
+
if (target !== '_blank') {
|
|
29
|
+
context.report({
|
|
30
|
+
node: node.openingElement,
|
|
31
|
+
messageId: 'missingTargetBlank'
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (!referrerPolicy) {
|
|
35
|
+
context.report({
|
|
36
|
+
node: node.openingElement,
|
|
37
|
+
messageId: 'missingReferrerPolicy'
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (target === '_blank' && content !== 'external') {
|
|
42
|
+
context.report({
|
|
43
|
+
node: node.openingElement,
|
|
44
|
+
messageId: 'missingContentExternal'
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getAttributeValue, isDBComponent } from '../../shared/utils.js';
|
|
3
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/db-ux-design-system/core-web/blob/main/packages/eslint-plugin/README.md#${name}`);
|
|
4
|
+
export default createRule({
|
|
5
|
+
name: 'navigation-item-back-button-text-required',
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Ensure DBNavigationItem has backButtonText for accessibility'
|
|
10
|
+
},
|
|
11
|
+
messages: {
|
|
12
|
+
missingBackButtonText: 'DBNavigationItem must have backButtonText attribute for accessibility'
|
|
13
|
+
},
|
|
14
|
+
schema: []
|
|
15
|
+
},
|
|
16
|
+
defaultOptions: [],
|
|
17
|
+
create(context) {
|
|
18
|
+
return {
|
|
19
|
+
JSXElement(node) {
|
|
20
|
+
if (!isDBComponent(node.openingElement, 'DBNavigationItem'))
|
|
21
|
+
return;
|
|
22
|
+
const backButtonText = getAttributeValue(node.openingElement, 'backButtonText');
|
|
23
|
+
if (!backButtonText) {
|
|
24
|
+
context.report({
|
|
25
|
+
node: node.openingElement,
|
|
26
|
+
messageId: 'missingBackButtonText'
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getAttributeValue, isDBComponent } from '../../shared/utils.js';
|
|
3
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/db-ux-design-system/core-web/blob/main/packages/eslint-plugin/README.md#${name}`);
|
|
4
|
+
export default createRule({
|
|
5
|
+
name: 'custom-select-tags-remove-text-required',
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Ensure DBCustomSelect with selectedType="tag" has removeTagsTexts'
|
|
10
|
+
},
|
|
11
|
+
messages: {
|
|
12
|
+
missingRemoveTagsTexts: 'DBCustomSelect with selectedType="tag" must have removeTagsTexts attribute for accessibility'
|
|
13
|
+
},
|
|
14
|
+
schema: []
|
|
15
|
+
},
|
|
16
|
+
defaultOptions: [],
|
|
17
|
+
create(context) {
|
|
18
|
+
return {
|
|
19
|
+
JSXElement(node) {
|
|
20
|
+
if (!isDBComponent(node.openingElement, 'DBCustomSelect'))
|
|
21
|
+
return;
|
|
22
|
+
const selectedType = getAttributeValue(node.openingElement, 'selectedType');
|
|
23
|
+
if (selectedType !== 'tag')
|
|
24
|
+
return;
|
|
25
|
+
const removeTagsTexts = getAttributeValue(node.openingElement, 'removeTagsTexts');
|
|
26
|
+
if (!removeTagsTexts) {
|
|
27
|
+
context.report({
|
|
28
|
+
node: node.openingElement,
|
|
29
|
+
messageId: 'missingRemoveTagsTexts'
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getAttributeValue, isDBComponent } from '../../shared/utils.js';
|
|
3
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/db-ux-design-system/core-web/blob/main/packages/eslint-plugin/README.md#${name}`);
|
|
4
|
+
function hasOptionChildren(node) {
|
|
5
|
+
return node.children.some((child) => {
|
|
6
|
+
if (child.type === 'JSXElement') {
|
|
7
|
+
const name = child.openingElement.name;
|
|
8
|
+
if (name.type === 'JSXIdentifier') {
|
|
9
|
+
return name.name === 'option';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return false;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export default createRule({
|
|
16
|
+
name: 'select-requires-options',
|
|
17
|
+
meta: {
|
|
18
|
+
type: 'problem',
|
|
19
|
+
docs: {
|
|
20
|
+
description: 'Ensure DBSelect has options property or option children'
|
|
21
|
+
},
|
|
22
|
+
messages: {
|
|
23
|
+
missingOptions: 'DBSelect must have either an options property or <option> children'
|
|
24
|
+
},
|
|
25
|
+
schema: []
|
|
26
|
+
},
|
|
27
|
+
defaultOptions: [],
|
|
28
|
+
create(context) {
|
|
29
|
+
return {
|
|
30
|
+
JSXElement(node) {
|
|
31
|
+
if (!isDBComponent(node.openingElement, 'DBSelect'))
|
|
32
|
+
return;
|
|
33
|
+
const options = getAttributeValue(node.openingElement, 'options');
|
|
34
|
+
const hasChildren = hasOptionChildren(node);
|
|
35
|
+
if (!options && !hasChildren) {
|
|
36
|
+
context.report({
|
|
37
|
+
node: node.openingElement,
|
|
38
|
+
messageId: 'missingOptions'
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
2
|
+
import { getAttributeValue, isDBComponent } from '../../shared/utils.js';
|
|
3
|
+
const createRule = ESLintUtils.RuleCreator((name) => `https://github.com/db-ux-design-system/core-web/blob/main/packages/eslint-plugin/README.md#${name}`);
|
|
4
|
+
export default createRule({
|
|
5
|
+
name: 'tag-removable-remove-button-required',
|
|
6
|
+
meta: {
|
|
7
|
+
type: 'problem',
|
|
8
|
+
docs: {
|
|
9
|
+
description: 'Ensure DBTag with behavior="removable" has removeButton'
|
|
10
|
+
},
|
|
11
|
+
messages: {
|
|
12
|
+
missingRemoveButton: 'DBTag with behavior="removable" must have removeButton attribute for accessibility'
|
|
13
|
+
},
|
|
14
|
+
schema: []
|
|
15
|
+
},
|
|
16
|
+
defaultOptions: [],
|
|
17
|
+
create(context) {
|
|
18
|
+
return {
|
|
19
|
+
JSXElement(node) {
|
|
20
|
+
if (!isDBComponent(node.openingElement, 'DBTag'))
|
|
21
|
+
return;
|
|
22
|
+
const behavior = getAttributeValue(node.openingElement, 'behavior');
|
|
23
|
+
if (behavior !== 'removable')
|
|
24
|
+
return;
|
|
25
|
+
const removeButton = getAttributeValue(node.openingElement, 'removeButton');
|
|
26
|
+
if (!removeButton) {
|
|
27
|
+
context.report({
|
|
28
|
+
node: node.openingElement,
|
|
29
|
+
messageId: 'missingRemoveButton'
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
});
|