@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.
Files changed (49) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/README.md +754 -0
  3. package/build/index.d.ts +99 -0
  4. package/build/index.js +79 -0
  5. package/build/rules/accordion/no-nested-accordion.d.ts +5 -0
  6. package/build/rules/accordion/no-nested-accordion.js +37 -0
  7. package/build/rules/badge/badge-corner-placement-rules.d.ts +5 -0
  8. package/build/rules/badge/badge-corner-placement-rules.js +76 -0
  9. package/build/rules/badge/badge-no-inline-in-interactive.d.ts +5 -0
  10. package/build/rules/badge/badge-no-inline-in-interactive.js +67 -0
  11. package/build/rules/button/button-no-text-requires-tooltip.d.ts +5 -0
  12. package/build/rules/button/button-no-text-requires-tooltip.js +59 -0
  13. package/build/rules/button/button-single-icon-attribute.d.ts +5 -0
  14. package/build/rules/button/button-single-icon-attribute.js +35 -0
  15. package/build/rules/button/button-type-required.d.ts +5 -0
  16. package/build/rules/button/button-type-required.js +45 -0
  17. package/build/rules/close-button/close-button-text-required.d.ts +5 -0
  18. package/build/rules/close-button/close-button-text-required.js +40 -0
  19. package/build/rules/content/text-or-children-required.d.ts +5 -0
  20. package/build/rules/content/text-or-children-required.js +49 -0
  21. package/build/rules/form/form-label-required.d.ts +5 -0
  22. package/build/rules/form/form-label-required.js +47 -0
  23. package/build/rules/form/form-validation-message-required.d.ts +5 -0
  24. package/build/rules/form/form-validation-message-required.js +93 -0
  25. package/build/rules/header/header-burger-menu-label-required.d.ts +5 -0
  26. package/build/rules/header/header-burger-menu-label-required.js +32 -0
  27. package/build/rules/icon/prefer-icon-attribute.d.ts +5 -0
  28. package/build/rules/icon/prefer-icon-attribute.js +67 -0
  29. package/build/rules/input/input-file-type-validation.d.ts +5 -0
  30. package/build/rules/input/input-file-type-validation.js +52 -0
  31. package/build/rules/input/input-type-required.d.ts +5 -0
  32. package/build/rules/input/input-type-required.js +40 -0
  33. package/build/rules/link/link-external-security.d.ts +5 -0
  34. package/build/rules/link/link-external-security.js +50 -0
  35. package/build/rules/navigation/navigation-item-back-button-text-required.d.ts +5 -0
  36. package/build/rules/navigation/navigation-item-back-button-text-required.js +32 -0
  37. package/build/rules/select/custom-select-tags-remove-text-required.d.ts +5 -0
  38. package/build/rules/select/custom-select-tags-remove-text-required.js +35 -0
  39. package/build/rules/select/select-requires-options.d.ts +5 -0
  40. package/build/rules/select/select-requires-options.js +44 -0
  41. package/build/rules/tag/tag-removable-remove-button-required.d.ts +5 -0
  42. package/build/rules/tag/tag-removable-remove-button-required.js +35 -0
  43. package/build/rules/tooltip/no-interactive-tooltip-content.d.ts +5 -0
  44. package/build/rules/tooltip/no-interactive-tooltip-content.js +47 -0
  45. package/build/rules/tooltip/tooltip-requires-interactive-parent.d.ts +5 -0
  46. package/build/rules/tooltip/tooltip-requires-interactive-parent.js +47 -0
  47. package/build/shared/utils.d.ts +5 -0
  48. package/build/shared/utils.js +61 -0
  49. package/package.json +32 -1
@@ -0,0 +1,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"missingLabel", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;
@@ -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,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"missingInvalidMessage", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;
@@ -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,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"missingBurgerMenuLabel", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;
@@ -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,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"preferAttribute", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;
@@ -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,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"missingAccept" | "invalidMultiple" | "invalidAccept", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;
@@ -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,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"missingType", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;
@@ -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,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"missingTargetBlank" | "missingReferrerPolicy" | "missingContentExternal", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;
@@ -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,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"missingBackButtonText", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;
@@ -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,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"missingRemoveTagsTexts", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;
@@ -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,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"missingOptions", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;
@@ -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,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"missingRemoveButton", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;
@@ -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
+ });
@@ -0,0 +1,5 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ declare const _default: ESLintUtils.RuleModule<"noInteractive", [], unknown, ESLintUtils.RuleListener> & {
3
+ name: string;
4
+ };
5
+ export default _default;