You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/scripts/eidos-lint-all.ts

168 lines
5.0 KiB

eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
/**
* Lint every eidos component CSS against its morfo contract.
*
* Usage: npx tsx scripts/eidos-lint-all.ts
*
* Prints a per-component summary so the drift between eidos and the
* morfo declarations is visible at a glance.
*/
import { existsSync, readFileSync, readdirSync } from 'node:fs'
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
import { resolve } from 'node:path'
import { compileMorfo } from '../src/uix/morfo/compile'
import { lintEidosCss } from '../src/uix/eidos/lint'
import type { Morfo } from '../src/uix/morfo/types'
const EIDOS_ONLY_ATTRS = new Set([
'data-archetype',
'data-block',
'data-collapsed',
'data-combobox-control',
'data-color',
'data-columns',
'data-dragging',
'data-event',
'data-event-family',
'data-event-id',
'data-event-intent',
'data-event-phase',
'data-fitted',
'data-icon-only',
'data-indicator-placement',
'data-motion',
'data-motion-disabled',
'data-position',
'data-ready',
'data-scrollable',
'data-sheet',
'data-size',
'data-floating-wrapper',
'data-svg',
'data-svg-direction',
'data-variant'
])
const RUNTIME_SIGNAL_ATTRS = new Set([
'data-disabled',
'data-invalid',
'data-last-action',
'data-orientation',
'data-readonly',
'data-side',
'data-state'
])
const EIDOS_ONLY_PART_SUFFIXES = [
'footer',
'handle',
'header',
'indicator',
'label',
'main',
'row',
'row-label',
'status'
] as const
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
async function main() {
const eidosDir = resolve('src/uix/eidos/components')
const cssFiles = readdirSync(eidosDir, { withFileTypes: true }).flatMap((entry) => {
if (entry.isFile() && entry.name.endsWith('.css')) {
const name = entry.name.replace(/\.css$/, '')
return [{ name, path: resolve(eidosDir, entry.name) }]
}
if (entry.isDirectory()) {
const path = resolve(eidosDir, entry.name, `${entry.name}.css`)
return existsSync(path) ? [{ name: entry.name, path }] : []
}
return []
})
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
console.log('component morfo eidos invalid unused')
console.log('─────────────────────────────────────────────────────')
let totalInvalid = 0
let totalEidosOnly = 0
let totalUnused = 0
const driftHotspots: { name: string; eidosOnly: string[]; invalid: string[] }[] = []
for (const file of cssFiles) {
const name = file.name
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
const morfoPath = resolve(`src/uix/morfo/components/${name}.ts`)
try {
readFileSync(morfoPath)
} catch {
console.log(`${name.padEnd(22)}(no morfo file — skipped)`)
continue
}
const mod = (await import(`../src/uix/morfo/components/${name}`)) as Record<string, unknown>
const exportName = `${name.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase())}Morfo`
const morfo = mod[exportName] as Morfo | undefined
if (!morfo) {
console.log(`${name.padEnd(22)}(${exportName} not exported — skipped)`)
continue
}
const compiled = compileMorfo(morfo)
const partMarkers = new Set(Object.values(compiled.parts.attrs))
const css = readFileSync(file.path, 'utf-8')
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
const report = lintEidosCss(css, compiled)
console.log(
`${name.padEnd(22)}${String(report.counts.morfoBacked).padEnd(7)}${String(report.counts.eidosOnly).padEnd(7)}${String(report.counts.invalid).padEnd(9)}${report.unusedFromContract.length}`
)
totalInvalid += report.counts.invalid
totalEidosOnly += report.counts.eidosOnly
totalUnused += report.unusedFromContract.length
// Filter eidos-only that look like drift (data-* on a part where the morfo
// never declared the attr — vs design tokens like data-color/-size/-variant).
const drift = report.findings.filter(
(f) =>
f.status === 'eidos-only' &&
(f.eidosOnlyAttrs ?? f.attrs).some(
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
(a) =>
a.attr.startsWith('data-') &&
!partMarkers.has(a.attr) &&
!isAllowedEidosOnlyAttr(a.attr)
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
)
)
const invalid = report.findings.filter((f) => f.status === 'invalid')
if (drift.length || invalid.length) {
driftHotspots.push({
name,
eidosOnly: drift.map((f) => f.rule),
invalid: invalid.map((f) => `${f.rule} — ${f.reason}`)
})
}
}
console.log('─────────────────────────────────────────────────────')
console.log(`totals${' '.repeat(16)} ${totalEidosOnly} ${totalInvalid} ${totalUnused}`)
if (driftHotspots.length) {
console.log('\nDrift hotspots (eidos uses data-* attrs the morfo does not declare):')
for (const h of driftHotspots) {
if (!h.eidosOnly.length && !h.invalid.length) continue
console.log(`\n ${h.name}`)
for (const r of h.invalid) console.log(` ✗ ${r}`)
for (const r of h.eidosOnly) console.log(` · ${r}`)
}
} else {
console.log('\nNo drift hotspots beyond documented Eidos-only attrs/parts.')
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
}
if (totalInvalid > 0) process.exit(1)
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
}
function isAllowedEidosOnlyAttr(attr: string): boolean {
if (EIDOS_ONLY_ATTRS.has(attr)) return true
if (RUNTIME_SIGNAL_ATTRS.has(attr)) return true
return EIDOS_ONLY_PART_SUFFIXES.some((suffix) => attr.endsWith(`-${suffix}`))
}
eidos: lint a CSS file against its morfo contract Consumes `compileMorfo(morfo).contracts.cssSelectors` to classify every `[data-*]` selector in an eidos CSS file: - morfo-backed: the runtime writes the attr; eidos reacts to it. - eidos-only: the marker is present (`[data-toggle]`) but at least one `data-*` is not declared on the morfo part. Legitimate design tokens (`data-color`, `data-size`, `data-variant`) and drift cases (`data-dialog-header` — a part the morfo no longer declares) both land here; the lint tool reports them so authors can decide. - invalid: the attr IS declared on the morfo, but with a value outside the declared enum. Bug. Also reports `unusedFromContract`: selectors the compiler promises that no eidos rule consumes — the inverse direction of drift. Two CLI entry points: - `scripts/eidos-lint.ts <component>` — single-component report - `scripts/eidos-lint-all.ts` — sweep across every eidos component Initial sweep finds 0 invalid, 134 eidos-only, 82 unused contract selectors across 11 components. Real drift hotspots: dialog/drawer `header`/`footer` (eidos parts the morfos don't declare), popover's `data-side × data-last-action` compounds, tooltip's `data-state='delayed-open'`. Deliberate left as-is for the user to triage — fixes belong in a separate commit. Tests cover toggle (clean baseline), dialog (drift detector for header/footer + dead `data-disabled`), and a synthetic invalid case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
main().catch((err) => {
console.error(err)
process.exit(2)
})

Powered by TurnKey Linux.