@design.estate/wcctools 6.0.0 → 6.2.0
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 +33 -0
- package/dist_shell/bundle.js +405 -368
- package/dist_shell/bundle.js.map +1 -1
- package/dist_shell/bundle.js.third-party-notices.json +52 -0
- package/dist_shell/bundle.js.third-party-notices.txt +107 -1
- package/dist_shell/index.html +1 -1
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.bundlestatus.d.ts +36 -0
- package/dist_ts/classes.bundlestatus.js +110 -0
- package/dist_ts/classes.devapi.d.ts +3 -0
- package/dist_ts/classes.devapi.js +8 -1
- package/dist_ts/classes.devserver.d.ts +45 -10
- package/dist_ts/classes.devserver.js +123 -49
- package/dist_ts/cli.js +12 -3
- package/dist_ts/index.d.ts +0 -2
- package/dist_ts/index.js +1 -3
- package/dist_ts/plugins.d.ts +7 -2
- package/dist_ts/plugins.js +9 -3
- package/dist_ts/standards/baselines.d.ts +27 -0
- package/dist_ts/standards/baselines.js +83 -0
- package/dist_ts/standards/checker.d.ts +21 -0
- package/dist_ts/standards/checker.js +88 -0
- package/dist_ts/standards/classes.gitrepo.d.ts +13 -0
- package/dist_ts/standards/classes.gitrepo.js +43 -0
- package/dist_ts/standards/classes.sourceedits.d.ts +15 -0
- package/dist_ts/standards/classes.sourceedits.js +54 -0
- package/dist_ts/standards/classes.standardfixer.d.ts +40 -0
- package/dist_ts/standards/classes.standardfixer.js +210 -0
- package/dist_ts/standards/classes.standardproject.d.ts +80 -0
- package/dist_ts/standards/classes.standardproject.js +195 -0
- package/dist_ts/standards/classes.standardtree.d.ts +56 -0
- package/dist_ts/standards/classes.standardtree.js +207 -0
- package/dist_ts/standards/cli.d.ts +7 -0
- package/dist_ts/standards/cli.js +89 -0
- package/dist_ts/standards/config.d.ts +33 -0
- package/dist_ts/standards/config.js +139 -0
- package/dist_ts/standards/errors.d.ts +9 -0
- package/dist_ts/standards/errors.js +17 -0
- package/dist_ts/standards/helpers.ast.d.ts +56 -0
- package/dist_ts/standards/helpers.ast.js +172 -0
- package/dist_ts/standards/helpers.paths.d.ts +36 -0
- package/dist_ts/standards/helpers.paths.js +86 -0
- package/dist_ts/standards/index.d.ts +14 -0
- package/dist_ts/standards/index.js +15 -0
- package/dist_ts/standards/output.d.ts +7 -0
- package/dist_ts/standards/output.js +57 -0
- package/dist_ts/standards/ratchet.d.ts +15 -0
- package/dist_ts/standards/ratchet.js +45 -0
- package/dist_ts/standards/rule.d.ts +50 -0
- package/dist_ts/standards/rule.js +9 -0
- package/dist_ts/standards/rules/barrel.element-index.d.ts +7 -0
- package/dist_ts/standards/rules/barrel.element-index.js +108 -0
- package/dist_ts/standards/rules/barrel.no-demo-export.d.ts +3 -0
- package/dist_ts/standards/rules/barrel.no-demo-export.js +29 -0
- package/dist_ts/standards/rules/demo.fixture-not-exported.d.ts +3 -0
- package/dist_ts/standards/rules/demo.fixture-not-exported.js +29 -0
- package/dist_ts/standards/rules/demo.groups.d.ts +6 -0
- package/dist_ts/standards/rules/demo.groups.js +72 -0
- package/dist_ts/standards/rules/demo.required.d.ts +3 -0
- package/dist_ts/standards/rules/demo.required.js +48 -0
- package/dist_ts/standards/rules/demo.separate-file.d.ts +3 -0
- package/dist_ts/standards/rules/demo.separate-file.js +38 -0
- package/dist_ts/standards/rules/demo.shape.d.ts +3 -0
- package/dist_ts/standards/rules/demo.shape.js +38 -0
- package/dist_ts/standards/rules/docs.component-index.d.ts +8 -0
- package/dist_ts/standards/rules/docs.component-index.js +84 -0
- package/dist_ts/standards/rules/element.exported.d.ts +3 -0
- package/dist_ts/standards/rules/element.exported.js +33 -0
- package/dist_ts/standards/rules/element.literal-tag.d.ts +3 -0
- package/dist_ts/standards/rules/element.literal-tag.js +30 -0
- package/dist_ts/standards/rules/element.reachable.d.ts +3 -0
- package/dist_ts/standards/rules/element.reachable.js +48 -0
- package/dist_ts/standards/rules/element.tag-map.d.ts +3 -0
- package/dist_ts/standards/rules/element.tag-map.js +83 -0
- package/dist_ts/standards/rules/i18n.literals.d.ts +3 -0
- package/dist_ts/standards/rules/i18n.literals.js +52 -0
- package/dist_ts/standards/rules/index.d.ts +12 -0
- package/dist_ts/standards/rules/index.js +83 -0
- package/dist_ts/standards/rules/layout.element-folder.d.ts +3 -0
- package/dist_ts/standards/rules/layout.element-folder.js +47 -0
- package/dist_ts/standards/rules/layout.entry-file-name.d.ts +3 -0
- package/dist_ts/standards/rules/layout.entry-file-name.js +71 -0
- package/dist_ts/standards/rules/layout.entry.d.ts +3 -0
- package/dist_ts/standards/rules/layout.entry.js +38 -0
- package/dist_ts/standards/rules/layout.group-folder.d.ts +3 -0
- package/dist_ts/standards/rules/layout.group-folder.js +22 -0
- package/dist_ts/standards/rules/layout.shared-00.d.ts +3 -0
- package/dist_ts/standards/rules/layout.shared-00.js +36 -0
- package/dist_ts/standards/rules/naming.class-matches-tag.d.ts +3 -0
- package/dist_ts/standards/rules/naming.class-matches-tag.js +26 -0
- package/dist_ts/standards/rules/naming.lowercase-files.d.ts +3 -0
- package/dist_ts/standards/rules/naming.lowercase-files.js +26 -0
- package/dist_ts/standards/rules/naming.tag-prefix.d.ts +3 -0
- package/dist_ts/standards/rules/naming.tag-prefix.js +23 -0
- package/dist_ts/standards/rules/props.accessor.d.ts +3 -0
- package/dist_ts/standards/rules/props.accessor.js +35 -0
- package/dist_ts/standards/rules/props.object-no-attribute.d.ts +3 -0
- package/dist_ts/standards/rules/props.object-no-attribute.js +42 -0
- package/dist_ts/standards/rules/props.reflect-primitive.d.ts +5 -0
- package/dist_ts/standards/rules/props.reflect-primitive.js +41 -0
- package/dist_ts/standards/rules/props.typed.d.ts +6 -0
- package/dist_ts/standards/rules/props.typed.js +64 -0
- package/dist_ts/standards/rules/shared.d.ts +38 -0
- package/dist_ts/standards/rules/shared.js +103 -0
- package/dist_ts/standards/rules/style.bdtheme.d.ts +5 -0
- package/dist_ts/standards/rules/style.bdtheme.js +28 -0
- package/dist_ts_interfaces/index.d.ts +1 -0
- package/dist_ts_interfaces/index.js +2 -1
- package/dist_ts_interfaces/requests.d.ts +35 -0
- package/dist_ts_interfaces/standard.d.ts +93 -0
- package/dist_ts_interfaces/standard.js +6 -0
- package/dist_ts_shell/bundlestatus.d.ts +15 -0
- package/dist_ts_shell/bundlestatus.js +64 -0
- package/dist_ts_shell/elements/wcc-contextmenu.d.ts +3 -0
- package/dist_ts_shell/elements/wcc-contextmenu.js +18 -3
- package/dist_ts_shell/elements/wcc-preview-frame.d.ts +6 -0
- package/dist_ts_shell/elements/wcc-preview-frame.js +50 -2
- package/dist_ts_shell/elements/wcc-shell.d.ts +15 -0
- package/dist_ts_shell/elements/wcc-shell.js +45 -3
- package/dist_ts_shell/plugins.d.ts +2 -1
- package/dist_ts_shell/plugins.js +3 -2
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/package.json +8 -3
- package/readme.md +40 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.bundlestatus.ts +123 -0
- package/ts/classes.devapi.ts +9 -0
- package/ts/classes.devserver.ts +127 -47
- package/ts/cli.ts +12 -2
- package/ts/index.ts +0 -2
- package/ts/plugins.ts +10 -2
- package/ts/standards/baselines.ts +100 -0
- package/ts/standards/checker.ts +114 -0
- package/ts/standards/classes.gitrepo.ts +48 -0
- package/ts/standards/classes.sourceedits.ts +58 -0
- package/ts/standards/classes.standardfixer.ts +234 -0
- package/ts/standards/classes.standardproject.ts +250 -0
- package/ts/standards/classes.standardtree.ts +220 -0
- package/ts/standards/cli.ts +86 -0
- package/ts/standards/config.ts +160 -0
- package/ts/standards/errors.ts +18 -0
- package/ts/standards/helpers.ast.ts +208 -0
- package/ts/standards/helpers.paths.ts +119 -0
- package/ts/standards/index.ts +22 -0
- package/ts/standards/output.ts +65 -0
- package/ts/standards/ratchet.ts +63 -0
- package/ts/standards/rule.ts +58 -0
- package/ts/standards/rules/barrel.element-index.ts +112 -0
- package/ts/standards/rules/barrel.no-demo-export.ts +30 -0
- package/ts/standards/rules/demo.fixture-not-exported.ts +30 -0
- package/ts/standards/rules/demo.groups.ts +74 -0
- package/ts/standards/rules/demo.required.ts +49 -0
- package/ts/standards/rules/demo.separate-file.ts +40 -0
- package/ts/standards/rules/demo.shape.ts +42 -0
- package/ts/standards/rules/docs.component-index.ts +88 -0
- package/ts/standards/rules/element.exported.ts +35 -0
- package/ts/standards/rules/element.literal-tag.ts +30 -0
- package/ts/standards/rules/element.reachable.ts +49 -0
- package/ts/standards/rules/element.tag-map.ts +87 -0
- package/ts/standards/rules/i18n.literals.ts +58 -0
- package/ts/standards/rules/index.ts +87 -0
- package/ts/standards/rules/layout.element-folder.ts +49 -0
- package/ts/standards/rules/layout.entry-file-name.ts +73 -0
- package/ts/standards/rules/layout.entry.ts +40 -0
- package/ts/standards/rules/layout.group-folder.ts +23 -0
- package/ts/standards/rules/layout.shared-00.ts +37 -0
- package/ts/standards/rules/naming.class-matches-tag.ts +27 -0
- package/ts/standards/rules/naming.lowercase-files.ts +27 -0
- package/ts/standards/rules/naming.tag-prefix.ts +24 -0
- package/ts/standards/rules/props.accessor.ts +37 -0
- package/ts/standards/rules/props.object-no-attribute.ts +45 -0
- package/ts/standards/rules/props.reflect-primitive.ts +44 -0
- package/ts/standards/rules/props.typed.ts +70 -0
- package/ts/standards/rules/shared.ts +127 -0
- package/ts/standards/rules/style.bdtheme.ts +31 -0
- package/ts_interfaces/bridge.ts +95 -0
- package/ts_interfaces/catalog.ts +37 -0
- package/ts_interfaces/index.ts +4 -0
- package/ts_interfaces/plugins.ts +3 -0
- package/ts_interfaces/requests.ts +65 -0
- package/ts_interfaces/standard.ts +103 -0
- package/ts_shared/index.ts +1 -0
- package/ts_shared/plugins.ts +3 -0
- package/ts_shared/previewroute.ts +58 -0
- package/ts_shell/bundlestatus.ts +68 -0
- package/ts_shell/elements/wcc-contextmenu.ts +306 -0
- package/ts_shell/elements/wcc-preview-frame.ts +167 -0
- package/ts_shell/elements/wcc-properties.ts +998 -0
- package/ts_shell/elements/wcc-record-button.ts +108 -0
- package/ts_shell/elements/wcc-recording-panel.ts +1005 -0
- package/ts_shell/elements/wcc-shell.ts +485 -0
- package/ts_shell/elements/wcc-sidebar.ts +1419 -0
- package/ts_shell/index.html +21 -0
- package/ts_shell/index.ts +4 -0
- package/ts_shell/plugins.ts +12 -0
- package/ts_shell/previewconnection.ts +103 -0
- package/ts_shell/services/recorder.service.ts +451 -0
- package/ts_shell/types/dom-mediacapture-stub/index.d.ts +12 -0
- package/ts_shell/types/dom-mediacapture-stub/package.json +6 -0
- package/ts_shell/types/dom-webcodecs-stub/index.d.ts +2 -0
- package/ts_shell/types/dom-webcodecs-stub/package.json +6 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as ast from '../helpers.ast.js';
|
|
3
|
+
import { baseOf, dirOf, isDemoFile, resolveSpecifier } from '../helpers.paths.js';
|
|
4
|
+
import { catalogElements, elementKey, isCustomElementName, isInElementFolder, rootIdentifier } from './shared.js';
|
|
5
|
+
const ts = plugins.typescript;
|
|
6
|
+
/** Inside an element folder the entry file is `<tag>.ts` and the demo file is `<tag>.demo.ts`. */
|
|
7
|
+
export const layoutEntryFileNameRule = {
|
|
8
|
+
id: 'layout/entry-file-name',
|
|
9
|
+
severity: { base: 'warn' },
|
|
10
|
+
fixMode: 'auto',
|
|
11
|
+
detect: ({ project }) => {
|
|
12
|
+
const findings = [];
|
|
13
|
+
const elements = catalogElements(project);
|
|
14
|
+
for (const element of elements) {
|
|
15
|
+
if (!element.tag || !isInElementFolder(element)) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
const tag = element.tag;
|
|
19
|
+
// The expected file names come from the tag: only a valid custom element name is usable for a move.
|
|
20
|
+
const usableTag = isCustomElementName(tag);
|
|
21
|
+
const folder = dirOf(element.file);
|
|
22
|
+
const entry = `${folder}/${tag}.ts`;
|
|
23
|
+
if (element.file !== entry) {
|
|
24
|
+
const finding = {
|
|
25
|
+
file: element.file,
|
|
26
|
+
position: element.decoratorCall.getStart(),
|
|
27
|
+
key: elementKey(element),
|
|
28
|
+
message: `the entry file of <${tag}> is ${baseOf(element.file)}; expected ${tag}.ts`,
|
|
29
|
+
};
|
|
30
|
+
if (usableTag && elements.filter((otherArg) => otherArg.file === element.file).length === 1 && !project.exists(entry)) {
|
|
31
|
+
finding.fix = (builderArg) => builderArg.move(element.file, entry);
|
|
32
|
+
}
|
|
33
|
+
findings.push(finding);
|
|
34
|
+
}
|
|
35
|
+
// The demo file the static demo is imported from.
|
|
36
|
+
const demoMember = ast.findStaticProperty(element.classNode, 'demo');
|
|
37
|
+
const initializer = demoMember?.initializer;
|
|
38
|
+
if (!initializer) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const references = ts.isArrayLiteralExpression(initializer) ? [...initializer.elements] : [initializer];
|
|
42
|
+
const demoFiles = new Set();
|
|
43
|
+
for (const reference of references) {
|
|
44
|
+
const identifier = rootIdentifier(reference);
|
|
45
|
+
const source = identifier ? ast.importSourceOf(element.sourceFile, identifier) : null;
|
|
46
|
+
const resolved = source ? resolveSpecifier(element.file, source, (fileArg) => project.files.has(fileArg)) : null;
|
|
47
|
+
if (resolved && isDemoFile(resolved.target) && dirOf(resolved.target) === folder) {
|
|
48
|
+
demoFiles.add(resolved.target);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const expectedDemo = `${folder}/${tag}.demo.ts`;
|
|
52
|
+
for (const demoFile of demoFiles) {
|
|
53
|
+
if (demoFile === expectedDemo) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const finding = {
|
|
57
|
+
file: element.file,
|
|
58
|
+
position: demoMember.getStart(),
|
|
59
|
+
key: elementKey(element),
|
|
60
|
+
message: `the demo file of <${tag}> is ${baseOf(demoFile)}; expected ${tag}.demo.ts`,
|
|
61
|
+
};
|
|
62
|
+
if (usableTag && demoFiles.size === 1 && !project.exists(expectedDemo)) {
|
|
63
|
+
finding.fix = (builderArg) => builderArg.move(demoFile, expectedDemo);
|
|
64
|
+
}
|
|
65
|
+
findings.push(finding);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return findings;
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF5b3V0LmVudHJ5LWZpbGUtbmFtZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL3N0YW5kYXJkcy9ydWxlcy9sYXlvdXQuZW50cnktZmlsZS1uYW1lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxLQUFLLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUVsRixPQUFPLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxtQkFBbUIsRUFBRSxpQkFBaUIsRUFBRSxjQUFjLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFbEgsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztBQUU5QixrR0FBa0c7QUFDbEcsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQWtCO0lBQ3BELEVBQUUsRUFBRSx3QkFBd0I7SUFDNUIsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRTtJQUMxQixPQUFPLEVBQUUsTUFBTTtJQUNmLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRTtRQUN0QixNQUFNLFFBQVEsR0FBbUIsRUFBRSxDQUFDO1FBQ3BDLE1BQU0sUUFBUSxHQUFHLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxQyxLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDaEQsU0FBUztZQUNYLENBQUM7WUFDRCxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDO1lBQ3hCLG9HQUFvRztZQUNwRyxNQUFNLFNBQVMsR0FBRyxt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
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as ast from '../helpers.ast.js';
|
|
3
|
+
const ts = plugins.typescript;
|
|
4
|
+
/** `html/index.ts` exists and calls `setupWccTools({ sections })`; `html/index.html` exists. */
|
|
5
|
+
export const layoutEntryRule = {
|
|
6
|
+
id: 'layout/entry',
|
|
7
|
+
severity: { base: 'error' },
|
|
8
|
+
fixMode: 'none',
|
|
9
|
+
detect: ({ project }) => {
|
|
10
|
+
const findings = [];
|
|
11
|
+
const entry = 'html/index.ts';
|
|
12
|
+
if (!project.files.has(entry)) {
|
|
13
|
+
findings.push({ file: entry, position: 0, key: entry, message: 'html/index.ts is missing' });
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
let found = false;
|
|
17
|
+
const visit = (nodeArg) => {
|
|
18
|
+
if (ts.isCallExpression(nodeArg) && ast.calleeName(nodeArg.expression) === 'setupWccTools') {
|
|
19
|
+
const config = nodeArg.arguments[0];
|
|
20
|
+
if (config && ts.isObjectLiteralExpression(config) && config.properties.some((propertyArg) => (ts.isPropertyAssignment(propertyArg) || ts.isShorthandPropertyAssignment(propertyArg))
|
|
21
|
+
&& ts.isIdentifier(propertyArg.name) && propertyArg.name.text === 'sections')) {
|
|
22
|
+
found = true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
ts.forEachChild(nodeArg, visit);
|
|
26
|
+
};
|
|
27
|
+
visit(project.sourceFile(entry));
|
|
28
|
+
if (!found) {
|
|
29
|
+
findings.push({ file: entry, position: 0, key: entry, message: 'html/index.ts does not call setupWccTools({ sections })' });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (!project.files.has('html/index.html')) {
|
|
33
|
+
findings.push({ file: 'html/index.html', position: 0, key: 'html/index.html', message: 'html/index.html is missing' });
|
|
34
|
+
}
|
|
35
|
+
return findings;
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF5b3V0LmVudHJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvc3RhbmRhcmRzL3J1bGVzL2xheW91dC5lbnRyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sS0FBSyxHQUFHLE1BQU0sbUJBQW1CLENBQUM7QUFHekMsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztBQUU5QixnR0FBZ0c7QUFDaEcsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFrQjtJQUM1QyxFQUFFLEVBQUUsY0FBYztJQUNsQixRQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFO0lBQzNCLE9BQU8sRUFBRSxNQUFNO0lBQ2YsTUFBTSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFO1FBQ3RCLE1BQU0sUUFBUSxHQUFtQixFQUFFLENBQUM7UUFDcEMsTUFBTSxLQUFLLEdBQUcsZUFBZSxDQUFDO1FBQzlCLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzlCLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsQ0FBQyxDQUFDO1FBQy9GLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxLQUFLLEdBQUcsS0FBSyxDQUFDO1lBQ2xCLE1BQU0sS0FBSyxHQUFHLENBQUMsT0FBa0IsRUFBUSxFQUFFO2dCQUN6QyxJQUFJLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsS0FBSyxlQUFlLEVBQUUsQ0FBQztvQkFDM0YsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDcEMsSUFBSSxNQUFNLElBQUksRUFBRSxDQUFDLHlCQUF5QixDQUFDLE1BQU0sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FDM0YsQ0FBQyxFQUFFLENBQUMsb0JBQW9CLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDLDZCQUE2QixDQUFDLFdBQVcsQ0FBQyxDQUFDOzJCQUNwRixFQUFFLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxVQUFVLENBQUMsRUFBRSxDQUFDO3dCQUNoRixLQUFLLEdBQUcsSUFBSSxDQUFDO29CQUNmLENBQUM7Z0JBQ0gsQ0FBQztnQkFDRCxFQUFFLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNsQyxDQUFDLENBQUM7WUFDRixLQUFLLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ2pDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDWCxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLHlEQUF5RCxFQUFFLENBQUMsQ0FBQztZQUM5SCxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUM7WUFDMUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxpQkFBaUIsRUFBRSxRQUFRLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxpQkFBaUIsRUFBRSxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsQ0FBQyxDQUFDO1FBQ3pILENBQUM7UUFDRCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0NBQ0YsQ0FBQyJ9
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { catalogElements, elementKey } from './shared.js';
|
|
2
|
+
/** dees: element folders sit under `ts_web/elements/00group-<area>/`. */
|
|
3
|
+
export const layoutGroupFolderRule = {
|
|
4
|
+
id: 'layout/group-folder',
|
|
5
|
+
severity: { dees: 'warn' },
|
|
6
|
+
fixMode: 'none',
|
|
7
|
+
detect: ({ project }) => {
|
|
8
|
+
const findings = [];
|
|
9
|
+
for (const element of catalogElements(project)) {
|
|
10
|
+
if (element.file.startsWith('ts_web/elements/') && !/^ts_web\/elements\/00group-[^/]+\//.test(element.file)) {
|
|
11
|
+
findings.push({
|
|
12
|
+
file: element.file,
|
|
13
|
+
position: element.decoratorCall.getStart(),
|
|
14
|
+
key: elementKey(element),
|
|
15
|
+
message: `<${element.tag ?? '?'}> is not inside a ts_web/elements/00group-<area>/ folder`,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return findings;
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF5b3V0Lmdyb3VwLWZvbGRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL3N0YW5kYXJkcy9ydWxlcy9sYXlvdXQuZ3JvdXAtZm9sZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxlQUFlLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRTFELHlFQUF5RTtBQUN6RSxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBa0I7SUFDbEQsRUFBRSxFQUFFLHFCQUFxQjtJQUN6QixRQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFO0lBQzFCLE9BQU8sRUFBRSxNQUFNO0lBQ2YsTUFBTSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFO1FBQ3RCLE1BQU0sUUFBUSxHQUFtQixFQUFFLENBQUM7UUFDcEMsS0FBSyxNQUFNLE9BQU8sSUFBSSxlQUFlLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUMvQyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLGtCQUFrQixDQUFDLElBQUksQ0FBQyxvQ0FBb0MsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQzVHLFFBQVEsQ0FBQyxJQUFJLENBQUM7b0JBQ1osSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO29CQUNsQixRQUFRLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUU7b0JBQzFDLEdBQUcsRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDO29CQUN4QixPQUFPLEVBQUUsSUFBSSxPQUFPLENBQUMsR0FBRyxJQUFJLEdBQUcsMERBQTBEO2lCQUMxRixDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7Q0FDRixDQUFDIn0=
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { baseOf, dirOf, isDemoFile } from '../helpers.paths.js';
|
|
2
|
+
import { elementsDir } from './shared.js';
|
|
3
|
+
/** A module at the root of `ts_web/elements/` that declares no element is named `00<name>.ts`. */
|
|
4
|
+
export const layoutShared00Rule = {
|
|
5
|
+
id: 'layout/shared-00',
|
|
6
|
+
severity: { base: 'info' },
|
|
7
|
+
fixMode: 'auto',
|
|
8
|
+
detect: ({ project }) => {
|
|
9
|
+
const findings = [];
|
|
10
|
+
const rootElements = project.elements.filter((elementArg) => dirOf(elementArg.file) === elementsDir);
|
|
11
|
+
const elementFiles = new Set(project.elements.map((elementArg) => elementArg.file));
|
|
12
|
+
for (const file of project.webFiles) {
|
|
13
|
+
const name = baseOf(file);
|
|
14
|
+
if (dirOf(file) !== elementsDir || name === 'index.ts' || name.startsWith('00') || isDemoFile(file) || elementFiles.has(file)) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
// Companion files of a flat element (`<tag>.styles.ts`) move with the element instead.
|
|
18
|
+
if (rootElements.some((elementArg) => elementArg.tag && name.startsWith(`${elementArg.tag}.`))) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
const target = `${elementsDir}/00${name}`;
|
|
22
|
+
const finding = {
|
|
23
|
+
file,
|
|
24
|
+
position: 0,
|
|
25
|
+
key: file,
|
|
26
|
+
message: `${name} declares no element; shared modules at the root of ts_web/elements are named 00${name}`,
|
|
27
|
+
};
|
|
28
|
+
if (!project.exists(target)) {
|
|
29
|
+
finding.fix = (builderArg) => builderArg.move(file, target);
|
|
30
|
+
}
|
|
31
|
+
findings.push(finding);
|
|
32
|
+
}
|
|
33
|
+
return findings;
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF5b3V0LnNoYXJlZC0wMC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL3N0YW5kYXJkcy9ydWxlcy9sYXlvdXQuc2hhcmVkLTAwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRWhFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFMUMsa0dBQWtHO0FBQ2xHLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFrQjtJQUMvQyxFQUFFLEVBQUUsa0JBQWtCO0lBQ3RCLFFBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUU7SUFDMUIsT0FBTyxFQUFFLE1BQU07SUFDZixNQUFNLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUU7UUFDdEIsTUFBTSxRQUFRLEdBQW1CLEVBQUUsQ0FBQztRQUNwQyxNQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxXQUFXLENBQUMsQ0FBQztRQUNyRyxNQUFNLFlBQVksR0FBRyxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDcEYsS0FBSyxNQUFNLElBQUksSUFBSSxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDcEMsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzFCLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLFdBQVcsSUFBSSxJQUFJLEtBQUssVUFBVSxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLFlBQVksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDOUgsU0FBUztZQUNYLENBQUM7WUFDRCx1RkFBdUY7WUFDdkYsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxVQUFVLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQy9GLFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxNQUFNLEdBQUcsR0FBRyxXQUFXLE1BQU0sSUFBSSxFQUFFLENBQUM7WUFDMUMsTUFBTSxPQUFPLEdBQWlCO2dCQUM1QixJQUFJO2dCQUNKLFFBQVEsRUFBRSxDQUFDO2dCQUNYLEdBQUcsRUFBRSxJQUFJO2dCQUNULE9BQU8sRUFBRSxHQUFHLElBQUksbUZBQW1GLElBQUksRUFBRTthQUMxRyxDQUFDO1lBQ0YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztnQkFDNUIsT0FBTyxDQUFDLEdBQUcsR0FBRyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDOUQsQ0FBQztZQUNELFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDekIsQ0FBQztRQUNELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7Q0FDRixDQUFDIn0=
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { catalogElements, elementKey } from './shared.js';
|
|
2
|
+
/** The class name, lowercased, equals the tag with hyphens removed. */
|
|
3
|
+
export const namingClassMatchesTagRule = {
|
|
4
|
+
id: 'naming/class-matches-tag',
|
|
5
|
+
severity: { base: 'warn' },
|
|
6
|
+
fixMode: 'none',
|
|
7
|
+
allowlistCategories: ['published'],
|
|
8
|
+
detect: ({ project }) => {
|
|
9
|
+
const findings = [];
|
|
10
|
+
for (const element of catalogElements(project)) {
|
|
11
|
+
if (!element.tag || !element.className) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
if (element.className.toLowerCase() !== element.tag.replace(/-/g, '')) {
|
|
15
|
+
findings.push({
|
|
16
|
+
file: element.file,
|
|
17
|
+
position: element.classNode.name.getStart(),
|
|
18
|
+
key: elementKey(element),
|
|
19
|
+
message: `class ${element.className} does not match <${element.tag}>`,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return findings;
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFtaW5nLmNsYXNzLW1hdGNoZXMtdGFnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvc3RhbmRhcmRzL3J1bGVzL25hbWluZy5jbGFzcy1tYXRjaGVzLXRhZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUUxRCx1RUFBdUU7QUFDdkUsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQWtCO0lBQ3RELEVBQUUsRUFBRSwwQkFBMEI7SUFDOUIsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRTtJQUMxQixPQUFPLEVBQUUsTUFBTTtJQUNmLG1CQUFtQixFQUFFLENBQUMsV0FBVyxDQUFDO0lBQ2xDLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRTtRQUN0QixNQUFNLFFBQVEsR0FBbUIsRUFBRSxDQUFDO1FBQ3BDLEtBQUssTUFBTSxPQUFPLElBQUksZUFBZSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDL0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ3ZDLFNBQVM7WUFDWCxDQUFDO1lBQ0QsSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLFdBQVcsRUFBRSxLQUFLLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUN0RSxRQUFRLENBQUMsSUFBSSxDQUFDO29CQUNaLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSyxDQUFDLFFBQVEsRUFBRTtvQkFDNUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUM7b0JBQ3hCLE9BQU8sRUFBRSxTQUFTLE9BQU8sQ0FBQyxTQUFTLG9CQUFvQixPQUFPLENBQUMsR0FBRyxHQUFHO2lCQUN0RSxDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7Q0FDRixDQUFDIn0=
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** File and folder names under `ts_web/` are lowercase. */
|
|
2
|
+
export const namingLowercaseFilesRule = {
|
|
3
|
+
id: 'naming/lowercase-files',
|
|
4
|
+
severity: { base: 'error' },
|
|
5
|
+
fixMode: 'auto',
|
|
6
|
+
detect: ({ project }) => {
|
|
7
|
+
const findings = [];
|
|
8
|
+
const lowered = new Map();
|
|
9
|
+
for (const file of project.files.keys()) {
|
|
10
|
+
lowered.set(file.toLowerCase(), (lowered.get(file.toLowerCase()) ?? 0) + 1);
|
|
11
|
+
}
|
|
12
|
+
for (const file of project.webFiles) {
|
|
13
|
+
if (!/[A-Z]/.test(file)) {
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
const target = file.toLowerCase();
|
|
17
|
+
const finding = { file, position: 0, key: file, message: `${file} is not lowercase; expected ${target}` };
|
|
18
|
+
if (lowered.get(target) === 1 && !project.exists(target)) {
|
|
19
|
+
finding.fix = (builderArg) => builderArg.move(file, target);
|
|
20
|
+
}
|
|
21
|
+
findings.push(finding);
|
|
22
|
+
}
|
|
23
|
+
return findings;
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFtaW5nLmxvd2VyY2FzZS1maWxlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL3N0YW5kYXJkcy9ydWxlcy9uYW1pbmcubG93ZXJjYXNlLWZpbGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLDJEQUEyRDtBQUMzRCxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBa0I7SUFDckQsRUFBRSxFQUFFLHdCQUF3QjtJQUM1QixRQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFO0lBQzNCLE9BQU8sRUFBRSxNQUFNO0lBQ2YsTUFBTSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFO1FBQ3RCLE1BQU0sUUFBUSxHQUFtQixFQUFFLENBQUM7UUFDcEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7UUFDMUMsS0FBSyxNQUFNLElBQUksSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7WUFDeEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzlFLENBQUM7UUFDRCxLQUFLLE1BQU0sSUFBSSxJQUFJLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNwQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUN4QixTQUFTO1lBQ1gsQ0FBQztZQUNELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNsQyxNQUFNLE9BQU8sR0FBaUIsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxHQUFHLElBQUksK0JBQStCLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDeEgsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztnQkFDekQsT0FBTyxDQUFDLEdBQUcsR0FBRyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDOUQsQ0FBQztZQUNELFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDekIsQ0FBQztRQUNELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7Q0FDRixDQUFDIn0=
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { elementKey } from './shared.js';
|
|
2
|
+
/** Every tag starts with `<tagPrefix>-`. Applies to fixture elements in demo files too: they share the page. */
|
|
3
|
+
export const namingTagPrefixRule = {
|
|
4
|
+
id: 'naming/tag-prefix',
|
|
5
|
+
severity: { base: 'error' },
|
|
6
|
+
fixMode: 'none',
|
|
7
|
+
allowlistCategories: ['published'],
|
|
8
|
+
detect: ({ project, config }) => {
|
|
9
|
+
const findings = [];
|
|
10
|
+
for (const element of project.elements) {
|
|
11
|
+
if (element.tag && !element.tag.startsWith(`${config.tagPrefix}-`)) {
|
|
12
|
+
findings.push({
|
|
13
|
+
file: element.file,
|
|
14
|
+
position: element.decoratorCall.getStart(),
|
|
15
|
+
key: elementKey(element),
|
|
16
|
+
message: `<${element.tag}> does not start with the tag prefix '${config.tagPrefix}-'`,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return findings;
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFtaW5nLnRhZy1wcmVmaXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9zdGFuZGFyZHMvcnVsZXMvbmFtaW5nLnRhZy1wcmVmaXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUV6QyxnSEFBZ0g7QUFDaEgsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQWtCO0lBQ2hELEVBQUUsRUFBRSxtQkFBbUI7SUFDdkIsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRTtJQUMzQixPQUFPLEVBQUUsTUFBTTtJQUNmLG1CQUFtQixFQUFFLENBQUMsV0FBVyxDQUFDO0lBQ2xDLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7UUFDOUIsTUFBTSxRQUFRLEdBQW1CLEVBQUUsQ0FBQztRQUNwQyxLQUFLLE1BQU0sT0FBTyxJQUFJLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUN2QyxJQUFJLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxTQUFTLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ25FLFFBQVEsQ0FBQyxJQUFJLENBQUM7b0JBQ1osSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO29CQUNsQixRQUFRLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUU7b0JBQzFDLEdBQUcsRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDO29CQUN4QixPQUFPLEVBQUUsSUFBSSxPQUFPLENBQUMsR0FBRyx5Q0FBeUMsTUFBTSxDQUFDLFNBQVMsSUFBSTtpQkFDdEYsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0NBQ0YsQ0FBQyJ9
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as ast from '../helpers.ast.js';
|
|
3
|
+
import { propertyKey } from './shared.js';
|
|
4
|
+
const ts = plugins.typescript;
|
|
5
|
+
/** Members decorated with `@property` or `@state` use the `accessor` keyword (standard decorators). */
|
|
6
|
+
export const propsAccessorRule = {
|
|
7
|
+
id: 'props/accessor',
|
|
8
|
+
severity: { base: 'error' },
|
|
9
|
+
fixMode: 'auto',
|
|
10
|
+
detect: ({ project }) => {
|
|
11
|
+
const findings = [];
|
|
12
|
+
if (project.experimentalDecorators) {
|
|
13
|
+
return findings;
|
|
14
|
+
}
|
|
15
|
+
for (const property of project.properties) {
|
|
16
|
+
const member = property.member;
|
|
17
|
+
if (!ts.isPropertyDeclaration(member) || ast.hasModifier(member, ts.SyntaxKind.AccessorKeyword)) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const finding = {
|
|
21
|
+
file: property.file,
|
|
22
|
+
position: member.name.getStart(),
|
|
23
|
+
key: propertyKey(property),
|
|
24
|
+
message: `@${property.decorator} ${property.name} is a field; standard decorators need 'accessor ${property.name}'`,
|
|
25
|
+
};
|
|
26
|
+
if (!ast.hasModifier(member, ts.SyntaxKind.DeclareKeyword)) {
|
|
27
|
+
const at = member.name.getStart();
|
|
28
|
+
finding.fix = (builderArg) => builderArg.edit(property.file, at, at, 'accessor ');
|
|
29
|
+
}
|
|
30
|
+
findings.push(finding);
|
|
31
|
+
}
|
|
32
|
+
return findings;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvcHMuYWNjZXNzb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9zdGFuZGFyZHMvcnVsZXMvcHJvcHMuYWNjZXNzb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEtBQUssR0FBRyxNQUFNLG1CQUFtQixDQUFDO0FBRXpDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFMUMsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztBQUU5Qix1R0FBdUc7QUFDdkcsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQWtCO0lBQzlDLEVBQUUsRUFBRSxnQkFBZ0I7SUFDcEIsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRTtJQUMzQixPQUFPLEVBQUUsTUFBTTtJQUNmLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRTtRQUN0QixNQUFNLFFBQVEsR0FBbUIsRUFBRSxDQUFDO1FBQ3BDLElBQUksT0FBTyxDQUFDLHNCQUFzQixFQUFFLENBQUM7WUFDbkMsT0FBTyxRQUFRLENBQUM7UUFDbEIsQ0FBQztRQUNELEtBQUssTUFBTSxRQUFRLElBQUksT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzFDLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUM7WUFDL0IsSUFBSSxDQUFDLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsSUFBSSxHQUFHLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hHLFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxPQUFPLEdBQWlCO2dCQUM1QixJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUk7Z0JBQ25CLFFBQVEsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRTtnQkFDaEMsR0FBRyxFQUFFLFdBQVcsQ0FBQyxRQUFRLENBQUM7Z0JBQzFCLE9BQU8sRUFBRSxJQUFJLFFBQVEsQ0FBQyxTQUFTLElBQUksUUFBUSxDQUFDLElBQUksbURBQW1ELFFBQVEsQ0FBQyxJQUFJLEdBQUc7YUFDcEgsQ0FBQztZQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7Z0JBQzNELE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ2xDLE9BQU8sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ3BGLENBQUM7WUFDRCxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3pCLENBQUM7UUFDRCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0NBQ0YsQ0FBQyJ9
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as ast from '../helpers.ast.js';
|
|
3
|
+
import { addOptionFix } from './props.typed.js';
|
|
4
|
+
import { coreTypeOf, isArrayTypeNode, propertyKey, publicProperties } from './shared.js';
|
|
5
|
+
const ts = plugins.typescript;
|
|
6
|
+
/** An array, object literal type or `I`-prefixed interface annotation. */
|
|
7
|
+
const isObjectAnnotation = (typeArg) => {
|
|
8
|
+
if (!typeArg) {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
return isArrayTypeNode(typeArg)
|
|
12
|
+
|| ts.isTypeLiteralNode(typeArg)
|
|
13
|
+
|| (ts.isTypeReferenceNode(typeArg) && ts.isIdentifier(typeArg.typeName) && /^I[A-Z]/.test(typeArg.typeName.text));
|
|
14
|
+
};
|
|
15
|
+
/** A public property holding an object or array declares `type: Object`/`type: Array` or `attribute: false`. */
|
|
16
|
+
export const propsObjectNoAttributeRule = {
|
|
17
|
+
id: 'props/object-no-attribute',
|
|
18
|
+
severity: { base: 'warn' },
|
|
19
|
+
fixMode: 'auto',
|
|
20
|
+
detect: ({ project }) => {
|
|
21
|
+
const findings = [];
|
|
22
|
+
for (const property of publicProperties(project)) {
|
|
23
|
+
if (property.dynamicOptions || !isObjectAnnotation(coreTypeOf(property))) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const options = property.options;
|
|
27
|
+
const type = options ? ast.objectPropertyText(options, 'type') : null;
|
|
28
|
+
if (type === 'Object' || type === 'Array' || (options && ast.objectPropertyText(options, 'attribute') === 'false')) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
findings.push({
|
|
32
|
+
file: property.file,
|
|
33
|
+
position: property.call.getStart(),
|
|
34
|
+
key: propertyKey(property),
|
|
35
|
+
message: `@property ${property.name} holds an object or array but declares neither type: Object/Array nor attribute: false`,
|
|
36
|
+
fix: addOptionFix(property, 'attribute: false', 'last'),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return findings;
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvcHMub2JqZWN0LW5vLWF0dHJpYnV0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL3N0YW5kYXJkcy9ydWxlcy9wcm9wcy5vYmplY3Qtbm8tYXR0cmlidXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxLQUFLLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQztBQUV6QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxlQUFlLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXpGLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUM7QUFFOUIsMEVBQTBFO0FBQzFFLE1BQU0sa0JBQWtCLEdBQUcsQ0FBQyxPQUE2QixFQUFXLEVBQUU7SUFDcEUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2IsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBQ0QsT0FBTyxlQUFlLENBQUMsT0FBTyxDQUFDO1dBQzFCLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUM7V0FDN0IsQ0FBQyxFQUFFLENBQUMsbUJBQW1CLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDdkgsQ0FBQyxDQUFDO0FBRUYsZ0hBQWdIO0FBQ2hILE1BQU0sQ0FBQyxNQUFNLDBCQUEwQixHQUFrQjtJQUN2RCxFQUFFLEVBQUUsMkJBQTJCO0lBQy9CLFFBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUU7SUFDMUIsT0FBTyxFQUFFLE1BQU07SUFDZixNQUFNLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUU7UUFDdEIsTUFBTSxRQUFRLEdBQW1CLEVBQUUsQ0FBQztRQUNwQyxLQUFLLE1BQU0sUUFBUSxJQUFJLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDakQsSUFBSSxRQUFRLENBQUMsY0FBYyxJQUFJLENBQUMsa0JBQWtCLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDekUsU0FBUztZQUNYLENBQUM7WUFDRCxNQUFNLE9BQU8sR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDO1lBQ2pDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ3RFLElBQUksSUFBSSxLQUFLLFFBQVEsSUFBSSxJQUFJLEtBQUssT0FBTyxJQUFJLENBQUMsT0FBTyxJQUFJLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDLEtBQUssT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDbkgsU0FBUztZQUNYLENBQUM7WUFDRCxRQUFRLENBQUMsSUFBSSxDQUFDO2dCQUNaLElBQUksRUFBRSxRQUFRLENBQUMsSUFBSTtnQkFDbkIsUUFBUSxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUNsQyxHQUFHLEVBQUUsV0FBVyxDQUFDLFFBQVEsQ0FBQztnQkFDMUIsT0FBTyxFQUFFLGFBQWEsUUFBUSxDQUFDLElBQUksd0ZBQXdGO2dCQUMzSCxHQUFHLEVBQUUsWUFBWSxDQUFDLFFBQVEsRUFBRSxrQkFBa0IsRUFBRSxNQUFNLENBQUM7YUFDeEQsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUNELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7Q0FDRixDQUFDIn0=
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { IStandardRule } from '../rule.js';
|
|
2
|
+
/** Global attributes with native behaviour that stay unreflected without an allowlist entry. */
|
|
3
|
+
export declare const reflectExemptNames: readonly string[];
|
|
4
|
+
/** A primitive public property declares `reflect: true` or `attribute: false`. */
|
|
5
|
+
export declare const propsReflectPrimitiveRule: IStandardRule;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as ast from '../helpers.ast.js';
|
|
2
|
+
import { addOptionFix } from './props.typed.js';
|
|
3
|
+
import { propertyKey, publicProperties } from './shared.js';
|
|
4
|
+
/** Global attributes with native behaviour that stay unreflected without an allowlist entry. */
|
|
5
|
+
export const reflectExemptNames = ['title', 'hidden', 'dir', 'lang', 'role', 'inert', 'draggable'];
|
|
6
|
+
const primitiveTypes = ['String', 'Number', 'Boolean'];
|
|
7
|
+
/** A primitive public property declares `reflect: true` or `attribute: false`. */
|
|
8
|
+
export const propsReflectPrimitiveRule = {
|
|
9
|
+
id: 'props/reflect-primitive',
|
|
10
|
+
severity: { base: 'error' },
|
|
11
|
+
fixMode: 'opt-in',
|
|
12
|
+
allowlistCategories: ['user-data', 'object', 'large-text', 'global-attribute'],
|
|
13
|
+
detect: ({ project }) => {
|
|
14
|
+
const findings = [];
|
|
15
|
+
for (const property of publicProperties(project)) {
|
|
16
|
+
if (property.dynamicOptions || reflectExemptNames.includes(property.name)) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const options = property.options;
|
|
20
|
+
const type = options ? ast.objectPropertyText(options, 'type') : null;
|
|
21
|
+
if (type !== null && !primitiveTypes.includes(type)) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (options && (ast.objectPropertyText(options, 'attribute') === 'false' || ast.objectPropertyText(options, 'reflect') === 'true')) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const explicitReflect = options ? ast.objectProperty(options, 'reflect') : null;
|
|
28
|
+
findings.push({
|
|
29
|
+
file: property.file,
|
|
30
|
+
position: property.call.getStart(),
|
|
31
|
+
key: propertyKey(property),
|
|
32
|
+
message: `public primitive @property ${property.name} declares neither reflect: true nor attribute: false`,
|
|
33
|
+
fix: explicitReflect
|
|
34
|
+
? (builderArg) => builderArg.edit(property.file, explicitReflect.initializer.getStart(), explicitReflect.initializer.end, 'true')
|
|
35
|
+
: addOptionFix(property, 'reflect: true', 'last'),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return findings;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvcHMucmVmbGVjdC1wcmltaXRpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9zdGFuZGFyZHMvcnVsZXMvcHJvcHMucmVmbGVjdC1wcmltaXRpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQztBQUV6QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUU1RCxnR0FBZ0c7QUFDaEcsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQXNCLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsV0FBVyxDQUFDLENBQUM7QUFFdEgsTUFBTSxjQUFjLEdBQUcsQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBRXZELGtGQUFrRjtBQUNsRixNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBa0I7SUFDdEQsRUFBRSxFQUFFLHlCQUF5QjtJQUM3QixRQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFO0lBQzNCLE9BQU8sRUFBRSxRQUFRO0lBQ2pCLG1CQUFtQixFQUFFLENBQUMsV0FBVyxFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUUsa0JBQWtCLENBQUM7SUFDOUUsTUFBTSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFO1FBQ3RCLE1BQU0sUUFBUSxHQUFtQixFQUFFLENBQUM7UUFDcEMsS0FBSyxNQUFNLFFBQVEsSUFBSSxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ2pELElBQUksUUFBUSxDQUFDLGNBQWMsSUFBSSxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQzFFLFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQztZQUNqQyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUN0RSxJQUFJLElBQUksS0FBSyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ3BELFNBQVM7WUFDWCxDQUFDO1lBQ0QsSUFBSSxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsT0FBTyxFQUFFLFdBQVcsQ0FBQyxLQUFLLE9BQU8sSUFBSSxHQUFHLENBQUMsa0JBQWtCLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQ25JLFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ2hGLFFBQVEsQ0FBQyxJQUFJLENBQUM7Z0JBQ1osSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJO2dCQUNuQixRQUFRLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7Z0JBQ2xDLEdBQUcsRUFBRSxXQUFXLENBQUMsUUFBUSxDQUFDO2dCQUMxQixPQUFPLEVBQUUsOEJBQThCLFFBQVEsQ0FBQyxJQUFJLHNEQUFzRDtnQkFDMUcsR0FBRyxFQUFFLGVBQWU7b0JBQ2xCLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLGVBQWUsQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLEVBQUUsZUFBZSxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDO29CQUNqSSxDQUFDLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxlQUFlLEVBQUUsTUFBTSxDQUFDO2FBQ3BELENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0NBQ0YsQ0FBQyJ9
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { IStandardProperty } from '../classes.standardproject.js';
|
|
2
|
+
import type { IStandardRule, TFixAction } from '../rule.js';
|
|
3
|
+
/** The edit that adds `propertyTextArg` to a property decorator's options, creating the options literal when absent. */
|
|
4
|
+
export declare const addOptionFix: (propertyArg: IStandardProperty, propertyTextArg: string, placementArg: "first" | "last") => TFixAction;
|
|
5
|
+
/** A public property declares `type`. */
|
|
6
|
+
export declare const propsTypedRule: IStandardRule;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as ast from '../helpers.ast.js';
|
|
3
|
+
import { coreTypeOf, isArrayTypeNode, propertyKey, publicProperties } from './shared.js';
|
|
4
|
+
const ts = plugins.typescript;
|
|
5
|
+
/** The Lit `type` that the property's annotation maps to, or null when the annotation does not decide it. */
|
|
6
|
+
const litTypeFor = (propertyArg) => {
|
|
7
|
+
const typeNode = coreTypeOf(propertyArg);
|
|
8
|
+
if (!typeNode) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
switch (typeNode.kind) {
|
|
12
|
+
case ts.SyntaxKind.StringKeyword:
|
|
13
|
+
return 'String';
|
|
14
|
+
case ts.SyntaxKind.NumberKeyword:
|
|
15
|
+
return 'Number';
|
|
16
|
+
case ts.SyntaxKind.BooleanKeyword:
|
|
17
|
+
return 'Boolean';
|
|
18
|
+
}
|
|
19
|
+
if (ts.isUnionTypeNode(typeNode) && typeNode.types.every((typeArg) => (ts.isLiteralTypeNode(typeArg) && ts.isStringLiteral(typeArg.literal))
|
|
20
|
+
|| typeArg.kind === ts.SyntaxKind.UndefinedKeyword
|
|
21
|
+
|| (ts.isLiteralTypeNode(typeArg) && typeArg.literal.kind === ts.SyntaxKind.NullKeyword))) {
|
|
22
|
+
return 'String';
|
|
23
|
+
}
|
|
24
|
+
if (ts.isLiteralTypeNode(typeNode) && ts.isStringLiteral(typeNode.literal)) {
|
|
25
|
+
return 'String';
|
|
26
|
+
}
|
|
27
|
+
return isArrayTypeNode(typeNode) ? 'Array' : null;
|
|
28
|
+
};
|
|
29
|
+
/** The edit that adds `propertyTextArg` to a property decorator's options, creating the options literal when absent. */
|
|
30
|
+
export const addOptionFix = (propertyArg, propertyTextArg, placementArg) => (builderArg) => {
|
|
31
|
+
if (propertyArg.options) {
|
|
32
|
+
const edit = placementArg === 'first'
|
|
33
|
+
? ast.prependObjectPropertyEdit(propertyArg.options, propertyTextArg)
|
|
34
|
+
: ast.appendObjectPropertyEdit(propertyArg.options, propertyTextArg);
|
|
35
|
+
builderArg.edit(propertyArg.file, edit.start, edit.end, edit.text);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const at = propertyArg.call.arguments.pos;
|
|
39
|
+
builderArg.edit(propertyArg.file, at, at, `{ ${propertyTextArg} }`);
|
|
40
|
+
};
|
|
41
|
+
/** A public property declares `type`. */
|
|
42
|
+
export const propsTypedRule = {
|
|
43
|
+
id: 'props/typed',
|
|
44
|
+
severity: { base: 'warn' },
|
|
45
|
+
fixMode: 'auto',
|
|
46
|
+
detect: ({ project }) => {
|
|
47
|
+
const findings = [];
|
|
48
|
+
for (const property of publicProperties(project)) {
|
|
49
|
+
if (property.dynamicOptions || (property.options && ast.objectProperty(property.options, 'type'))) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const litType = litTypeFor(property);
|
|
53
|
+
findings.push({
|
|
54
|
+
file: property.file,
|
|
55
|
+
position: property.call.getStart(),
|
|
56
|
+
key: propertyKey(property),
|
|
57
|
+
message: `@property ${property.name} declares no type`,
|
|
58
|
+
fix: litType ? addOptionFix(property, `type: ${litType}`, 'first') : undefined,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return findings;
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvcHMudHlwZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9zdGFuZGFyZHMvcnVsZXMvcHJvcHMudHlwZWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEtBQUssR0FBRyxNQUFNLG1CQUFtQixDQUFDO0FBR3pDLE9BQU8sRUFBRSxVQUFVLEVBQUUsZUFBZSxFQUFFLFdBQVcsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUV6RixNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDO0FBRTlCLDZHQUE2RztBQUM3RyxNQUFNLFVBQVUsR0FBRyxDQUFDLFdBQThCLEVBQWlCLEVBQUU7SUFDbkUsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3pDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNkLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUNELFFBQVEsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3RCLEtBQUssRUFBRSxDQUFDLFVBQVUsQ0FBQyxhQUFhO1lBQzlCLE9BQU8sUUFBUSxDQUFDO1FBQ2xCLEtBQUssRUFBRSxDQUFDLFVBQVUsQ0FBQyxhQUFhO1lBQzlCLE9BQU8sUUFBUSxDQUFDO1FBQ2xCLEtBQUssRUFBRSxDQUFDLFVBQVUsQ0FBQyxjQUFjO1lBQy9CLE9BQU8sU0FBUyxDQUFDO0lBQ3JCLENBQUM7SUFDRCxJQUFJLEVBQUUsQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUNuRSxDQUFDLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztXQUNuRSxP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
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as ast from '../helpers.ast.js';
|
|
2
|
+
import type { IStandardElement, IStandardProperty, StandardProject } from '../classes.standardproject.js';
|
|
3
|
+
import type { IFixBuilder } from '../rule.js';
|
|
4
|
+
export declare const elementsDir = "ts_web/elements";
|
|
5
|
+
/** `ts_web/elements/00group-<area>` or `ts_web/elements` itself. */
|
|
6
|
+
export declare const isElementParentDir: (dirArg: string) => boolean;
|
|
7
|
+
/**
|
|
8
|
+
* A valid custom element name in the ASCII subset the standard allows: a lowercase letter first,
|
|
9
|
+
* then lowercase letters, digits, `-`, `.` and `_`, at least one `-`, and not a reserved name. Such
|
|
10
|
+
* a tag is also a safe file and folder name, so only these tags feed fixes that derive paths or code.
|
|
11
|
+
*/
|
|
12
|
+
export declare const isCustomElementName: (tagArg: string) => boolean;
|
|
13
|
+
/** True when an element's entry file sits in its own element folder `…/<tag>/`. */
|
|
14
|
+
export declare const isInElementFolder: (elementArg: IStandardElement) => boolean;
|
|
15
|
+
/** The `<area>` of `ts_web/elements/00group-<area>/…`, or null. */
|
|
16
|
+
export declare const groupAreaOf: (fileArg: string) => string | null;
|
|
17
|
+
/** Elements outside demo files: the catalog's own elements. */
|
|
18
|
+
export declare const catalogElements: (projectArg: StandardProject) => IStandardElement[];
|
|
19
|
+
/** Public `@property` members outside demo files. */
|
|
20
|
+
export declare const publicProperties: (projectArg: StandardProject) => IStandardProperty[];
|
|
21
|
+
export declare const elementKey: (elementArg: IStandardElement) => string;
|
|
22
|
+
export declare const propertyKey: (propertyArg: IStandardProperty) => string;
|
|
23
|
+
/** The type annotation of a property member without `undefined` and `null` union members. */
|
|
24
|
+
export declare const coreTypeOf: (propertyArg: IStandardProperty) => ast.TTypeNode | null;
|
|
25
|
+
export declare const isArrayTypeNode: (typeArg: ast.TTypeNode) => boolean;
|
|
26
|
+
/** The position at the start of the line after the last `export … from` statement, or at the end of the file. */
|
|
27
|
+
export declare const exportInsertionPoint: (sourceFileArg: ast.TSourceFile) => {
|
|
28
|
+
position: number;
|
|
29
|
+
prefix: string;
|
|
30
|
+
};
|
|
31
|
+
/** Adds `export * from '<target>';` to a barrel. */
|
|
32
|
+
export declare const addReexport: (builderArg: IFixBuilder, projectArg: StandardProject, barrelArg: string, targetArg: string) => void;
|
|
33
|
+
/** Removes a whole statement including its line break; from the line start when only indentation precedes it. */
|
|
34
|
+
export declare const removeStatement: (builderArg: IFixBuilder, fileArg: string, statementArg: ast.TNode) => void;
|
|
35
|
+
/** The identifier a `static demo` value refers to at its root, e.g. `demoFunc` or `demos` in `demos.main`. */
|
|
36
|
+
export declare const rootIdentifier: (expressionArg: ast.TExpression) => string | null;
|
|
37
|
+
/** The start of the line following the line a position is on. */
|
|
38
|
+
export declare const nextLineStart: (textArg: string, positionArg: number) => number;
|