@design.estate/wcctools 6.0.0 → 6.1.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.
Files changed (150) hide show
  1. package/changelog.md +13 -0
  2. package/dist_shell/bundle.js +3 -3
  3. package/dist_shell/bundle.js.map +1 -1
  4. package/dist_ts/00_commitinfo_data.js +1 -1
  5. package/dist_ts/cli.js +8 -2
  6. package/dist_ts/plugins.d.ts +7 -2
  7. package/dist_ts/plugins.js +9 -3
  8. package/dist_ts/standards/baselines.d.ts +27 -0
  9. package/dist_ts/standards/baselines.js +83 -0
  10. package/dist_ts/standards/checker.d.ts +21 -0
  11. package/dist_ts/standards/checker.js +88 -0
  12. package/dist_ts/standards/classes.gitrepo.d.ts +13 -0
  13. package/dist_ts/standards/classes.gitrepo.js +43 -0
  14. package/dist_ts/standards/classes.sourceedits.d.ts +15 -0
  15. package/dist_ts/standards/classes.sourceedits.js +54 -0
  16. package/dist_ts/standards/classes.standardfixer.d.ts +40 -0
  17. package/dist_ts/standards/classes.standardfixer.js +210 -0
  18. package/dist_ts/standards/classes.standardproject.d.ts +80 -0
  19. package/dist_ts/standards/classes.standardproject.js +195 -0
  20. package/dist_ts/standards/classes.standardtree.d.ts +56 -0
  21. package/dist_ts/standards/classes.standardtree.js +207 -0
  22. package/dist_ts/standards/cli.d.ts +7 -0
  23. package/dist_ts/standards/cli.js +89 -0
  24. package/dist_ts/standards/config.d.ts +33 -0
  25. package/dist_ts/standards/config.js +139 -0
  26. package/dist_ts/standards/errors.d.ts +9 -0
  27. package/dist_ts/standards/errors.js +17 -0
  28. package/dist_ts/standards/helpers.ast.d.ts +56 -0
  29. package/dist_ts/standards/helpers.ast.js +172 -0
  30. package/dist_ts/standards/helpers.paths.d.ts +36 -0
  31. package/dist_ts/standards/helpers.paths.js +86 -0
  32. package/dist_ts/standards/index.d.ts +14 -0
  33. package/dist_ts/standards/index.js +15 -0
  34. package/dist_ts/standards/output.d.ts +7 -0
  35. package/dist_ts/standards/output.js +57 -0
  36. package/dist_ts/standards/ratchet.d.ts +15 -0
  37. package/dist_ts/standards/ratchet.js +45 -0
  38. package/dist_ts/standards/rule.d.ts +50 -0
  39. package/dist_ts/standards/rule.js +9 -0
  40. package/dist_ts/standards/rules/barrel.element-index.d.ts +7 -0
  41. package/dist_ts/standards/rules/barrel.element-index.js +108 -0
  42. package/dist_ts/standards/rules/barrel.no-demo-export.d.ts +3 -0
  43. package/dist_ts/standards/rules/barrel.no-demo-export.js +29 -0
  44. package/dist_ts/standards/rules/demo.fixture-not-exported.d.ts +3 -0
  45. package/dist_ts/standards/rules/demo.fixture-not-exported.js +29 -0
  46. package/dist_ts/standards/rules/demo.groups.d.ts +6 -0
  47. package/dist_ts/standards/rules/demo.groups.js +72 -0
  48. package/dist_ts/standards/rules/demo.required.d.ts +3 -0
  49. package/dist_ts/standards/rules/demo.required.js +48 -0
  50. package/dist_ts/standards/rules/demo.separate-file.d.ts +3 -0
  51. package/dist_ts/standards/rules/demo.separate-file.js +38 -0
  52. package/dist_ts/standards/rules/demo.shape.d.ts +3 -0
  53. package/dist_ts/standards/rules/demo.shape.js +38 -0
  54. package/dist_ts/standards/rules/docs.component-index.d.ts +8 -0
  55. package/dist_ts/standards/rules/docs.component-index.js +84 -0
  56. package/dist_ts/standards/rules/element.exported.d.ts +3 -0
  57. package/dist_ts/standards/rules/element.exported.js +33 -0
  58. package/dist_ts/standards/rules/element.literal-tag.d.ts +3 -0
  59. package/dist_ts/standards/rules/element.literal-tag.js +30 -0
  60. package/dist_ts/standards/rules/element.reachable.d.ts +3 -0
  61. package/dist_ts/standards/rules/element.reachable.js +48 -0
  62. package/dist_ts/standards/rules/element.tag-map.d.ts +3 -0
  63. package/dist_ts/standards/rules/element.tag-map.js +83 -0
  64. package/dist_ts/standards/rules/i18n.literals.d.ts +3 -0
  65. package/dist_ts/standards/rules/i18n.literals.js +52 -0
  66. package/dist_ts/standards/rules/index.d.ts +12 -0
  67. package/dist_ts/standards/rules/index.js +83 -0
  68. package/dist_ts/standards/rules/layout.element-folder.d.ts +3 -0
  69. package/dist_ts/standards/rules/layout.element-folder.js +47 -0
  70. package/dist_ts/standards/rules/layout.entry-file-name.d.ts +3 -0
  71. package/dist_ts/standards/rules/layout.entry-file-name.js +71 -0
  72. package/dist_ts/standards/rules/layout.entry.d.ts +3 -0
  73. package/dist_ts/standards/rules/layout.entry.js +38 -0
  74. package/dist_ts/standards/rules/layout.group-folder.d.ts +3 -0
  75. package/dist_ts/standards/rules/layout.group-folder.js +22 -0
  76. package/dist_ts/standards/rules/layout.shared-00.d.ts +3 -0
  77. package/dist_ts/standards/rules/layout.shared-00.js +36 -0
  78. package/dist_ts/standards/rules/naming.class-matches-tag.d.ts +3 -0
  79. package/dist_ts/standards/rules/naming.class-matches-tag.js +26 -0
  80. package/dist_ts/standards/rules/naming.lowercase-files.d.ts +3 -0
  81. package/dist_ts/standards/rules/naming.lowercase-files.js +26 -0
  82. package/dist_ts/standards/rules/naming.tag-prefix.d.ts +3 -0
  83. package/dist_ts/standards/rules/naming.tag-prefix.js +23 -0
  84. package/dist_ts/standards/rules/props.accessor.d.ts +3 -0
  85. package/dist_ts/standards/rules/props.accessor.js +35 -0
  86. package/dist_ts/standards/rules/props.object-no-attribute.d.ts +3 -0
  87. package/dist_ts/standards/rules/props.object-no-attribute.js +42 -0
  88. package/dist_ts/standards/rules/props.reflect-primitive.d.ts +5 -0
  89. package/dist_ts/standards/rules/props.reflect-primitive.js +41 -0
  90. package/dist_ts/standards/rules/props.typed.d.ts +6 -0
  91. package/dist_ts/standards/rules/props.typed.js +64 -0
  92. package/dist_ts/standards/rules/shared.d.ts +38 -0
  93. package/dist_ts/standards/rules/shared.js +103 -0
  94. package/dist_ts/standards/rules/style.bdtheme.d.ts +5 -0
  95. package/dist_ts/standards/rules/style.bdtheme.js +28 -0
  96. package/dist_ts_interfaces/index.d.ts +1 -0
  97. package/dist_ts_interfaces/index.js +2 -1
  98. package/dist_ts_interfaces/standard.d.ts +93 -0
  99. package/dist_ts_interfaces/standard.js +6 -0
  100. package/dist_ts_web/00_commitinfo_data.js +1 -1
  101. package/package.json +4 -2
  102. package/readme.md +34 -1
  103. package/ts/00_commitinfo_data.ts +1 -1
  104. package/ts/cli.ts +8 -1
  105. package/ts/plugins.ts +10 -2
  106. package/ts/standards/baselines.ts +100 -0
  107. package/ts/standards/checker.ts +114 -0
  108. package/ts/standards/classes.gitrepo.ts +48 -0
  109. package/ts/standards/classes.sourceedits.ts +58 -0
  110. package/ts/standards/classes.standardfixer.ts +234 -0
  111. package/ts/standards/classes.standardproject.ts +250 -0
  112. package/ts/standards/classes.standardtree.ts +220 -0
  113. package/ts/standards/cli.ts +86 -0
  114. package/ts/standards/config.ts +160 -0
  115. package/ts/standards/errors.ts +18 -0
  116. package/ts/standards/helpers.ast.ts +208 -0
  117. package/ts/standards/helpers.paths.ts +119 -0
  118. package/ts/standards/index.ts +22 -0
  119. package/ts/standards/output.ts +65 -0
  120. package/ts/standards/ratchet.ts +63 -0
  121. package/ts/standards/rule.ts +58 -0
  122. package/ts/standards/rules/barrel.element-index.ts +112 -0
  123. package/ts/standards/rules/barrel.no-demo-export.ts +30 -0
  124. package/ts/standards/rules/demo.fixture-not-exported.ts +30 -0
  125. package/ts/standards/rules/demo.groups.ts +74 -0
  126. package/ts/standards/rules/demo.required.ts +49 -0
  127. package/ts/standards/rules/demo.separate-file.ts +40 -0
  128. package/ts/standards/rules/demo.shape.ts +42 -0
  129. package/ts/standards/rules/docs.component-index.ts +88 -0
  130. package/ts/standards/rules/element.exported.ts +35 -0
  131. package/ts/standards/rules/element.literal-tag.ts +30 -0
  132. package/ts/standards/rules/element.reachable.ts +49 -0
  133. package/ts/standards/rules/element.tag-map.ts +87 -0
  134. package/ts/standards/rules/i18n.literals.ts +58 -0
  135. package/ts/standards/rules/index.ts +87 -0
  136. package/ts/standards/rules/layout.element-folder.ts +49 -0
  137. package/ts/standards/rules/layout.entry-file-name.ts +73 -0
  138. package/ts/standards/rules/layout.entry.ts +40 -0
  139. package/ts/standards/rules/layout.group-folder.ts +23 -0
  140. package/ts/standards/rules/layout.shared-00.ts +37 -0
  141. package/ts/standards/rules/naming.class-matches-tag.ts +27 -0
  142. package/ts/standards/rules/naming.lowercase-files.ts +27 -0
  143. package/ts/standards/rules/naming.tag-prefix.ts +24 -0
  144. package/ts/standards/rules/props.accessor.ts +37 -0
  145. package/ts/standards/rules/props.object-no-attribute.ts +45 -0
  146. package/ts/standards/rules/props.reflect-primitive.ts +44 -0
  147. package/ts/standards/rules/props.typed.ts +70 -0
  148. package/ts/standards/rules/shared.ts +127 -0
  149. package/ts/standards/rules/style.bdtheme.ts +31 -0
  150. package/ts_web/00_commitinfo_data.ts +1 -1
@@ -0,0 +1,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** Every entry file outside demo files is reachable from `ts_web/index.ts`. */
3
+ export declare const elementReachableRule: IStandardRule;
@@ -0,0 +1,48 @@
1
+ import { rootBarrel } from '../classes.standardproject.js';
2
+ import { dirOf } from '../helpers.paths.js';
3
+ import { addReexport, catalogElements, elementKey } from './shared.js';
4
+ /** Every entry file outside demo files is reachable from `ts_web/index.ts`. */
5
+ export const elementReachableRule = {
6
+ id: 'element/reachable',
7
+ severity: { base: 'error' },
8
+ fixMode: 'auto',
9
+ allowlistCategories: ['internal'],
10
+ detect: ({ project }) => {
11
+ const findings = [];
12
+ const reached = project.reachableFrom(rootBarrel);
13
+ for (const element of catalogElements(project)) {
14
+ if (reached.has(element.file)) {
15
+ continue;
16
+ }
17
+ const finding = {
18
+ file: element.file,
19
+ position: element.decoratorCall.getStart(),
20
+ key: elementKey(element),
21
+ message: `<${element.tag ?? '?'}> in ${element.file} is not reachable from ${rootBarrel}`,
22
+ };
23
+ // Walk up to the nearest reachable barrel; an unreachable barrel that already re-exports the file is exported instead.
24
+ let candidate = element.file;
25
+ let dir = dirOf(element.file);
26
+ while (dir.startsWith('ts_web')) {
27
+ const barrel = `${dir}/index.ts`;
28
+ if (barrel !== candidate && project.files.has(barrel)) {
29
+ if (reached.has(barrel)) {
30
+ const target = candidate;
31
+ finding.fix = (builderArg) => addReexport(builderArg, project, barrel, target);
32
+ break;
33
+ }
34
+ if (project.reexports(barrel).some((reexportArg) => reexportArg.target === candidate)) {
35
+ candidate = barrel;
36
+ }
37
+ }
38
+ if (dir === 'ts_web') {
39
+ break;
40
+ }
41
+ dir = dirOf(dir);
42
+ }
43
+ findings.push(finding);
44
+ }
45
+ return findings;
46
+ },
47
+ };
48
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxlbWVudC5yZWFjaGFibGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9zdGFuZGFyZHMvcnVsZXMvZWxlbWVudC5yZWFjaGFibGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzNELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUU1QyxPQUFPLEVBQUUsV0FBVyxFQUFFLGVBQWUsRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFdkUsK0VBQStFO0FBQy9FLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFrQjtJQUNqRCxFQUFFLEVBQUUsbUJBQW1CO0lBQ3ZCLFFBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUU7SUFDM0IsT0FBTyxFQUFFLE1BQU07SUFDZixtQkFBbUIsRUFBRSxDQUFDLFVBQVUsQ0FBQztJQUNqQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUU7UUFDdEIsTUFBTSxRQUFRLEdBQW1CLEVBQUUsQ0FBQztRQUNwQyxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2xELEtBQUssTUFBTSxPQUFPLElBQUksZUFBZSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDL0MsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUM5QixTQUFTO1lBQ1gsQ0FBQztZQUNELE1BQU0sT0FBTyxHQUFpQjtnQkFDNUIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO2dCQUNsQixRQUFRLEVBQUUsT0FBTyxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUU7Z0JBQzFDLEdBQUcsRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDO2dCQUN4QixPQUFPLEVBQUUsSUFBSSxPQUFPLENBQUMsR0FBRyxJQUFJLEdBQUcsUUFBUSxPQUFPLENBQUMsSUFBSSwwQkFBMEIsVUFBVSxFQUFFO2FBQzFGLENBQUM7WUFDRix1SEFBdUg7WUFDdkgsSUFBSSxTQUFTLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztZQUM3QixJQUFJLEdBQUcsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzlCLE9BQU8sR0FBRyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUNoQyxNQUFNLE1BQU0sR0FBRyxHQUFHLEdBQUcsV0FBVyxDQUFDO2dCQUNqQyxJQUFJLE1BQU0sS0FBSyxTQUFTLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztvQkFDdEQsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7d0JBQ3hCLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQzt3QkFDekIsT0FBTyxDQUFDLEdBQUcsR0FBRyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO3dCQUMvRSxNQUFNO29CQUNSLENBQUM7b0JBQ0QsSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsV0FBVyxDQUFDLE1BQU0sS0FBSyxTQUFTLENBQUMsRUFBRSxDQUFDO3dCQUN0RixTQUFTLEdBQUcsTUFBTSxDQUFDO29CQUNyQixDQUFDO2dCQUNILENBQUM7Z0JBQ0QsSUFBSSxHQUFHLEtBQUssUUFBUSxFQUFFLENBQUM7b0JBQ3JCLE1BQU07Z0JBQ1IsQ0FBQztnQkFDRCxHQUFHLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ25CLENBQUM7WUFDRCxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3pCLENBQUM7UUFDRCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0NBQ0YsQ0FBQyJ9
@@ -0,0 +1,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** The entry file declares `declare global { interface HTMLElementTagNameMap { '<tag>': <Class> } }`. */
3
+ export declare const elementTagMapRule: IStandardRule;
@@ -0,0 +1,83 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import * as ast from '../helpers.ast.js';
3
+ import { catalogElements, elementKey, isCustomElementName } from './shared.js';
4
+ const ts = plugins.typescript;
5
+ /** The tags of a file's `declare global { interface HTMLElementTagNameMap { … } }` and the first such interface. */
6
+ const tagMapOf = (sourceFileArg) => {
7
+ const tags = new Set();
8
+ let declaration = null;
9
+ for (const statement of sourceFileArg.statements) {
10
+ if (!ts.isModuleDeclaration(statement) || !ts.isIdentifier(statement.name) || statement.name.text !== 'global'
11
+ || !statement.body || !ts.isModuleBlock(statement.body)) {
12
+ continue;
13
+ }
14
+ for (const inner of statement.body.statements) {
15
+ if (ts.isInterfaceDeclaration(inner) && inner.name.text === 'HTMLElementTagNameMap') {
16
+ declaration ??= inner;
17
+ for (const member of inner.members) {
18
+ if (ts.isPropertySignature(member) && member.name && (ts.isStringLiteral(member.name) || ts.isIdentifier(member.name))) {
19
+ tags.add(member.name.text);
20
+ }
21
+ }
22
+ }
23
+ }
24
+ }
25
+ return { tags, declaration };
26
+ };
27
+ /** Adds every missing element of one file to its tag map, or appends a tag map block to the file. */
28
+ const tagMapFix = (missingArg) => (builderArg) => {
29
+ const sourceFile = missingArg[0].sourceFile;
30
+ const file = missingArg[0].file;
31
+ const text = sourceFile.text;
32
+ const { declaration } = tagMapOf(sourceFile);
33
+ if (declaration) {
34
+ const closeBrace = declaration.end - 1;
35
+ const lineStart = text.lastIndexOf('\n', closeBrace - 1) + 1;
36
+ const firstMember = declaration.members[0];
37
+ const indentation = firstMember
38
+ ? ast.indentationAt(text, firstMember.getStart())
39
+ : `${ast.indentationAt(text, declaration.getStart())} `;
40
+ const lines = missingArg.map((elementArg) => `${indentation}'${elementArg.tag}': ${elementArg.className};\n`).join('');
41
+ if (/^[ \t]*$/.test(text.slice(lineStart, closeBrace))) {
42
+ builderArg.edit(file, lineStart, lineStart, lines);
43
+ }
44
+ else {
45
+ builderArg.edit(file, closeBrace, closeBrace, `\n${lines}`);
46
+ }
47
+ return;
48
+ }
49
+ const members = missingArg.map((elementArg) => ` '${elementArg.tag}': ${elementArg.className};\n`).join('');
50
+ const prefix = text.length === 0 || text.endsWith('\n') ? '' : '\n';
51
+ builderArg.edit(file, text.length, text.length, `${prefix}\ndeclare global {\n interface HTMLElementTagNameMap {\n${members} }\n}\n`);
52
+ };
53
+ /** The entry file declares `declare global { interface HTMLElementTagNameMap { '<tag>': <Class> } }`. */
54
+ export const elementTagMapRule = {
55
+ id: 'element/tag-map',
56
+ severity: { base: 'warn' },
57
+ fixMode: 'auto',
58
+ detect: ({ project }) => {
59
+ const findings = [];
60
+ const byFile = new Map();
61
+ for (const element of catalogElements(project)) {
62
+ if (element.tag && !tagMapOf(element.sourceFile).tags.has(element.tag)) {
63
+ byFile.set(element.file, [...(byFile.get(element.file) ?? []), element]);
64
+ }
65
+ }
66
+ for (const missing of byFile.values()) {
67
+ // The tag is written into the source: only valid custom element names are.
68
+ const fixable = missing.every((elementArg) => elementArg.className && isCustomElementName(elementArg.tag));
69
+ const fix = fixable ? tagMapFix(missing) : undefined;
70
+ for (const element of missing) {
71
+ findings.push({
72
+ file: element.file,
73
+ position: element.decoratorCall.getStart(),
74
+ key: elementKey(element),
75
+ message: `HTMLElementTagNameMap of ${element.file} does not declare '${element.tag}'`,
76
+ fix,
77
+ });
78
+ }
79
+ }
80
+ return findings;
81
+ },
82
+ };
83
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWxlbWVudC50YWctbWFwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvc3RhbmRhcmRzL3J1bGVzL2VsZW1lbnQudGFnLW1hcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sS0FBSyxHQUFHLE1BQU0sbUJBQW1CLENBQUM7QUFHekMsT0FBTyxFQUFFLGVBQWUsRUFBRSxVQUFVLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFL0UsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztBQUU5QixvSEFBb0g7QUFDcEgsTUFBTSxRQUFRLEdBQUcsQ0FBQyxhQUE4QixFQUFzRixFQUFFO0lBQ3RJLE1BQU0sSUFBSSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7SUFDL0IsSUFBSSxXQUFXLEdBQW1ELElBQUksQ0FBQztJQUN2RSxLQUFLLE1BQU0sU0FBUyxJQUFJLGFBQWEsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNqRCxJQUFJLENBQUMsRUFBRSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUTtlQUN6RyxDQUFDLFNBQVMsQ0FBQyxJQUFJLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQzFELFNBQVM7UUFDWCxDQUFDO1FBQ0QsS0FBSyxNQUFNLEtBQUssSUFBSSxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzlDLElBQUksRUFBRSxDQUFDLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLHVCQUF1QixFQUFFLENBQUM7Z0JBQ3BGLFdBQVcsS0FBSyxLQUFLLENBQUM7Z0JBQ3RCLEtBQUssTUFBTSxNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUNuQyxJQUFJLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsSUFBSSxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDO3dCQUN2SCxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQzdCLENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLENBQUM7QUFDL0IsQ0FBQyxDQUFDO0FBRUYscUdBQXFHO0FBQ3JHLE1BQU0sU0FBUyxHQUFHLENBQUMsVUFBOEIsRUFBYyxFQUFFLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRTtJQUMvRSxNQUFNLFVBQVUsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDO0lBQzVDLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDaEMsTUFBTSxJQUFJLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQztJQUM3QixNQUFNLEVBQUUsV0FBVyxFQUFFLEdBQUcsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzdDLElBQUksV0FBVyxFQUFFLENBQUM7UUFDaEIsTUFBTSxVQUFVLEdBQUcsV0FBVyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUM7UUFDdkMsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsVUFBVSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM3RCxNQUFNLFdBQVcsR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzNDLE1BQU0sV0FBVyxHQUFHLFdBQVc7WUFDN0IsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUNqRCxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsUUFBUSxFQUFFLENBQUMsSUFBSSxDQUFDO1FBQzNELE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLEdBQUcsV0FBVyxJQUFJLFVBQVUsQ0FBQyxHQUFHLE1BQU0sVUFBVSxDQUFDLFNBQVMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZILElBQUksVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDdkQsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNyRCxDQUFDO2FBQU0sQ0FBQztZQUNOLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsS0FBSyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQzlELENBQUM7UUFDRCxPQUFPO0lBQ1QsQ0FBQztJQUNELE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLFFBQVEsVUFBVSxDQUFDLEdBQUcsTUFBTSxVQUFVLENBQUMsU0FBUyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDL0csTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDcEUsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsTUFBTSw0REFBNEQsT0FBTyxVQUFVLENBQUMsQ0FBQztBQUMxSSxDQUFDLENBQUM7QUFFRix5R0FBeUc7QUFDekcsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQWtCO0lBQzlDLEVBQUUsRUFBRSxpQkFBaUI7SUFDckIsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRTtJQUMxQixPQUFPLEVBQUUsTUFBTTtJQUNmLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRTtRQUN0QixNQUFNLFFBQVEsR0FBbUIsRUFBRSxDQUFDO1FBQ3BDLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxFQUE4QixDQUFDO1FBQ3JELEtBQUssTUFBTSxPQUFPLElBQUksZUFBZSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDL0MsSUFBSSxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN2RSxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUMzRSxDQUFDO1FBQ0gsQ0FBQztRQUNELEtBQUssTUFBTSxPQUFPLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDdEMsMkVBQTJFO1lBQzNFLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxTQUFTLElBQUksbUJBQW1CLENBQUMsVUFBVSxDQUFDLEdBQUksQ0FBQyxDQUFDLENBQUM7WUFDNUcsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUNyRCxLQUFLLE1BQU0sT0FBTyxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUM5QixRQUFRLENBQUMsSUFBSSxDQUFDO29CQUNaLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxhQUFhLENBQUMsUUFBUSxFQUFFO29CQUMxQyxHQUFHLEVBQUUsVUFBVSxDQUFDLE9BQU8sQ0FBQztvQkFDeEIsT0FBTyxFQUFFLDRCQUE0QixPQUFPLENBQUMsSUFBSSxzQkFBc0IsT0FBTyxDQUFDLEdBQUcsR0FBRztvQkFDckYsR0FBRztpQkFDSixDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7Q0FDRixDQUFDIn0=
@@ -0,0 +1,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** dees: no English literal a reader sees outside demo files, `ts_web/i18n/`, `ts_web/demos/` and `ts_web/pages/`. A ratchet. */
3
+ export declare const i18nLiteralsRule: IStandardRule;
@@ -0,0 +1,52 @@
1
+ import * as plugins from '../../plugins.js';
2
+ import * as ast from '../helpers.ast.js';
3
+ import { isDemoFile } from '../helpers.paths.js';
4
+ const ts = plugins.typescript;
5
+ /** The words belong to the catalog; demos, demo data, the i18n catalog and the demo pages show sample content. */
6
+ const isExempt = (fileArg) => isDemoFile(fileArg)
7
+ || fileArg.startsWith('ts_web/i18n/')
8
+ || fileArg.startsWith('ts_web/demos/')
9
+ || fileArg.startsWith('ts_web/pages/');
10
+ const wordAttributes = 'aria-label|aria-description|aria-valuetext|title|placeholder|label|text|heading|subheading|alt';
11
+ const wordProperties = new Set(['name', 'label', 'text', 'heading', 'subheading', 'title', 'placeholder', 'message', 'description', 'confirmLabel', 'cancelLabel', 'emptyText', 'tooltip', 'hint']);
12
+ const word = /^[A-Z][a-z]+(?:[ '’,.?!…-]+[A-Za-z]+)*[.?!…]?$/;
13
+ /** The patterns of dees-catalog's scripts/check-literal-ratchet.cjs that apply to template and string text. */
14
+ const textPatterns = () => [
15
+ // aria-label="Progress"
16
+ new RegExp(`\\s(?:${wordAttributes})="([A-Za-z][^"$]*[a-z][^"$]*)"`, 'g'),
17
+ // >Cancel< and > Back <
18
+ /(?<![=-])>\s*([A-Z][a-z]+(?:[ '’,.?!…-]+[A-Za-z]+)*[.?!…]?)\s*</g,
19
+ ];
20
+ /** dees: no English literal a reader sees outside demo files, `ts_web/i18n/`, `ts_web/demos/` and `ts_web/pages/`. A ratchet. */
21
+ export const i18nLiteralsRule = {
22
+ id: 'i18n/literals',
23
+ severity: { dees: 'error' },
24
+ fixMode: 'none',
25
+ detect: ({ project }) => {
26
+ const findings = [];
27
+ for (const file of project.webFiles) {
28
+ if (isExempt(file)) {
29
+ continue;
30
+ }
31
+ const visit = (nodeArg) => {
32
+ if (ts.isStringLiteral(nodeArg) || ts.isNoSubstitutionTemplateLiteral(nodeArg)
33
+ || ts.isTemplateHead(nodeArg) || ts.isTemplateMiddle(nodeArg) || ts.isTemplateTail(nodeArg)) {
34
+ const text = nodeArg.getText();
35
+ for (const pattern of textPatterns()) {
36
+ for (const match of text.matchAll(pattern)) {
37
+ findings.push({ file, position: nodeArg.getStart() + match.index, key: file, message: `English literal ${match[0].trim()}` });
38
+ }
39
+ }
40
+ }
41
+ if (ts.isPropertyAssignment(nodeArg) && (ts.isIdentifier(nodeArg.name) || ts.isStringLiteral(nodeArg.name))
42
+ && wordProperties.has(nodeArg.name.text) && ts.isStringLiteral(nodeArg.initializer) && word.test(nodeArg.initializer.text)) {
43
+ findings.push({ file, position: nodeArg.getStart(), key: file, message: `English literal ${nodeArg.getText()}` });
44
+ }
45
+ ts.forEachChild(nodeArg, visit);
46
+ };
47
+ visit(project.sourceFile(file));
48
+ }
49
+ return findings;
50
+ },
51
+ };
52
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaTE4bi5saXRlcmFscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL3N0YW5kYXJkcy9ydWxlcy9pMThuLmxpdGVyYWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxLQUFLLEdBQUcsTUFBTSxtQkFBbUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFHakQsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztBQUU5QixrSEFBa0g7QUFDbEgsTUFBTSxRQUFRLEdBQUcsQ0FBQyxPQUFlLEVBQVcsRUFBRSxDQUM1QyxVQUFVLENBQUMsT0FBTyxDQUFDO09BQ2hCLE9BQU8sQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDO09BQ2xDLE9BQU8sQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDO09BQ25DLE9BQU8sQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDLENBQUM7QUFFekMsTUFBTSxjQUFjLEdBQUcsZ0dBQWdHLENBQUM7QUFDeEgsTUFBTSxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUNwTSxNQUFNLElBQUksR0FBRyxnREFBZ0QsQ0FBQztBQUU5RCwrR0FBK0c7QUFDL0csTUFBTSxZQUFZLEdBQUcsR0FBYSxFQUFFLENBQUM7SUFDbkMsd0JBQXdCO0lBQ3hCLElBQUksTUFBTSxDQUFDLFNBQVMsY0FBYyxpQ0FBaUMsRUFBRSxHQUFHLENBQUM7SUFDekUsd0JBQXdCO0lBQ3hCLGtFQUFrRTtDQUNuRSxDQUFD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
@@ -0,0 +1,12 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ export { reflectExemptNames } from './props.reflect-primitive.js';
3
+ export { renderComponentIndex } from './docs.component-index.js';
4
+ /** Every rule of docs/standard.md, in the order of the document. */
5
+ export declare const standardRules: readonly IStandardRule[];
6
+ /**
7
+ * The order `wcctools fix` applies rules in: content edits first, then file moves (which rewrite imports),
8
+ * then barrels and reachability on the final layout, then the generated docs.
9
+ */
10
+ export declare const fixOrder: readonly string[];
11
+ /** Findings the checker itself produces for the allowlist. */
12
+ export declare const allowlistStaleRuleId = "allowlist/stale";
@@ -0,0 +1,83 @@
1
+ import { barrelElementIndexRule } from './barrel.element-index.js';
2
+ import { barrelNoDemoExportRule } from './barrel.no-demo-export.js';
3
+ import { demoFixtureNotExportedRule } from './demo.fixture-not-exported.js';
4
+ import { demoGroupsRule } from './demo.groups.js';
5
+ import { demoRequiredRule } from './demo.required.js';
6
+ import { demoSeparateFileRule } from './demo.separate-file.js';
7
+ import { demoShapeRule } from './demo.shape.js';
8
+ import { docsComponentIndexRule } from './docs.component-index.js';
9
+ import { elementExportedRule } from './element.exported.js';
10
+ import { elementLiteralTagRule } from './element.literal-tag.js';
11
+ import { elementReachableRule } from './element.reachable.js';
12
+ import { elementTagMapRule } from './element.tag-map.js';
13
+ import { i18nLiteralsRule } from './i18n.literals.js';
14
+ import { layoutElementFolderRule } from './layout.element-folder.js';
15
+ import { layoutEntryFileNameRule } from './layout.entry-file-name.js';
16
+ import { layoutEntryRule } from './layout.entry.js';
17
+ import { layoutGroupFolderRule } from './layout.group-folder.js';
18
+ import { layoutShared00Rule } from './layout.shared-00.js';
19
+ import { namingClassMatchesTagRule } from './naming.class-matches-tag.js';
20
+ import { namingLowercaseFilesRule } from './naming.lowercase-files.js';
21
+ import { namingTagPrefixRule } from './naming.tag-prefix.js';
22
+ import { propsAccessorRule } from './props.accessor.js';
23
+ import { propsObjectNoAttributeRule } from './props.object-no-attribute.js';
24
+ import { propsReflectPrimitiveRule } from './props.reflect-primitive.js';
25
+ import { propsTypedRule } from './props.typed.js';
26
+ import { styleBdThemeRule } from './style.bdtheme.js';
27
+ export { reflectExemptNames } from './props.reflect-primitive.js';
28
+ export { renderComponentIndex } from './docs.component-index.js';
29
+ /** Every rule of docs/standard.md, in the order of the document. */
30
+ export const standardRules = [
31
+ layoutEntryRule,
32
+ layoutElementFolderRule,
33
+ layoutEntryFileNameRule,
34
+ layoutGroupFolderRule,
35
+ layoutShared00Rule,
36
+ namingLowercaseFilesRule,
37
+ namingTagPrefixRule,
38
+ namingClassMatchesTagRule,
39
+ elementLiteralTagRule,
40
+ elementExportedRule,
41
+ elementTagMapRule,
42
+ elementReachableRule,
43
+ barrelElementIndexRule,
44
+ barrelNoDemoExportRule,
45
+ demoShapeRule,
46
+ demoRequiredRule,
47
+ demoSeparateFileRule,
48
+ demoGroupsRule,
49
+ demoFixtureNotExportedRule,
50
+ propsAccessorRule,
51
+ propsTypedRule,
52
+ propsReflectPrimitiveRule,
53
+ propsObjectNoAttributeRule,
54
+ styleBdThemeRule,
55
+ i18nLiteralsRule,
56
+ docsComponentIndexRule,
57
+ ];
58
+ /**
59
+ * The order `wcctools fix` applies rules in: content edits first, then file moves (which rewrite imports),
60
+ * then barrels and reachability on the final layout, then the generated docs.
61
+ */
62
+ export const fixOrder = [
63
+ 'element/exported',
64
+ 'element/tag-map',
65
+ 'props/accessor',
66
+ 'props/typed',
67
+ 'props/object-no-attribute',
68
+ 'props/reflect-primitive',
69
+ 'demo/groups',
70
+ 'demo/required',
71
+ 'barrel/no-demo-export',
72
+ 'demo/fixture-not-exported',
73
+ 'naming/lowercase-files',
74
+ 'layout/shared-00',
75
+ 'layout/entry-file-name',
76
+ 'layout/element-folder',
77
+ 'barrel/element-index',
78
+ 'element/reachable',
79
+ 'docs/component-index',
80
+ ];
81
+ /** Findings the checker itself produces for the allowlist. */
82
+ export const allowlistStaleRuleId = 'allowlist/stale';
83
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9zdGFuZGFyZHMvcnVsZXMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDbkUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDcEUsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDNUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQy9ELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNuRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM1RCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN0RCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUN0RSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDcEQsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDakUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDM0QsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDMUUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDdkUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDeEQsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDNUUsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDekUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRXRELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRWpFLG9FQUFvRTtBQUNwRSxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQTZCO0lBQ3JELGVBQWU7SUFDZix1QkFBdUI7SUFDdkIsdUJBQXVCO0lBQ3ZCLHFCQUFxQjtJQUNyQixrQkFBa0I7SUFDbEIsd0JBQXdCO0lBQ3hCLG1CQUFtQjtJQUNuQix5QkFBeUI7SUFDekIscUJBQXFCO0lBQ3JCLG1CQUFtQjtJQUNuQixpQkFBaUI7SUFDakIsb0JBQW9CO0lBQ3BCLHNCQUFzQjtJQUN0QixzQkFBc0I7SUFDdEIsYUFBYTtJQUNiLGdCQUFnQjtJQUNoQixvQkFBb0I7SUFDcEIsY0FBYztJQUNkLDBCQUEwQjtJQUMxQixpQkFBaUI7SUFDakIsY0FBYztJQUNkLHlCQUF5QjtJQUN6QiwwQkFBMEI7SUFDMUIsZ0JBQWdCO0lBQ2hCLGdCQUFnQjtJQUNoQixzQkFBc0I7Q0FDdkIsQ0FBQztBQUVGOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLFFBQVEsR0FBc0I7SUFDekMsa0JBQWtCO0lBQ2xCLGlCQUFpQjtJQUNqQixnQkFBZ0I7SUFDaEIsYUFBYTtJQUNiLDJCQUEyQjtJQUMzQix5QkFBeUI7SUFDekIsYUFBYTtJQUNiLGVBQWU7SUFDZix1QkFBdUI7SUFDdkIsMkJBQTJCO0lBQzNCLHdCQUF3QjtJQUN4QixrQkFBa0I7SUFDbEIsd0JBQXdCO0lBQ3hCLHVCQUF1QjtJQUN2QixzQkFBc0I7SUFDdEIsbUJBQW1CO0lBQ25CLHNCQUFzQjtDQUN2QixDQUFDO0FBRUYsOERBQThEO0FBQzlELE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLGlCQUFpQixDQUFDIn0=
@@ -0,0 +1,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** Every element's entry file lives in its own element folder `ts_web/elements/[00group-<area>/]<tag>/<tag>.ts`. */
3
+ export declare const layoutElementFolderRule: IStandardRule;
@@ -0,0 +1,47 @@
1
+ import { baseOf, dirOf } from '../helpers.paths.js';
2
+ import { catalogElements, elementKey, elementsDir, isCustomElementName, isElementParentDir, isInElementFolder } from './shared.js';
3
+ /** Every element's entry file lives in its own element folder `ts_web/elements/[00group-<area>/]<tag>/<tag>.ts`. */
4
+ export const layoutElementFolderRule = {
5
+ id: 'layout/element-folder',
6
+ severity: { base: 'warn' },
7
+ fixMode: 'auto',
8
+ detect: ({ project }) => {
9
+ const findings = [];
10
+ const elements = catalogElements(project);
11
+ for (const element of elements) {
12
+ if (!element.tag || isInElementFolder(element)) {
13
+ continue;
14
+ }
15
+ const currentDir = dirOf(element.file);
16
+ const group = /^ts_web\/elements\/(00group-[^/]+)(\/|$)/.exec(currentDir)?.[1];
17
+ const folder = `${elementsDir}/${group ? `${group}/` : ''}${element.tag}`;
18
+ const finding = {
19
+ file: element.file,
20
+ position: element.decoratorCall.getStart(),
21
+ key: elementKey(element),
22
+ message: `<${element.tag}> is declared in ${element.file}; its element folder is ${folder}/`,
23
+ };
24
+ const elementsInFile = elements.filter((otherArg) => otherArg.file === element.file);
25
+ const folderTaken = [...project.files.keys()].some((fileArg) => fileArg.startsWith(`${folder}/`)) || project.exists(folder);
26
+ // Only flat files move mechanically: a misnamed folder holds more than this element. The folder
27
+ // is named after the tag, so only a valid custom element name is usable.
28
+ if (isCustomElementName(element.tag) && elementsInFile.length === 1 && isElementParentDir(currentDir) && !folderTaken) {
29
+ const tag = element.tag;
30
+ const companions = [...project.files.keys()].filter((fileArg) => fileArg !== element.file && dirOf(fileArg) === currentDir && baseOf(fileArg).startsWith(`${tag}.`) && baseOf(fileArg) !== 'index.ts');
31
+ finding.fix = (builderArg) => {
32
+ const entry = `${folder}/${tag}.ts`;
33
+ const index = `${folder}/index.ts`;
34
+ builderArg.create(index, `export * from './${tag}.js';\n`);
35
+ builderArg.move(element.file, entry);
36
+ for (const companion of companions) {
37
+ builderArg.move(companion, `${folder}/${baseOf(companion)}`);
38
+ }
39
+ builderArg.redirectBarrelExports(element.file, index);
40
+ };
41
+ }
42
+ findings.push(finding);
43
+ }
44
+ return findings;
45
+ },
46
+ };
47
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF5b3V0LmVsZW1lbnQtZm9sZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvc3RhbmRhcmRzL3J1bGVzL2xheW91dC5lbGVtZW50LWZvbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRXBELE9BQU8sRUFBRSxlQUFlLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBRSxrQkFBa0IsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUVuSSxvSEFBb0g7QUFDcEgsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQWtCO0lBQ3BELEVBQUUsRUFBRSx1QkFBdUI7SUFDM0IsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRTtJQUMxQixPQUFPLEVBQUUsTUFBTTtJQUNmLE1BQU0sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRTtRQUN0QixNQUFNLFFBQVEsR0FBbUIsRUFBRSxDQUFDO1FBQ3BDLE1BQU0sUUFBUSxHQUFHLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxQyxLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxJQUFJLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQy9DLFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUN2QyxNQUFNLEtBQUssR0FBRywwQ0FBMEMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUMvRSxNQUFNLE1BQU0sR0FBRyxHQUFHLFdBQVcsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxHQUFHLENBQUMs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
@@ -0,0 +1,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** Inside an element folder the entry file is `<tag>.ts` and the demo file is `<tag>.demo.ts`. */
3
+ export declare const layoutEntryFileNameRule: IStandardRule;
@@ -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,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** `html/index.ts` exists and calls `setupWccTools({ sections })`; `html/index.html` exists. */
3
+ export declare const layoutEntryRule: IStandardRule;
@@ -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,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** dees: element folders sit under `ts_web/elements/00group-<area>/`. */
3
+ export declare const layoutGroupFolderRule: IStandardRule;
@@ -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,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** A module at the root of `ts_web/elements/` that declares no element is named `00<name>.ts`. */
3
+ export declare const layoutShared00Rule: IStandardRule;
@@ -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,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** The class name, lowercased, equals the tag with hyphens removed. */
3
+ export declare const namingClassMatchesTagRule: IStandardRule;
@@ -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=