eslint-plugin-kerfjs 5.0.0-beta.50 → 5.0.0-beta.51

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.
@@ -11,5 +11,14 @@ Stable diagnostics are `KUI-L013` (raw or unknown shorthand), `KUI-L014`
11
11
  spacing shorthand). Messages name the preferred shorthand or helper. Dynamic
12
12
  values are left to TypeScript rather than guessed.
13
13
 
14
+ Only component exports carry an entry's contracts. A catalog entry's
15
+ `publicExports` also lists the helpers its props consume (`Select` ships
16
+ `uiColor`, `List` ships `px`, `rem`, and `flex`); a helper call such as
17
+ `flex({ gap: '12px' })` is not a `List` call and is never checked as one. A
18
+ component export is one whose name starts with an uppercase letter, the rule
19
+ JSX itself uses to tell a component tag from an intrinsic element; a default
20
+ import keeps its subpath's entry. `@kerfjs/ui`'s catalog check enforces the
21
+ convention for the package, and `kerf-ui-analyze` applies the same rule.
22
+
14
23
  Third-party component suites can provide the same contracts in a composition
15
24
  catalog through `settings.kerfjs.ui.catalog` and its matching selection catalog.
package/index.js CHANGED
@@ -13,7 +13,7 @@ import uiPublicBoundaries from './lib/rules/ui-public-boundaries.js';
13
13
  import uiWiring from './lib/rules/ui-wiring.js';
14
14
 
15
15
  const plugin = {
16
- meta: { name: 'eslint-plugin-kerfjs', version: '5.0.0-beta.50' },
16
+ meta: { name: 'eslint-plugin-kerfjs', version: '5.0.0-beta.51' },
17
17
  rules: {
18
18
  'no-inline-jsx-event-handlers': noInlineJsxEventHandlers,
19
19
  'no-raw-with-dynamic-arg': noRawWithDynamicArg,
@@ -100,7 +100,7 @@ export default {
100
100
  ...(cssContract.canonicalShorthands ?? []).map(
101
101
  (item) => `\`${item}\``,
102
102
  ),
103
- ...(cssContract.helpers ?? []).map((item) => `\`${item}()`),
103
+ ...(cssContract.helpers ?? []).map((item) => `\`${item}()\``),
104
104
  ].join(' or ') || 'a cataloged component prop';
105
105
  for (const value of valuesFor(cssContract.path)) {
106
106
  if (!value) continue;
@@ -9,6 +9,20 @@ const loadCommonJs = createRequire(import.meta.url);
9
9
 
10
10
  export const UI_CONTRACT_LOAD_CODE = 'KUI-L090';
11
11
 
12
+ // A catalog entry's `publicExports` mixes the component render function with
13
+ // helpers the component's props consume (`Select` ships `uiColor`, `List`
14
+ // ships `px`/`rem`/`flex`). Only the render function stands for the entry, so
15
+ // only it may carry the entry's contracts. A component export is one whose
16
+ // name starts with an uppercase letter: JSX itself treats a lowercase tag as an
17
+ // intrinsic element, so a lowercase export can never be a component tag, and
18
+ // `@kerfjs/ui`'s catalog check (`check-component-catalog.mjs`) enforces the
19
+ // converse for the package: every uppercase runtime export returns `SafeHtml`
20
+ // and every lowercase one does not. A default import has no name to inspect
21
+ // and keeps its subpath's entry.
22
+ export function isComponentExport(name) {
23
+ return name === 'default' || /^[A-Z]/.test(name);
24
+ }
25
+
12
26
  const readJson = (path) => JSON.parse(readFileSync(path, 'utf8'));
13
27
 
14
28
  function packageAsset(cwd, name) {
@@ -135,7 +149,7 @@ export function loadUiContract(context) {
135
149
  if (entry.delivery?.moduleImport)
136
150
  imports.set(entry.delivery.moduleImport, key);
137
151
  for (const name of entry.publicExports ?? []) {
138
- exports.set(name, key);
152
+ if (isComponentExport(name)) exports.set(name, key);
139
153
  addHelperSource(name, selection.package);
140
154
  }
141
155
  for (const wiring of entry.wiring ?? [])
@@ -185,11 +199,12 @@ export function importRegistry(program, contract) {
185
199
  specifier.type === 'ImportDefaultSpecifier'
186
200
  ? 'default'
187
201
  : (specifier.imported.name ?? specifier.imported.value);
188
- const key =
189
- directKey ??
190
- (source === contract.package
191
- ? contract.exports?.get(imported)
192
- : undefined);
202
+ const key = !isComponentExport(imported)
203
+ ? undefined
204
+ : (directKey ??
205
+ (source === contract.package
206
+ ? contract.exports?.get(imported)
207
+ : undefined));
193
208
  if (key) locals.set(specifier.local.name, key);
194
209
  helpers.set(specifier.local.name, { imported, source });
195
210
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-kerfjs",
3
- "version": "5.0.0-beta.50",
3
+ "version": "5.0.0-beta.51",
4
4
  "description": "ESLint rules that enforce kerf's hard rules — catches AI-shaped bugs at edit time.",
5
5
  "type": "module",
6
6
  "license": "MIT",