@dnncommunity/dnn-elements 0.24.3-beta.1 → 0.24.4-beta.3
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/dist/collection/eslint-plugin/__tests__/no-label-slot-in-checkbox.tests.js +26 -0
- package/dist/collection/eslint-plugin/__tests__/no-label-slot-in-checkbox.tests.js.map +1 -0
- package/dist/collection/eslint-plugin/index.js +5 -0
- package/dist/collection/eslint-plugin/index.js.map +1 -0
- package/dist/collection/eslint-plugin/src/rules/no-label-slot-in-checkbox.js +58 -0
- package/dist/collection/eslint-plugin/src/rules/no-label-slot-in-checkbox.js.map +1 -0
- package/dist/types/eslint-plugin/__tests__/no-label-slot-in-checkbox.tests.d.ts +1 -0
- package/dist/types/eslint-plugin/dist/no-label-slot-in-checkbox.d.ts +2 -0
- package/dist/types/eslint-plugin/index.d.ts +3 -0
- package/dist/types/eslint-plugin/src/rules/no-label-slot-in-checkbox.d.ts +2 -0
- package/package.json +11 -7
- package/src/eslint-plugin/__tests__/no-label-slot-in-checkbox.tests.ts +27 -0
- package/src/eslint-plugin/dist/no-label-slot-in-checkbox.d.ts +2 -0
- package/src/eslint-plugin/dist/no-label-slot-in-checkbox.js +61 -0
- package/src/eslint-plugin/dist/no-label-slot-in-checkbox.js.map +1 -0
- package/src/eslint-plugin/index.ts +5 -0
- package/src/eslint-plugin/src/rules/no-label-slot-in-checkbox.ts +65 -0
- package/src/eslint-plugin/tsconfig.json +16 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { RuleTester } from "eslint";
|
|
2
|
+
import { noLabelSlotInCheckbox } from "../src/rules/no-label-slot-in-checkbox";
|
|
3
|
+
const tsParser = require.resolve("@typescript-eslint/parser");
|
|
4
|
+
const ruleTester = new RuleTester({
|
|
5
|
+
parser: tsParser,
|
|
6
|
+
parserOptions: {
|
|
7
|
+
ecmaVersion: 2022,
|
|
8
|
+
ecmaFeatures: {
|
|
9
|
+
jsx: true,
|
|
10
|
+
},
|
|
11
|
+
sourceType: "module",
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
ruleTester.run("no-label-slot-in-checkbox", noLabelSlotInCheckbox, {
|
|
15
|
+
valid: [
|
|
16
|
+
{ code: "<dnn-checkbox></dnn-checkbox>" },
|
|
17
|
+
],
|
|
18
|
+
invalid: [
|
|
19
|
+
{
|
|
20
|
+
code: "<dnn-checkbox onClick={e => console.log(e)}><label>Label Text</label></dnn-checkbox>",
|
|
21
|
+
errors: [{ messageId: "noLabelSlotInCheckbox" }],
|
|
22
|
+
output: "<label>\nLabel Text\n<dnn-checkbox onClick={e => console.log(e)}></dnn-checkbox>\n</label>",
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=no-label-slot-in-checkbox.tests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-label-slot-in-checkbox.tests.js","sourceRoot":"","sources":["../../../src/eslint-plugin/__tests__/no-label-slot-in-checkbox.tests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;AAE9D,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC;IAC9B,MAAM,EAAE,QAAQ;IAChB,aAAa,EAAE;QACX,WAAW,EAAE,IAAI;QACjB,YAAY,EAAE;YACV,GAAG,EAAE,IAAI;SACZ;QACD,UAAU,EAAE,QAAQ;KACvB;CACJ,CAAC,CAAC;AAEH,UAAU,CAAC,GAAG,CAAC,2BAA2B,EAAE,qBAAqB,EAAE;IAC/D,KAAK,EAAE;QACH,EAAE,IAAI,EAAE,+BAA+B,EAAE;KAC5C;IACD,OAAO,EAAE;QACL;YACI,IAAI,EAAE,sFAAsF;YAC5F,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,uBAAuB,EAAE,CAAC;YAChD,MAAM,EAAE,4FAA4F;SACvG;KACJ;CACJ,CAAC,CAAC","sourcesContent":["import { RuleTester } from \"eslint\";\r\nimport { noLabelSlotInCheckbox } from \"../src/rules/no-label-slot-in-checkbox\";\r\nconst tsParser = require.resolve(\"@typescript-eslint/parser\");\r\n\r\nconst ruleTester = new RuleTester({\r\n parser: tsParser,\r\n parserOptions: {\r\n ecmaVersion: 2022,\r\n ecmaFeatures: {\r\n jsx: true,\r\n },\r\n sourceType: \"module\",\r\n },\r\n});\r\n\r\nruleTester.run(\"no-label-slot-in-checkbox\", noLabelSlotInCheckbox, {\r\n valid: [\r\n { code: \"<dnn-checkbox></dnn-checkbox>\" },\r\n ],\r\n invalid: [\r\n {\r\n code: \"<dnn-checkbox onClick={e => console.log(e)}><label>Label Text</label></dnn-checkbox>\",\r\n errors: [{ messageId: \"noLabelSlotInCheckbox\" }],\r\n output: \"<label>\\nLabel Text\\n<dnn-checkbox onClick={e => console.log(e)}></dnn-checkbox>\\n</label>\",\r\n },\r\n ],\r\n});"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/eslint-plugin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAE9E,MAAM,CAAC,MAAM,KAAK,GAAG;IACjB,2BAA2B,EAAE,qBAAqB;CACrD,CAAC","sourcesContent":["import { noLabelSlotInCheckbox } from \"./src/rules/no-label-slot-in-checkbox\";\r\n\r\nexport const rules = {\r\n \"no-label-slot-in-checkbox\": noLabelSlotInCheckbox\r\n};"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export const noLabelSlotInCheckbox = {
|
|
2
|
+
meta: {
|
|
3
|
+
type: "problem",
|
|
4
|
+
docs: {
|
|
5
|
+
description: "Disallow label slot in checkbox",
|
|
6
|
+
recommended: true,
|
|
7
|
+
url: "https://github.com/DNNCommunity/dnn-elements/releases/tag/v0.24.0",
|
|
8
|
+
},
|
|
9
|
+
messages: {
|
|
10
|
+
noLabelSlotInCheckbox: "Label slot is not allowed in dnn-checkbox, wrap dnn-checkbox with a label instead."
|
|
11
|
+
},
|
|
12
|
+
fixable: "code",
|
|
13
|
+
},
|
|
14
|
+
create(context) {
|
|
15
|
+
return {
|
|
16
|
+
JSXOpeningElement(node) {
|
|
17
|
+
if (node.type === "JSXOpeningElement") {
|
|
18
|
+
const jsxNode = node;
|
|
19
|
+
if (jsxNode.name.type === "JSXIdentifier" && jsxNode.name.name === "dnn-checkbox") {
|
|
20
|
+
const parent = context.getAncestors().find(ancestor => ancestor.type === "JSXElement");
|
|
21
|
+
if (parent) {
|
|
22
|
+
const hasLabel = parent.children.some(child => {
|
|
23
|
+
return child.type === "JSXElement" &&
|
|
24
|
+
child.openingElement.name.type === "JSXIdentifier" &&
|
|
25
|
+
child.openingElement.name.name === "label";
|
|
26
|
+
});
|
|
27
|
+
if (hasLabel) {
|
|
28
|
+
context.report({
|
|
29
|
+
node: node,
|
|
30
|
+
messageId: "noLabelSlotInCheckbox",
|
|
31
|
+
fix: (fixer) => {
|
|
32
|
+
if (parent && parent.type === "JSXElement" && Array.isArray(parent.children)) {
|
|
33
|
+
const label = parent.children.find(child => child &&
|
|
34
|
+
child.type === "JSXElement" &&
|
|
35
|
+
child.openingElement &&
|
|
36
|
+
child.openingElement.name &&
|
|
37
|
+
child.openingElement.name.type === "JSXIdentifier" &&
|
|
38
|
+
child.openingElement.name.name === "label");
|
|
39
|
+
if (label && label.type === "JSXElement") {
|
|
40
|
+
const labelText = context.sourceCode.getText(label).replace(/<label>|<\/label>/g, '').trim();
|
|
41
|
+
const checkboxText = context.sourceCode.getText(node);
|
|
42
|
+
// Combine the label text and checkbox into a label wrapper with multiline formatting
|
|
43
|
+
const fixedText = `<label>\n${labelText}\n${checkboxText}</dnn-checkbox>\n</label>`;
|
|
44
|
+
return fixer.replaceText(parent, fixedText);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=no-label-slot-in-checkbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-label-slot-in-checkbox.js","sourceRoot":"","sources":["../../../../src/eslint-plugin/src/rules/no-label-slot-in-checkbox.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,qBAAqB,GAAoB;IAClD,IAAI,EAAE;QACF,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACF,WAAW,EAAE,iCAAiC;YAC9C,WAAW,EAAE,IAAI;YACjB,GAAG,EAAE,mEAAmE;SAC3E;QACD,QAAQ,EAAE;YACN,qBAAqB,EAAE,oFAAoF;SAC9G;QACD,OAAO,EAAE,MAAM;KAClB;IACD,MAAM,CAAC,OAAyB;QAC5B,OAAO;YACH,iBAAiB,CAAC,IAAe;gBAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;oBACpC,MAAM,OAAO,GAAG,IAAyB,CAAC;oBAC1C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;wBAChF,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;wBACvF,IAAI,MAAM,EAAE,CAAC;4BACT,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;gCAC1C,OAAO,KAAK,CAAC,IAAI,KAAK,YAAY;oCAC9B,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe;oCAClD,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC;4BACnD,CAAC,CAAC,CAAC;4BACH,IAAI,QAAQ,EAAE,CAAC;gCACX,OAAO,CAAC,MAAM,CAAC;oCACX,IAAI,EAAE,IAAI;oCACV,SAAS,EAAE,uBAAuB;oCAClC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;wCACX,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;4CAC3E,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CACvC,KAAK;gDACL,KAAK,CAAC,IAAI,KAAK,YAAY;gDAC3B,KAAK,CAAC,cAAc;gDACpB,KAAK,CAAC,cAAc,CAAC,IAAI;gDACzB,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe;gDAClD,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;4CAEhD,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gDACvC,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gDAC7F,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gDAEtD,qFAAqF;gDACrF,MAAM,SAAS,GAAG,YAAY,SAAS,KAAK,YAAY,2BAA2B,CAAC;gDAEpF,OAAO,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;4CAChD,CAAC;wCACL,CAAC;wCAED,OAAO,IAAI,CAAC;oCAChB,CAAC;iCACJ,CAAC,CAAC;4BACP,CAAC;wBACL,CAAC;oBACL,CAAC;gBACL,CAAC;YACL,CAAC;SACJ,CAAC;IACN,CAAC;CACJ,CAAC","sourcesContent":["import type { Rule } from 'eslint';\r\nimport type { JSXOpeningElement } from \"estree-jsx\";\r\n\r\nexport const noLabelSlotInCheckbox: Rule.RuleModule = {\r\n meta: {\r\n type: \"problem\",\r\n docs: {\r\n description: \"Disallow label slot in checkbox\",\r\n recommended: true,\r\n url: \"https://github.com/DNNCommunity/dnn-elements/releases/tag/v0.24.0\",\r\n },\r\n messages: {\r\n noLabelSlotInCheckbox: \"Label slot is not allowed in dnn-checkbox, wrap dnn-checkbox with a label instead.\"\r\n },\r\n fixable: \"code\",\r\n },\r\n create(context: Rule.RuleContext): Rule.RuleListener {\r\n return {\r\n JSXOpeningElement(node: Rule.Node) {\r\n if (node.type === \"JSXOpeningElement\") {\r\n const jsxNode = node as JSXOpeningElement;\r\n if (jsxNode.name.type === \"JSXIdentifier\" && jsxNode.name.name === \"dnn-checkbox\") {\r\n const parent = context.getAncestors().find(ancestor => ancestor.type === \"JSXElement\");\r\n if (parent) {\r\n const hasLabel = parent.children.some(child => {\r\n return child.type === \"JSXElement\" &&\r\n child.openingElement.name.type === \"JSXIdentifier\" &&\r\n child.openingElement.name.name === \"label\";\r\n });\r\n if (hasLabel) {\r\n context.report({\r\n node: node,\r\n messageId: \"noLabelSlotInCheckbox\",\r\n fix: (fixer) => {\r\n if (parent && parent.type === \"JSXElement\" && Array.isArray(parent.children)) {\r\n const label = parent.children.find(child => \r\n child &&\r\n child.type === \"JSXElement\" &&\r\n child.openingElement &&\r\n child.openingElement.name &&\r\n child.openingElement.name.type === \"JSXIdentifier\" &&\r\n child.openingElement.name.name === \"label\");\r\n\r\n if (label && label.type === \"JSXElement\") {\r\n const labelText = context.sourceCode.getText(label).replace(/<label>|<\\/label>/g, '').trim();\r\n const checkboxText = context.sourceCode.getText(node);\r\n\r\n // Combine the label text and checkbox into a label wrapper with multiline formatting\r\n const fixedText = `<label>\\n${labelText}\\n${checkboxText}</dnn-checkbox>\\n</label>`;\r\n\r\n return fixer.replaceText(parent, fixedText);\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n };\r\n }\r\n};\r\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dnncommunity/dnn-elements",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.4-beta.3",
|
|
4
4
|
"description": "Dnn themed custom elements.",
|
|
5
5
|
"repository": "https://github.com/dnncommunity/dnn-elements",
|
|
6
6
|
"homepage": "https://dnncommunity.github.io/dnn-elements",
|
|
@@ -15,10 +15,11 @@
|
|
|
15
15
|
"unpkg": "dist/dnn/dnn.js",
|
|
16
16
|
"files": [
|
|
17
17
|
"dist/",
|
|
18
|
-
"loader/"
|
|
18
|
+
"loader/",
|
|
19
|
+
"src/eslint-plugin/"
|
|
19
20
|
],
|
|
20
21
|
"scripts": {
|
|
21
|
-
"build": "npm run eslint && stencil build --docs",
|
|
22
|
+
"build": "npm run build:eslint-plugin && npm run eslint && stencil build --docs",
|
|
22
23
|
"postbuild": "license-checker-rseidelsohn --out licenses.json --json --direct --relativeLicensePath --relativeModulePath",
|
|
23
24
|
"watch": "stencil build --dev --watch",
|
|
24
25
|
"start": "stencil build --dev --watch --serve",
|
|
@@ -26,11 +27,13 @@
|
|
|
26
27
|
"poststart": "license-checker-rseidelsohn --out licenses.json --json --direct --relativeLicensePath --relativeModulePath",
|
|
27
28
|
"test": "stencil test --spec --e2e",
|
|
28
29
|
"test.watch": "stencil test --spec --e2e --watchAll",
|
|
30
|
+
"test.eslint": "jest --config jest.eslint.config.js",
|
|
29
31
|
"generate": "stencil generate",
|
|
30
32
|
"eslint": "eslint",
|
|
31
33
|
"storybook": "storybook dev -p 6006",
|
|
32
|
-
"build-storybook": "
|
|
33
|
-
"deploy-storybook": "gh-pages -d storybook-static --branch site"
|
|
34
|
+
"build-storybook": "echo 'Storybook build is disabled for this release.'",
|
|
35
|
+
"deploy-storybook": "gh-pages -d storybook-static --branch site",
|
|
36
|
+
"build:eslint-plugin": "tsc -p src/eslint-plugin/tsconfig.json"
|
|
34
37
|
},
|
|
35
38
|
"devDependencies": {
|
|
36
39
|
"@chromatic-com/storybook": "^3.1.0",
|
|
@@ -48,6 +51,7 @@
|
|
|
48
51
|
"@storybook/web-components": "^8.3.2",
|
|
49
52
|
"@storybook/web-components-webpack5": "^8.3.2",
|
|
50
53
|
"@timkendrick/monaco-editor": "^0.0.9",
|
|
54
|
+
"@types/estree-jsx": "^1.0.5",
|
|
51
55
|
"@types/jest": "^29.5.10",
|
|
52
56
|
"@typescript-eslint/eslint-plugin": "^8.0.1",
|
|
53
57
|
"@typescript-eslint/parser": "^8.0.1",
|
|
@@ -67,8 +71,8 @@
|
|
|
67
71
|
"react-dom": "^18.2.0",
|
|
68
72
|
"rollup-plugin-node-polyfills": "^0.2.1",
|
|
69
73
|
"storybook": "^8.3.2",
|
|
70
|
-
"
|
|
71
|
-
"typescript
|
|
74
|
+
"ts-jest": "^29.3.2",
|
|
75
|
+
"typescript": "5.6.3"
|
|
72
76
|
},
|
|
73
77
|
"dependencies": {
|
|
74
78
|
"jodit": "^4.2.27"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { RuleTester } from "eslint";
|
|
2
|
+
import { noLabelSlotInCheckbox } from "../src/rules/no-label-slot-in-checkbox";
|
|
3
|
+
const tsParser = require.resolve("@typescript-eslint/parser");
|
|
4
|
+
|
|
5
|
+
const ruleTester = new RuleTester({
|
|
6
|
+
parser: tsParser,
|
|
7
|
+
parserOptions: {
|
|
8
|
+
ecmaVersion: 2022,
|
|
9
|
+
ecmaFeatures: {
|
|
10
|
+
jsx: true,
|
|
11
|
+
},
|
|
12
|
+
sourceType: "module",
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
ruleTester.run("no-label-slot-in-checkbox", noLabelSlotInCheckbox, {
|
|
17
|
+
valid: [
|
|
18
|
+
{ code: "<dnn-checkbox></dnn-checkbox>" },
|
|
19
|
+
],
|
|
20
|
+
invalid: [
|
|
21
|
+
{
|
|
22
|
+
code: "<dnn-checkbox onClick={e => console.log(e)}><label>Label Text</label></dnn-checkbox>",
|
|
23
|
+
errors: [{ messageId: "noLabelSlotInCheckbox" }],
|
|
24
|
+
output: "<label>\nLabel Text\n<dnn-checkbox onClick={e => console.log(e)}></dnn-checkbox>\n</label>",
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.noLabelSlotInCheckbox = void 0;
|
|
4
|
+
exports.noLabelSlotInCheckbox = {
|
|
5
|
+
meta: {
|
|
6
|
+
type: "problem",
|
|
7
|
+
docs: {
|
|
8
|
+
description: "Disallow label slot in checkbox",
|
|
9
|
+
recommended: true,
|
|
10
|
+
url: "https://github.com/DNNCommunity/dnn-elements/releases/tag/v0.24.0",
|
|
11
|
+
},
|
|
12
|
+
messages: {
|
|
13
|
+
noLabelSlotInCheckbox: "Label slot is not allowed in dnn-checkbox, wrap dnn-checkbox with a label instead."
|
|
14
|
+
},
|
|
15
|
+
fixable: "code",
|
|
16
|
+
},
|
|
17
|
+
create(context) {
|
|
18
|
+
return {
|
|
19
|
+
JSXOpeningElement(node) {
|
|
20
|
+
if (node.type === "JSXOpeningElement") {
|
|
21
|
+
const jsxNode = node;
|
|
22
|
+
if (jsxNode.name.type === "JSXIdentifier" && jsxNode.name.name === "dnn-checkbox") {
|
|
23
|
+
const parent = context.getAncestors().find(ancestor => ancestor.type === "JSXElement");
|
|
24
|
+
if (parent) {
|
|
25
|
+
const hasLabel = parent.children.some(child => {
|
|
26
|
+
return child.type === "JSXElement" &&
|
|
27
|
+
child.openingElement.name.type === "JSXIdentifier" &&
|
|
28
|
+
child.openingElement.name.name === "label";
|
|
29
|
+
});
|
|
30
|
+
if (hasLabel) {
|
|
31
|
+
context.report({
|
|
32
|
+
node: node,
|
|
33
|
+
messageId: "noLabelSlotInCheckbox",
|
|
34
|
+
fix: (fixer) => {
|
|
35
|
+
if (parent && parent.type === "JSXElement" && Array.isArray(parent.children)) {
|
|
36
|
+
const label = parent.children.find(child => child &&
|
|
37
|
+
child.type === "JSXElement" &&
|
|
38
|
+
child.openingElement &&
|
|
39
|
+
child.openingElement.name &&
|
|
40
|
+
child.openingElement.name.type === "JSXIdentifier" &&
|
|
41
|
+
child.openingElement.name.name === "label");
|
|
42
|
+
if (label && label.type === "JSXElement") {
|
|
43
|
+
const labelText = context.sourceCode.getText(label).replace(/<label>|<\/label>/g, '').trim();
|
|
44
|
+
const checkboxText = context.sourceCode.getText(node);
|
|
45
|
+
// Combine the label text and checkbox into a label wrapper with multiline formatting
|
|
46
|
+
const fixedText = `<label>\n${labelText}\n${checkboxText}</dnn-checkbox>\n</label>`;
|
|
47
|
+
return fixer.replaceText(parent, fixedText);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=no-label-slot-in-checkbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-label-slot-in-checkbox.js","sourceRoot":"","sources":["../src/rules/no-label-slot-in-checkbox.ts"],"names":[],"mappings":";;;AAGa,QAAA,qBAAqB,GAAoB;IAClD,IAAI,EAAE;QACF,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACF,WAAW,EAAE,iCAAiC;YAC9C,WAAW,EAAE,IAAI;YACjB,GAAG,EAAE,mEAAmE;SAC3E;QACD,QAAQ,EAAE;YACN,qBAAqB,EAAE,oFAAoF;SAC9G;QACD,OAAO,EAAE,MAAM;KAClB;IACD,MAAM,CAAC,OAAyB;QAC5B,OAAO;YACH,iBAAiB,CAAC,IAAe;gBAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;oBACpC,MAAM,OAAO,GAAG,IAAyB,CAAC;oBAC1C,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;wBAChF,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;wBACvF,IAAI,MAAM,EAAE,CAAC;4BACT,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;gCAC1C,OAAO,KAAK,CAAC,IAAI,KAAK,YAAY;oCAC9B,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe;oCAClD,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC;4BACnD,CAAC,CAAC,CAAC;4BACH,IAAI,QAAQ,EAAE,CAAC;gCACX,OAAO,CAAC,MAAM,CAAC;oCACX,IAAI,EAAE,IAAI;oCACV,SAAS,EAAE,uBAAuB;oCAClC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE;wCACX,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;4CAC3E,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CACvC,KAAK;gDACL,KAAK,CAAC,IAAI,KAAK,YAAY;gDAC3B,KAAK,CAAC,cAAc;gDACpB,KAAK,CAAC,cAAc,CAAC,IAAI;gDACzB,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,eAAe;gDAClD,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;4CAEhD,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gDACvC,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gDAC7F,MAAM,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gDAEtD,qFAAqF;gDACrF,MAAM,SAAS,GAAG,YAAY,SAAS,KAAK,YAAY,2BAA2B,CAAC;gDAEpF,OAAO,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;4CAChD,CAAC;wCACL,CAAC;wCAED,OAAO,IAAI,CAAC;oCAChB,CAAC;iCACJ,CAAC,CAAC;4BACP,CAAC;wBACL,CAAC;oBACL,CAAC;gBACL,CAAC;YACL,CAAC;SACJ,CAAC;IACN,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Rule } from 'eslint';
|
|
2
|
+
import type { JSXOpeningElement } from "estree-jsx";
|
|
3
|
+
|
|
4
|
+
export const noLabelSlotInCheckbox: Rule.RuleModule = {
|
|
5
|
+
meta: {
|
|
6
|
+
type: "problem",
|
|
7
|
+
docs: {
|
|
8
|
+
description: "Disallow label slot in checkbox",
|
|
9
|
+
recommended: true,
|
|
10
|
+
url: "https://github.com/DNNCommunity/dnn-elements/releases/tag/v0.24.0",
|
|
11
|
+
},
|
|
12
|
+
messages: {
|
|
13
|
+
noLabelSlotInCheckbox: "Label slot is not allowed in dnn-checkbox, wrap dnn-checkbox with a label instead."
|
|
14
|
+
},
|
|
15
|
+
fixable: "code",
|
|
16
|
+
},
|
|
17
|
+
create(context: Rule.RuleContext): Rule.RuleListener {
|
|
18
|
+
return {
|
|
19
|
+
JSXOpeningElement(node: Rule.Node) {
|
|
20
|
+
if (node.type === "JSXOpeningElement") {
|
|
21
|
+
const jsxNode = node as JSXOpeningElement;
|
|
22
|
+
if (jsxNode.name.type === "JSXIdentifier" && jsxNode.name.name === "dnn-checkbox") {
|
|
23
|
+
const parent = context.getAncestors().find(ancestor => ancestor.type === "JSXElement");
|
|
24
|
+
if (parent) {
|
|
25
|
+
const hasLabel = parent.children.some(child => {
|
|
26
|
+
return child.type === "JSXElement" &&
|
|
27
|
+
child.openingElement.name.type === "JSXIdentifier" &&
|
|
28
|
+
child.openingElement.name.name === "label";
|
|
29
|
+
});
|
|
30
|
+
if (hasLabel) {
|
|
31
|
+
context.report({
|
|
32
|
+
node: node,
|
|
33
|
+
messageId: "noLabelSlotInCheckbox",
|
|
34
|
+
fix: (fixer) => {
|
|
35
|
+
if (parent && parent.type === "JSXElement" && Array.isArray(parent.children)) {
|
|
36
|
+
const label = parent.children.find(child =>
|
|
37
|
+
child &&
|
|
38
|
+
child.type === "JSXElement" &&
|
|
39
|
+
child.openingElement &&
|
|
40
|
+
child.openingElement.name &&
|
|
41
|
+
child.openingElement.name.type === "JSXIdentifier" &&
|
|
42
|
+
child.openingElement.name.name === "label");
|
|
43
|
+
|
|
44
|
+
if (label && label.type === "JSXElement") {
|
|
45
|
+
const labelText = context.sourceCode.getText(label).replace(/<label>|<\/label>/g, '').trim();
|
|
46
|
+
const checkboxText = context.sourceCode.getText(node);
|
|
47
|
+
|
|
48
|
+
// Combine the label text and checkbox into a label wrapper with multiline formatting
|
|
49
|
+
const fixedText = `<label>\n${labelText}\n${checkboxText}</dnn-checkbox>\n</label>`;
|
|
50
|
+
|
|
51
|
+
return fixer.replaceText(parent, fixedText);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"moduleResolution": "Node",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"types": ["jest", "node", "estree-jsx"],
|
|
12
|
+
"forceConsistentCasingInFileNames": true,
|
|
13
|
+
"sourceMap": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["src", "jest.config.js"]
|
|
16
|
+
}
|