@starci/eslint-canon-fe 9.16.1 → 9.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -14
- package/dist/drawing.js +1 -1
- package/dist/function-budget.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/config.d.ts +1 -2
- package/dist/lib/config.js +2 -2
- package/dist/lib/own-hook-origin.d.ts +1 -1
- package/dist/lib/package-root.d.ts +1 -1
- package/dist/lib/package-root.js +1 -1
- package/dist/ui-rulings.d.ts +1 -1
- package/dist/ui-rulings.js +1 -1
- package/docs/control-height.md +1 -1
- package/docs/grammar-shim.md +1 -1
- package/docs/hooks-folder.md +1 -1
- package/docs/surface-rules.md +2 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 9.16.2 - 2026-11-07
|
|
4
|
+
|
|
5
|
+
- A patch: peers `@starci/hfs` ~6.0.0. Comments, rule docs and messages cite rules by their ids and carry no ruling history; the counting cohort entries carry no ruling field.
|
|
6
|
+
|
|
3
7
|
## 9.16.1 - 2026-11-07
|
|
4
8
|
|
|
5
9
|
- A patch: `starci-fe/control-height` no longer names `SegmentedControl` (removed from `@starci/grammar` 0.24.0); the controls it holds to the one 40px height are Button, IconButton, Switch, Input, SearchField, Select, Tabs, Textarea, NumberField and ComboBox. Its docs follow.
|
|
@@ -14,11 +18,11 @@
|
|
|
14
18
|
|
|
15
19
|
## 9.15.0 - 2026-11-05
|
|
16
20
|
|
|
17
|
-
- Changed
|
|
21
|
+
- Changed: the canon reads the @starci/hfs runtime from the installed hfs at run time, which it peers by `~5.13.0`, and bundles no copy; `runtime/` keeps only the project graph rule, the jsdoc, sonar and next helpers and the package-scripts template, and the stale forks (slots 3.13.0) are gone.
|
|
18
22
|
|
|
19
23
|
## 9.14.4 - 2026-11-05
|
|
20
24
|
|
|
21
|
-
- Changed: the runtime copy of the canon pins gives the Grammar family its same-minor range
|
|
25
|
+
- Changed: the runtime copy of the canon pins gives the Grammar family its same-minor range and names `@starci/hfs` 5.12.0 and the Grammar family 0.22.0.
|
|
22
26
|
|
|
23
27
|
## 9.14.3 - 2026-11-05
|
|
24
28
|
|
|
@@ -249,8 +253,8 @@
|
|
|
249
253
|
## 9.6.3 - 2026-10-31
|
|
250
254
|
|
|
251
255
|
- Changed: the bundled canon pins name the 0.16.3 cohort (@starci/grammar, eslint-grammar-core and eslint-grammar-offset-pop 0.16.3, eslint-canon-fe 9.6.3, eslint-canon-be 3.9.3, stylelint-canon 2.3.0, jest-preset 2.6.0, hfs 4.13.0); ChatWorkspace and PaneLayout are removed with no alias; PaneGrid and Pane are the one generic pane grid: grammar names are generic. The surface-rules spec uses PaneGrid.
|
|
252
|
-
- Added: lib/freestyle (`exemptFreestyle`, `freestyleContext`): no-arbitrary-value, no-app-surface-paint, no-raw-brand-value, no-list-panel-padding, no-inline-class-name and no-native-img do not report the raw elements inside a `<Freestyle>` subtree of the same file; a Grammar component inside it is judged as before
|
|
253
|
-
- Added: the lint result cache of `starci app check
|
|
256
|
+
- Added: lib/freestyle (`exemptFreestyle`, `freestyleContext`): no-arbitrary-value, no-app-surface-paint, no-raw-brand-value, no-list-panel-padding, no-inline-class-name and no-native-img do not report the raw elements inside a `<Freestyle>` subtree of the same file; a Grammar component inside it is judged as before. Specs: src/freestyle.spec.ts.
|
|
257
|
+
- Added: the lint result cache of `starci app check`: `crossFileInputs`, the files and folders each rule reads beyond the linted file (an fs-audit spec proves every rule declares what it reads), and the `projectGraph` export the cache keys a file's lint record on.
|
|
254
258
|
|
|
255
259
|
## 9.6.2 - 2026-10-31
|
|
256
260
|
|
|
@@ -343,7 +347,7 @@
|
|
|
343
347
|
|
|
344
348
|
## 9.5.4 - 2026-10-29
|
|
345
349
|
|
|
346
|
-
- Changed: the bundled slot manifest 3.13.0 admits `pgmq` in `ruleParams.db.extensions` (the lite event bus
|
|
350
|
+
- Changed: the bundled slot manifest 3.13.0 admits `pgmq` in `ruleParams.db.extensions` (the lite event bus), retires `ruleParams.db.queueOutbox` and `sides.be.queueOutbox` with the pg_cron half of R258, lists `public.event_bus_send`, `public.event_bus_read`, `public.event_bus_archive`, `public.event_bus_bury`, `public.event_bus_dead_letters` and `public.event_bus_requeue` in place of `public.event_bus_write` in `ruleParams.be.dbFunctions`, and moves slot `app.db.image` to `.starcistacks/images/db/Dockerfile` (admitted by the lite `app.starcistacks` allows); the bundled rule catalog keeps R258 `DB_PGMQ_DECLARED` as the event-bus law, retires `DB_CRON_OWNED` and adds R336 `BE_EVENT_BUS_LITE_SHAPE`; the bundled canon pins name hfs 4.11.3, eslint-canon-be 3.8.2, eslint-canon-fe 9.5.4 and the Grammar family 0.15.15. No front-end rule changed.
|
|
347
351
|
|
|
348
352
|
## 9.5.3 - 2026-10-29
|
|
349
353
|
|
|
@@ -415,12 +419,12 @@
|
|
|
415
419
|
|
|
416
420
|
## 9.3.0 - 2026-10-28
|
|
417
421
|
|
|
418
|
-
- Changed (breaking for apps):
|
|
422
|
+
- Changed (breaking for apps): a pure half takes `{ shape?, props, on? }`; `base-props-atom` refuses the retired `state` key with a message naming the rename, and `no-data-status-shape` reads `XShape` unions (and still the old `XState` names, so a status word is caught during the rename).
|
|
419
423
|
- Changed: the bundled runtime copies follow the retirement of `@starci/cli`: the bundled canon pins replace the retired `@starci/cli` with `starci-harness` 1.1.0-alpha.1 (`source: cli/package.json`), the one command line a product installs for `starci app`, and follow the harness packages (Grammar family 0.14.0, hfs 4.9.0, canon-fe 9.3.0, canon-be 3.5.0); the runtime finds an app's `starci` bin in its installed `starci-harness`.
|
|
420
424
|
|
|
421
425
|
## 9.2.0 - 2026-10-27
|
|
422
426
|
|
|
423
|
-
- Changed:
|
|
427
|
+
- Changed: the bundled Grammar catalog declares exactly two families, `core` (`@starci/eslint-grammar-core`, `coreGrammarConfig`) and `offset-pop`; `starci`, `starci-core` and `heritage` are refused. The Grammar entry checks (button intent, control height, surface rules, UI rulings) accept `@starci/grammar/<common|core|offset-pop>`. The bundled canon pins follow the harness packages (Grammar family 0.13.0, hfs 4.8.0, canon-fe 9.2.0, canon-be 3.4.57, stylelint-canon 2.1.0).
|
|
424
428
|
- Changed: the doc comment of `lint-escape-hatch.mjs` names the three patterns that own the refused spellings instead of spelling them again. No rule or behaviour changed.
|
|
425
429
|
|
|
426
430
|
## 9.1.11 - 2026-10-27
|
|
@@ -434,7 +438,7 @@
|
|
|
434
438
|
## 9.1.9 - 2026-10-26
|
|
435
439
|
|
|
436
440
|
- Added: starci-fe/control-height (R320 FE_CONTROL_HEIGHT), selection-fill-no-check and no-grammar-internal-selector.
|
|
437
|
-
- Changed: the bundled runtime copies carry the light push gate
|
|
441
|
+
- Changed: the bundled runtime copies carry the light push gate.
|
|
438
442
|
|
|
439
443
|
## 9.1.8 - 2026-10-26
|
|
440
444
|
|
|
@@ -527,7 +531,7 @@
|
|
|
527
531
|
## 8.4.30 - 2026-10-23
|
|
528
532
|
- Changed: the bundled canon pins select @starci/hfs 4.7.24 and @starci/cli 1.7.24.
|
|
529
533
|
- Added: the type-aware rules the back end already borrowed, at error: `@typescript-eslint/no-floating-promises`, `no-misused-promises`, `switch-exhaustiveness-check` and the `no-unsafe-assignment`, `-member-access`, `-call`, `-return`, `-argument` family.
|
|
530
|
-
- Changed: no Sonar way rule is left to the server (
|
|
534
|
+
- Changed: no Sonar way rule is left to the server (no loosening): S3403, S3800, S3782 and S6582 run at error, `unicorn/consistent-function-scoping` runs with its default options, and S7785 (`unicorn/prefer-top-level-await`) runs in the front end (ESM).
|
|
531
535
|
- Added: `starciPlainSourceConfig({ root })` for a TypeScript front-end tree that is no HFS app (a runtime package, the harness UI): typed linting, the inline-directive fence, the React Hooks, type-aware and Sonar way rules and every canon rule that needs no slot view (`SLOT_FREE_RULES`), all at error.
|
|
532
536
|
|
|
533
537
|
## 8.4.29 - 2026-10-22
|
|
@@ -616,9 +620,9 @@
|
|
|
616
620
|
|
|
617
621
|
## 8.4.1 - 2026-10-17
|
|
618
622
|
|
|
619
|
-
- Changed: the bundled runtime copies follow the runtime of 1.0.0-alpha.19
|
|
620
|
-
- Changed (R287 `FE_CALLBACK_SHAPE`, a18.1 NIVO request F2
|
|
621
|
-
- Changed (R287 `FE_CALLBACK_SHAPE`, a18.1 NIVO request F
|
|
623
|
+
- Changed: the bundled runtime copies follow the runtime of 1.0.0-alpha.19: the failure codes, the slot manifest (`exampleNa`) and the rule catalog (`specNa`, `exampleNa`) carry the removal of the runtime's own specs; package behavior is unchanged.
|
|
624
|
+
- Changed (R287 `FE_CALLBACK_SHAPE`, a18.1 NIVO request F2): the auth callback may call pure text helpers of the app's `modules/routes` or `modules/auth` (`requestOrigin`, `safeNextPath`; resolved by TypeScript symbol: synchronous, no await, no I/O global, only owner helpers and `modules/config` readers), use static route tables (`AUTH_ROUTES`), and read the exchange outcome's `success` or `ok` flag. An impure, async or non-text helper, a helper outside those owners and a credential passed to a helper are still refused.
|
|
625
|
+
- Changed (R287 `FE_CALLBACK_SHAPE`, a18.1 NIVO request F): the auth callback may await one `verifyOtp({ token_hash, type })` of the auth owner (`auth.verifyOtp` or `verifyOtp` from `modules/auth/server`), built from exactly the query values `token_hash` and `type`, beside the one `exchangeAuthCode(code)`; the token hash never reaches a redirect.
|
|
622
626
|
- Fixed (R55 `FE_CLIENT_BOUNDARY`, a18.1 NIVO request I): the finding on a page or layout owner now says the owner stays a server component that renders the client block or overlay carrying the directive. The rule is unchanged.
|
|
623
627
|
|
|
624
628
|
## 8.3.0 - 2026-10-15
|
|
@@ -639,11 +643,11 @@
|
|
|
639
643
|
|
|
640
644
|
## 8.2.16 - 2026-10-13
|
|
641
645
|
|
|
642
|
-
- Changed: the heroicons family is the one application icon set again
|
|
646
|
+
- Changed: the heroicons family is the one application icon set again: `heroicons-is-the-glyph-vendor` admits exactly `@heroicons/react/24/outline`, `@heroicons/react/16/solid` and the matching `@starci/heroicons` subpaths (read from the fe-stack `icons` concern), and refuses Phosphor and every other glyph catalogue, a package the catalog forbids included; `one-icon-set` (8.2.15) is gone. Only the Icon leaf and the toast module import a glyph. The bundled runtime mirror carries the fe-stack catalog and the canon pins with `@heroicons/react` 2.2.0 and `@starci/heroicons` 0.3.3.
|
|
643
647
|
|
|
644
648
|
## 8.2.15 - 2026-10-13
|
|
645
649
|
|
|
646
|
-
- Changed: carry the runtime mirror of HFS manifest 3.0.0 (one front-end standard for the lite and the full edition
|
|
650
|
+
- Changed: carry the runtime mirror of HFS manifest 3.0.0 (one front-end standard for the lite and the full edition) and the canon pins for Grammar 0.9.14, HFS 4.2.14, jest-preset 2.2.7 and CLI 1.2.14.
|
|
647
651
|
- Added: `fe-stack-import` (law `fe-stack`, finding code `FE_STACK_FORBIDDEN`): an import (static, re-export, dynamic, `require`, type-only included) of a package any concern of the fe-stack catalog (`runtime/knowledge/hfs/fe-stack.yaml`) forbids, and `@supabase/*` outside `modules/auth` (slot `fe.modules.auth`), are refused. The catalog is read from the runtime copy; a missing copy stops the lint run with the fix.
|
|
648
652
|
- Changed: the transport law follows the Apollo GraphQL + axios API layer. `fetch` (and `Request`, `EventSource`, `sendBeacon`) is legal in every file of the API layer (`modules/api`, the shared api package), `@apollo/client` only there, `axios` only in its REST calls (`modules/api/rest/`), `socket.io-client` only in `hooks/socketio/` (`fetch-only-in-api-client`, message `placed`); `client-fetch-has-signal` and `no-shared-transport-state` judge the whole layer (the generated `graphql/__generated__/` excepted); `no-hand-typed-wire` admits GraphQL documents in the API layer (one file per operation) and refuses them elsewhere; `one-outcome-union` names `GraphQLResponse` in `modules/api/graphql/types.ts` as the one vocabulary and also reads a `success` discriminant. The `modules/db` outcome home and the server reader role are gone.
|
|
649
653
|
- Changed: `hooks-folder-holds-hooks-only` judges the hooks families `hooks/{swr,rhf,zustand,socketio,effects,reuseables}` by the files their slots name (message `family`); `SwrSideEffects.tsx` and `SocketIoSideEffects.tsx` are legal `.tsx` files of `hooks/`.
|
package/dist/drawing.js
CHANGED
|
@@ -94,7 +94,7 @@ export const basePropsAtom = defineRule({
|
|
|
94
94
|
action: "`{{path}}` is a function inside `props`. Actions live in `on`; feature composition may receive named `render` callbacks that take atoms and return rendered blocks.",
|
|
95
95
|
onData: "`on.{{key}}` is not an action. `on` holds functions only; data belongs in `props`.",
|
|
96
96
|
member: "`{{key}}` is not part of the pure contract. A pure half takes `shape`, `props` and `on`{{children}}.",
|
|
97
|
-
renamed: "
|
|
97
|
+
renamed: "The drawn shape is named `shape`, never `state`: rename it `shape`.",
|
|
98
98
|
},
|
|
99
99
|
},
|
|
100
100
|
create(context) {
|
package/dist/function-budget.js
CHANGED
|
@@ -11,7 +11,7 @@ export const functionLineBudget = defineRule({
|
|
|
11
11
|
},
|
|
12
12
|
},
|
|
13
13
|
create(context) {
|
|
14
|
-
//
|
|
14
|
+
// A manifest without `ruleParams.functionLines` gets the cap of 80 lines.
|
|
15
15
|
const max = hfsOf(context).ruleParams.functionLines ?? 80;
|
|
16
16
|
if (!Number.isInteger(max) || max < 1)
|
|
17
17
|
throw new RangeError("ruleParams.functionLines must be a positive integer");
|
package/dist/index.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export declare const rules: Record<string, Rule>;
|
|
|
38
38
|
*
|
|
39
39
|
* Every FE canon rule is an error. Existing debt is fixed before adoption; lowering architecture
|
|
40
40
|
* to warn teaches every later author that the boundary is optional and is not a supported rollout. The one
|
|
41
|
-
* exception is the closed counting cohort of lib/config.ts (`COUNTING`),
|
|
41
|
+
* exception is the closed counting cohort of lib/config.ts (`COUNTING`), a warn for one release.
|
|
42
42
|
*/
|
|
43
43
|
export declare const recommended: Record<string, "error" | "warn">;
|
|
44
44
|
/** Flat-config options that make inline directives ineffective rather than merely forbidden. */
|
package/dist/index.js
CHANGED
|
@@ -132,7 +132,7 @@ export const rules = Object.fromEntries(CONTRIBUTIONS.flatMap((entry) => Object.
|
|
|
132
132
|
*
|
|
133
133
|
* Every FE canon rule is an error. Existing debt is fixed before adoption; lowering architecture
|
|
134
134
|
* to warn teaches every later author that the boundary is optional and is not a supported rollout. The one
|
|
135
|
-
* exception is the closed counting cohort of lib/config.ts (`COUNTING`),
|
|
135
|
+
* exception is the closed counting cohort of lib/config.ts (`COUNTING`), a warn for one release.
|
|
136
136
|
*/
|
|
137
137
|
export const recommended = Object.fromEntries(CONTRIBUTIONS.flatMap((entry) => Object.entries(entry.recommended)));
|
|
138
138
|
/** Flat-config options that make inline directives ineffective rather than merely forbidden. */
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -28,13 +28,12 @@ export declare const IGNORED: readonly string[];
|
|
|
28
28
|
*/
|
|
29
29
|
export declare const BORROWED: Readonly<Record<string, "error">>;
|
|
30
30
|
/**
|
|
31
|
-
* The counting cohort: a rule
|
|
31
|
+
* The counting cohort: a rule that ships at `warn` for one release while a codemod moves apps onto the API
|
|
32
32
|
* it asks for, each with the HFS rule id it enforces. `starci app check --gate lint` reports and counts its findings and never fails
|
|
33
33
|
* on them; the next cohort moves the rule to error and deletes its entry. No other rule may be below error.
|
|
34
34
|
*/
|
|
35
35
|
export declare const COUNTING: Readonly<Record<string, {
|
|
36
36
|
readonly rule: string;
|
|
37
|
-
readonly ruling: string;
|
|
38
37
|
}>>;
|
|
39
38
|
/**
|
|
40
39
|
* The flat config of one front-end repository.
|
package/dist/lib/config.js
CHANGED
|
@@ -41,12 +41,12 @@ export const BORROWED = Object.freeze({
|
|
|
41
41
|
});
|
|
42
42
|
const levelOf = (setting) => (Array.isArray(setting) ? setting[0] : setting);
|
|
43
43
|
/**
|
|
44
|
-
* The counting cohort: a rule
|
|
44
|
+
* The counting cohort: a rule that ships at `warn` for one release while a codemod moves apps onto the API
|
|
45
45
|
* it asks for, each with the HFS rule id it enforces. `starci app check --gate lint` reports and counts its findings and never fails
|
|
46
46
|
* on them; the next cohort moves the rule to error and deletes its entry. No other rule may be below error.
|
|
47
47
|
*/
|
|
48
48
|
export const COUNTING = Object.freeze({
|
|
49
|
-
"starci-fe/no-spacing-utility": { rule: "R350"
|
|
49
|
+
"starci-fe/no-spacing-utility": { rule: "R350" },
|
|
50
50
|
});
|
|
51
51
|
/**
|
|
52
52
|
* The flat config of one front-end repository.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Resolve a `use*` import that comes from the app's own hooks folders (`hooks/swr`, `hooks/<domain>`, `hooks/zustand/<store>`...) by
|
|
3
|
-
* TypeScript symbol resolution, never by the spelling of the name (R56 `FE_HOOKS_ARE_HOOKS
|
|
3
|
+
* TypeScript symbol resolution, never by the spelling of the name (R56 `FE_HOOKS_ARE_HOOKS`).
|
|
4
4
|
*
|
|
5
5
|
* A composite product hook is built from the hooks beneath it: `hooks/<domain>/use<Name>.ts` composes the `use{Query,Mutate}<X>Swr`
|
|
6
6
|
* wrappers of `hooks/swr`. The import is followed through barrels and re-exports to the declaration, and counts only when that declaration
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export declare const PACKAGE_ROOT: string;
|
|
3
3
|
/**
|
|
4
4
|
* The runtime of the installed @starci/hfs (its peer, a same-minor range): the slot manifest, the architecture machine and its catalogs are read from it
|
|
5
|
-
* at run time, never from a copy bundled here, so an hfs data change releases hfs alone
|
|
5
|
+
* at run time, never from a copy bundled here, so an hfs data change releases hfs alone.
|
|
6
6
|
*/
|
|
7
7
|
export declare const RUNTIME_ROOT: string;
|
|
8
8
|
/** The files this package keeps of its own in runtime/ (the project graph rule, the jsdoc, sonar and next helpers, the package-scripts template). */
|
package/dist/lib/package-root.js
CHANGED
|
@@ -9,7 +9,7 @@ import { fileURLToPath } from "node:url";
|
|
|
9
9
|
export const PACKAGE_ROOT = fileURLToPath(new URL("../..", import.meta.url));
|
|
10
10
|
/**
|
|
11
11
|
* The runtime of the installed @starci/hfs (its peer, a same-minor range): the slot manifest, the architecture machine and its catalogs are read from it
|
|
12
|
-
* at run time, never from a copy bundled here, so an hfs data change releases hfs alone
|
|
12
|
+
* at run time, never from a copy bundled here, so an hfs data change releases hfs alone.
|
|
13
13
|
*/
|
|
14
14
|
export const RUNTIME_ROOT = join(dirname(createRequire(import.meta.url).resolve("@starci/hfs/package.json")), "runtime");
|
|
15
15
|
/** The files this package keeps of its own in runtime/ (the project graph rule, the jsdoc, sonar and next helpers, the package-scripts template). */
|
package/dist/ui-rulings.d.ts
CHANGED
|
@@ -7,5 +7,5 @@ export declare const rules: {
|
|
|
7
7
|
"selection-fill-no-check": import("./lib/rule.js").Rule<"indicator", []>;
|
|
8
8
|
"no-grammar-internal-selector": import("./lib/rule.js").Rule<"internal", []>;
|
|
9
9
|
};
|
|
10
|
-
/** Both
|
|
10
|
+
/** Both rules are universal errors in the frontend canon. */
|
|
11
11
|
export declare const recommended: Recommended;
|
package/dist/ui-rulings.js
CHANGED
|
@@ -117,5 +117,5 @@ export const rules = {
|
|
|
117
117
|
"selection-fill-no-check": selectionFillNoCheck,
|
|
118
118
|
"no-grammar-internal-selector": noGrammarInternalSelector,
|
|
119
119
|
};
|
|
120
|
-
/** Both
|
|
120
|
+
/** Both rules are universal errors in the frontend canon. */
|
|
121
121
|
export const recommended = Object.fromEntries(Object.keys(rules).map((name) => [`starci-fe/${name}`, "error"]));
|
package/docs/control-height.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Control height (CONTROL-HEIGHT-1)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
One control height, 40px (HeroUI's own `h-10`), is the default of every standalone Grammar control: Button, IconButton, Input, SearchField, Select, Tabs, Switch, the chrome Avatar, Textarea and the composer send button. Grammar draws it; an app never states it.
|
|
4
4
|
|
|
5
5
|
| Rule | Finding code | Required behavior |
|
|
6
6
|
| --- | --- | --- |
|
package/docs/grammar-shim.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Grammar shims (R321)
|
|
2
2
|
|
|
3
|
-
Law module: `grammar-shim.mjs`. HFS rule: R321. Knowledge: `contexts/code/fe/ui.md` FE-UI-1 (the app makes no visual choice; the Grammar owns every visual element)
|
|
3
|
+
Law module: `grammar-shim.mjs`. HFS rule: R321. Knowledge: `contexts/code/fe/ui.md` FE-UI-1 (the app makes no visual choice; the Grammar owns every visual element).
|
|
4
4
|
|
|
5
5
|
An app imports a Grammar component where it renders it. It never hands one on from an app path under its own name: such a shim makes one app green while the defect it works around (a missing `"use client"`, a wrong prop, a broken export) stays in the Grammar for every other app. The defect is reported to the Grammar instead; an op files `blocked` naming the package, the component and the error.
|
|
6
6
|
|
package/docs/hooks-folder.md
CHANGED
|
@@ -8,7 +8,7 @@ Every rule below is an error in `starciFeConfig`; none can be switched off or su
|
|
|
8
8
|
|
|
9
9
|
## `starci-fe/hooks-folder-holds-hooks-only`
|
|
10
10
|
|
|
11
|
-
`hooks/` holds `use*.ts` hooks under the names their family slot gives and, per domain, one `<domain>.shared.ts`; nothing else. A hook file exports one hook; `server-only` and `next/headers` are never imported there. A hook is a function that calls a hook: a React, SWR or Redux hook, a `use*` imported from the app's own `hooks/` folders (a `hooks/swr` wrapper or a sibling domain hook, resolved by TypeScript symbol resolution through barrels; that hook's own file is judged when it is linted), or a library hook from an explicit list (`next-intl` `useTranslations`/`useLocale`/`useFormatter`/`useNow`/`useTimeZone`/`useMessages`, `next/navigation`, `next-themes` `useTheme`, `react-hook-form`, `zustand`). A `use*` from outside every `hooks/` folder or an unlisted library is not a hook by its spelling, and a file that exports a helper, a constant or a component still fails
|
|
11
|
+
`hooks/` holds `use*.ts` hooks under the names their family slot gives and, per domain, one `<domain>.shared.ts`; nothing else. A hook file exports one hook; `server-only` and `next/headers` are never imported there. A hook is a function that calls a hook: a React, SWR or Redux hook, a `use*` imported from the app's own `hooks/` folders (a `hooks/swr` wrapper or a sibling domain hook, resolved by TypeScript symbol resolution through barrels; that hook's own file is judged when it is linted), or a library hook from an explicit list (`next-intl` `useTranslations`/`useLocale`/`useFormatter`/`useNow`/`useTimeZone`/`useMessages`, `next/navigation`, `next-themes` `useTheme`, `react-hook-form`, `zustand`). A `use*` from outside every `hooks/` folder or an unlisted library is not a hook by its spelling, and a file that exports a helper, a constant or a component still fails.
|
|
12
12
|
|
|
13
13
|
**Invalid** (`src/hooks/course/readCourse.ts`)
|
|
14
14
|
|
package/docs/surface-rules.md
CHANGED
|
@@ -59,7 +59,7 @@ const Frame = () => (
|
|
|
59
59
|
|
|
60
60
|
## `starci-fe/no-table-in-card`
|
|
61
61
|
|
|
62
|
-
Finding code: `FE_TABLE_IN_CARD` (R351). A `DataTable` is not placed in a `SurfaceCard`. Plain rows with a few facts are a `SurfaceCard kind="list"` with the label outside and the note in its `footer`; a table that compares records across many columns sits in its section with no card around it. The rule reads the file: a Grammar `DataTable` enclosed by a Grammar `SurfaceCard` element is a finding, and so is a `DataTable` rendered by a component of the same file (a declaration, a variable's function, a `memo` or `forwardRef` wrapper, followed through other components of the file) that a `SurfaceCard` encloses. A card in another file that renders a table component is judged where the card is written. There is no inline exemption; a table
|
|
62
|
+
Finding code: `FE_TABLE_IN_CARD` (R351). A `DataTable` is not placed in a `SurfaceCard`. Plain rows with a few facts are a `SurfaceCard kind="list"` with the label outside and the note in its `footer`; a table that compares records across many columns sits in its section with no card around it. The rule reads the file: a Grammar `DataTable` enclosed by a Grammar `SurfaceCard` element is a finding, and so is a `DataTable` rendered by a component of the same file (a declaration, a variable's function, a `memo` or `forwardRef` wrapper, followed through other components of the file) that a `SurfaceCard` encloses. A card in another file that renders a table component is judged where the card is written. There is no inline exemption; a table complex enough to sit in a card is named in this rule.
|
|
63
63
|
|
|
64
64
|
Invalid:
|
|
65
65
|
|
|
@@ -127,7 +127,7 @@ const Filter = () => <FilterButtonGroup label="Team" options={options} value={te
|
|
|
127
127
|
|
|
128
128
|
## `starci-fe/no-heading-above-card`
|
|
129
129
|
|
|
130
|
-
Finding code: `FE_HEADING_ABOVE_CARD` (R354). A card
|
|
130
|
+
Finding code: `FE_HEADING_ABOVE_CARD` (R354). A card carries its own label, so a heading over it is wrong. A Grammar `Section` (not `kind="list"`) whose only child is one `SurfaceCard` is refused, and so is a card whose `ariaLabel` is the `Section`'s `title`. Several cards under one `Section` stay legal, and a `Section` holding anything else is not judged. The fix moves the title to the card's `label`, the count to `fact`, the action to `labelEnd` and the note to `footer`.
|
|
131
131
|
|
|
132
132
|
Invalid:
|
|
133
133
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starci/eslint-canon-fe",
|
|
3
|
-
"version": "9.16.
|
|
3
|
+
"version": "9.16.2",
|
|
4
4
|
"description": "Universal front-end lint laws for TypeScript and Next.js, independent of the selected Grammar family.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"node": ">=22.13.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@starci/hfs": "~
|
|
54
|
+
"@starci/hfs": "~6.0.0",
|
|
55
55
|
"eslint": ">=9",
|
|
56
56
|
"eslint-plugin-react-hooks": ">=7",
|
|
57
57
|
"typescript": ">=5.9"
|