@design.estate/wcctools 5.1.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 (262) hide show
  1. package/.smartconfig.json +7 -3
  2. package/changelog.md +28 -0
  3. package/cli.js +3 -0
  4. package/dist_shell/bundle.js +2970 -0
  5. package/dist_shell/bundle.js.map +1 -0
  6. package/dist_shell/bundle.js.third-party-notices.json +1722 -0
  7. package/dist_shell/bundle.js.third-party-notices.txt +4195 -0
  8. package/dist_shell/index.html +21 -0
  9. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  10. package/dist_ts/00_commitinfo_data.js +9 -0
  11. package/dist_ts/classes.devapi.d.ts +11 -0
  12. package/dist_ts/classes.devapi.js +21 -0
  13. package/dist_ts/classes.devserver.d.ts +49 -0
  14. package/dist_ts/classes.devserver.js +142 -0
  15. package/dist_ts/cli.d.ts +6 -0
  16. package/dist_ts/cli.js +51 -0
  17. package/dist_ts/index.d.ts +3 -0
  18. package/dist_ts/index.js +4 -0
  19. package/dist_ts/paths.d.ts +4 -0
  20. package/dist_ts/paths.js +6 -0
  21. package/dist_ts/plugins.d.ts +20 -0
  22. package/dist_ts/plugins.js +27 -0
  23. package/dist_ts/shellcontent.d.ts +9 -0
  24. package/dist_ts/shellcontent.js +42 -0
  25. package/dist_ts/standards/baselines.d.ts +27 -0
  26. package/dist_ts/standards/baselines.js +83 -0
  27. package/dist_ts/standards/checker.d.ts +21 -0
  28. package/dist_ts/standards/checker.js +88 -0
  29. package/dist_ts/standards/classes.gitrepo.d.ts +13 -0
  30. package/dist_ts/standards/classes.gitrepo.js +43 -0
  31. package/dist_ts/standards/classes.sourceedits.d.ts +15 -0
  32. package/dist_ts/standards/classes.sourceedits.js +54 -0
  33. package/dist_ts/standards/classes.standardfixer.d.ts +40 -0
  34. package/dist_ts/standards/classes.standardfixer.js +210 -0
  35. package/dist_ts/standards/classes.standardproject.d.ts +80 -0
  36. package/dist_ts/standards/classes.standardproject.js +195 -0
  37. package/dist_ts/standards/classes.standardtree.d.ts +56 -0
  38. package/dist_ts/standards/classes.standardtree.js +207 -0
  39. package/dist_ts/standards/cli.d.ts +7 -0
  40. package/dist_ts/standards/cli.js +89 -0
  41. package/dist_ts/standards/config.d.ts +33 -0
  42. package/dist_ts/standards/config.js +139 -0
  43. package/dist_ts/standards/errors.d.ts +9 -0
  44. package/dist_ts/standards/errors.js +17 -0
  45. package/dist_ts/standards/helpers.ast.d.ts +56 -0
  46. package/dist_ts/standards/helpers.ast.js +172 -0
  47. package/dist_ts/standards/helpers.paths.d.ts +36 -0
  48. package/dist_ts/standards/helpers.paths.js +86 -0
  49. package/dist_ts/standards/index.d.ts +14 -0
  50. package/dist_ts/standards/index.js +15 -0
  51. package/dist_ts/standards/output.d.ts +7 -0
  52. package/dist_ts/standards/output.js +57 -0
  53. package/dist_ts/standards/ratchet.d.ts +15 -0
  54. package/dist_ts/standards/ratchet.js +45 -0
  55. package/dist_ts/standards/rule.d.ts +50 -0
  56. package/dist_ts/standards/rule.js +9 -0
  57. package/dist_ts/standards/rules/barrel.element-index.d.ts +7 -0
  58. package/dist_ts/standards/rules/barrel.element-index.js +108 -0
  59. package/dist_ts/standards/rules/barrel.no-demo-export.d.ts +3 -0
  60. package/dist_ts/standards/rules/barrel.no-demo-export.js +29 -0
  61. package/dist_ts/standards/rules/demo.fixture-not-exported.d.ts +3 -0
  62. package/dist_ts/standards/rules/demo.fixture-not-exported.js +29 -0
  63. package/dist_ts/standards/rules/demo.groups.d.ts +6 -0
  64. package/dist_ts/standards/rules/demo.groups.js +72 -0
  65. package/dist_ts/standards/rules/demo.required.d.ts +3 -0
  66. package/dist_ts/standards/rules/demo.required.js +48 -0
  67. package/dist_ts/standards/rules/demo.separate-file.d.ts +3 -0
  68. package/dist_ts/standards/rules/demo.separate-file.js +38 -0
  69. package/dist_ts/standards/rules/demo.shape.d.ts +3 -0
  70. package/dist_ts/standards/rules/demo.shape.js +38 -0
  71. package/dist_ts/standards/rules/docs.component-index.d.ts +8 -0
  72. package/dist_ts/standards/rules/docs.component-index.js +84 -0
  73. package/dist_ts/standards/rules/element.exported.d.ts +3 -0
  74. package/dist_ts/standards/rules/element.exported.js +33 -0
  75. package/dist_ts/standards/rules/element.literal-tag.d.ts +3 -0
  76. package/dist_ts/standards/rules/element.literal-tag.js +30 -0
  77. package/dist_ts/standards/rules/element.reachable.d.ts +3 -0
  78. package/dist_ts/standards/rules/element.reachable.js +48 -0
  79. package/dist_ts/standards/rules/element.tag-map.d.ts +3 -0
  80. package/dist_ts/standards/rules/element.tag-map.js +83 -0
  81. package/dist_ts/standards/rules/i18n.literals.d.ts +3 -0
  82. package/dist_ts/standards/rules/i18n.literals.js +52 -0
  83. package/dist_ts/standards/rules/index.d.ts +12 -0
  84. package/dist_ts/standards/rules/index.js +83 -0
  85. package/dist_ts/standards/rules/layout.element-folder.d.ts +3 -0
  86. package/dist_ts/standards/rules/layout.element-folder.js +47 -0
  87. package/dist_ts/standards/rules/layout.entry-file-name.d.ts +3 -0
  88. package/dist_ts/standards/rules/layout.entry-file-name.js +71 -0
  89. package/dist_ts/standards/rules/layout.entry.d.ts +3 -0
  90. package/dist_ts/standards/rules/layout.entry.js +38 -0
  91. package/dist_ts/standards/rules/layout.group-folder.d.ts +3 -0
  92. package/dist_ts/standards/rules/layout.group-folder.js +22 -0
  93. package/dist_ts/standards/rules/layout.shared-00.d.ts +3 -0
  94. package/dist_ts/standards/rules/layout.shared-00.js +36 -0
  95. package/dist_ts/standards/rules/naming.class-matches-tag.d.ts +3 -0
  96. package/dist_ts/standards/rules/naming.class-matches-tag.js +26 -0
  97. package/dist_ts/standards/rules/naming.lowercase-files.d.ts +3 -0
  98. package/dist_ts/standards/rules/naming.lowercase-files.js +26 -0
  99. package/dist_ts/standards/rules/naming.tag-prefix.d.ts +3 -0
  100. package/dist_ts/standards/rules/naming.tag-prefix.js +23 -0
  101. package/dist_ts/standards/rules/props.accessor.d.ts +3 -0
  102. package/dist_ts/standards/rules/props.accessor.js +35 -0
  103. package/dist_ts/standards/rules/props.object-no-attribute.d.ts +3 -0
  104. package/dist_ts/standards/rules/props.object-no-attribute.js +42 -0
  105. package/dist_ts/standards/rules/props.reflect-primitive.d.ts +5 -0
  106. package/dist_ts/standards/rules/props.reflect-primitive.js +41 -0
  107. package/dist_ts/standards/rules/props.typed.d.ts +6 -0
  108. package/dist_ts/standards/rules/props.typed.js +64 -0
  109. package/dist_ts/standards/rules/shared.d.ts +38 -0
  110. package/dist_ts/standards/rules/shared.js +103 -0
  111. package/dist_ts/standards/rules/style.bdtheme.d.ts +5 -0
  112. package/dist_ts/standards/rules/style.bdtheme.js +28 -0
  113. package/dist_ts_interfaces/bridge.d.ts +88 -0
  114. package/dist_ts_interfaces/bridge.js +2 -0
  115. package/dist_ts_interfaces/catalog.d.ts +32 -0
  116. package/dist_ts_interfaces/catalog.js +6 -0
  117. package/dist_ts_interfaces/index.d.ts +4 -0
  118. package/dist_ts_interfaces/index.js +5 -0
  119. package/dist_ts_interfaces/plugins.d.ts +2 -0
  120. package/dist_ts_interfaces/plugins.js +3 -0
  121. package/dist_ts_interfaces/requests.d.ts +15 -0
  122. package/dist_ts_interfaces/requests.js +2 -0
  123. package/dist_ts_interfaces/standard.d.ts +93 -0
  124. package/dist_ts_interfaces/standard.js +6 -0
  125. package/dist_ts_shared/index.d.ts +1 -0
  126. package/dist_ts_shared/index.js +2 -0
  127. package/dist_ts_shared/plugins.d.ts +2 -0
  128. package/dist_ts_shared/plugins.js +3 -0
  129. package/dist_ts_shared/previewroute.d.ts +18 -0
  130. package/dist_ts_shared/previewroute.js +47 -0
  131. package/{dist_ts_web → dist_ts_shell}/elements/wcc-contextmenu.js +1 -1
  132. package/dist_ts_shell/elements/wcc-preview-frame.d.ts +23 -0
  133. package/dist_ts_shell/elements/wcc-preview-frame.js +197 -0
  134. package/dist_ts_shell/elements/wcc-properties.d.ts +49 -0
  135. package/{dist_ts_web → dist_ts_shell}/elements/wcc-properties.js +149 -216
  136. package/{dist_ts_web → dist_ts_shell}/elements/wcc-record-button.js +1 -1
  137. package/{dist_ts_web → dist_ts_shell}/elements/wcc-recording-panel.d.ts +2 -2
  138. package/{dist_ts_web → dist_ts_shell}/elements/wcc-recording-panel.js +12 -16
  139. package/dist_ts_shell/elements/wcc-shell.d.ts +87 -0
  140. package/dist_ts_shell/elements/wcc-shell.js +524 -0
  141. package/{dist_ts_web → dist_ts_shell}/elements/wcc-sidebar.d.ts +12 -10
  142. package/{dist_ts_web → dist_ts_shell}/elements/wcc-sidebar.js +137 -183
  143. package/dist_ts_shell/index.d.ts +4 -0
  144. package/dist_ts_shell/index.js +5 -0
  145. package/dist_ts_shell/plugins.d.ts +4 -0
  146. package/dist_ts_shell/plugins.js +5 -0
  147. package/dist_ts_shell/previewconnection.d.ts +30 -0
  148. package/dist_ts_shell/previewconnection.js +86 -0
  149. package/dist_ts_shell/services/recorder.service.js +353 -0
  150. package/dist_ts_web/00_commitinfo_data.js +2 -2
  151. package/dist_ts_web/catalog.d.ts +45 -0
  152. package/dist_ts_web/catalog.js +153 -0
  153. package/dist_ts_web/elementproperties.d.ts +15 -0
  154. package/dist_ts_web/elementproperties.js +89 -0
  155. package/dist_ts_web/elements/wcc-preview.d.ts +19 -0
  156. package/dist_ts_web/elements/wcc-preview.js +164 -0
  157. package/dist_ts_web/elements/wcc-standalone-notice.d.ts +14 -0
  158. package/dist_ts_web/elements/wcc-standalone-notice.js +110 -0
  159. package/dist_ts_web/elements/wcctools.helpers.d.ts +2 -6
  160. package/dist_ts_web/elements/wcctools.helpers.js +1 -7
  161. package/dist_ts_web/index.d.ts +2 -5
  162. package/dist_ts_web/index.js +38 -17
  163. package/dist_ts_web/previewbridge.d.ts +39 -0
  164. package/dist_ts_web/previewbridge.js +153 -0
  165. package/dist_ts_web/renderedtree.d.ts +5 -0
  166. package/dist_ts_web/renderedtree.js +37 -0
  167. package/dist_ts_web/wcctools.interfaces.d.ts +3 -6
  168. package/dist_ts_web/wcctools.interfaces.js +1 -1
  169. package/dist_ts_web/wcctools.plugins.d.ts +3 -1
  170. package/dist_ts_web/wcctools.plugins.js +4 -2
  171. package/package.json +17 -7
  172. package/readme.md +93 -28
  173. package/ts/00_commitinfo_data.ts +8 -0
  174. package/ts/classes.devapi.ts +25 -0
  175. package/ts/classes.devserver.ts +161 -0
  176. package/ts/cli.ts +53 -0
  177. package/ts/index.ts +3 -0
  178. package/ts/paths.ts +7 -0
  179. package/ts/plugins.ts +37 -0
  180. package/ts/shellcontent.ts +42 -0
  181. package/ts/standards/baselines.ts +100 -0
  182. package/ts/standards/checker.ts +114 -0
  183. package/ts/standards/classes.gitrepo.ts +48 -0
  184. package/ts/standards/classes.sourceedits.ts +58 -0
  185. package/ts/standards/classes.standardfixer.ts +234 -0
  186. package/ts/standards/classes.standardproject.ts +250 -0
  187. package/ts/standards/classes.standardtree.ts +220 -0
  188. package/ts/standards/cli.ts +86 -0
  189. package/ts/standards/config.ts +160 -0
  190. package/ts/standards/errors.ts +18 -0
  191. package/ts/standards/helpers.ast.ts +208 -0
  192. package/ts/standards/helpers.paths.ts +119 -0
  193. package/ts/standards/index.ts +22 -0
  194. package/ts/standards/output.ts +65 -0
  195. package/ts/standards/ratchet.ts +63 -0
  196. package/ts/standards/rule.ts +58 -0
  197. package/ts/standards/rules/barrel.element-index.ts +112 -0
  198. package/ts/standards/rules/barrel.no-demo-export.ts +30 -0
  199. package/ts/standards/rules/demo.fixture-not-exported.ts +30 -0
  200. package/ts/standards/rules/demo.groups.ts +74 -0
  201. package/ts/standards/rules/demo.required.ts +49 -0
  202. package/ts/standards/rules/demo.separate-file.ts +40 -0
  203. package/ts/standards/rules/demo.shape.ts +42 -0
  204. package/ts/standards/rules/docs.component-index.ts +88 -0
  205. package/ts/standards/rules/element.exported.ts +35 -0
  206. package/ts/standards/rules/element.literal-tag.ts +30 -0
  207. package/ts/standards/rules/element.reachable.ts +49 -0
  208. package/ts/standards/rules/element.tag-map.ts +87 -0
  209. package/ts/standards/rules/i18n.literals.ts +58 -0
  210. package/ts/standards/rules/index.ts +87 -0
  211. package/ts/standards/rules/layout.element-folder.ts +49 -0
  212. package/ts/standards/rules/layout.entry-file-name.ts +73 -0
  213. package/ts/standards/rules/layout.entry.ts +40 -0
  214. package/ts/standards/rules/layout.group-folder.ts +23 -0
  215. package/ts/standards/rules/layout.shared-00.ts +37 -0
  216. package/ts/standards/rules/naming.class-matches-tag.ts +27 -0
  217. package/ts/standards/rules/naming.lowercase-files.ts +27 -0
  218. package/ts/standards/rules/naming.tag-prefix.ts +24 -0
  219. package/ts/standards/rules/props.accessor.ts +37 -0
  220. package/ts/standards/rules/props.object-no-attribute.ts +45 -0
  221. package/ts/standards/rules/props.reflect-primitive.ts +44 -0
  222. package/ts/standards/rules/props.typed.ts +70 -0
  223. package/ts/standards/rules/shared.ts +127 -0
  224. package/ts/standards/rules/style.bdtheme.ts +31 -0
  225. package/ts_web/00_commitinfo_data.ts +1 -1
  226. package/ts_web/catalog.ts +194 -0
  227. package/ts_web/elementproperties.ts +96 -0
  228. package/ts_web/elements/wcc-preview.ts +111 -0
  229. package/ts_web/elements/wcc-standalone-notice.ts +65 -0
  230. package/ts_web/elements/wcctools.helpers.ts +2 -10
  231. package/ts_web/index.ts +38 -19
  232. package/ts_web/previewbridge.ts +189 -0
  233. package/ts_web/readme.md +26 -85
  234. package/ts_web/renderedtree.ts +43 -0
  235. package/ts_web/wcctools.interfaces.ts +4 -7
  236. package/ts_web/wcctools.plugins.ts +6 -1
  237. package/dist_bundle/bundle.js +0 -92419
  238. package/dist_bundle/bundle.js.map +0 -1
  239. package/dist_ts_web/elements/wcc-dashboard.d.ts +0 -119
  240. package/dist_ts_web/elements/wcc-dashboard.js +0 -700
  241. package/dist_ts_web/elements/wcc-frame.d.ts +0 -22
  242. package/dist_ts_web/elements/wcc-frame.js +0 -256
  243. package/dist_ts_web/elements/wcc-properties.d.ts +0 -43
  244. package/dist_ts_web/pages/index.d.ts +0 -1
  245. package/dist_ts_web/pages/index.js +0 -2
  246. package/dist_ts_web/services/recorder.service.js +0 -353
  247. package/ts_web/elements/wcc-contextmenu.ts +0 -291
  248. package/ts_web/elements/wcc-dashboard.ts +0 -672
  249. package/ts_web/elements/wcc-frame.ts +0 -189
  250. package/ts_web/elements/wcc-properties.ts +0 -1089
  251. package/ts_web/elements/wcc-record-button.ts +0 -108
  252. package/ts_web/elements/wcc-recording-panel.ts +0 -1010
  253. package/ts_web/elements/wcc-sidebar.ts +0 -1470
  254. package/ts_web/pages/index.ts +0 -1
  255. package/ts_web/services/recorder.service.ts +0 -451
  256. package/ts_web/types/dom-mediacapture-stub/index.d.ts +0 -12
  257. package/ts_web/types/dom-mediacapture-stub/package.json +0 -6
  258. package/ts_web/types/dom-webcodecs-stub/index.d.ts +0 -2
  259. package/ts_web/types/dom-webcodecs-stub/package.json +0 -6
  260. /package/{dist_ts_web → dist_ts_shell}/elements/wcc-contextmenu.d.ts +0 -0
  261. /package/{dist_ts_web → dist_ts_shell}/elements/wcc-record-button.d.ts +0 -0
  262. /package/{dist_ts_web → dist_ts_shell}/services/recorder.service.d.ts +0 -0
@@ -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=
@@ -0,0 +1,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** File and folder names under `ts_web/` are lowercase. */
3
+ export declare const namingLowercaseFilesRule: IStandardRule;
@@ -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,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** Every tag starts with `<tagPrefix>-`. Applies to fixture elements in demo files too: they share the page. */
3
+ export declare const namingTagPrefixRule: IStandardRule;
@@ -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,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** Members decorated with `@property` or `@state` use the `accessor` keyword (standard decorators). */
3
+ export declare const propsAccessorRule: IStandardRule;
@@ -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,3 @@
1
+ import type { IStandardRule } from '../rule.js';
2
+ /** A public property holding an object or array declares `type: Object`/`type: Array` or `attribute: false`. */
3
+ export declare const propsObjectNoAttributeRule: IStandardRule;
@@ -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;