@geonosis/oxlint-plugin-biological-architecture 2.13.0 → 3.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.
- package/CHANGELOG.md +12 -0
- package/README.md +2 -2
- package/RULES.md +7 -6
- package/corpus/.oxlintrc.json +1 -0
- package/corpus/icon-controls/bad-unnamed-icon-button.tsx +8 -0
- package/corpus/icon-controls/good-named-icon-button.tsx +19 -0
- package/corpus/manifest.json +1 -0
- package/dist/discover-atoms.d.ts +5 -6
- package/dist/discover-atoms.js +33 -24
- package/dist/index.d.ts +7 -54
- package/dist/index.js +182 -7973
- package/dist/presets.d.ts +6 -8
- package/dist/presets.js +138 -6
- package/dist/rules/atom-no-deps.d.ts +21 -0
- package/dist/rules/atom-no-deps.js +29 -0
- package/dist/rules/boundary-time-is-primitive.d.ts +56 -0
- package/dist/rules/boundary-time-is-primitive.js +134 -0
- package/dist/rules/cell-must-be-stateful.d.ts +22 -0
- package/dist/rules/cell-must-be-stateful.js +75 -0
- package/dist/rules/cell-must-not-compose-cell.d.ts +21 -0
- package/dist/rules/cell-must-not-compose-cell.js +29 -0
- package/dist/rules/cell-no-cross-feature-organelles.d.ts +21 -0
- package/dist/rules/cell-no-cross-feature-organelles.js +37 -0
- package/dist/rules/cell-no-tissues.d.ts +21 -0
- package/dist/rules/cell-no-tissues.js +23 -0
- package/dist/rules/cells-folder-index-is-barrel.d.ts +35 -0
- package/dist/rules/cells-folder-index-is-barrel.js +66 -0
- package/dist/rules/compound-must-be-stateless.d.ts +39 -0
- package/dist/rules/compound-must-be-stateless.js +86 -0
- package/dist/rules/compound-no-stores.d.ts +21 -0
- package/dist/rules/compound-no-stores.js +25 -0
- package/dist/rules/constants-in-constants-file.d.ts +41 -0
- package/dist/rules/constants-in-constants-file.js +41 -0
- package/dist/rules/dialect-through-the-seam.d.ts +63 -0
- package/dist/rules/dialect-through-the-seam.js +102 -0
- package/dist/rules/durable-body-reads-through-steps.d.ts +78 -0
- package/dist/rules/durable-body-reads-through-steps.js +122 -0
- package/dist/rules/effect-hook-naming.d.ts +48 -0
- package/dist/rules/effect-hook-naming.js +82 -0
- package/dist/rules/emit-declares-attempts.d.ts +62 -0
- package/dist/rules/emit-declares-attempts.js +102 -0
- package/dist/rules/font-roles-only.d.ts +78 -0
- package/dist/rules/font-roles-only.js +88 -0
- package/dist/rules/icon-control-has-name.d.ts +53 -0
- package/dist/rules/icon-control-has-name.js +65 -0
- package/dist/rules/layer-walls.d.ts +97 -0
- package/dist/rules/layer-walls.js +138 -0
- package/dist/rules/lib/cells-barrel.d.ts +2 -0
- package/dist/rules/lib/cells-barrel.js +6 -0
- package/dist/rules/lib/colors.d.ts +24 -0
- package/dist/rules/lib/colors.js +261 -0
- package/dist/rules/lib/context.d.ts +26 -0
- package/dist/rules/lib/context.js +0 -0
- package/dist/rules/lib/direction-rule.d.ts +65 -0
- package/dist/rules/lib/direction-rule.js +125 -0
- package/dist/rules/lib/doors.d.ts +26 -0
- package/dist/rules/lib/doors.js +89 -0
- package/dist/rules/lib/hooks.d.ts +20 -0
- package/dist/rules/lib/hooks.js +21 -0
- package/dist/rules/lib/imports.d.ts +52 -0
- package/dist/rules/lib/imports.js +25 -0
- package/dist/rules/lib/landing.d.ts +50 -0
- package/dist/rules/lib/landing.js +111 -0
- package/dist/rules/lib/literal-call.d.ts +11 -0
- package/dist/rules/lib/literal-call.js +10 -0
- package/dist/rules/lib/module-text.d.ts +43 -0
- package/dist/{chunk-H7UQNDFE.js → rules/lib/module-text.js} +44 -30
- package/dist/rules/lib/mutations.d.ts +19 -0
- package/dist/rules/lib/mutations.js +27 -0
- package/dist/rules/lib/nodes.d.ts +25 -0
- package/dist/rules/lib/nodes.js +71 -0
- package/dist/rules/lib/objects.d.ts +17 -0
- package/dist/rules/lib/objects.js +35 -0
- package/dist/rules/lib/options.d.ts +74 -0
- package/dist/rules/lib/options.js +64 -0
- package/dist/rules/lib/package-imports.d.ts +6 -0
- package/dist/rules/lib/package-imports.js +43 -0
- package/dist/rules/lib/paths.d.ts +47 -0
- package/dist/rules/lib/paths.js +28 -0
- package/dist/rules/lib/pattern-match.d.ts +16 -0
- package/dist/rules/lib/pattern-match.js +29 -0
- package/dist/rules/lib/probe.d.ts +55 -0
- package/dist/rules/lib/probe.js +39 -0
- package/dist/rules/lib/reexports.d.ts +20 -0
- package/dist/rules/lib/reexports.js +40 -0
- package/dist/rules/lib/render-tracking.d.ts +54 -0
- package/dist/rules/lib/render-tracking.js +27 -0
- package/dist/rules/lib/schema.d.ts +14 -0
- package/dist/rules/lib/schema.js +11 -0
- package/dist/rules/lib/shared-features.d.ts +24 -0
- package/dist/rules/lib/shared-features.js +16 -0
- package/dist/rules/lib/steps.d.ts +19 -0
- package/dist/rules/lib/steps.js +37 -0
- package/dist/rules/lib/styling.d.ts +65 -0
- package/dist/rules/lib/styling.js +90 -0
- package/dist/rules/lib/tiers.d.ts +31 -0
- package/dist/rules/lib/tiers.js +32 -0
- package/dist/rules/lib/tissue-entrypoint.d.ts +5 -0
- package/dist/rules/lib/tissue-entrypoint.js +15 -0
- package/dist/rules/lib/tsconfig-paths.d.ts +5 -0
- package/dist/rules/lib/tsconfig-paths.js +109 -0
- package/dist/rules/lib/visitors.d.ts +31 -0
- package/dist/rules/lib/visitors.js +38 -0
- package/dist/rules/list-take-without-order.d.ts +36 -0
- package/dist/rules/list-take-without-order.js +84 -0
- package/dist/rules/max-comment-density.d.ts +49 -0
- package/dist/rules/max-comment-density.js +72 -0
- package/dist/rules/molecule-atoms-only.d.ts +21 -0
- package/dist/rules/molecule-atoms-only.js +28 -0
- package/dist/rules/molecule-must-compose.d.ts +25 -0
- package/dist/rules/molecule-must-compose.js +73 -0
- package/dist/rules/mutating-step-declares-retry.d.ts +57 -0
- package/dist/rules/mutating-step-declares-retry.js +92 -0
- package/dist/rules/named-when-block.d.ts +37 -0
- package/dist/rules/named-when-block.js +59 -0
- package/dist/rules/next-route-segment-is-thin-delegate.d.ts +56 -0
- package/dist/rules/next-route-segment-is-thin-delegate.js +194 -0
- package/dist/rules/no-brand-names.d.ts +64 -0
- package/dist/rules/no-brand-names.js +80 -0
- package/dist/rules/no-card-shaped-div.d.ts +67 -0
- package/dist/rules/no-card-shaped-div.js +73 -0
- package/dist/rules/no-cross-feature-stores.d.ts +21 -0
- package/dist/rules/no-cross-feature-stores.js +31 -0
- package/dist/rules/no-d1-transaction.d.ts +69 -0
- package/dist/rules/no-d1-transaction.js +90 -0
- package/dist/rules/no-date-string-compare.d.ts +28 -0
- package/dist/rules/no-date-string-compare.js +100 -0
- package/dist/rules/no-duplicate-jsx-patterns.d.ts +55 -0
- package/dist/rules/no-duplicate-jsx-patterns.js +103 -0
- package/dist/rules/no-generic-utility-package.d.ts +38 -0
- package/dist/rules/no-generic-utility-package.js +86 -0
- package/dist/rules/no-hook-in-component-disguise.d.ts +96 -0
- package/dist/rules/no-hook-in-component-disguise.js +229 -0
- package/dist/rules/no-index-count-as-exact.d.ts +42 -0
- package/dist/rules/no-index-count-as-exact.js +65 -0
- package/dist/rules/no-inert-hidden-jsx.d.ts +40 -0
- package/dist/rules/no-inert-hidden-jsx.js +75 -0
- package/dist/rules/no-inline-data-in-jsx.d.ts +24 -0
- package/dist/rules/no-inline-data-in-jsx.js +71 -0
- package/dist/rules/no-invalid-feature-folders.d.ts +36 -0
- package/dist/rules/no-invalid-feature-folders.js +88 -0
- package/dist/rules/no-loader-side-effect-in-index-file.d.ts +55 -0
- package/dist/rules/no-loader-side-effect-in-index-file.js +77 -0
- package/dist/rules/no-logic-in-component-files.d.ts +49 -0
- package/dist/rules/no-logic-in-component-files.js +105 -0
- package/dist/rules/no-mock-db-in-integration.d.ts +88 -0
- package/dist/rules/no-mock-db-in-integration.js +105 -0
- package/dist/rules/no-orm-outside-db.d.ts +21 -0
- package/dist/rules/no-orm-outside-db.js +37 -0
- package/dist/rules/no-raw-html-atoms.d.ts +82 -0
- package/dist/rules/no-raw-html-atoms.js +91 -0
- package/dist/rules/no-raw-sql-outside-allowed.d.ts +61 -0
- package/dist/rules/no-raw-sql-outside-allowed.js +57 -0
- package/dist/rules/no-react-namespace.d.ts +39 -0
- package/dist/rules/no-react-namespace.js +46 -0
- package/dist/rules/no-renamed-html-props.d.ts +38 -0
- package/dist/rules/no-renamed-html-props.js +80 -0
- package/dist/rules/no-render-prop-reader.d.ts +67 -0
- package/dist/rules/no-render-prop-reader.js +59 -0
- package/dist/rules/no-runtime-dead-affordance.d.ts +69 -0
- package/dist/rules/no-runtime-dead-affordance.js +86 -0
- package/dist/rules/no-swallowed-catch.d.ts +36 -0
- package/dist/rules/no-swallowed-catch.js +92 -0
- package/dist/rules/no-trivial-wrapper-component.d.ts +61 -0
- package/dist/rules/no-trivial-wrapper-component.js +147 -0
- package/dist/rules/no-ts-in-bio-folders.d.ts +52 -0
- package/dist/rules/no-ts-in-bio-folders.js +58 -0
- package/dist/rules/no-type-definitions-in-components.d.ts +33 -0
- package/dist/rules/no-type-definitions-in-components.js +48 -0
- package/dist/rules/no-unregistered-plugin-dir.d.ts +116 -0
- package/dist/rules/no-unregistered-plugin-dir.js +138 -0
- package/dist/rules/no-void-port.d.ts +65 -0
- package/dist/rules/no-void-port.js +53 -0
- package/dist/rules/organelle-dependency.d.ts +21 -0
- package/dist/rules/organelle-dependency.js +37 -0
- package/dist/rules/organelle-single-source.d.ts +19 -0
- package/dist/rules/organelle-single-source.js +97 -0
- package/dist/rules/plugin-route-namespaced.d.ts +79 -0
- package/dist/rules/plugin-route-namespaced.js +137 -0
- package/dist/rules/queries-require-org-scope.d.ts +88 -0
- package/dist/rules/queries-require-org-scope.js +83 -0
- package/dist/rules/queue-loop-is-the-library.d.ts +28 -0
- package/dist/rules/queue-loop-is-the-library.js +35 -0
- package/dist/rules/route-no-inline-mutation.d.ts +81 -0
- package/dist/rules/route-no-inline-mutation.js +125 -0
- package/dist/rules/router-schema-parity.d.ts +60 -0
- package/dist/rules/router-schema-parity.js +95 -0
- package/dist/rules/service-name-not-reserved.d.ts +47 -0
- package/dist/rules/service-name-not-reserved.js +112 -0
- package/dist/rules/ssot-no-inline-facts.d.ts +68 -0
- package/dist/rules/ssot-no-inline-facts.js +221 -0
- package/dist/rules/ssot-no-process-env.d.ts +55 -0
- package/dist/rules/ssot-no-process-env.js +51 -0
- package/dist/rules/step-declares-compensation-or-none.d.ts +34 -0
- package/dist/rules/step-declares-compensation-or-none.js +52 -0
- package/dist/rules/step-opens-its-own-cell.d.ts +82 -0
- package/dist/rules/step-opens-its-own-cell.js +163 -0
- package/dist/rules/store-route-scopes-tenant-data.d.ts +52 -0
- package/dist/rules/store-route-scopes-tenant-data.js +150 -0
- package/dist/rules/subpath-over-barrel.d.ts +67 -0
- package/dist/rules/subpath-over-barrel.js +153 -0
- package/dist/rules/subscriber-declares-id.d.ts +39 -0
- package/dist/rules/subscriber-declares-id.js +79 -0
- package/dist/rules/tables-declare-their-plane.d.ts +44 -0
- package/dist/rules/tables-declare-their-plane.js +64 -0
- package/dist/rules/tenant-tables-carry-org-id.d.ts +66 -0
- package/dist/rules/tenant-tables-carry-org-id.js +64 -0
- package/dist/rules/test-no-clock-polling-for-promise-flips.d.ts +42 -0
- package/dist/rules/test-no-clock-polling-for-promise-flips.js +130 -0
- package/dist/rules/time-through-the-door.d.ts +86 -0
- package/dist/rules/time-through-the-door.js +138 -0
- package/dist/rules/tissue-must-compose.d.ts +41 -0
- package/dist/rules/tissue-must-compose.js +113 -0
- package/dist/rules/tissue-no-data-props.d.ts +27 -0
- package/dist/rules/tissue-no-data-props.js +148 -0
- package/dist/rules/tissue-no-hooks.d.ts +43 -0
- package/dist/rules/tissue-no-hooks.js +72 -0
- package/dist/rules/tissue-no-organelles.d.ts +21 -0
- package/dist/rules/tissue-no-organelles.js +17 -0
- package/dist/rules/tissue-no-stores.d.ts +21 -0
- package/dist/rules/tissue-no-stores.js +17 -0
- package/dist/rules/todo-names-its-plan.d.ts +75 -0
- package/dist/rules/todo-names-its-plan.js +68 -0
- package/dist/rules/tokens-only-colors.d.ts +100 -0
- package/dist/rules/tokens-only-colors.js +129 -0
- package/dist/rules/unique-query-step-name.d.ts +50 -0
- package/dist/rules/unique-query-step-name.js +130 -0
- package/dist/rules/worker-handles-are-scoped.d.ts +65 -0
- package/dist/rules/worker-handles-are-scoped.js +97 -0
- package/dist/rules/zustand-v5-best-practices.d.ts +65 -0
- package/dist/rules/zustand-v5-best-practices.js +107 -0
- package/package.json +4 -4
- package/dist/chunk-ZY3XIRRE.js +0 -145
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @geonosis/oxlint-plugin-biological-architecture
|
|
2
2
|
|
|
3
|
+
## 3.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 27d169d: `icon-control-has-name`, in the `frontend` preset: a `<button>` or `<a>` — or a control atom the repo names in `controls` — whose only content is an icon (a component whose name matches `icons`, `Icon$` by default, or an inline `<svg>`) and that carries no `aria-label`, `aria-labelledby` or `title` has no name a screen reader can read. A spread is left alone. It needs no option to run.
|
|
8
|
+
|
|
9
|
+
## 3.0.0
|
|
10
|
+
|
|
11
|
+
### Major Changes
|
|
12
|
+
|
|
13
|
+
- 237a353: `document-sagas-are-generic` and `documents-share-one-table`, retired in 2.7.0 and kept as no-ops until this major, are gone: a config that still names either is refused by oxlint with "rule not found". Remove them from the config. `RETIRED_RULES` is no longer exported.
|
|
14
|
+
|
|
3
15
|
## 2.13.0
|
|
4
16
|
|
|
5
17
|
## 2.12.0
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @geonosis/oxlint-plugin-biological-architecture
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
81 architecture rules as an oxlint JS plugin: which tier a file belongs to, what it may import,
|
|
4
4
|
where state is allowed to live, and the backend invariants that go with them. Nothing is hardcoded
|
|
5
5
|
to a repo — every list of brands, features, tables or paths is an option. A rule enabled without the
|
|
6
6
|
options it needs says so once a run and judges nothing, rather than passing silently.
|
|
@@ -57,7 +57,7 @@ everything below the organelle is inert. A cell never composes another cell.
|
|
|
57
57
|
|
|
58
58
|
| preset | rules | what it is |
|
|
59
59
|
| --- | --- | --- |
|
|
60
|
-
| `frontend` (= `recommended`) |
|
|
60
|
+
| `frontend` (= `recommended`) | 38 | tier direction, state placement, element choice, file shape |
|
|
61
61
|
| `backend-workflows` | 15 | workflows, time, the data layer, single source of truth |
|
|
62
62
|
| `backend-medusa` | 13 | Medusa steps, emits, subscribers, loaders and the store route surface |
|
|
63
63
|
| `tenant-scoping` | 4 | every row placed, scoped and narrowed to one tenant |
|
package/RULES.md
CHANGED
|
@@ -11,13 +11,12 @@ One plugin name, two rule sets, no shared code. **33 rules had the same filename
|
|
|
11
11
|
|
|
12
12
|
The union here is **52 rules** — 54 when it was cut, less `document-sagas-are-generic` and
|
|
13
13
|
`documents-share-one-table`, retired in 2.7.0 because both enforced one consumer's document kinds —
|
|
14
|
-
plus twenty-
|
|
14
|
+
plus twenty-nine the kit wrote for itself: `layer-walls`, `emit-declares-attempts`,
|
|
15
15
|
`cell-no-cross-feature-organelles`, the `backend-medusa` ten, `no-unregistered-plugin-dir` +
|
|
16
16
|
`router-schema-parity`, the `themekit` two, `no-mock-db-in-integration`, `todo-names-its-plan`,
|
|
17
17
|
`boundary-time-is-primitive`, `durable-body-reads-through-steps`, `subpath-over-barrel` and the six
|
|
18
|
-
of the W67 batch — **
|
|
19
|
-
|
|
20
|
-
Every one of the twenty-eight is marked **written here** in the inventory, and the table below is
|
|
18
|
+
of the W67 batch, and `icon-control-has-name` — **81**. The two retired ids went in 3.0.0.
|
|
19
|
+
Every one of the twenty-nine is marked **written here** in the inventory, and the table below is
|
|
21
20
|
held against that column rather than kept by hand.
|
|
22
21
|
|
|
23
22
|
| | count |
|
|
@@ -27,8 +26,8 @@ held against that column rather than kept by hand.
|
|
|
27
26
|
| A Medusa storefront only | 3 |
|
|
28
27
|
| A Workers + D1 app only | 16 |
|
|
29
28
|
| **union** | **52** |
|
|
30
|
-
| written here |
|
|
31
|
-
| **total** | **
|
|
29
|
+
| written here | 29 |
|
|
30
|
+
| **total** | **81** |
|
|
32
31
|
|
|
33
32
|
## How divergence was resolved
|
|
34
33
|
|
|
@@ -722,6 +721,7 @@ every repo's.
|
|
|
722
721
|
| `dialect-through-the-seam` | backend-workflows | `seam` | `onImportSource` + `mergeVisitors` + `paths` + `options` | — | yes | a Workers + D1 app only, de-hardcoded |
|
|
723
722
|
| `durable-body-reads-through-steps` | backend-workflows | `ports` | `nodes` + `objects` + `steps` + `options` | — | — | **written here** (#167, design-026 §8) |
|
|
724
723
|
| `effect-hook-naming` | frontend | — | `paths` | yes | yes | diverged |
|
|
724
|
+
| `icon-control-has-name` | frontend | — | `nodes` + `options` | — | — | **written here** |
|
|
725
725
|
| `emit-declares-attempts` | backend-medusa | — | `options` | — | — | **written here** |
|
|
726
726
|
| `font-roles-only` | themekit | `roles` | `paths` + `options` + `styling` | — | — | **written here** (U2) |
|
|
727
727
|
| `layer-walls` | tooling | `layers` | `onImportSource` + `imports` + `paths` + `options` | — | — | **written here** |
|
|
@@ -879,6 +879,7 @@ option not named here is one no rule reads.
|
|
|
879
879
|
| `effect-hook-naming` | — |
|
|
880
880
|
| `emit-declares-attempts` | `budgetHelpers`, `emitters` |
|
|
881
881
|
| `font-roles-only` | `allow`, `exemptModules`, `prefix`, `roles` |
|
|
882
|
+
| `icon-control-has-name` | `controls`, `icons` |
|
|
882
883
|
| `layer-walls` | `externals`, `layers`, `typeOnly` |
|
|
883
884
|
| `list-take-without-order` | `callees`, `orderKeys` |
|
|
884
885
|
| `max-comment-density` | — |
|
package/corpus/.oxlintrc.json
CHANGED
|
@@ -171,6 +171,7 @@
|
|
|
171
171
|
]
|
|
172
172
|
],
|
|
173
173
|
"biological-architecture/no-raw-sql-outside-allowed": "error",
|
|
174
|
+
"biological-architecture/icon-control-has-name": "error",
|
|
174
175
|
"biological-architecture/no-react-namespace": "error",
|
|
175
176
|
"biological-architecture/no-runtime-dead-affordance": [
|
|
176
177
|
"error",
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// BREACH: a screen reader announces "button" and nothing else.
|
|
2
|
+
import { BinIcon } from '@kit/ui/atoms/icons/bin-icon'
|
|
3
|
+
|
|
4
|
+
export const RemoveLine = ({ onRemove }: { onRemove: () => void }): JSX.Element => (
|
|
5
|
+
<button type="button" onClick={onRemove}>
|
|
6
|
+
<BinIcon />
|
|
7
|
+
</button>
|
|
8
|
+
)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BinIcon } from '@kit/ui/atoms/icons/bin-icon'
|
|
2
|
+
|
|
3
|
+
export const RemoveLine = ({
|
|
4
|
+
label,
|
|
5
|
+
onRemove
|
|
6
|
+
}: {
|
|
7
|
+
label: string
|
|
8
|
+
onRemove: () => void
|
|
9
|
+
}): JSX.Element => (
|
|
10
|
+
<div>
|
|
11
|
+
<button type="button" onClick={onRemove} aria-label={label}>
|
|
12
|
+
<BinIcon />
|
|
13
|
+
</button>
|
|
14
|
+
<button type="button" onClick={onRemove}>
|
|
15
|
+
<BinIcon />
|
|
16
|
+
<span className="sr-only">{label}</span>
|
|
17
|
+
</button>
|
|
18
|
+
</div>
|
|
19
|
+
)
|
package/corpus/manifest.json
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"biological-architecture/effect-hook-naming",
|
|
17
17
|
"biological-architecture/emit-declares-attempts",
|
|
18
18
|
"biological-architecture/font-roles-only",
|
|
19
|
+
"biological-architecture/icon-control-has-name",
|
|
19
20
|
"biological-architecture/layer-walls",
|
|
20
21
|
"biological-architecture/list-take-without-order",
|
|
21
22
|
"biological-architecture/max-comment-density",
|
package/dist/discover-atoms.d.ts
CHANGED
|
@@ -17,12 +17,12 @@ interface RestrictedSyntaxEntry {
|
|
|
17
17
|
* for every native element wrapped by an atom. Apply these entries to
|
|
18
18
|
* molecules, compounds, cells, and tissues (NOT atoms themselves).
|
|
19
19
|
*/
|
|
20
|
-
declare function buildAtomRestrictions(atomsDir: string, importPathPrefix?: string): RestrictedSyntaxEntry[];
|
|
20
|
+
export declare function buildAtomRestrictions(atomsDir: string, importPathPrefix?: string): RestrictedSyntaxEntry[];
|
|
21
21
|
/**
|
|
22
22
|
* Build atom restrictions in the format expected by the no-raw-html-atoms rule.
|
|
23
23
|
* This replaces no-restricted-syntax for linters that don't support it (e.g. oxlint).
|
|
24
24
|
*/
|
|
25
|
-
declare function buildAtomRuleRestrictions(atomsDir: string, importPathPrefix?: string): AtomRestriction[];
|
|
25
|
+
export declare function buildAtomRuleRestrictions(atomsDir: string, importPathPrefix?: string): AtomRestriction[];
|
|
26
26
|
/**
|
|
27
27
|
* Scan the atoms directory and build a mapping from native HTML element
|
|
28
28
|
* to the atom that wraps it. This is used to generate no-restricted-syntax
|
|
@@ -33,7 +33,7 @@ declare function buildAtomRuleRestrictions(atomsDir: string, importPathPrefix?:
|
|
|
33
33
|
* exactly matches the element name is preferred as the canonical one.
|
|
34
34
|
* Variants are kept as alternatives in the error message.
|
|
35
35
|
*/
|
|
36
|
-
declare function scanAtomMappings(atomsDir: string): AtomMapping[];
|
|
36
|
+
export declare function scanAtomMappings(atomsDir: string): AtomMapping[];
|
|
37
37
|
/**
|
|
38
38
|
* The native element an atom wraps, read from the one place every atom says so: its props type.
|
|
39
39
|
*
|
|
@@ -46,6 +46,5 @@ declare function scanAtomMappings(atomsDir: string): AtomMapping[];
|
|
|
46
46
|
*
|
|
47
47
|
* The name is kept because consumers import it.
|
|
48
48
|
*/
|
|
49
|
-
declare function detectFirstNativeJsxElement(source: string): null | string;
|
|
50
|
-
|
|
51
|
-
export { buildAtomRestrictions, buildAtomRuleRestrictions, detectFirstNativeJsxElement, scanAtomMappings };
|
|
49
|
+
export declare function detectFirstNativeJsxElement(source: string): null | string;
|
|
50
|
+
export {};
|
package/dist/discover-atoms.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
stripComments
|
|
3
|
-
} from "./chunk-H7UQNDFE.js";
|
|
4
|
-
|
|
5
1
|
// src/discover-atoms.ts
|
|
6
|
-
import { readdirSync, readFileSync } from "fs";
|
|
7
|
-
import { basename, join } from "path";
|
|
8
|
-
|
|
9
|
-
var
|
|
2
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
3
|
+
import { basename, join } from "node:path";
|
|
4
|
+
import { stripComments } from "./rules/lib/module-text.js";
|
|
5
|
+
var GENERIC_ELEMENTS = new Set(["div", "span"]);
|
|
6
|
+
var HTML_ELEMENTS = new Set([
|
|
10
7
|
"a",
|
|
11
8
|
"abbr",
|
|
12
9
|
"address",
|
|
@@ -181,17 +178,22 @@ function buildAtomRuleRestrictions(atomsDir, importPathPrefix = "@kit/ui/atoms")
|
|
|
181
178
|
}
|
|
182
179
|
function scanAtomMappings(atomsDir) {
|
|
183
180
|
const entries = readdirSync(atomsDir, { withFileTypes: true });
|
|
184
|
-
const candidates =
|
|
181
|
+
const candidates = new Map;
|
|
185
182
|
for (const entry of entries) {
|
|
186
|
-
if (!entry.isFile())
|
|
187
|
-
|
|
188
|
-
if (
|
|
183
|
+
if (!entry.isFile())
|
|
184
|
+
continue;
|
|
185
|
+
if (!entry.name.endsWith(".tsx"))
|
|
186
|
+
continue;
|
|
187
|
+
if (NOT_AN_ATOM.test(entry.name))
|
|
188
|
+
continue;
|
|
189
189
|
const atomFile = entry.name;
|
|
190
190
|
const atomName = basename(atomFile, ".tsx");
|
|
191
191
|
const content = readFileSync(join(atomsDir, atomFile), "utf8");
|
|
192
192
|
const nativeElement = detectFirstNativeJsxElement(content);
|
|
193
|
-
if (!nativeElement)
|
|
194
|
-
|
|
193
|
+
if (!nativeElement)
|
|
194
|
+
continue;
|
|
195
|
+
if (GENERIC_ELEMENTS.has(nativeElement))
|
|
196
|
+
continue;
|
|
195
197
|
const existing = candidates.get(nativeElement) || [];
|
|
196
198
|
existing.push({ atomFile, atomName, nativeElement });
|
|
197
199
|
candidates.set(nativeElement, existing);
|
|
@@ -200,44 +202,51 @@ function scanAtomMappings(atomsDir) {
|
|
|
200
202
|
for (const [element, list] of candidates) {
|
|
201
203
|
const exact = list.find((m) => m.atomName === element);
|
|
202
204
|
const chosen = exact ?? list[0];
|
|
203
|
-
if (chosen)
|
|
205
|
+
if (chosen)
|
|
206
|
+
mappings.push(chosen);
|
|
204
207
|
}
|
|
205
208
|
return mappings;
|
|
206
209
|
}
|
|
207
210
|
function detectFirstNativeJsxElement(source) {
|
|
208
211
|
const withoutComments = stripComments(source);
|
|
209
212
|
const declared = elementFromPropsType(withoutComments);
|
|
210
|
-
if (declared)
|
|
213
|
+
if (declared)
|
|
214
|
+
return declared;
|
|
211
215
|
const slot = SLOT_FALLBACK.exec(withoutComments)?.[1];
|
|
212
|
-
if (slot && HTML_ELEMENTS.has(slot))
|
|
216
|
+
if (slot && HTML_ELEMENTS.has(slot))
|
|
217
|
+
return slot;
|
|
213
218
|
return elementFromJsx(withoutComments);
|
|
214
219
|
}
|
|
215
220
|
function elementFromPropsType(source) {
|
|
216
221
|
const found = [];
|
|
217
222
|
for (const match of source.matchAll(COMPONENT_PROPS)) {
|
|
218
223
|
const element = match[1];
|
|
219
|
-
if (element && HTML_ELEMENTS.has(element))
|
|
224
|
+
if (element && HTML_ELEMENTS.has(element))
|
|
225
|
+
found.push({ at: match.index, element });
|
|
220
226
|
}
|
|
221
227
|
for (const match of source.matchAll(HTML_ATTRIBUTES)) {
|
|
222
228
|
const element = elementOfAttributes(match[1], match[2]);
|
|
223
|
-
if (element)
|
|
229
|
+
if (element)
|
|
230
|
+
found.push({ at: match.index, element });
|
|
224
231
|
}
|
|
225
232
|
return found.toSorted((a, b) => a.at - b.at)[0]?.element ?? null;
|
|
226
233
|
}
|
|
227
234
|
function elementOfAttributes(prefix, domInterface) {
|
|
228
|
-
if (prefix !==
|
|
235
|
+
if (prefix !== undefined) {
|
|
229
236
|
const lower = prefix.toLowerCase();
|
|
230
237
|
const named = TAG_OF_ATTRIBUTES_PREFIX[lower] ?? lower;
|
|
231
|
-
if (HTML_ELEMENTS.has(named))
|
|
238
|
+
if (HTML_ELEMENTS.has(named))
|
|
239
|
+
return named;
|
|
232
240
|
}
|
|
233
|
-
const mapped = domInterface ===
|
|
234
|
-
return mapped !==
|
|
241
|
+
const mapped = domInterface === undefined ? undefined : TAG_OF_DOM_INTERFACE[domInterface];
|
|
242
|
+
return mapped !== undefined && HTML_ELEMENTS.has(mapped) ? mapped : null;
|
|
235
243
|
}
|
|
236
244
|
function elementFromJsx(withoutComments) {
|
|
237
245
|
const cleaned = withoutComments.replaceAll(/(["'`])(?:\\.|(?!\1)[^\\])*\1/g, '""');
|
|
238
246
|
for (const match of cleaned.matchAll(JSX_TAG)) {
|
|
239
247
|
const tag = match[1];
|
|
240
|
-
if (tag && HTML_ELEMENTS.has(tag))
|
|
248
|
+
if (tag && HTML_ELEMENTS.has(tag))
|
|
249
|
+
return tag;
|
|
241
250
|
}
|
|
242
251
|
return null;
|
|
243
252
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,52 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The file a rule says MUST fire it, given the options it was handed.
|
|
6
|
-
*
|
|
7
|
-
* `requireOption` closed one hole: an enabled rule with no option reports that, once a run,
|
|
8
|
-
* instead of reading as a clean tree. It leaves the next one open. A rule CONFIGURED with a repo's own
|
|
9
|
-
* vocabulary — its own brand, `packages/workflows/src/`, `@repo/db` — cannot be exercised by a corpus
|
|
10
|
-
* that ships fixtures saying `acme` and `corpus/workflows/`, so "fires nowhere" is what an
|
|
11
|
-
* adoption's doctor reports about a rule the repo is enforcing perfectly well. Both consumers filed
|
|
12
|
-
* exactly that on 2026-08-30, and both were right about the fact and wrong about whose defect it is.
|
|
13
|
-
*
|
|
14
|
-
* A probe is the answer the rule itself can give: hand it the options and it writes the smallest
|
|
15
|
-
* source that must fire it under THOSE options, at a path that lands where it looks. It is a claim,
|
|
16
|
-
* so it is tested through the real binary — a probe that does not fire is a rule that cannot be
|
|
17
|
-
* exercised, and the honest thing then is to say so rather than to widen the probe until it does.
|
|
18
|
-
*/
|
|
19
|
-
type Probe = {
|
|
20
|
-
/** Repo-root-relative, `/`-separated. It must satisfy every PATH option the rule reads. */
|
|
21
|
-
path: string;
|
|
22
|
-
source: string;
|
|
23
|
-
};
|
|
24
|
-
/**
|
|
25
|
-
* A probe that needs a TREE rather than a file.
|
|
26
|
-
*
|
|
27
|
-
* A rule that reads a sibling off disk — a registry, a schema's twin — cannot be exercised by one
|
|
28
|
-
* file however right its source is: `no-unregistered-plugin-dir` returns silently when the registry
|
|
29
|
-
* its options name is not there, so the single-file probe fired nothing and every consumer
|
|
30
|
-
* enforcing the rule over a real registry read as a permanent FAIL. The answer is not a widened
|
|
31
|
-
* probe, which would be the rule claiming evidence it does not have; it is a probe that may declare
|
|
32
|
-
* the sibling too, and a reader that mounts all of them.
|
|
33
|
-
*/
|
|
34
|
-
type ProbeTree = {
|
|
35
|
-
files: readonly Probe[];
|
|
36
|
-
};
|
|
37
|
-
type ProbeFn = (options: readonly unknown[]) => Probe | ProbeTree;
|
|
38
|
-
|
|
39
|
-
type RetiredRule = Rule & {
|
|
40
|
-
meta: Rule['meta'] & {
|
|
41
|
-
retired: {
|
|
42
|
-
reason: string;
|
|
43
|
-
since: string;
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
declare const RETIRED_RULES: Record<'document-sagas-are-generic' | 'documents-share-one-table', RetiredRule>;
|
|
48
|
-
|
|
49
|
-
type Rule = {
|
|
1
|
+
import type { ProbeFn } from './rules/lib/probe.js';
|
|
2
|
+
export type Rule = {
|
|
50
3
|
create: (context: never) => Record<string, unknown>;
|
|
51
4
|
fixShape: string;
|
|
52
5
|
meta: {
|
|
@@ -74,8 +27,9 @@ type Rule = {
|
|
|
74
27
|
packages: readonly string[];
|
|
75
28
|
};
|
|
76
29
|
};
|
|
77
|
-
declare const rules: Record<string, Rule>;
|
|
78
|
-
|
|
30
|
+
export declare const rules: Record<string, Rule>;
|
|
31
|
+
export { PRESETS, RENAMED_TO, rulesOfPreset } from './presets.js';
|
|
32
|
+
export type { Preset, PresetName } from './presets.js';
|
|
79
33
|
declare const plugin: {
|
|
80
34
|
configs: {
|
|
81
35
|
'backend-d1': {
|
|
@@ -96,7 +50,7 @@ declare const plugin: {
|
|
|
96
50
|
'backend-workflows-cf': {
|
|
97
51
|
rules: Record<string, "error">;
|
|
98
52
|
};
|
|
99
|
-
'comment-ceiling': Preset;
|
|
53
|
+
'comment-ceiling': import('./presets.js').Preset;
|
|
100
54
|
'failure-paths': {
|
|
101
55
|
rules: Record<string, "error">;
|
|
102
56
|
};
|
|
@@ -131,5 +85,4 @@ declare const plugin: {
|
|
|
131
85
|
};
|
|
132
86
|
rules: Record<string, Rule>;
|
|
133
87
|
};
|
|
134
|
-
|
|
135
|
-
export { Preset, RETIRED_RULES, type Rule, plugin as default, rules };
|
|
88
|
+
export default plugin;
|