@estiva-app/ui 0.57.3 → 0.58.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/dist/ContainerHeader.d.ts.map +1 -1
- package/dist/DialogShell.d.ts.map +1 -1
- package/dist/NavItem.d.ts.map +1 -1
- package/dist/Popover.d.ts +3 -2
- package/dist/Popover.d.ts.map +1 -1
- package/dist/SectionHeader.d.ts +7 -1
- package/dist/SectionHeader.d.ts.map +1 -1
- package/dist/ShowMore.d.ts +27 -0
- package/dist/ShowMore.d.ts.map +1 -0
- package/dist/SuggestionMenu.d.ts.map +1 -1
- package/dist/eslint/index.js +1 -0
- package/dist/eslint/index.js.map +2 -2
- package/dist/eslint/no-restyled-part.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +127 -89
- package/dist/index.js.map +4 -4
- package/dist/looks.d.ts +2 -0
- package/dist/looks.d.ts.map +1 -1
- package/package.json +1 -1
- package/registry.json +66 -4
- package/src/ComposerTriggers.test.tsx +3 -0
- package/src/ContainerHeader.mdx +1 -1
- package/src/ContainerHeader.tsx +3 -2
- package/src/DialogShell.tsx +2 -0
- package/src/ListColumn.mdx +1 -1
- package/src/NavItem.tsx +3 -2
- package/src/Popover.mdx +3 -1
- package/src/Popover.tsx +3 -2
- package/src/SectionHeader.mdx +6 -4
- package/src/SectionHeader.stories.tsx +7 -2
- package/src/SectionHeader.test.tsx +6 -0
- package/src/SectionHeader.tsx +10 -2
- package/src/ShowMore.mdx +62 -0
- package/src/ShowMore.stories.tsx +39 -0
- package/src/ShowMore.test.tsx +44 -0
- package/src/ShowMore.tsx +63 -0
- package/src/SuggestionMenu.tsx +2 -1
- package/src/eslint/no-restyled-part.ts +1 -0
- package/src/index.ts +1 -0
- package/src/looks.ts +3 -0
- package/src/registry/registry.test.ts +4 -4
- package/stories/Choosing.mdx +2 -1
package/dist/eslint/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/eslint/index.ts", "../../src/eslint/has-a-page-and-a-story.ts", "../../src/eslint/escape.ts", "../../src/eslint/no-hand-rolled-behaviour.ts", "../../src/eslint/no-handmade-empty-state.ts", "../../src/eslint/no-restyled-part.ts", "../../src/eslint/no-handmade-header.ts", "../../src/eslint/no-copied-look.ts", "../../src/eslint/looks-of.ts", "../../src/eslint/no-field-outside-a-form.ts", "../../src/eslint/no-native-title.ts", "../../src/eslint/no-raw-element.ts", "../../src/eslint/no-rebuilt-behaviour.ts", "../../src/eslint/raw-element-outside-a-wrapper.ts", "../../src/eslint/rule-ids.ts"],
|
|
4
|
-
"sourcesContent": ["/// <reference types=\"node\" />\n/**\n * `@estiva-app/ui/eslint` \u2014 the UI Guardrails' lint rules, as a plugin (UIG-3,\n * seam S1 in docs/GATES.md \u00A716).\n *\n * A plugin rather than config, so every app \u2014 Peek, Ship, Leaf \u2014 gets a new\n * rule through an ordinary version bump, and an app's editor hook runs the\n * very rule code its CI runs.\n *\n * import estiva from '@estiva-app/ui/eslint'\n * export default [{ files: ['src/**\\/*.tsx'], ...estiva.configs.recommended }]\n *\n * Register it under `estiva` (the configs do): the rule ids are\n * `estiva/<rule>`, and `countGates` counts those ids.\n *\n * Built on its own by build.mjs, for Node, into `dist/eslint/`; nothing here\n * reaches the components' browser bundle.\n */\nimport { createRequire } from 'node:module'\nimport type { ESLint, Linter } from 'eslint'\nimport { componentHasAPage, componentHasAStory } from './has-a-page-and-a-story'\nimport { noHandRolledBehaviour } from './no-hand-rolled-behaviour'\nimport { noHandmadeEmptyState } from './no-handmade-empty-state'\nimport { noHandmadeHeader } from './no-handmade-header'\nimport { noCopiedLook } from './no-copied-look'\nimport { noFieldOutsideAForm } from './no-field-outside-a-form'\nimport { noNativeTitle } from './no-native-title'\nimport { noRawElement } from './no-raw-element'\nimport { noRebuiltBehaviour } from './no-rebuilt-behaviour'\nimport { noRestyledPart } from './no-restyled-part'\nimport { rawElementOutsideAWrapper } from './raw-element-outside-a-wrapper'\nimport { APP_RULE_IDS, PLUGIN_KEY, type AppRuleName } from './rule-ids'\n\nexport { ESCAPE_MARKER, MIN_REASON, SETTINGS_KEY, isEscaped, type EstivaSettings } from './escape'\nexport { OWNED_BEHAVIOURS, type OwnedBehaviour } from './no-rebuilt-behaviour'\nexport { PART_LOOK_PROPS, PLACEMENT } from './no-restyled-part'\nexport { PARTS_WITH_A_TITLE } from './no-native-title'\nexport { MIN_COVER, MIN_SHARED } from './looks-of'\nexport { FIELD_PARTS } from './no-field-outside-a-form'\n\nconst { version } = createRequire(import.meta.url)('../../package.json') as { version: string }\n\nexport { APP_RULE_IDS, PLUGIN_KEY }\n\n/**\n * The rules an **app** runs: they say an app must not build what the package\n * already has \u2014 a raw control (UIG-7), or a behaviour one of its parts owns\n * (UIG-8) \u2014 nor restyle a part it uses (UIG-9). `recommended` and `strict`\n * carry these and only these. Their names live in `rule-ids.ts`, which\n * `create-estiva-app` reads without loading a rule; `satisfies` fails the\n * typecheck when a rule is missing from either.\n */\nconst appRules = {\n 'no-raw-element': noRawElement,\n 'no-rebuilt-behaviour': noRebuiltBehaviour,\n 'no-restyled-part': noRestyledPart,\n 'no-handmade-header': noHandmadeHeader,\n 'no-handmade-empty-state': noHandmadeEmptyState,\n 'no-native-title': noNativeTitle,\n 'no-copied-look': noCopiedLook,\n 'no-field-outside-a-form': noFieldOutsideAForm,\n} satisfies Record<AppRuleName, unknown>\n\n/**\n * The rules the **package itself** runs, pointed inward (UIG-5): don't bury a\n * raw element inside a component, don't rebuild what Base UI owns, don't ship a\n * component without a page or a story.\n *\n * They are in `configs.package`, never in `recommended`, on purpose. Peek and\n * Ship spread `recommended`, so a rule added here must not arrive in an app\n * with the next version bump: an app's components are not primitives, so\n * \"buried inside a component\" means nothing there (`no-raw-element` is the\n * app's version, UIG-7), and an app has no `.mdx` pages at all. `index.test.ts` holds the\n * apps' list to exactly the app rules.\n *\n * Five rules are in both sets: `no-restyled-part` (UIG-9), and the\n * fingerprints `no-handmade-header` (UIG-22), `no-handmade-empty-state`\n * (UIG-23), `no-native-title` (UIG-24) and `no-copied-look` (UIG-25, a\n * warning). The package restyles none of its own parts either (Katerina, 17\n * September), and \"my review isn't enough\" (23 September).\n */\nconst packageRules = {\n 'raw-element-outside-a-wrapper': rawElementOutsideAWrapper,\n 'no-hand-rolled-behaviour': noHandRolledBehaviour,\n 'component-has-a-page': componentHasAPage,\n 'component-has-a-story': componentHasAStory,\n 'no-restyled-part': noRestyledPart,\n 'no-handmade-header': noHandmadeHeader,\n 'no-handmade-empty-state': noHandmadeEmptyState,\n 'no-native-title': noNativeTitle,\n 'no-copied-look': noCopiedLook,\n}\n\nconst rules = { ...appRules, ...packageRules }\n\nconst plugin = {\n meta: { name: '@estiva-app/ui/eslint', version },\n rules,\n configs: {} as { recommended: Linter.Config; strict: Linter.Config; package: Linter.Config },\n} satisfies ESLint.Plugin\n\n/** The ids `package` carries \u2014 what this package's own gate runs and counts (UIG-5). */\nexport const PACKAGE_RULE_IDS = Object.keys(packageRules).map((name) => `${PLUGIN_KEY}/${name}`)\n\n/**\n * `recommended` switches every **app** rule on at the level it was ruled at: an\n * error blocks, a warning is reported and never blocks. `strict` makes every app\n * rule an error. They part at the first warning-level rule, `no-copied-look`\n * (UIG-25): `recommended` warns on it, `strict` blocks on it.\n *\n * `package` is the inward set (UIG-5), which only this package runs.\n */\nplugin.configs.recommended = {\n name: '@estiva-app/ui/recommended',\n plugins: { [PLUGIN_KEY]: plugin },\n rules: {\n [`${PLUGIN_KEY}/no-raw-element`]: 'error',\n [`${PLUGIN_KEY}/no-rebuilt-behaviour`]: 'error',\n [`${PLUGIN_KEY}/no-restyled-part`]: 'error',\n [`${PLUGIN_KEY}/no-handmade-header`]: 'error',\n [`${PLUGIN_KEY}/no-handmade-empty-state`]: 'error',\n [`${PLUGIN_KEY}/no-native-title`]: 'error',\n // A warning, never an error (Katerina, 13 September): likeness is a judgement.\n [`${PLUGIN_KEY}/no-copied-look`]: 'warn',\n [`${PLUGIN_KEY}/no-field-outside-a-form`]: 'error',\n },\n}\nplugin.configs.strict = {\n name: '@estiva-app/ui/strict',\n plugins: { [PLUGIN_KEY]: plugin },\n rules: Object.fromEntries(APP_RULE_IDS.map((id) => [id, 'error'])),\n}\nplugin.configs.package = {\n name: '@estiva-app/ui/package',\n plugins: { [PLUGIN_KEY]: plugin },\n // Every inward rule blocks, but the copied look, which warns here too (UIG-25).\n rules: Object.fromEntries(PACKAGE_RULE_IDS.map((id) => [id, id === `${PLUGIN_KEY}/no-copied-look` ? 'warn' : 'error'])),\n}\n\nexport default plugin\n\nexport interface GateRuleCount {\n errors: number\n warnings: number\n escapes: number\n}\n\nexport interface GateCount {\n /** Per rule id, including rules with nothing to report. */\n rules: Record<string, GateRuleCount>\n /**\n * Reports of these rules that an `eslint-disable` directive silenced. Not\n * an escape: a gate fails on any of these (docs/GATES.md \u00A716, S4).\n */\n disabled: { filePath: string; line: number; ruleId: string }[]\n}\n\n/**\n * Count what a lint of these rules found, for `.gates-count.json` (seam S3).\n *\n * Run the lint with `settings: { estiva: { reportEscapes: true } }` for the\n * escapes to be counted; without it they are silent and count 0. A marker\n * with no reason, or inside a directive, counts as an error of its rule.\n *\n * `seed` is which rules the count lists when they found nothing, and it is the\n * app rules unless a caller says otherwise: an app's count file must not gain\n * rows for the inward rules (UIG-5) that its gate does not run. This package's\n * own count script passes `PACKAGE_RULE_IDS`.\n */\nexport function countGates(results: ESLint.LintResult[], seed: readonly string[] = APP_RULE_IDS): GateCount {\n const counts: Record<string, GateRuleCount> = Object.fromEntries(seed.map((id) => [id, { errors: 0, warnings: 0, escapes: 0 }]))\n const disabled: GateCount['disabled'] = []\n const ours = (ruleId: string | null | undefined): ruleId is string => typeof ruleId === 'string' && ruleId.startsWith(`${PLUGIN_KEY}/`)\n for (const result of results) {\n for (const message of result.messages) {\n // Seeded or not: every rule of this plugin that reported is counted, so a\n // lint of a set the caller did not name is still counted in full.\n if (!ours(message.ruleId)) continue\n const count = (counts[message.ruleId] ??= { errors: 0, warnings: 0, escapes: 0 })\n if (message.messageId === 'escaped') count.escapes += 1\n else if (message.severity === 2) count.errors += 1\n else count.warnings += 1\n }\n for (const message of result.suppressedMessages ?? []) {\n if (ours(message.ruleId)) disabled.push({ filePath: result.filePath, line: message.line, ruleId: message.ruleId })\n }\n }\n return { rules: counts, disabled }\n}\n", "import { existsSync } from 'node:fs'\nimport type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\n/**\n * A component of the package with no page, and one with no story (UIG-5, P2 and\n * P3).\n *\n * A component nobody can read about is a component nobody uses correctly, and\n * one nobody can look at is one nobody reviews. Both were at zero when these\n * were switched on; they are here so the next component cannot arrive without\n * them.\n *\n * The pair is by file name, beside the component, which is how this package is\n * laid out: `Button.tsx`, `Button.mdx`, `Button.stories.tsx`, `Button.test.tsx`\n * side by side in `src/`.\n *\n * **The false positive to avoid** (UIG-1 confirmed it is real): `FieldLine` and\n * `MenuItem` have a page and a story but no `.tsx` of their own \u2014 they are\n * exported from a sibling. These rules read a component file and ask for its\n * page and its story, never the other way round, so a page without a component\n * is not this rule's business.\n *\n * A file that stays without one says why at its top: `// @estiva-escape: <why>`.\n */\ninterface ProgramNode {\n body: { loc?: Rule.Node['loc']; range?: [number, number] }[]\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n}\n\n/** A component file: a `.tsx` in the package's source that is not a story or a test. */\nfunction componentFile(filename: string): boolean {\n return filename.endsWith('.tsx') && !/\\.(stories|test)\\.tsx$/.test(filename)\n}\n\nfunction sibling(filename: string, extension: string): string {\n return filename.replace(/\\.tsx$/, extension)\n}\n\n/**\n * Report on the file's first statement, so the escape is a comment at the top of\n * the file \u2014 the only place a reason for a missing page could go.\n */\nfunction reportOnFile(context: Rule.RuleContext, program: ProgramNode, messageId: string, data: Record<string, string>): void {\n const anchor = program.body[0] ?? program\n if (anchor.loc && anchor.range && isEscaped(context, { loc: anchor.loc, range: anchor.range })) return\n context.report({ loc: anchor.loc ?? program.loc, messageId, data })\n}\n\nexport const componentHasAPage: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'Every component of the package has a usage page beside it' },\n schema: [],\n messages: {\n missing: '{{name}} has no page. Write {{page}} beside it \u2014 what it is, when, when not, how, and what it owns \u2014 or say why not at the top of the file.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n return {\n Program(node) {\n const filename = context.filename\n if (!componentFile(filename)) return\n const page = sibling(filename, '.mdx')\n if (existsSync(page)) return\n const name = filename.split(/[\\\\/]/).pop() ?? filename\n reportOnFile(context, node as unknown as ProgramNode, 'missing', { name, page: page.split(/[\\\\/]/).pop() ?? page })\n },\n }\n },\n}\n\nexport const componentHasAStory: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'Every component of the package has a story beside it' },\n schema: [],\n messages: {\n missing: '{{name}} has no story. Write {{story}} beside it, so it can be seen and reviewed, or say why not at the top of the file.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n return {\n Program(node) {\n const filename = context.filename\n if (!componentFile(filename)) return\n const story = sibling(filename, '.stories.tsx')\n if (existsSync(story)) return\n const name = filename.split(/[\\\\/]/).pop() ?? filename\n reportOnFile(context, node as unknown as ProgramNode, 'missing', { name, story: story.split(/[\\\\/]/).pop() ?? story })\n },\n }\n },\n}\n", "import type { AST, Rule } from 'eslint'\n\n/**\n * The escape marker (UIG-3, seam S4 in docs/GATES.md \u00A716): one written reason\n * why one element stays as it is.\n *\n * A line comment directly above the element, naming the rule it keeps off,\n *\n * // @estiva-escape(no-raw-element): <reason>\n *\n * or, where the element is a JSX child, the JSX comment on the line above,\n *\n * {/* @estiva-escape(no-raw-element): <reason> *\\/}\n *\n * with at least ten characters of reason, spaces not counted. It escapes only\n * the rules it names (Katerina's ruling B3, 25 September: one reason used to\n * switch off every rule on the element, so a raw button that also wrote a\n * dialog's role by hand passed under one reason). Two rules on one element are\n * named together, `@estiva-escape(no-raw-element, no-rebuilt-behaviour)`, each\n * on purpose. A marker that names no rule escapes nothing, and says which name\n * to write.\n *\n * Not `eslint-disable`. A directive switches a rule off without saying it was\n * meant, and the count of escapes (`.gates-count.json`) could not see it. A\n * marker written inside a directive that switches one of these rules off is\n * reported for that reason.\n *\n * The token lint's older notes (`eslint-disable-next-line <rule> -- @estiva-escape:\n * <reason>`, Katerina's ruling A2 of 15 September) are not read here: they\n * escape the token lint's rules, which are not this plugin's, and they stay as\n * they are (Katerina, 15 September).\n */\nexport const ESCAPE_MARKER = '@estiva-escape'\n\n/** Characters of reason, spaces not counted. */\nexport const MIN_REASON = 10\n\n/** The key under ESLint's `settings` this plugin reads. */\nexport const SETTINGS_KEY = 'estiva'\n\n/**\n * Every rule spreads these into its `meta.messages`, because `isEscaped`\n * reports through the rule that called it.\n */\nexport const ESCAPE_MESSAGES = {\n escapeWithoutReason: `An escape needs its reason, at least ${MIN_REASON} characters: \\`// ${ESCAPE_MARKER}({{rule}}): <why this stays>\\`. An escape with no reason hides nothing.`,\n escapeInDirective: `Write the escape as its own comment on the line above: \\`// ${ESCAPE_MARKER}({{rule}}): <reason>\\`. Inside an eslint-disable comment it switches the rule off instead of recording why.`,\n escapeWithoutRule: `Name the rule this escape keeps off: \\`${ESCAPE_MARKER}({{rule}}): <reason>\\`. An escape now keeps off only the rules it names.`,\n escaped: 'Escaped: {{reason}}',\n} as const\n\n/** A rule's name as a marker writes it: `no-raw-element` for `estiva/no-raw-element`. */\nexport const shortRuleName = (id: string) => id.slice(id.lastIndexOf('/') + 1)\n\n/**\n * What a marker says, read from a comment's text: the rules it names (none when\n * it names none) and its reason. Null when the comment carries no marker.\n */\nexport function readMarker(text: string): { rules: string[]; reason: string } | null {\n const at = text.indexOf(ESCAPE_MARKER)\n if (at === -1) return null\n const rest = text.slice(at + ESCAPE_MARKER.length)\n const named = /^\\s*\\(([^)]*)\\)/.exec(rest)\n const rules = named ? named[1].split(/[\\s,]+/).filter(Boolean).map(shortRuleName) : []\n const reason = (named ? rest.slice(named[0].length) : rest).replace(/^\\s*:/, '').trim()\n return { rules, reason }\n}\n\nexport interface EstivaSettings {\n /**\n * Report every sanctioned escape as a message with the id `escaped`, so a\n * count can read them. Off in the lint anyone runs; on only in the count.\n */\n reportEscapes?: boolean\n}\n\ninterface Located {\n loc?: AST.SourceLocation | null\n range?: [number, number]\n}\n\nconst DIRECTIVE = /^\\s*eslint-disable(?:-next-line|-line)?(?=\\s|$)([^]*)$/\n\n/** The rules a directive names: what comes before its ` -- ` description. None means every rule. */\nfunction directiveRules(rest: string): string[] {\n const dashes = rest.search(/(?:^|\\s)--(?:\\s|$)/)\n return (dashes === -1 ? rest : rest.slice(0, dashes)).split(/[\\s,]+/).filter(Boolean)\n}\n\n/** Only spaces and a JSX expression's closing brace between the marker and the element. */\nconst BETWEEN = /^[\\s}]*$/\n\n/**\n * Whether the element at `node` carries a valid escape on the line above.\n *\n * Every rule of this plugin calls it before it reports. It reports, through\n * that rule, a marker with too short a reason and a marker inside an\n * eslint-disable directive for this rule; either way the element is not\n * escaped, so the rule reports it too.\n */\nexport function isEscaped(context: Rule.RuleContext, node: Located): boolean {\n const { sourceCode } = context\n if (!node.loc || !node.range) return false\n const line = node.loc.start.line\n const nodeStart = node.range[0]\n\n const comment = sourceCode\n .getAllComments()\n .find((c) => c.loc && c.range && c.loc.end.line === line - 1 && BETWEEN.test(sourceCode.text.slice(c.range[1], nodeStart)))\n if (!comment?.loc) return false\n\n const marker = readMarker(comment.value)\n if (!marker) return false\n const rule = shortRuleName(context.id)\n\n const directive = DIRECTIVE.exec(comment.value)\n if (directive) {\n const rules = directiveRules(directive[1])\n // A directive for other rules (the token lint's notes) is not an escape of this one.\n if (rules.length > 0 && !rules.includes(context.id)) return false\n context.report({ loc: comment.loc, messageId: 'escapeInDirective', data: { rule } })\n return false\n }\n\n // Named, but not this rule: another rule on the element may be the one it keeps off.\n if (marker.rules.length > 0 && !marker.rules.includes(rule)) return false\n if (marker.rules.length === 0) {\n context.report({ loc: comment.loc, messageId: 'escapeWithoutRule', data: { rule } })\n return false\n }\n\n const { reason } = marker\n if (reason.replace(/\\s/g, '').length < MIN_REASON) {\n context.report({ loc: comment.loc, messageId: 'escapeWithoutReason', data: { rule } })\n return false\n }\n\n const settings = context.settings[SETTINGS_KEY] as EstivaSettings | undefined\n if (settings?.reportEscapes) context.report({ loc: comment.loc, messageId: 'escaped', data: { reason } })\n return true\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\n/**\n * Behaviour Base UI already owns, written by hand inside the package (UIG-5,\n * P1 \u2014 the migration's standing rule D6 as a machine).\n *\n * This is the rule with the most to lose. A hand-made portal or a global\n * listener inside `DialogShell` is inherited by every caller in every app, and\n * nobody sees it from there.\n *\n * Two facts, both mechanical, both the signature of a floating part rebuilt by\n * hand:\n *\n * - **`createPortal`**, or importing it from `react-dom`. Base UI's parts carry\n * their own portal.\n * - **a listener on `window` or `document`** for the events a floating part\n * lives on \u2014 resize, scroll, an outside press, a key. Base UI's Positioner\n * follows the anchor and its Root closes on an outside press and on Escape.\n *\n * What it deliberately does not try to read: measuring arithmetic. `Popover`\n * hands Base UI a virtual anchor with a `getBoundingClientRect`, which is the\n * documented way to anchor to a rectangle rather than an element, and a rule\n * that guessed at arithmetic would report it. Anything that shape is caught by\n * a reader, not by this.\n *\n * A place that keeps one says why on the line above: `// @estiva-escape: <why>`.\n */\nconst FLOATING_EVENTS = new Set(['resize', 'scroll', 'mousedown', 'pointerdown', 'keydown', 'keyup', 'focusin', 'focusout', 'click'])\n\ninterface Node {\n type: string\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n}\n\ninterface Identifier extends Node {\n name: string\n}\n\ninterface ImportDeclaration extends Node {\n source: { value: unknown }\n specifiers: { type: string; imported?: { name?: string }; local?: { name?: string }; loc?: Rule.Node['loc']; range?: [number, number] }[]\n}\n\ninterface CallExpression extends Node {\n callee: { type: string; name?: string; object?: { type: string; name?: string }; property?: { type: string; name?: string } }\n arguments: { type: string; value?: unknown }[]\n parent?: { type: string; loc?: Rule.Node['loc']; range?: [number, number]; parent?: CallExpression['parent'] }\n}\n\n/**\n * The statement a call sits in, which is what an escape is written above:\n * `return createPortal(\u2026)` puts the call in the middle of its line, and a\n * comment above the line is above the statement.\n */\nfunction statement(node: { loc: NonNullable<Rule.Node['loc']>; range: [number, number]; parent?: CallExpression['parent'] }): {\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n} {\n for (let p = node.parent; p; p = p.parent) {\n if (!/(Statement|Declaration)$/.test(p.type)) continue\n if (p.loc && p.range) return { loc: p.loc, range: p.range }\n break\n }\n return { loc: node.loc, range: node.range }\n}\n\nexport const noHandRolledBehaviour: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'Overlay behaviour written by hand where Base UI has a part (D6)' },\n schema: [],\n messages: {\n portal:\n 'A portal written by hand. Base UI\\'s parts carry their own (Popover, Menu, Select, Tooltip, Dialog, Toast): use the part, or say why this one stays.',\n listener:\n 'A `{{event}}` listener on `{{target}}`. A floating part follows its anchor and closes on an outside press and on Escape by itself (Base UI Positioner and Root): use the part, or say why this one stays.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n return {\n ImportDeclaration(node: Rule.Node) {\n const declaration = node as unknown as ImportDeclaration\n if (declaration.source.value !== 'react-dom') return\n for (const specifier of declaration.specifiers) {\n if (specifier.type !== 'ImportSpecifier' || specifier.imported?.name !== 'createPortal') continue\n // The escape goes above the import line, not above the name inside it.\n if (isEscaped(context, declaration)) return\n context.report({ loc: declaration.loc, messageId: 'portal' })\n return\n }\n },\n CallExpression(node: Rule.Node) {\n const call = node as unknown as CallExpression\n const { callee } = call\n\n if (callee.type === 'Identifier' && callee.name === 'createPortal') {\n if (isEscaped(context, statement(call))) return\n context.report({ loc: call.loc, messageId: 'portal' })\n return\n }\n\n if (callee.type !== 'MemberExpression' || callee.property?.name !== 'addEventListener') return\n const target = callee.object?.type === 'Identifier' ? callee.object.name : undefined\n if (target !== 'window' && target !== 'document') return\n const [first] = call.arguments\n const event = first?.type === 'Literal' && typeof first.value === 'string' ? first.value : undefined\n if (!event || !FLOATING_EVENTS.has(event)) return\n if (isEscaped(context, statement(call))) return\n context.report({ loc: call.loc, messageId: 'listener', data: { event, target } })\n },\n }\n },\n}\n", "import { statSync } from 'node:fs'\nimport type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\nimport {\n bindingOfTag,\n classesOf,\n functionComponents,\n parseFile,\n partsOfFile,\n resolveModule,\n walk,\n type Node,\n type Parser,\n type PartBinding,\n} from './no-restyled-part'\n\ntype Locals = Map<string, PartBinding | 'namespace'>\n\nconst child = (node: Node, key: string) => node[key] as Node | null | undefined\nconst children = (node: Node, key: string) => ((node[key] as (Node | null)[] | undefined) ?? []).filter((n): n is Node => !!n)\nconst nameOf = (node: Node | null | undefined): string | undefined =>\n node?.type === 'Identifier' || node?.type === 'JSXIdentifier' ? (node.name as string) : undefined\nconst tagName = (element: Node) => nameOf(child(child(element, 'openingElement') as Node, 'name'))\n/**\n * Whether a name is the part itself: imported, re-exported, or an app wrapper\n * that hands everything on (Peek's `EmptyState`). A component that only hands\n * its `className` to one (Ship's `Activity`) is the app's own, and is followed.\n */\nconst isPart = (binding: PartBinding | undefined, part: string) => binding?.part === part && binding.props === 'all'\nconst attributeOf = (opening: Node, name: string) => children(opening, 'attributes').find((a) => a.type === 'JSXAttribute' && nameOf(child(a, 'name')) === name)\n\n// ---------------------------------------------------------------- shape 1: a line drawn by hand\n\n/**\n * An empty state is a line, not a paragraph of prose. The words are not read:\n * UIG-1's pass on words alone fired on a hint and a status note, and words\n * missed four of Peek's dialogs (\"There is nowhere else to move it\u2026\", \"Every\n * topic is already in your Open work.\"). Where the line sits decides.\n */\nconst SHORT = 120\n\n/**\n * The element's words, when words are all it holds: text, a string, a name\n * dropped into a sentence (\"There is nowhere else in {teamName} to put it.\").\n * A line with no words of its own \u2014 a count, a message's body \u2014 is not one.\n */\nfunction onlyWords(element: Node): string | undefined {\n let line = ''\n let own = ''\n for (const kid of children(element, 'children')) {\n let piece: string\n if (kid.type === 'JSXText') piece = String(kid.value)\n else if (kid.type === 'JSXExpressionContainer') {\n const e = child(kid, 'expression') as Node\n if (e.type === 'JSXEmptyExpression') continue\n if (e.type === 'Literal' && typeof e.value === 'string') piece = e.value\n else if (e.type === 'TemplateLiteral' && children(e, 'expressions').length === 0) piece = children(e, 'quasis').map((q) => (q.value as { cooked: string }).cooked).join('')\n else if (e.type === 'Identifier' || e.type === 'MemberExpression') {\n line += 'x'\n continue\n } else return undefined\n } else return undefined\n own += piece\n line += piece\n }\n if (!/[a-z]{2,}/i.test(own)) return undefined\n return line.replace(/\\s+/g, ' ').trim()\n}\n\nconst isCount = (node: Node | null | undefined): boolean => {\n if (node?.type === 'ChainExpression') return isCount(child(node, 'expression'))\n return node?.type === 'MemberExpression' && !node.computed && /^(?:length|size)$/.test(nameOf(child(node, 'property')) ?? '')\n}\nconst isNumber = (node: Node | null | undefined, n: number) => node?.type === 'Literal' && node.value === n\n\n/**\n * What a condition says about a list: `empty` when it is true for an empty one\n * (`rows.length === 0`, `!rows.length`, `isEmpty(rows)`), `full` when it is\n * true for a list with rows (`rows.length > 0`, `rows.length`), nothing when it\n * does not ask. `a && b` says what either side says.\n */\nfunction whenTrue(test: Node | null | undefined): 'empty' | 'full' | undefined {\n if (!test) return undefined\n if (isCount(test)) return 'full'\n switch (test.type) {\n case 'UnaryExpression': {\n if (test.operator !== '!') return undefined\n const inner = whenTrue(child(test, 'argument'))\n return inner === 'empty' ? 'full' : inner === 'full' ? 'empty' : undefined\n }\n case 'LogicalExpression':\n if (test.operator !== '&&') return undefined\n return whenTrue(child(test, 'left')) ?? whenTrue(child(test, 'right'))\n case 'BinaryExpression': {\n let [count, other, op] = [child(test, 'left'), child(test, 'right'), String(test.operator)]\n if (!isCount(count)) [count, other, op] = [other, count, ({ '<': '>', '>': '<', '<=': '>=', '>=': '<=' } as Record<string, string>)[op] ?? op]\n if (!isCount(count)) return undefined\n if (isNumber(other, 0)) return op === '===' || op === '==' || op === '<=' ? 'empty' : op === '>' || op === '!==' || op === '!=' ? 'full' : undefined\n if (isNumber(other, 1)) return op === '<' ? 'empty' : op === '>=' ? 'full' : undefined\n return undefined\n }\n case 'CallExpression': {\n const callee = child(test, 'callee')\n const name = callee?.type === 'MemberExpression' ? nameOf(child(callee, 'property')) : nameOf(callee)\n return name && /^is(?:Empty|Blank)$/.test(name) ? 'empty' : undefined\n }\n default:\n return undefined\n }\n}\n\nconst isMapCall = (node: Node | null | undefined) => {\n const callee = node?.type === 'CallExpression' ? child(node, 'callee') : undefined\n return callee?.type === 'MemberExpression' && nameOf(child(callee, 'property')) === 'map'\n}\n\n/**\n * Whether a branch **is** a list: a `.map(\u2026)`, or a box that holds only that \u2014\n * `<ul>{rows.map(\u2026)}</ul>`. A branch that shows something else and lists a few\n * things inside it (an answer with its sources) is not the list the line stands\n * in for.\n */\nfunction isAList(branch: Node | null | undefined, depth = 0): boolean {\n if (!branch || depth > 2) return false\n if (isMapCall(branch)) return true\n if (branch.type !== 'JSXElement' && branch.type !== 'JSXFragment') return false\n if (branch.type === 'JSXElement' && !/^[a-z]/.test(tagName(branch) ?? '')) return false\n const kids = children(branch, 'children').filter((k) => !(k.type === 'JSXText' && !String(k.value).trim()) && !(k.type === 'JSXExpressionContainer' && (child(k, 'expression') as Node).type === 'JSXEmptyExpression'))\n return kids.length === 1 && (kids[0].type === 'JSXExpressionContainer' ? isMapCall(child(kids[0], 'expression')) : isAList(kids[0], depth + 1))\n}\n\n/** A box around one thing and nothing else: a wrapper that pads or places the line. */\nfunction soleChildOf(parent: Node | undefined, element: Node): boolean {\n if (parent?.type !== 'JSXElement' || !/^[a-z]/.test(tagName(parent) ?? '')) return false\n const kids = children(parent, 'children').filter((k) => !(k.type === 'JSXText' && !String(k.value).trim()) && !(k.type === 'JSXExpressionContainer' && (child(k, 'expression') as Node).type === 'JSXEmptyExpression'))\n return kids.length === 1 && kids[0] === element\n}\n\n/**\n * Whether the element stands where a list's rows would be: one side of a\n * condition whose other side maps a list, or under a condition that asks if\n * something is empty \u2014 `cond && \u2026`, `cond ? \u2026 : \u2026`, `if (cond) return \u2026`.\n */\nfunction standsInForAList(element: Node): boolean {\n let at = element\n for (let depth = 0; depth < 3 && soleChildOf(at.parent, at); depth += 1) at = at.parent as Node\n const parent = at.parent\n if (!parent) return false\n if (parent.type === 'ConditionalExpression' && parent.test !== at) {\n const consequent = parent.consequent === at\n const other = child(parent, consequent ? 'alternate' : 'consequent')\n return whenTrue(child(parent, 'test')) === (consequent ? 'empty' : 'full') || isAList(other)\n }\n if (parent.type === 'LogicalExpression' && parent.operator === '&&' && parent.right === at) return whenTrue(child(parent, 'left')) === 'empty'\n if (parent.type === 'ReturnStatement') {\n let holder = parent.parent\n if (holder?.type === 'BlockStatement' && children(holder, 'body').length === 1) holder = holder.parent\n return holder?.type === 'IfStatement' && child(holder, 'consequent') !== undefined && whenTrue(child(holder, 'test')) === 'empty'\n }\n return false\n}\n\n// ---------------------------------------------------------------- shape 2: the right part at the wrong scope\n\n/** A content box that fills its viewport: `min-h-full` or `h-full` on `contentClassName`. */\nconst FILLS = /^(?:min-h-full|h-full)$/\n\n/** What a box does that a page-scope EmptyState already does itself: centre, or leave room round it. */\nconst CENTRES = /^(?:justify-center|items-center|content-center|place-(?:items|content)-center)$/\nconst PADS = /^p[xytrblse]?-/\n\n/** The only element a box holds, when it holds one and nothing else but blank space. */\nfunction onlyElement(box: Node): Node | undefined {\n const kids = children(box, 'children').filter((kid) => !(kid.type === 'JSXText' && !String(kid.value).trim()))\n return kids.length === 1 && kids[0].type === 'JSXElement' ? kids[0] : undefined\n}\n\nfunction isPageScope(opening: Node): boolean {\n const scope = attributeOf(opening, 'scope')\n if (!scope) return true\n const value = child(scope, 'value')\n return value?.type === 'Literal' && value.value === 'page'\n}\n\ninterface FileFacts {\n file: string\n locals: Locals\n components: Map<string, Node>\n /** A local name imported from the app's own files: where from, and under what name. */\n imports: Map<string, { file: string; name: string }>\n}\n\nconst factsCache = new Map<string, { mtime: number; facts: FileFacts | null }>()\n\nfunction factsOf(file: string, program: Node, parser: Parser): FileFacts {\n const imports = new Map<string, { file: string; name: string }>()\n for (const statement of children(program, 'body')) {\n if (statement.type !== 'ImportDeclaration' || statement.importKind === 'type') continue\n const target = resolveModule(file, String((child(statement, 'source') as Node).value))\n if (!target) continue\n for (const specifier of children(statement, 'specifiers')) {\n if (specifier.type !== 'ImportSpecifier' || specifier.importKind === 'type') continue\n const local = nameOf(child(specifier, 'local'))\n const imported = nameOf(child(specifier, 'imported'))\n if (local && imported) imports.set(local, { file: target, name: imported })\n }\n }\n return { file, locals: partsOfFile(file, program, parser), components: functionComponents(program), imports }\n}\n\nfunction factsOfFile(file: string, parser: Parser): FileFacts | null {\n const mtime = statSync(file).mtimeMs\n const cached = factsCache.get(file)\n if (cached && cached.mtime === mtime) return cached.facts\n factsCache.set(file, { mtime, facts: null })\n const program = parseFile(parser, file)\n const facts = program ? factsOf(file, program, parser) : null\n factsCache.set(file, { mtime, facts })\n return facts\n}\n\ninterface PageState {\n file: string\n line: number\n}\n\n/**\n * Every page-scope `EmptyState` a component can draw, following the app's own\n * components it draws in turn, in its file and in the files it imports from,\n * four deep.\n */\nfunction pageStatesOf(facts: FileFacts, name: string, parser: Parser, depth: number, seen: Set<string>): PageState[] {\n const key = `${facts.file}#${name}`\n if (depth > 4 || seen.has(key)) return []\n seen.add(key)\n const local = facts.components.get(name)\n if (!local) {\n const from = facts.imports.get(name)\n const there = from ? factsOfFile(from.file, parser) : null\n return there && from ? pageStatesOf(there, from.name, parser, depth + 1, seen) : []\n }\n const found: PageState[] = []\n walk(local, (node) => {\n if (node.type !== 'JSXOpeningElement') return\n const tag = child(node, 'name')\n const binding = bindingOfTag(tag, facts.locals)\n if (isPart(binding, 'EmptyState')) {\n if (isPageScope(node)) found.push({ file: facts.file, line: node.loc?.start.line ?? 0 })\n return\n }\n const component = binding?.props === 'all' ? undefined : nameOf(tag)\n if (component && /^[A-Z]/.test(component)) found.push(...pageStatesOf(facts, component, parser, depth + 1, seen))\n })\n return found\n}\n\nconst fileName = (file: string) => file.replace(/\\\\/g, '/').split('/').pop()\n\n/**\n * UIG-23: an empty state drawn by hand, or the right part at the wrong scope.\n *\n * **A line drawn by hand.** A plain box whose only content is a short line\n * saying there is nothing (\"No tickets yet.\") where a list's rows would be: one\n * side of a condition whose other side maps the list, or under a condition that\n * asks if something is empty. Both halves are needed. The words alone fire on a\n * hint and a status note (UIG-1 measured it); the place alone fires on any\n * line a list shows beside itself.\n *\n * **The wrong scope.** A `page`-scope `EmptyState` centres in the room a flex\n * column gives it. Inside a `ScrollArea` the content box is only as tall as\n * what is in it, so the state sits at the top of its pane. The rule looks at\n * the `ScrollArea`'s content and at every component of the app's own placed in\n * it, following them into their files, because that is how four of them\n * arrived on Folders in one merge (peek `7f22e5e`): the state was drawn in one\n * file and scrolled in another. A `contentClassName` with `min-h-full` or\n * `h-full` gives the state its room, and passes.\n *\n * **A box that places it** (UIG-42). A plain box holding only a page-scope\n * `EmptyState` and centring or padding it does the part's own job, and a box\n * like that pinned the starter's home page 64px from the top (UIG-10). A box\n * that is only the flex column the state asks for passes, and so does any box\n * round a `section` state, which takes its inset from the box (Katerina, 14\n * September).\n *\n * Not judged: the package's `EmptyState` and a part's own lines (a\n * `FieldLine`, a palette's empty row) \u2014 a part is already a part.\n */\nexport const noHandmadeEmptyState: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'An empty state drawn by hand, or a page-scope EmptyState that cannot centre' },\n schema: [],\n messages: {\n handmade:\n 'A line saying there is nothing is an EmptyState. Use `EmptyState` from @estiva-app/ui: `scope=\"section\"` inside a section, `scope=\"page\"` for a whole page.',\n wrongScope:\n 'A page-scope EmptyState inside a ScrollArea sits at the top of its pane, not the middle: the ScrollArea\\'s content is only as tall as what is in it. Use `scope=\"section\"` when the pane has anything else on it; when the whole pane is empty, draw the page EmptyState in place of the ScrollArea, not inside it.',\n boxedPage:\n 'This box {{what}} a page-scope EmptyState, which centres itself in the room a flex column gives it and takes no padding. A box that places it can push it out of the middle, as the starter\\'s home page did (UIG-10). Draw the EmptyState straight into the column, with `className=\"h-full\"` outside a flex column.',\n wrongScopeVia:\n '`{{component}}` draws a page-scope EmptyState ({{where}}) inside this ScrollArea, where it sits at the top of its pane, not the middle: the ScrollArea\\'s content is only as tall as what is in it. Use `scope=\"section\"` there when the pane has anything else on it; when the whole pane is empty, draw the page EmptyState in place of the ScrollArea, not inside it.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const parser = (context.languageOptions?.parser ?? {}) as Parser\n const file = context.filename\n let facts: FileFacts | undefined\n // A ScrollArea inside another is walked by both; each state is reported once.\n const reported = new Set<Node>()\n const scopeOf = (node: Node) => context.sourceCode.getScope(node as unknown as Parameters<typeof context.sourceCode.getScope>[0])\n\n return {\n Program(program) {\n facts = factsOf(file, program as unknown as Node, parser)\n },\n JSXElement(ruleNode: Rule.Node) {\n const element = ruleNode as unknown as Node\n const opening = child(element, 'openingElement') as Node\n const tag = tagName(element)\n\n if (tag && /^[a-z]/.test(tag)) {\n // Shape 3 (UIG-42): a plain box around a page-scope EmptyState that centres or pads it.\n const only = facts && onlyElement(element)\n const inner = only && (child(only, 'openingElement') as Node)\n // Props spread in (`{...args}`) may carry the scope, so it is not judged.\n const spread = inner && children(inner, 'attributes').some((a) => a.type === 'JSXSpreadAttribute')\n if (inner && !spread && isPart(bindingOfTag(child(inner, 'name'), facts!.locals), 'EmptyState') && isPageScope(inner)) {\n const className = attributeOf(opening, 'className')\n const own = className ? classesOf(child(className, 'value'), scopeOf).map((c) => c.replace(/^(?:[^:\\s[\\]]+:)+/, '')) : []\n const centres = own.some((c) => CENTRES.test(c))\n const pads = own.some((c) => PADS.test(c))\n if ((centres || pads) && !isEscaped(context, opening)) {\n const what = centres && pads ? 'centres and pads' : centres ? 'centres' : 'pads'\n context.report({ loc: opening.loc as NonNullable<Rule.Node['loc']>, messageId: 'boxedPage', data: { what } })\n }\n return\n }\n\n // Shape 1: a plain box holding only a \"nothing\" line, where a list would be.\n const words = onlyWords(element)\n if (!words || words.length > SHORT) return\n if (!standsInForAList(element)) return\n if (isEscaped(context, opening)) return\n context.report({ loc: opening.loc as NonNullable<Rule.Node['loc']>, messageId: 'handmade' })\n return\n }\n\n // Shape 2: a page-scope EmptyState in a ScrollArea that does not fill.\n if (!facts || !isPart(bindingOfTag(child(opening, 'name'), facts.locals), 'ScrollArea')) return\n const content = attributeOf(opening, 'contentClassName')\n if (content && classesOf(child(content, 'value'), scopeOf).some((c) => FILLS.test(c.replace(/^(?:[^:\\s[\\]]+:)+/, '')))) return\n const here = facts\n for (const kid of children(element, 'children')) {\n walk(kid, (node) => {\n if (node.type !== 'JSXOpeningElement') return\n const name = child(node, 'name')\n const binding = bindingOfTag(name, here.locals)\n if (isPart(binding, 'EmptyState')) {\n if (!isPageScope(node) || reported.has(node) || isEscaped(context, node)) return\n reported.add(node)\n context.report({ loc: node.loc as NonNullable<Rule.Node['loc']>, messageId: 'wrongScope' })\n return\n }\n const component = binding?.props === 'all' ? undefined : nameOf(name)\n if (!component || !/^[A-Z]/.test(component)) return\n const states = pageStatesOf(here, component, parser, 0, new Set())\n if (!states.length || reported.has(node) || isEscaped(context, node)) return\n reported.add(node)\n // In reading order: file, then line.\n for (const state of [...states].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line)) {\n const where = state.file === file ? `line ${state.line}` : `${fileName(state.file)}:${state.line}`\n context.report({ loc: node.loc as NonNullable<Rule.Node['loc']>, messageId: 'wrongScopeVia', data: { component, where } })\n }\n })\n }\n },\n }\n },\n}\n", "import { existsSync, readFileSync, statSync } from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\nimport type { Rule, Scope } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\n/**\n * A part of the package is placed from outside, never restyled (UIG-9; Katerina's\n * ruling B8 of 13 September, \"only position and spacing pass into our\n * components\").\n *\n * Every part takes `className`, and some take a second class prop for an inner\n * box (`contentClassName`, `bodyClassName`\u2026). Through either, an app could push\n * a colour, a text size or a border into a part and quietly undo it: the token\n * lint only asks whether a class is a real token, never whether the part should\n * take it. This rule reads every class passed into a part and lets through only\n * placement \u2014 where the part sits and how much room it takes.\n *\n * **Which elements are parts: by where they come from, never by name.** No list\n * of names is kept, so a part added to the package later is covered the day it\n * is added.\n *\n * - In an app: anything imported from `@estiva-app/ui`, and anything imported\n * from the app's own files that is one of those \u2014 a re-export (Peek's\n * `components/ui/Button.tsx`), a wrapper that hands its props on to a part\n * (`{...rest}`), or a component that hands its own `className` on to a part\n * (Peek's `ConversationCard` into `Card`). Relative imports and the apps' `@/`\n * alias are followed; `@/` is the `src` folder beside the nearest\n * `package.json`.\n * - Inside the package (Katerina, 17 September): a name `src/index.ts` exports,\n * imported from a sibling file or declared in the same file.\n *\n * **What it reads:** a string, a template, `cn()`/`clsx()` and their arguments,\n * both sides of a condition, a `const` in the same file and the values of a\n * class map read from one. A class the code works out while it runs passes: the\n * rule cannot read it.\n *\n * `EmptyState` takes no padding either (Katerina's ruling 6 of 14 September):\n * its room comes from the box its rows live in.\n *\n * `Form` takes no layout for its fields (Katerina, 28 September): it stacks\n * them 24px apart itself, so every form reads the same. A form that is not a\n * list of fields says `layout=\"free\"`, and then lays itself out.\n */\n\n// ---------------------------------------------------------------- the classes\n\n/** Where a part sits and how much room it takes. Read on the utility, after its variants. */\nexport const PLACEMENT: { what: string; pattern: RegExp }[] = [\n { what: 'space around', pattern: /^m[xytrblse]?-/ },\n { what: 'space inside', pattern: /^p[xytrblse]?-/ },\n { what: 'width and height', pattern: /^(?:w|h|size|min-w|min-h|max-w|max-h)-/ },\n { what: 'shown, and how it lays out', pattern: /^(?:hidden|block|inline|inline-block|inline-flex|inline-grid|flex|grid|contents|flow-root)$/ },\n { what: 'its place in a row or a grid', pattern: /^(?:grow|shrink)$|^(?:flex|basis|grow|shrink|order|gap|gap-x|gap-y|space-x|space-y|col|row|grid-cols|grid-rows|grid-flow|auto-cols|auto-rows)-/ },\n { what: 'alignment', pattern: /^(?:self|justify|justify-items|justify-self|items|place-content|place-items|place-self)-|^content-(?!\\[)/ },\n { what: 'position', pattern: /^(?:static|relative|absolute|fixed|sticky)$|^(?:inset|inset-x|inset-y|top|right|bottom|left|start|end|z)-/ },\n // Draws nothing: it names the part, so what is inside can answer its hover (`group-hover:`).\n { what: 'a name for hover', pattern: /^(?:group|peer)(?:\\/[\\w-]+)?$/ },\n]\n\n/**\n * The same, as `style` keys (Katerina's ruling B6, 25 September): `style` on a\n * part is read like its `className`, so a radius, a weight or an opacity cannot\n * go in by the other door. CSS's own names for space, size, flex and grid, and\n * position; `transform` and `translate` move a part without changing its look.\n * A custom property (`--name`) passes: the part decides what it means.\n */\nexport const PLACEMENT_STYLE =\n /^(?:margin|padding|inset|scrollMargin)(?:Top|Right|Bottom|Left|Block|Inline|BlockStart|BlockEnd|InlineStart|InlineEnd)?$|^(?:width|height|minWidth|minHeight|maxWidth|maxHeight|inlineSize|blockSize|minInlineSize|minBlockSize|maxInlineSize|maxBlockSize)$|^(?:display|flex|flexGrow|flexShrink|flexBasis|order|gap|rowGap|columnGap|alignSelf|justifySelf|placeSelf|gridArea|gridColumn|gridColumnStart|gridColumnEnd|gridRow|gridRowStart|gridRowEnd)$|^(?:position|top|right|bottom|left|zIndex|transform|translate)$/\n\n/**\n * A variant that draws another box or reaches inside the part: `before:`,\n * `after:`, `[&>*]:`, `*:`\u2026 A placement class behind one of these is not the\n * part's placement.\n */\nconst REACHING_VARIANT = /^\\[|^(?:before|after|placeholder|file|marker|selection|first-letter|first-line|backdrop|\\*|\\*\\*)$/\n\n/** A class list's variants and its utility: `sm:[&>*]:shrink-0` \u2192 `['sm', '[&>*]']`, `shrink-0`. */\nexport function splitClass(token: string): { variants: string[]; utility: string } {\n const variants: string[] = []\n let current = ''\n let depth = 0\n for (const character of token) {\n if (character === '[') depth += 1\n if (character === ']') depth -= 1\n if (character === ':' && depth === 0) {\n variants.push(current)\n current = ''\n } else current += character\n }\n return { variants, utility: current.replace(/^!/, '').replace(/!$/, '').replace(/^-/, '') }\n}\n\n/** Whether a class only places the part. */\nexport function isPlacement(token: string): boolean {\n const { variants, utility } = splitClass(token)\n if (variants.some((variant) => REACHING_VARIANT.test(variant))) return false\n return PLACEMENT.some(({ pattern }) => pattern.test(utility))\n}\n\n/** How a form's fields are laid out: its display, direction, gaps and alignment. */\nconst FIELDS_LAYOUT = /^(?:block|flex|grid|inline-flex|inline-grid|contents|flow-root)$|^(?:gap|gap-x|gap-y|space-x|space-y|grid-cols|grid-rows|grid-flow|auto-cols|auto-rows|items|justify|justify-items|place-content|place-items)-|^flex-(?:row|col|wrap|nowrap)|^content-(?!\\[)/\n\nconst isFieldsLayout = (token: string) => {\n const { variants, utility } = splitClass(token)\n return !variants.some((variant) => REACHING_VARIANT.test(variant)) && FIELDS_LAYOUT.test(utility)\n}\n\n/** Room between a box's children, down the page or across it: what spaces a Form from its neighbours. */\nconst isSpacing = (token: string) => {\n const { variants, utility } = splitClass(token)\n return !variants.some((variant) => REACHING_VARIANT.test(variant)) && /^(?:gap|gap-x|gap-y|space-x|space-y)-/.test(utility)\n}\n\nconst isPadding = (token: string) => {\n const { variants, utility } = splitClass(token)\n return !variants.some((variant) => REACHING_VARIANT.test(variant)) && /^p[xytrblse]?-/.test(utility)\n}\n\n/**\n * The props a part has for how it looks, named in the message. Held to the\n * package's source by `no-restyled-part.test.ts`: every prop here exists, and\n * every look prop an exported part has is here. A part missing from this table\n * has none, and the message says to ask for one.\n */\nexport const PART_LOOK_PROPS: Record<string, string[]> = {\n AppShell: ['variant'],\n Avatar: ['size'],\n AvatarGroup: ['size'],\n Banner: ['tone'],\n Button: ['variant', 'size'],\n Card: ['fill', 'hover', 'attention', 'selected', 'active', 'hovered', 'quietUntilHover', 'unreadable', 'clip'],\n Checkbox: ['row'],\n Chip: ['type'],\n CollapsibleSection: ['look'],\n Divider: ['tone', 'orientation'],\n EmptyState: ['scope'],\n FieldLine: ['tone'],\n IconButton: ['variant', 'pressed', 'glow'],\n InputChip: ['truncate'],\n Kbd: ['tone'],\n Link: ['variant', 'truncate', 'cover'],\n MenuItem: ['size', 'selected', 'destructive'],\n MenuSub: ['selected'],\n NavItem: ['active'],\n Person: ['size'],\n ProgressBar: ['variant'],\n Property: ['layout'],\n RailItem: ['active'],\n Reaction: ['pressed'],\n ReactionPicker: ['surface'],\n RichText: ['size'],\n SectionHeader: ['hover', 'look'],\n SectionLabel: ['tone', 'truncate'],\n Select: ['size'],\n Tabs: ['size'],\n TextInput: ['size'],\n Toast: ['type'],\n Toolbar: ['surface'],\n ToolbarButton: ['variant', 'pressed', 'glow'],\n TopBar: ['variant'],\n}\n\n/** The class props of a part: `className`, and the ones for an inner box. */\nconst CLASS_PROP = /^(?:className|[a-z][A-Za-z]*ClassName)$/\n\n// ---------------------------------------------------------------- the nodes\n\ninterface Node {\n type: string\n range: [number, number]\n loc?: NonNullable<Rule.Node['loc']>\n parent?: Node\n [key: string]: unknown\n}\n\nconst child = (node: Node, key: string) => node[key] as Node | null | undefined\nconst children = (node: Node, key: string) => (node[key] as (Node | null)[] | undefined) ?? []\nconst nameOf = (node: Node | null | undefined): string | undefined =>\n node?.type === 'Identifier' || node?.type === 'JSXIdentifier' ? (node.name as string) : node?.type === 'Literal' && typeof node.value === 'string' ? node.value : undefined\n\n/** Walk every node under `root`, skipping the parser's bookkeeping keys. */\nfunction walk(root: Node, visit: (node: Node) => void): void {\n const stack: Node[] = [root]\n while (stack.length) {\n const node = stack.pop() as Node\n visit(node)\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range' || key === 'tokens' || key === 'comments') continue\n const value = node[key]\n if (Array.isArray(value)) for (const item of value) { if (item && typeof (item as Node).type === 'string') stack.push(item as Node) }\n else if (value && typeof (value as Node).type === 'string') stack.push(value as Node)\n }\n }\n}\n\n// ---------------------------------------------------------------- the parts\n\n/**\n * What a name is to this rule: the part it draws, and which of the caller's\n * class props reach which of the part's (`all` for a part, a re-export or a\n * wrapper; a map for a component that hands on its own `className`). `via` is\n * the app's own component in between, for the message.\n */\nexport interface PartBinding {\n part: string\n props: 'all' | Record<string, string>\n via?: string\n}\n\ninterface Parser {\n parseForESLint?: (code: string, options: unknown) => { ast: Node }\n parse?: (code: string, options: unknown) => Node\n}\n\ninterface ModuleFacts {\n mtime: number\n exports: Map<string, PartBinding>\n}\n\nconst PACKAGE = '@estiva-app/ui'\nconst moduleCache = new Map<string, ModuleFacts>()\nconst packageDirCache = new Map<string, string | null>()\nconst packagePartsCache = new Map<string, { mtime: number; parts: Set<string> }>()\n\nfunction parseFile(parser: Parser, filePath: string): Node | null {\n const code = readFileSync(filePath, 'utf8')\n const options = { filePath, ecmaVersion: 'latest', sourceType: 'module', ecmaFeatures: { jsx: filePath.endsWith('x') }, range: true, loc: true }\n try {\n if (parser.parseForESLint) return parser.parseForESLint(code, options).ast\n if (parser.parse) return parser.parse(code, options)\n } catch {\n // A file that does not parse is its own lint's business; it hands on no parts.\n }\n return null\n}\n\n/** The nearest folder holding a `package.json`, from a file. */\nfunction packageDirOf(file: string): string | null {\n const start = dirname(resolve(file))\n if (packageDirCache.has(start)) return packageDirCache.get(start) ?? null\n let dir = start\n for (;;) {\n if (existsSync(join(dir, 'package.json'))) break\n const up = dirname(dir)\n if (up === dir) {\n dir = ''\n break\n }\n dir = up\n }\n packageDirCache.set(start, dir || null)\n return dir || null\n}\n\nfunction resolveModule(fromFile: string, specifier: string): string | null {\n let base: string\n if (specifier.startsWith('.')) base = resolve(dirname(fromFile), specifier)\n else if (specifier.startsWith('@/')) {\n const dir = packageDirOf(fromFile)\n if (!dir) return null\n base = join(dir, 'src', specifier.slice(2))\n } else return null\n for (const candidate of [base, `${base}.tsx`, `${base}.ts`, join(base, 'index.tsx'), join(base, 'index.ts')]) {\n if (existsSync(candidate) && statSync(candidate).isFile()) return candidate\n }\n return null\n}\n\n/** The names this package's `src/index.ts` exports, when the file lives in `@estiva-app/ui` itself. */\nfunction packagePartsFor(file: string, parser: Parser): Set<string> | null {\n const dir = packageDirOf(file)\n if (!dir) return null\n let name: string | undefined\n try {\n name = (JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as { name?: string }).name\n } catch {\n return null\n }\n if (name !== PACKAGE) return null\n const index = join(dir, 'src', 'index.ts')\n if (!existsSync(index)) return null\n const mtime = statSync(index).mtimeMs\n const cached = packagePartsCache.get(index)\n if (cached && cached.mtime === mtime) return cached.parts\n const parts = new Set<string>()\n const ast = parseFile(parser, index)\n for (const statement of ast ? children(ast, 'body') : []) {\n if (statement?.type !== 'ExportNamedDeclaration' || statement.exportKind === 'type') continue\n for (const specifier of children(statement, 'specifiers')) {\n const exported = nameOf(child(specifier as Node, 'exported'))\n if (specifier?.exportKind !== 'type' && exported && /^[A-Z][a-z]/.test(exported)) parts.add(exported)\n }\n }\n packagePartsCache.set(index, { mtime, parts })\n return parts\n}\n\n/** A function component declared in a module: its name, and the function. */\nfunction functionComponents(program: Node): Map<string, Node> {\n const found = new Map<string, Node>()\n const unwrap = (node: Node | null | undefined): Node | null => {\n let current = node\n while (current?.type === 'CallExpression' && children(current, 'arguments').length) {\n const callee = child(current, 'callee')\n const text = callee?.type === 'Identifier' ? nameOf(callee) : callee?.type === 'MemberExpression' ? nameOf(child(callee, 'property')) : undefined\n if (text !== 'forwardRef' && text !== 'memo') return null\n current = children(current, 'arguments')[0]\n }\n return current?.type === 'ArrowFunctionExpression' || current?.type === 'FunctionExpression' ? current : null\n }\n walk(program, (node) => {\n if (node.type === 'FunctionDeclaration') {\n const name = nameOf(child(node, 'id'))\n if (name && /^[A-Z]/.test(name)) found.set(name, node)\n } else if (node.type === 'VariableDeclarator') {\n const name = nameOf(child(node, 'id'))\n const fn = unwrap(child(node, 'init'))\n if (name && /^[A-Z]/.test(name) && fn) found.set(name, fn)\n }\n })\n return found\n}\n\n/**\n * The parts a module's names stand for. `ownFile` is the file being linted: its\n * imports are read the same way, so a wrapper declared beside its use counts.\n */\nfunction moduleParts(file: string, program: Node, parser: Parser, stack: Set<string>): { locals: Map<string, PartBinding | 'namespace'>; exports: Map<string, PartBinding> } {\n const locals = new Map<string, PartBinding | 'namespace'>()\n const packageParts = packagePartsFor(file, parser)\n const body = children(program, 'body')\n\n const exportsOf = (specifier: string): Map<string, PartBinding> | 'package' | null => {\n if (specifier === PACKAGE) return 'package'\n const target = resolveModule(file, specifier)\n if (!target) return null\n if (packageParts) return 'package'\n return moduleExports(target, parser, stack)\n }\n\n for (const statement of body) {\n if (statement?.type !== 'ImportDeclaration' || statement.importKind === 'type') continue\n const source = exportsOf(String((child(statement, 'source') as Node).value))\n if (!source) continue\n for (const specifier of children(statement, 'specifiers')) {\n if (!specifier || specifier.importKind === 'type') continue\n const local = nameOf(child(specifier, 'local'))\n if (!local) continue\n if (specifier.type === 'ImportNamespaceSpecifier') {\n if (source === 'package' && !packageParts) locals.set(local, 'namespace')\n continue\n }\n const imported = specifier.type === 'ImportDefaultSpecifier' ? 'default' : nameOf(child(specifier, 'imported'))\n if (!imported) continue\n if (source === 'package') {\n const isPart = packageParts ? packageParts.has(imported) : /^[A-Z]/.test(imported)\n if (isPart) locals.set(local, { part: imported, props: 'all' })\n } else if (source.has(imported)) locals.set(local, source.get(imported) as PartBinding)\n }\n }\n\n // Inside the package, a part used in the file that declares it.\n const components = functionComponents(program)\n if (packageParts) for (const name of components.keys()) if (packageParts.has(name) && !locals.has(name)) locals.set(name, { part: name, props: 'all' })\n\n // In an app, a component that hands its props, or its own className, on to a part.\n if (!packageParts) {\n let changed = true\n for (let round = 0; changed && round < 10; round += 1) {\n changed = false\n for (const [name, fn] of components) {\n const binding = handsOnTo(fn, (tag) => bindingOfTag(tag, locals))\n if (!binding) continue\n const next = { ...binding, via: name }\n const previous = locals.get(name)\n if (!previous || JSON.stringify(previous) !== JSON.stringify(next)) {\n if (previous && previous !== 'namespace' && !previous.via) continue\n locals.set(name, next)\n changed = true\n }\n }\n }\n }\n\n const exports = new Map<string, PartBinding>()\n const localBinding = (name: string | undefined) => {\n const binding = name ? locals.get(name) : undefined\n return binding && binding !== 'namespace' ? binding : undefined\n }\n for (const statement of body) {\n if (!statement) continue\n if (statement.type === 'ExportNamedDeclaration') {\n const declaration = child(statement, 'declaration')\n if (declaration?.type === 'FunctionDeclaration') {\n const name = nameOf(child(declaration, 'id'))\n const binding = localBinding(name)\n if (name && binding) exports.set(name, binding)\n } else if (declaration?.type === 'VariableDeclaration') {\n for (const declarator of children(declaration, 'declarations')) {\n const name = nameOf(child(declarator as Node, 'id'))\n const init = child(declarator as Node, 'init')\n const binding = localBinding(name) ?? (init?.type === 'Identifier' ? localBinding(nameOf(init)) : undefined)\n if (name && binding) exports.set(name, binding)\n }\n }\n const source = child(statement, 'source')\n const from = source ? exportsOf(String(source.value)) : null\n for (const specifier of children(statement, 'specifiers')) {\n if (!specifier || specifier.exportKind === 'type') continue\n const local = nameOf(child(specifier, 'local'))\n const exported = nameOf(child(specifier, 'exported'))\n if (!local || !exported) continue\n if (!source) {\n const binding = localBinding(local)\n if (binding) exports.set(exported, binding)\n } else if (from === 'package') {\n if (/^[A-Z]/.test(local)) exports.set(exported, { part: local, props: 'all' })\n } else if (from?.has(local)) exports.set(exported, from.get(local) as PartBinding)\n }\n } else if (statement.type === 'ExportAllDeclaration' && !child(statement, 'exported')) {\n const from = exportsOf(String((child(statement, 'source') as Node).value))\n if (from && from !== 'package') for (const [name, binding] of from) exports.set(name, binding)\n } else if (statement.type === 'ExportDefaultDeclaration') {\n const declaration = child(statement, 'declaration')\n const name = declaration?.type === 'Identifier' ? nameOf(declaration) : nameOf(child(declaration as Node, 'id'))\n const binding = localBinding(name)\n if (binding) exports.set('default', binding)\n }\n }\n return { locals, exports }\n}\n\n/**\n * What a file's names stand for, found the way this rule finds them: for a rule\n * that asks whether a tag is one particular part, through an app's wrapper too\n * (UIG-23 asks for `EmptyState` and `ScrollArea`).\n */\nexport function partsOfFile(file: string, program: Node, parser: Parser): Map<string, PartBinding | 'namespace'> {\n return moduleParts(file, program, parser, new Set([file])).locals\n}\n\nexport { bindingOfTag, functionComponents, parseFile, resolveModule, walk, type Node, type Parser }\n\nfunction moduleExports(file: string, parser: Parser, stack: Set<string>): Map<string, PartBinding> {\n const mtime = statSync(file).mtimeMs\n const cached = moduleCache.get(file)\n if (cached && cached.mtime === mtime) return cached.exports\n if (stack.has(file)) return new Map()\n stack.add(file)\n const program = parseFile(parser, file)\n const exports = program ? moduleParts(file, program, parser, stack).exports : new Map<string, PartBinding>()\n stack.delete(file)\n moduleCache.set(file, { mtime, exports })\n return exports\n}\n\nfunction bindingOfTag(tag: Node | null | undefined, locals: Map<string, PartBinding | 'namespace'>): PartBinding | undefined {\n if (!tag) return undefined\n if (tag.type === 'JSXIdentifier') {\n const binding = locals.get(tag.name as string)\n return binding && binding !== 'namespace' ? binding : undefined\n }\n if (tag.type === 'JSXMemberExpression') {\n const object = child(tag, 'object')\n const property = nameOf(child(tag, 'property'))\n if (object?.type === 'JSXIdentifier' && locals.get(object.name as string) === 'namespace' && property) return { part: property, props: 'all' }\n }\n return undefined\n}\n\n/**\n * Whether a function component hands its props on to a part: its rest or its\n * whole props spread onto one (a wrapper), or its own class props passed into\n * one's class props (a component that places a part by its caller's word).\n */\nfunction handsOnTo(fn: Node, bindingOf: (tag: Node | null | undefined) => PartBinding | undefined): PartBinding | undefined {\n const param = children(fn, 'params')[0]\n if (!param) return undefined\n let restName: string | undefined\n let propsName: string | undefined\n const classParams = new Map<string, string>()\n if (param.type === 'ObjectPattern') {\n for (const property of children(param, 'properties')) {\n if (!property) continue\n if (property.type === 'RestElement') restName = nameOf(child(property, 'argument'))\n else if (property.type === 'Property') {\n const key = nameOf(child(property, 'key'))\n let value = child(property, 'value')\n if (value?.type === 'AssignmentPattern') value = child(value, 'left')\n const local = nameOf(value)\n if (key && local && CLASS_PROP.test(key)) classParams.set(local, key)\n }\n }\n } else if (param.type === 'Identifier') propsName = nameOf(param)\n\n let wrapper: PartBinding | undefined\n const forwarded: { part?: string; props: Record<string, string> } = { props: {} }\n const body = child(fn, 'body')\n if (!body) return undefined\n walk(body, (node) => {\n if (wrapper || node.type !== 'JSXOpeningElement') return\n const binding = bindingOf(child(node, 'name'))\n if (!binding) return\n for (const attribute of children(node, 'attributes')) {\n if (!attribute) continue\n if (attribute.type === 'JSXSpreadAttribute') {\n const argument = nameOf(child(attribute, 'argument'))\n if (argument && (argument === restName || argument === propsName)) wrapper = { part: binding.part, props: binding.props }\n continue\n }\n const prop = nameOf(child(attribute, 'name'))\n if (!prop || !CLASS_PROP.test(prop)) continue\n const partProp = binding.props === 'all' ? prop : binding.props[prop]\n if (!partProp) continue\n walk(attribute, (inner) => {\n let callerProp: string | undefined\n if (inner.type === 'Identifier') callerProp = classParams.get(inner.name as string)\n if (inner.type === 'MemberExpression' && nameOf(child(inner, 'object')) === propsName) {\n const key = nameOf(child(inner, 'property'))\n if (key && CLASS_PROP.test(key)) callerProp = key\n }\n if (!callerProp) return\n if (forwarded.part && forwarded.part !== binding.part) return\n forwarded.part = binding.part\n forwarded.props[callerProp] = partProp\n })\n }\n })\n if (wrapper) return wrapper\n return forwarded.part ? { part: forwarded.part, props: forwarded.props } : undefined\n}\n\n// ---------------------------------------------------------------- reading a class list\n\nconst CLASS_FUNCTIONS = new Set(['cn', 'clsx', 'cx', 'twMerge', 'classNames'])\n\n/** The `const` a name stands for in this file, if it is one. */\nfunction constantOf(identifier: Node, scope: Scope.Scope | null): Node | undefined {\n let current = scope\n while (current) {\n const variable = current.set.get(identifier.name as string)\n if (variable) {\n const definition = variable.defs[0] as unknown as { type: string; node: Node; parent?: Node } | undefined\n if (variable.defs.length !== 1 || definition?.type !== 'Variable') return undefined\n if ((definition.parent as Node | undefined)?.kind !== 'const') return undefined\n return child(definition.node, 'init') ?? undefined\n }\n current = current.upper\n }\n return undefined\n}\n\n/**\n * Every class the code spells out for a value, as far as it can be read in this\n * file. `asMap` reads an object as a class map (its values) rather than as a\n * `clsx` object (its keys).\n */\nexport function classesOf(value: Node | null | undefined, scopeOf: (node: Node) => Scope.Scope | null, asMap = false, seen = new Set<Node>()): string[] {\n if (!value || seen.has(value) || seen.size > 200) return []\n seen.add(value)\n const read = (node: Node | null | undefined, map = false) => classesOf(node, scopeOf, map, seen)\n const words = (text: unknown) => (typeof text === 'string' ? text.split(/\\s+/).filter(Boolean) : [])\n switch (value.type) {\n case 'Literal':\n return words(value.value)\n case 'TemplateLiteral':\n return [...children(value, 'quasis').flatMap((quasi) => words((quasi?.value as { cooked?: string }).cooked)), ...children(value, 'expressions').flatMap((e) => read(e))]\n case 'JSXExpressionContainer':\n case 'TSAsExpression':\n case 'TSSatisfiesExpression':\n case 'TSNonNullExpression':\n case 'ChainExpression':\n return read(child(value, 'expression'), asMap)\n case 'ConditionalExpression':\n return [...read(child(value, 'consequent')), ...read(child(value, 'alternate'))]\n case 'LogicalExpression':\n return value.operator === '&&' ? read(child(value, 'right')) : [...read(child(value, 'left')), ...read(child(value, 'right'))]\n case 'BinaryExpression':\n return value.operator === '+' ? [...read(child(value, 'left')), ...read(child(value, 'right'))] : []\n case 'ArrayExpression':\n return children(value, 'elements').flatMap((e) => read(e))\n case 'ObjectExpression':\n return children(value, 'properties').flatMap((property) => {\n if (property?.type !== 'Property') return []\n return asMap ? read(child(property, 'value'), true) : property.computed ? [] : words(nameOf(child(property, 'key')))\n })\n case 'CallExpression': {\n const callee = child(value, 'callee')\n return callee?.type === 'Identifier' && CLASS_FUNCTIONS.has(callee.name as string) ? children(value, 'arguments').flatMap((a) => read(a)) : []\n }\n case 'Identifier': {\n const constant = constantOf(value, scopeOf(value))\n return constant ? read(constant, asMap) : []\n }\n case 'MemberExpression': {\n const object = child(value, 'object')\n const target = object?.type === 'Identifier' ? constantOf(object, scopeOf(object)) : object\n const map = target?.type === 'TSAsExpression' || target?.type === 'TSSatisfiesExpression' ? child(target, 'expression') : target\n if (map?.type !== 'ObjectExpression') return []\n const property = child(value, 'property')\n const key = value.computed ? (property?.type === 'Literal' ? String(property.value) : undefined) : nameOf(property)\n return children(map, 'properties').flatMap((entry) => {\n if (entry?.type !== 'Property') return []\n if (key !== undefined && nameOf(child(entry, 'key')) !== key) return []\n return read(child(entry, 'value'), true)\n })\n }\n default:\n return []\n }\n}\n\n// ---------------------------------------------------------------- the rule\n\nconst code = (items: string[]) => items.map((item) => `\\`${item}\\``).join(' ')\nconst or = (items: string[]) => (items.length === 1 ? code(items) : `${items.slice(0, -1).map((i) => `\\`${i}\\``).join(', ')} or \\`${items[items.length - 1]}\\``)\n\nexport const noRestyledPart: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'Only placement passes into a part of @estiva-app/ui through a class prop' },\n schema: [],\n messages: {\n restyled:\n '{{classes}} on {{where}} changes how it looks. A part of @estiva-app/ui is placed from outside, never restyled: only space, size, flex and grid, and position pass in.{{use}} A look for what is around it goes on your own element around it.',\n restyledStyle:\n '{{keys}} in the `style` of {{where}} changes how it looks. A part of @estiva-app/ui is placed from outside, never restyled, by class or by style: only space, size, flex and grid, and position pass in.{{use}} A look for what is around it goes on your own element around it.',\n emptyStatePadding:\n '{{classes}} pads {{where}}. EmptyState takes no padding (Katerina, 14 September): its room comes from the box its rows live in, so put the padding on that box.',\n formLayout:\n '{{classes}} lays out the fields of {{where}}. A Form places its own fields, 24px apart (Katerina, 28 September), so every form reads the same: remove it. A form that is not a list of fields (a field and its button, a composer) says `layout=\"free\"` and lays itself out.',\n formSpacedFromOutside:\n '{{classes}} on the box around `Form` spaces the form from what is beside it, so the gap above its first field is not the form\u2019s 24px. Put what is beside it inside the `Form`, as one block before the fields, and drop the box: the Form puts 24px between them (Katerina, 1 October; MoveDialog in Peek does this).',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const parser = (context.languageOptions?.parser ?? {}) as Parser\n const file = context.filename\n const sourceCode = context.sourceCode\n const scopeOf = (node: Node) => sourceCode.getScope(node as unknown as Parameters<typeof sourceCode.getScope>[0])\n let locals: Map<string, PartBinding | 'namespace'> | undefined\n const escapes = new Map<Node, boolean>()\n const escaped = (anchor: Node) => {\n if (!escapes.has(anchor)) escapes.set(anchor, isEscaped(context, anchor))\n return escapes.get(anchor) === true\n }\n\n /** A `Form` lays out its own fields unless it says `layout=\"free\"`; a layout the rule cannot read passes. */\n const placesItsFields = (element: Node) =>\n !children(element, 'attributes').some((attribute) => {\n if (attribute?.type !== 'JSXAttribute' || nameOf(child(attribute, 'name')) !== 'layout') return false\n const value = child(attribute, 'value')\n const literal = value?.type === 'JSXExpressionContainer' ? child(value, 'expression') : value\n return !(literal?.type === 'Literal' && literal.value === 'fields')\n })\n\n const check = (element: Node, binding: PartBinding, prop: string, value: Node | null | undefined, at: Node) => {\n const partProp = binding.props === 'all' ? prop : binding.props[prop]\n if (!partProp || !value) return\n const classes = classesOf(value, scopeOf)\n const handedOn = binding.props === 'all' ? 'its props' : `its \\`${prop}\\``\n const via = binding.via && binding.via !== binding.part ? `\\`${binding.via}\\` (it hands ${handedOn} to \\`${binding.part}\\`)` : `\\`${binding.part}\\``\n const where = `${via}${partProp === 'className' ? '' : `'s \\`${partProp}\\``}`\n const restyled = [...new Set(classes.filter((token) => !isPlacement(token)))]\n const padding = binding.part === 'EmptyState' && binding.props === 'all' ? [...new Set(classes.filter(isPadding))] : []\n const layout = binding.part === 'Form' && partProp === 'className' && placesItsFields(element) ? [...new Set(classes.filter(isFieldsLayout))] : []\n if (!restyled.length && !padding.length && !layout.length) return\n if (escaped(element)) return\n if (restyled.length) {\n const props = PART_LOOK_PROPS[binding.part]\n const use = props ? ` Use its ${or(props)}.` : ` \\`${binding.part}\\` has no prop for this yet: ask Katerina, and it gets made in @estiva-app/ui.`\n context.report({ loc: at.loc as NonNullable<Rule.Node['loc']>, messageId: 'restyled', data: { classes: code(restyled), where, use } })\n }\n if (padding.length) context.report({ loc: at.loc as NonNullable<Rule.Node['loc']>, messageId: 'emptyStatePadding', data: { classes: code(padding), where } })\n if (layout.length) context.report({ loc: at.loc as NonNullable<Rule.Node['loc']>, messageId: 'formLayout', data: { classes: code(layout), where } })\n }\n\n /** `style` on a part: every key it can read must be placement (B6). */\n const checkStyle = (element: Node, binding: PartBinding, value: Node | null | undefined, at: Node) => {\n if (binding.props !== 'all' || value?.type !== 'JSXExpressionContainer') return\n let object = child(value, 'expression')\n if (object?.type === 'Identifier') object = constantOf(object, scopeOf(object))\n while (object?.type === 'TSAsExpression' || object?.type === 'TSSatisfiesExpression') object = child(object, 'expression')\n if (object?.type !== 'ObjectExpression') return\n const keys = children(object, 'properties')\n .map((property) => (property?.type === 'Property' && !property.computed ? nameOf(child(property, 'key')) : undefined))\n .filter((key): key is string => !!key && !key.startsWith('--') && !PLACEMENT_STYLE.test(key))\n if (!keys.length || escaped(element)) return\n const props = PART_LOOK_PROPS[binding.part]\n const use = props ? ` Use its ${or(props)}.` : ` \\`${binding.part}\\` has no prop for this yet: ask Katerina, and it gets made in @estiva-app/ui.`\n const where = binding.via && binding.via !== binding.part ? `\\`${binding.via}\\` (it hands its props to \\`${binding.part}\\`)` : `\\`${binding.part}\\``\n context.report({ loc: at.loc as NonNullable<Rule.Node['loc']>, messageId: 'restyledStyle', data: { keys: code([...new Set(keys)]), where, use } })\n }\n\n /**\n * A Form with something beside it, in a box that spaces them: the gap\n * above the first field is then the box's, not the Form's 24px (Peek's and\n * Ship's ArchiveDialog, 1 October: 12px). Read on the box's own class\n * props, `className` or a part's `bodyClassName`; a box with only the Form\n * in it spaces nothing.\n */\n const checkSpacedFromOutside = (opening: Node) => {\n const form = opening.parent as Node | undefined\n const box = form?.parent as Node | undefined\n if (form?.type !== 'JSXElement' || box?.type !== 'JSXElement') return\n const beside = children(box, 'children').filter((node) => {\n if (!node || node === form) return false\n if (node.type === 'JSXText') return String(node.value).trim() !== ''\n if (node.type === 'JSXExpressionContainer') return child(node, 'expression')?.type !== 'JSXEmptyExpression'\n return true\n })\n if (!beside.length) return\n const boxOpening = child(box, 'openingElement') as Node\n const spacing = children(boxOpening, 'attributes').flatMap((attribute) => {\n if (attribute?.type !== 'JSXAttribute') return []\n const prop = nameOf(child(attribute, 'name'))\n return prop === 'className' || prop === 'bodyClassName' ? classesOf(child(attribute, 'value'), scopeOf).filter(isSpacing) : []\n })\n if (!spacing.length || escaped(opening)) return\n context.report({ loc: opening.loc as NonNullable<Rule.Node['loc']>, messageId: 'formSpacedFromOutside', data: { classes: code([...new Set(spacing)]) } })\n }\n\n return {\n Program(program) {\n locals = moduleParts(file, program as unknown as Node, parser, new Set([file])).locals\n },\n JSXOpeningElement(ruleNode: Rule.Node) {\n const element = ruleNode as unknown as Node\n const binding = locals && bindingOfTag(child(element, 'name'), locals)\n if (!binding) return\n if (binding.part === 'Form' && binding.props === 'all' && placesItsFields(element)) checkSpacedFromOutside(element)\n for (const attribute of children(element, 'attributes')) {\n if (!attribute) continue\n if (attribute.type === 'JSXAttribute') {\n const prop = nameOf(child(attribute, 'name'))\n if (prop && CLASS_PROP.test(prop)) check(element, binding, prop, child(attribute, 'value'), attribute)\n else if (prop === 'style') checkStyle(element, binding, child(attribute, 'value'), attribute)\n continue\n }\n // `{...{ className }}`, or a `const` object spread onto the part.\n let spread = child(attribute, 'argument')\n if (spread?.type === 'Identifier') spread = constantOf(spread, scopeOf(spread))\n while (spread?.type === 'TSAsExpression' || spread?.type === 'TSSatisfiesExpression') spread = child(spread, 'expression')\n if (spread?.type !== 'ObjectExpression') continue\n for (const property of children(spread, 'properties')) {\n const key = property?.type === 'Property' && !property.computed ? nameOf(child(property, 'key')) : undefined\n if (key && CLASS_PROP.test(key)) check(element, binding, key, child(property as Node, 'value'), property as Node)\n }\n }\n },\n }\n },\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\n/** The JSX an element is made of, as far as this rule reads it. */\ninterface Node {\n type: string\n [key: string]: unknown\n}\n\ninterface JSXElement extends Node {\n type: 'JSXElement'\n openingElement: {\n name: { type: string; name?: string; object?: { name?: string }; property?: { name?: string } }\n attributes: { type: string; name?: { name?: string }; value?: Node | null }[]\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n }\n children: Node[]\n}\n\nconst isElement = (n: unknown): n is JSXElement => typeof n === 'object' && n !== null && (n as Node).type === 'JSXElement'\n\nfunction tagOf(el: JSXElement): string {\n const n = el.openingElement.name\n if (n.type === 'JSXIdentifier') return n.name ?? ''\n if (n.type === 'JSXMemberExpression') return `${n.object?.name ?? ''}.${n.property?.name ?? ''}`\n return ''\n}\n\nfunction attribute(el: JSXElement, name: string) {\n return el.openingElement.attributes.find((a) => a.type === 'JSXAttribute' && a.name?.name === name)\n}\n\n/** Every string literal under a node: a `cn()` call, a template, a ternary. */\nfunction strings(node: Node | null | undefined, out: string[] = []): string[] {\n if (!node || typeof node !== 'object') return out\n if (node.type === 'Literal' && typeof node.value === 'string') out.push(node.value)\n else if (node.type === 'TemplateLiteral') for (const q of node.quasis as { value: { cooked: string | null } }[]) out.push(q.value.cooked ?? '')\n for (const [key, value] of Object.entries(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue\n if (Array.isArray(value)) for (const v of value) strings(v as Node, out)\n else if (value && typeof value === 'object' && (value as Node).type) strings(value as Node, out)\n }\n return out\n}\n\n/** The classes an element is given, variants taken off: `md:px-3` is `px-3`. */\nfunction classesOf(el: JSXElement): string[] {\n const value = attribute(el, 'className')?.value\n if (!value) return []\n const text = value.type === 'Literal' ? String(value.value) : strings(value.expression as Node).join(' ')\n return text\n .split(/\\s+/)\n .filter(Boolean)\n .map((c) => c.replace(/^(?:[^:\\s[\\]]+:)+/, ''))\n}\n\n/**\n * An element's children as a reader sees them: whitespace and comments gone,\n * `{open && <X />}` read as `<X />`.\n */\nfunction meaningful(el: JSXElement): Node[] {\n const out: Node[] = []\n for (const child of el.children) {\n if (child.type === 'JSXText') {\n if (String(child.value).trim()) out.push(child)\n } else if (child.type === 'JSXExpressionContainer') {\n const e = child.expression as Node\n if (e.type === 'JSXEmptyExpression') continue\n if (e.type === 'LogicalExpression' && isElement(e.right)) out.push(e.right as Node)\n else if (isElement(e)) out.push(e)\n else out.push(child)\n } else if (child.type === 'JSXElement' || child.type === 'JSXFragment') out.push(child)\n }\n return out\n}\n\n/** Parts that draw a line of text: a title made of one is still a title. */\nconst TEXT_PARTS = new Set(['EditableText', 'Person', 'Breadcrumb', 'Link', 'SectionLabel', 'InlineChip'])\n/** What a title written as an expression looks like: a name, a field, a template, a fallback. */\nconst VALUE_EXPRESSIONS = new Set(['Identifier', 'MemberExpression', 'TemplateLiteral', 'Literal', 'LogicalExpression', 'ConditionalExpression', 'ChainExpression', 'CallExpression'])\n\n/** Whether the row carries a title: text, a value, a heading, or a part that draws text, three boxes deep at most. */\nfunction carriesTitle(el: JSXElement, depth = 0): boolean {\n if (depth > 3) return false\n for (const child of meaningful(el)) {\n if (child.type === 'JSXText') return true\n if (child.type === 'JSXExpressionContainer') {\n if (VALUE_EXPRESSIONS.has((child.expression as Node).type)) return true\n continue\n }\n if (!isElement(child)) continue\n const tag = tagOf(child)\n // `Dialog.Title`, `Parts.Title`: a part's title, named as one.\n if (/^h[1-6]$/.test(tag) || TEXT_PARTS.has(tag) || /\\.(?:Title|Heading)$/.test(tag)) return true\n // A part's own words are its label, a Button's \"Save\": only plain boxes are looked into.\n if (/^[a-z]/.test(tag) && carriesTitle(child, depth + 1)) return true\n }\n return false\n}\n\nconst ROW = (c: string[]) => c.includes('flex') && !c.includes('flex-col')\nconst OWN_SIDE_PADDING = (c: string[]) => c.some((x) => /^-?(?:p|px|pl|pr|ps|pe)-/.test(x))\n/** A column that takes the height it is given: the pane a header bar tops. */\nconst FILLS = (c: string[]) => c.includes('flex-col') && c.some((x) => /^(?:h-full|h-screen|flex-1|grow|min-h-0|h-dvh)$/.test(x))\n/** A header bar's own geometry: a column bar's height, or the hairline under it. */\nconst BAR = (c: string[]) => c.some((x) => /^(?:h|min-h)-(?:10|11|12|13|14|\\[(?:4[0-9]|5[0-6])px\\])$/.test(x)) || c.some((x) => /^border-b(?:-|$)/.test(x))\n/** A row a person presses is a row of its own kind, not a header. */\nconst INTERACTIVE = ['onClick', 'href', 'role', 'onKeyDown', 'onPointerDown']\n\n/**\n * UIG-22: a column's header bar built by hand.\n *\n * The general rules cannot see this one: a hand-made header is made entirely of\n * legal parts, a box, some text, some padding. So this rule reads the shape.\n * A row, first in a column, with side padding of its own and a title in it,\n * where the column fills the height it is given, or the row has a header bar's\n * height or the hairline under one. `ContainerHeader` is that bar: 48px, the\n * title, the column's buttons at the right edge, a hairline under it.\n *\n * What it leaves alone, on purpose: a group heading inside a list (the row one\n * section starts with), a label strip on a card, and a row a person presses.\n * Only a lowercase element is judged: a part is already a part.\n *\n * And the package's `ContainerHeader` on its own in an app (26 September): a\n * header over a box of the app's own is a panel made by hand, and the box is\n * what forgot to scroll \u2014 Peek's widget panel cut off a long description. The\n * message names `Panel`, whose body always scrolls.\n */\nexport const noHandmadeHeader: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: \"A column's header bar drawn by hand, or the package's header on its own in an app, where Panel is the part\" },\n schema: [],\n messages: {\n handmade:\n \"A column's header bar drawn by hand. Use `Panel` from @estiva-app/ui: its header (48px, the title, the column's buttons at the right edge in `actions`, a hairline under it) and a body under it that scrolls. For a list beside the page, `ListColumn`.\",\n bare:\n \"A panel put together by hand: `ContainerHeader` over a box of your own, which cuts off whatever does not fit. Use `Panel` from @estiva-app/ui: the same header (`title`, `actions`), a body that scrolls whenever it is taller, and a `footer` that stays put. For a list beside the page, `ListColumn`.\",\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n // The package's header, imported by name in an app (Katerina, 26 September): in an\n // app it comes with Panel or ListColumn, whose body scrolls. The package's own parts\n // import it from their sibling file, so this never reads them.\n const bare = new Set<string>()\n return {\n ImportDeclaration(node: Rule.Node) {\n const declaration = node as unknown as { source: { value: unknown }; specifiers: { type: string; imported?: { name?: string }; local: { name: string } }[] }\n if (declaration.source.value !== '@estiva-app/ui') return\n for (const specifier of declaration.specifiers) if (specifier.type === 'ImportSpecifier' && specifier.imported?.name === 'ContainerHeader') bare.add(specifier.local.name)\n },\n JSXOpeningElement(node: Rule.Node) {\n const element = node as unknown as JSXElement['openingElement']\n if (element.name.type !== 'JSXIdentifier' || !bare.has(element.name.name ?? '')) return\n if (isEscaped(context, element)) return\n context.report({ loc: element.loc, messageId: 'bare' })\n },\n JSXElement(node: Rule.Node) {\n const column = node as unknown as JSXElement\n const kids = meaningful(column)\n const first = kids[0]\n if (kids.length < 2 || !isElement(first) || !/^[a-z]/.test(tagOf(first))) return\n const own = classesOf(first)\n if (!ROW(own) || !OWN_SIDE_PADDING(own)) return\n if (INTERACTIVE.some((name) => attribute(first, name))) return\n if (!FILLS(classesOf(column)) && !BAR(own)) return\n if (!carriesTitle(first)) return\n if (isEscaped(context, first.openingElement)) return\n context.report({ loc: first.openingElement.loc, messageId: 'handmade' })\n },\n }\n },\n}\n", "import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'\nimport { dirname, join, relative, resolve } from 'node:path'\nimport type { Rule } from 'eslint'\nimport type ts from 'typescript'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\nimport { classUnits, componentsOf, copies, looksOf, parseForLooks, sharedLooksOf, type ClassUnit } from './looks-of'\n\n/**\n * UIG-25: a component's look typed again by hand. **A warning, never an error**\n * (Katerina, 13 September): a copy is found by how alike two lists are, and\n * likeness is a judgement \u2014 a warning gets read, a guess that blocks gets\n * switched off.\n *\n * Every class list in the file (see `looks-of.ts` for where one is read) is\n * compared, by its look words alone, against the looks of every catalogued\n * part in another file. A list is a copy when it shares `MIN_SHARED` look words\n * with one of a part's looks, covering `MIN_COVER` of the shorter of the two.\n *\n * - **In an app**, the parts are the package's \u2014 read from the catalogue the\n * installed package ships (`@estiva-app/ui/registry.json`, its `looks`) \u2014 and\n * the app's own exported components, read from its `src`. So a part added to\n * either is covered the day it is added, with no list kept here. The fix:\n * use the part.\n * - **In the package**, the parts are its own. The fix: write the look once in\n * `src/looks.ts` and use it in both.\n *\n * Left alone: a part's look in its own file, and a component named like the\n * part it wraps (Peek's `Avatar` over the package's). A constant imported from\n * another file is a look written once, not a copy. Peek and Ship copying each\n * other is not seen here \u2014 each app knows only itself and the package \u2014 and\n * is counted by `gates:status`.\n */\n\ninterface Look {\n part: string\n file: string\n look: string[]\n /** The installed package's part, this repo's own part, or a shared look (`\u2026_CLASSES`) this repo writes once. */\n from: 'package' | 'own' | 'shared'\n}\n\nconst packageDirCache = new Map<string, string | null>()\nfunction packageDirOf(file: string): string | null {\n const start = dirname(resolve(file))\n if (packageDirCache.has(start)) return packageDirCache.get(start) ?? null\n let dir = start\n for (;;) {\n if (existsSync(join(dir, 'package.json'))) break\n const up = dirname(dir)\n if (up === dir) {\n dir = ''\n break\n }\n dir = up\n }\n packageDirCache.set(start, dir || null)\n return dir || null\n}\n\nconst PACKAGE = '@estiva-app/ui'\nconst nameOf = (dir: string) => {\n try {\n return (JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as { name?: string }).name\n } catch {\n return undefined\n }\n}\n\n/** The installed package's parts and their looks, from the catalogue it ships. */\nconst shippedCache = new Map<string, { mtime: number; looks: Look[] }>()\nfunction shippedLooks(appDir: string): Look[] {\n for (let dir = appDir; ; dir = dirname(dir)) {\n const file = join(dir, 'node_modules', PACKAGE, 'registry.json')\n if (existsSync(file)) {\n const mtime = statSync(file).mtimeMs\n const cached = shippedCache.get(file)\n if (cached && cached.mtime === mtime) return cached.looks\n let looks: Look[] = []\n try {\n const registry = JSON.parse(readFileSync(file, 'utf8')) as { entries: { name: string; sourceFile: string; looks?: string[] }[] }\n looks = registry.entries.flatMap((e) => (e.looks ?? []).map((l) => ({ part: e.name, file: e.sourceFile, look: l.split(' '), from: 'package' as const })))\n } catch {\n // A catalogue that does not parse is its own check's business.\n }\n shippedCache.set(file, { mtime, looks })\n return looks\n }\n if (dirname(dir) === dir) return []\n }\n}\n\n/** The names a file exports. */\nfunction exportedNames(source: ts.SourceFile): Set<string> {\n const names = new Set<string>()\n const text = source.text\n for (const m of text.matchAll(/export\\s+(?:default\\s+)?(?:function|const)\\s+([A-Z]\\w*)/g)) names.add(m[1])\n for (const m of text.matchAll(/export\\s*\\{([^}]*)\\}/g)) for (const part of m[1].split(',')) {\n const name = part.trim().split(/\\s+as\\s+/).pop()\n if (name && /^[A-Z]/.test(name)) names.add(name)\n }\n return names\n}\n\n/** A repo's own exported components and their looks, from its `src`. */\nconst ownCache = new Map<string, { mtime: number; looks: Look[] }>()\nfunction ownLooks(repoDir: string): Look[] {\n const out: Look[] = []\n const walk = (dir: string) => {\n let names: string[] = []\n try {\n names = readdirSync(dir)\n } catch {\n return\n }\n for (const name of names) {\n if (name === 'node_modules' || name === 'dist') continue\n const path = join(dir, name)\n if (statSync(path).isDirectory()) walk(path)\n else if (/\\.tsx?$/.test(name) && !/\\.(?:stories|test)\\.tsx?$/.test(name) && !name.endsWith('.d.ts')) {\n const mtime = statSync(path).mtimeMs\n let cached = ownCache.get(path)\n if (!cached || cached.mtime !== mtime) {\n const text = readFileSync(path, 'utf8')\n const source = parseForLooks(path, text)\n const exported = name.endsWith('.tsx') ? [...componentsOf(source).keys()].filter((n) => exportedNames(source).has(n)) : []\n const file = relative(repoDir, path).replace(/\\\\/g, '/')\n const looks: Look[] = [...looksOf(source, exported)].flatMap(([part, lists]) => lists.map((l) => ({ part, file, look: l.split(' '), from: 'own' as const })))\n // A shared look written once (`\u2026_CLASSES`): a copy of it is told to use it.\n if (text.includes('_CLASSES')) for (const [part, lists] of sharedLooksOf(source)) for (const l of lists) looks.push({ part, file, look: l.split(' '), from: 'shared' })\n cached = { mtime, looks }\n ownCache.set(path, cached)\n }\n out.push(...cached.looks)\n }\n }\n }\n walk(join(repoDir, 'src'))\n return out\n}\n\nexport const noCopiedLook: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n docs: { description: \"A part's look typed again by hand, where the part (or a shared look) should be used\" },\n schema: [],\n messages: {\n usePart:\n \"This class list is `{{part}}`'s look, typed again ({{count}} words: {{words}}). Use `{{part}}` from {{from}}: a copy looks right today and stays behind the day `{{part}}` changes.\",\n shareIt:\n 'This look is also written in `{{part}}` ({{file}}): {{words}}. Write it once in src/looks.ts and use it in both, so the two cannot drift apart.',\n useShared:\n 'This class list is `{{part}}` ({{file}}), typed again: {{words}}. Use `{{part}}`: a look written once cannot drift apart.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const file = context.filename\n const repoDir = packageDirOf(file)\n if (!repoDir) return {}\n const inPackage = nameOf(repoDir) === PACKAGE\n return {\n Program() {\n const here = relative(repoDir, file).replace(/\\\\/g, '/')\n const source = parseForLooks(file, context.sourceCode.text)\n const declared = new Set(componentsOf(source).keys())\n const looks = [...(inPackage ? [] : shippedLooks(repoDir)), ...ownLooks(repoDir)].filter((l) => l.file !== here && !declared.has(l.part))\n if (!looks.length) return\n const units = classUnits(source)\n // A string inside a className is read with it; report the className once.\n const within = (u: ClassUnit) => units.some((o) => o !== u && o.via === 'attribute' && u.via === 'literal' && u.start >= o.start && u.end <= o.end)\n const reported = new Set<number>()\n for (const unit of units) {\n if (within(unit) || reported.has(unit.start)) continue\n let best: { look: Look; shared: string[] } | null = null\n for (const look of looks) {\n // A shared look is compared with the package's parts only: the parts here that use it are not its copies.\n if (unit.shared && look.from !== 'package') continue\n const shared = copies(unit.look, look.look)\n // On a tie, the shared look: using it is the whole fix.\n if (shared && (!best || shared.length > best.shared.length || (shared.length === best.shared.length && look.from === 'shared'))) best = { look, shared }\n }\n if (!best) continue\n // A className built from a constant of this file is reported once, at the constant.\n const found = best\n if (unit.via === 'attribute' && units.some((o) => o.via === 'literal' && !within(o) && found.shared.every((w) => o.look.includes(w)) && looks.some((l) => copies(o.look, l.look)))) continue\n const loc = { start: context.sourceCode.getLocFromIndex(unit.start), end: context.sourceCode.getLocFromIndex(unit.end) }\n const at = { start: context.sourceCode.getLocFromIndex(unit.anchor), end: loc.end }\n if (isEscaped(context, { loc: at, range: [unit.anchor, unit.end] })) continue\n reported.add(unit.start)\n const words = best.shared.map((w) => `\\`${w}\\``).join(' ')\n if (best.look.from === 'shared') context.report({ loc, messageId: 'useShared', data: { part: best.look.part, file: best.look.file, words } })\n else if (inPackage) context.report({ loc, messageId: 'shareIt', data: { part: best.look.part, file: best.look.file, words } })\n else\n context.report({\n loc,\n messageId: 'usePart',\n data: { part: best.look.part, count: String(best.shared.length), words, from: best.look.from === 'package' ? PACKAGE : `\\`${best.look.file}\\`` },\n })\n }\n },\n }\n },\n}\n", "import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join, resolve as resolvePath } from 'node:path'\nimport ts from 'typescript'\n\n/**\n * What a component looks like, read from its source: every class list it\n * writes (UIG-25). Shared by the catalogue, which records each part's looks in\n * `registry.json`, and by `estiva/no-copied-look`, which compares a class list\n * typed by hand against them \u2014 so the two always mean the same thing by \"look\".\n *\n * A class list is read wherever it is written: a `className` (or any\n * `\u2026ClassName`), through `cn()`/`clsx()`, a ternary, a `&&`, a template, a\n * `const` in the file, or a class map indexed by a key; and every string that\n * is a class list on its own. A constant imported from another file is not\n * followed: a look written once and imported is not a copy.\n *\n * Only the **look words** count \u2014 colour, text, border, corner, shadow.\n * Placement (where it sits, how much room it takes) is everyone's and says\n * nothing about which part a list is copied from.\n */\n\n/** Where a thing sits and how much room it takes: never part of a look (the same list as `no-restyled-part`'s PLACEMENT). */\nconst PLACEMENT = [\n /^m[xytrblse]?-/,\n /^p[xytrblse]?-/,\n /^(?:w|h|size|min-w|min-h|max-w|max-h)-/,\n /^(?:hidden|block|inline|inline-block|inline-flex|inline-grid|flex|grid|contents|flow-root)$/,\n /^(?:grow|shrink)$|^(?:flex|basis|grow|shrink|order|gap|gap-x|gap-y|space-x|space-y|col|row|grid-cols|grid-rows|grid-flow|auto-cols|auto-rows)-/,\n /^(?:self|justify|justify-items|justify-self|items|place-content|place-items|place-self)-|^content-(?!\\[)/,\n /^(?:static|relative|absolute|fixed|sticky)$|^(?:inset|inset-x|inset-y|top|right|bottom|left|start|end|z)-/,\n /^(?:group|peer)(?:\\/[\\w-]+)?$/,\n]\nconst bare = (token: string) => token.replace(/^(?:[^:\\s[\\]]+:)+/, '')\nexport const isPlacementWord = (token: string) => PLACEMENT.some((pattern) => pattern.test(bare(token)))\n\n/** A word that could be a Tailwind class: lower case, dashes, variants, arbitrary values. */\nconst CLASSY = /^!?(?:[a-z0-9-]+:|\\[[^\\]\\s]+\\]:)*-?[a-z@][a-z0-9-]*(?:-\\[[^\\]\\s]+\\]|\\/[\\w.[\\]-]+|-[\\w.]+)*$|^\\[[^\\]\\s]+\\]$/\nconst words = (text: string) => text.split(/\\s+/).filter(Boolean)\nconst CLASS_FUNCTIONS = new Set(['cn', 'clsx', 'cx', 'twMerge', 'classNames'])\nconst CLASS_PROP = /^(?:className|[a-z][A-Za-z]*ClassName)$/\n\n/** A string is a class list on its own when every word could be a class, and two at least have a dash or a variant. */\nfunction isClassList(text: string): boolean {\n const list = words(text)\n return list.length >= 3 && list.every((w) => CLASSY.test(w)) && list.filter((w) => /[-:[]/.test(w)).length >= 2\n}\n\nexport interface ClassUnit {\n /** Every class of the list, placement included, as written. */\n tokens: string[]\n /** Its look words only. */\n look: string[]\n /** Offsets in the file, for a report. */\n start: number\n end: number\n /** A `className` (resolved through the file), or a string that is a class list on its own. */\n via: 'attribute' | 'literal'\n /** Where an escape for it is read: the element a `className` is on, or the string itself. */\n anchor: number\n /** The value of an exported `\u2026_CLASSES` constant: a shared look, where it is written once. */\n shared: boolean\n}\n\nconst CAP = 24\n\n/**\n * Every class list a file writes. `follow` resolves a name the file imports,\n * for a part's own look: what it draws includes a look it takes from a shared\n * file. A list being checked is never followed \u2014 using a shared look is not\n * copying it.\n */\nexport function classUnits(source: ts.SourceFile, follow?: (name: string) => ts.Expression | undefined): ClassUnit[] {\n const consts = new Map<string, ts.Expression>()\n const collect = (node: ts.Node) => {\n if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer && ts.isVariableDeclarationList(node.parent) && node.parent.flags & ts.NodeFlags.Const) {\n consts.set(node.name.text, node.initializer)\n }\n ts.forEachChild(node, collect)\n }\n collect(source)\n\n const product = (lists: string[][][]): string[][] => {\n let out: string[][] = [[]]\n for (const alternatives of lists) {\n const next: string[][] = []\n for (const a of out) for (const b of alternatives) if (next.length < CAP) next.push([...a, ...b])\n out = next\n }\n return out\n }\n const resolve = (node: ts.Node | undefined, depth = 0): string[][] => {\n if (!node || depth > 8) return [[]]\n if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return [words(node.text)]\n if (ts.isTemplateExpression(node)) return product([[words(node.head.text)], ...node.templateSpans.flatMap((span) => [resolve(span.expression, depth + 1), [words(span.literal.text)]])])\n if (ts.isParenthesizedExpression(node) || ts.isAsExpression(node) || ts.isSatisfiesExpression(node) || ts.isNonNullExpression(node)) return resolve(node.expression, depth + 1)\n if (ts.isJsxExpression(node)) return resolve(node.expression, depth + 1)\n if (ts.isCallExpression(node)) return ts.isIdentifier(node.expression) && CLASS_FUNCTIONS.has(node.expression.text) ? product(node.arguments.map((a) => resolve(a, depth + 1))) : [[]]\n if (ts.isConditionalExpression(node)) return [...resolve(node.whenTrue, depth + 1), ...resolve(node.whenFalse, depth + 1)].slice(0, CAP)\n if (ts.isBinaryExpression(node)) {\n // Off first: a look is the part at rest, with each option taken one at a time, never all at once.\n if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) return [[], ...resolve(node.right, depth + 1)]\n if (node.operatorToken.kind === ts.SyntaxKind.BarBarToken || node.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken) return [...resolve(node.left, depth + 1), ...resolve(node.right, depth + 1)].slice(0, CAP)\n return [[]]\n }\n if (ts.isArrayLiteralExpression(node)) return product(node.elements.map((e) => resolve(e, depth + 1)))\n if (ts.isObjectLiteralExpression(node)) return [[], node.properties.flatMap((p) => (p.name && (ts.isIdentifier(p.name) || ts.isStringLiteral(p.name)) ? words(p.name.text) : []))]\n if (ts.isIdentifier(node)) {\n const init = consts.get(node.text) ?? follow?.(node.text)\n return init ? resolve(init, depth + 1) : [[]]\n }\n if (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) {\n let target: ts.Expression | undefined = node.expression\n if (ts.isIdentifier(target)) target = consts.get(target.text) ?? follow?.(target.text)\n while (target && (ts.isAsExpression(target) || ts.isSatisfiesExpression(target) || ts.isParenthesizedExpression(target))) target = target.expression\n if (!target || !ts.isObjectLiteralExpression(target)) return [[]]\n const key = ts.isPropertyAccessExpression(node) ? node.name.text : ts.isStringLiteral(node.argumentExpression) ? node.argumentExpression.text : null\n return target.properties\n .filter((p): p is ts.PropertyAssignment => ts.isPropertyAssignment(p) && (key === null || (!!p.name && (ts.isIdentifier(p.name) || ts.isStringLiteral(p.name)) && p.name.text === key)))\n .flatMap((p) => resolve(p.initializer, depth + 1))\n .slice(0, CAP)\n }\n return [[]]\n }\n\n const units: ClassUnit[] = []\n const seen = new Set<string>()\n const sharedAt = (node: ts.Node) => {\n for (let at: ts.Node | undefined = node; at; at = at.parent) {\n if (ts.isVariableDeclaration(at)) return ts.isIdentifier(at.name) && /_CLASSES$/.test(at.name.text) && !!at.parent?.parent && ts.isVariableStatement(at.parent.parent) && !!at.parent.parent.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)\n }\n return false\n }\n // A string's escape is read above the line it starts: the widest thing that starts on that line.\n const lineStart = (node: ts.Node) => {\n const line = source.getLineAndCharacterOfPosition(node.getStart(source)).line\n let at = node\n while (at.parent && !ts.isSourceFile(at.parent) && source.getLineAndCharacterOfPosition(at.parent.getStart(source)).line === line) at = at.parent\n return at.getStart(source)\n }\n const add = (tokens: string[], node: ts.Node, via: ClassUnit['via'], anchor = via === 'literal' ? lineStart(node) : node.getStart(source)) => {\n const list = [...new Set(tokens.filter((t) => CLASSY.test(t)))]\n const look = list.filter((t) => !isPlacementWord(t))\n if (look.length === 0) return\n const key = `${via}:${node.getStart(source)}:${[...list].sort().join(' ')}`\n if (seen.has(key)) return\n seen.add(key)\n units.push({ tokens: list, look, start: node.getStart(source), end: node.getEnd(), via, anchor, shared: via === 'literal' && sharedAt(node) })\n }\n const visit = (node: ts.Node) => {\n if (ts.isJsxAttribute(node) && ts.isIdentifier(node.name) && CLASS_PROP.test(node.name.text) && node.initializer) {\n // An escape goes on the line above the element, as it does for every rule of the plugin.\n const element = node.parent.parent\n for (const alternative of resolve(node.initializer)) add(alternative, node, 'attribute', element.getStart(source))\n }\n if ((ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) && isClassList(node.text)) add(words(node.text), node, 'literal')\n ts.forEachChild(node, visit)\n }\n visit(source)\n return units\n}\n\n/** The function components a file declares, by name, with where each one's body is. */\nexport function componentsOf(source: ts.SourceFile): Map<string, { start: number; end: number }> {\n const found = new Map<string, { start: number; end: number }>()\n const fn = (node: ts.Expression | undefined): ts.Node | undefined => {\n let current = node\n while (current && ts.isCallExpression(current) && current.arguments.length) current = current.arguments[0]\n return current && (ts.isArrowFunction(current) || ts.isFunctionExpression(current)) ? current : undefined\n }\n for (const statement of source.statements) {\n if (ts.isFunctionDeclaration(statement) && statement.name && /^[A-Z]/.test(statement.name.text)) found.set(statement.name.text, { start: statement.getStart(source), end: statement.getEnd() })\n if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n const body = fn(declaration.initializer)\n if (ts.isIdentifier(declaration.name) && /^[A-Z]/.test(declaration.name.text) && body) found.set(declaration.name.text, { start: body.getStart(source), end: body.getEnd() })\n }\n }\n }\n return found\n}\n\n/** A look is worth comparing when it has this many look words at least: fewer is a text style, not a part. */\nexport const MIN_LOOK_WORDS = 4\n\n/**\n * Each named component's looks: its class lists' look words, one space-joined\n * string per list, those with `MIN_LOOK_WORDS` or more. A list written outside\n * every component of the file (a top-level constant, a class map) belongs to\n * every component in it.\n */\nexport function looksOf(source: ts.SourceFile, names?: Iterable<string>): Map<string, string[]> {\n const components = componentsOf(source)\n const units = classUnits(source, importedConstants(source)).filter((u) => u.look.length >= MIN_LOOK_WORDS)\n const inside = (u: ClassUnit, r: { start: number; end: number }) => u.start >= r.start && u.start < r.end\n const out = new Map<string, string[]>()\n for (const name of names ?? components.keys()) {\n const range = components.get(name)\n const mine = units.filter((u) => (range ? inside(u, range) : false) || ![...components.values()].some((r) => inside(u, r)))\n out.set(name, [...new Set(mine.map((u) => u.look.join(' ')))])\n }\n return out\n}\n\n/** Read and parse a file for looks. */\nexport function parseForLooks(fileName: string, text: string): ts.SourceFile {\n return ts.createSourceFile(fileName, text, ts.ScriptTarget.Latest, true, fileName.endsWith('x') ? ts.ScriptKind.TSX : ts.ScriptKind.TS)\n}\n\n/** How much of a look a class list must share to be a copy of it (UIG-25, Katerina 24 September). */\nexport const MIN_SHARED = 4\nexport const MIN_COVER = 0.8\n\n/** The look words a list shares with a look, when it is a copy of it; otherwise null. */\nexport function copies(list: string[], look: string[]): string[] | null {\n const mine = new Set(list)\n const shared = look.filter((word) => mine.has(word))\n if (shared.length < MIN_SHARED) return null\n return shared.length / Math.min(list.length, look.length) >= MIN_COVER ? shared : null\n}\n\n/** The file a relative or `@/` import names, from the file that imports it. */\nfunction importTarget(fromFile: string, specifier: string): string | null {\n let base: string\n if (specifier.startsWith('.')) base = resolvePath(dirname(fromFile), specifier)\n else if (specifier.startsWith('@/')) {\n let dir = dirname(resolvePath(fromFile))\n while (!existsSync(join(dir, 'package.json')) && dirname(dir) !== dir) dir = dirname(dir)\n base = join(dir, 'src', specifier.slice(2))\n } else return null\n for (const candidate of [`${base}.ts`, `${base}.tsx`, join(base, 'index.ts')]) if (existsSync(candidate)) return candidate\n return null\n}\n\nconst constantsCache = new Map<string, Map<string, ts.Expression>>()\n/** A file's top-level `const`s, by name. */\nfunction constantsOf(file: string): Map<string, ts.Expression> {\n const cached = constantsCache.get(file)\n if (cached) return cached\n const found = new Map<string, ts.Expression>()\n const source = parseForLooks(file, readFileSync(file, 'utf8'))\n for (const statement of source.statements) {\n if (!ts.isVariableStatement(statement)) continue\n for (const d of statement.declarationList.declarations) if (ts.isIdentifier(d.name) && d.initializer) found.set(d.name.text, d.initializer)\n }\n constantsCache.set(file, found)\n return found\n}\n\n/** A resolver for the class constants a file imports from its own repo: `FIELD_BOX_CLASSES` from `./looks`. */\nexport function importedConstants(source: ts.SourceFile): (name: string) => ts.Expression | undefined {\n const imported = new Map<string, { file: string; name: string }>()\n for (const statement of source.statements) {\n if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) continue\n const bindings = statement.importClause?.namedBindings\n if (!bindings || !ts.isNamedImports(bindings)) continue\n const target = importTarget(source.fileName, statement.moduleSpecifier.text)\n if (!target) continue\n for (const element of bindings.elements) {\n const local = element.name.text\n if (/_CLASSES$/.test(element.propertyName?.text ?? local)) imported.set(local, { file: target, name: element.propertyName?.text ?? local })\n }\n }\n return (name) => {\n const from = imported.get(name)\n if (!from) return undefined\n try {\n return constantsOf(from.file).get(from.name)\n } catch {\n return undefined\n }\n }\n}\n\n/**\n * The shared looks a file declares: each exported `\u2026_CLASSES` constant, a string\n * or a map of strings, by name (`FIELD_SIZE_CLASSES.small`). A hand-typed copy of\n * one is told to use it.\n */\nexport function sharedLooksOf(source: ts.SourceFile): Map<string, string[]> {\n const out = new Map<string, string[]>()\n const lookWords = (text: string) => words(text).filter((w) => CLASSY.test(w) && !isPlacementWord(w))\n for (const statement of source.statements) {\n if (!ts.isVariableStatement(statement) || !statement.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) continue\n for (const d of statement.declarationList.declarations) {\n if (!ts.isIdentifier(d.name) || !/_CLASSES$/.test(d.name.text) || !d.initializer) continue\n let init: ts.Expression = d.initializer\n while (ts.isAsExpression(init) || ts.isSatisfiesExpression(init) || ts.isParenthesizedExpression(init)) init = init.expression\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const look = lookWords(init.text)\n if (look.length >= MIN_LOOK_WORDS) out.set(d.name.text, [look.join(' ')])\n } else if (ts.isObjectLiteralExpression(init)) {\n for (const p of init.properties) {\n if (!ts.isPropertyAssignment(p) || !p.name || !(ts.isIdentifier(p.name) || ts.isStringLiteral(p.name))) continue\n if (!(ts.isStringLiteral(p.initializer) || ts.isNoSubstitutionTemplateLiteral(p.initializer))) continue\n const look = lookWords(p.initializer.text)\n if (look.length >= MIN_LOOK_WORDS) out.set(`${d.name.text}.${p.name.text}`, [look.join(' ')])\n }\n }\n }\n }\n return out\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\nimport { bindingOfTag, partsOfFile, type Node, type Parser, type PartBinding } from './no-restyled-part'\n\n/**\n * The parts a person types into to send something. `Field` is the labelled\n * row; `TextInput` and `Textarea` are judged on their own only in a file that\n * draws no `Field`, so a field is reported once, at its label.\n */\nexport const FIELD_PARTS = ['Field', 'TextInput', 'Textarea'] as const\n\n/** The parts that are a `Form`: the package's own, and the palette's form level, which is one (UIG-29). */\nexport const FORM_PARTS = ['Form', 'CommandPaletteForm'] as const\n\nconst child = (node: Node, key: string) => node[key] as Node | null | undefined\nconst nameOf = (node: Node | null | undefined): string | undefined =>\n node?.type === 'JSXIdentifier' || node?.type === 'Identifier' ? (node.name as string) : undefined\n\n/**\n * A field outside a `Form` (Katerina, 1 October, after Peek's and Ship's\n * Archive dialog: a resolution typed into a `ConfirmDialog`, sent by its\n * button, with no form around it \u2014 Ctrl+Enter did nothing, and the field\n * stayed open while it archived).\n *\n * `Form` owns what a field needs to be sent: Enter and Ctrl+Enter, `busy`\n * switching every field off at once, and where focus goes after. A field\n * outside one has none of it, and the dialog around it is the wrong one: a\n * question with a field in it is a `DialogShell` with a `Form`\n * (ConfirmDialog's page, **When not**).\n *\n * Judged: a `Field`, a `TextInput` or a `Textarea` of the package (or an\n * app's re-export or wrapper of one) with no `Form` around it in the same\n * file. Not judged, on purpose:\n *\n * - `EditableText` and `SearchInput`: one saves itself as you leave it, the\n * other filters a list, and neither is sent (Form's page, **When not**);\n * - a `TextInput` or `Textarea` in a file that draws a `Field`: the `Field`\n * is reported, and a control handed to it from a function of its own (a\n * `switch` over field kinds) cannot be followed to it;\n * - the app's own components: a component that draws a field for a form its\n * caller holds says so with an escape on the field, naming that caller.\n */\nexport const noFieldOutsideAForm: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'A field with no Form around it' },\n schema: [],\n messages: {\n loose:\n '`{{part}}` has no `Form` around it, so nothing owns sending it: Enter and Ctrl+Enter, `busy`, and focus after. Put it in `Form` from @estiva-app/ui; in a dialog, that is `DialogShell` with a `Form`, never `ConfirmDialog` (Primitives/Form says how).',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const parser = (context.languageOptions?.parser ?? {}) as Parser\n let locals: Map<string, PartBinding | 'namespace'> | undefined\n const loose: { opening: Node; part: string }[] = []\n let drawsAField = false\n const partOf = (element: Node): string | undefined => {\n const tag = child(child(element, 'openingElement') as Node, 'name')\n const name = nameOf(tag)\n if (!name || /^[a-z]/.test(name)) return undefined\n const binding = locals && bindingOfTag(tag, locals)\n return binding && binding.props === 'all' ? binding.part : undefined\n }\n return {\n Program(program) {\n locals = partsOfFile(context.filename, program as unknown as Node, parser)\n },\n JSXElement(ruleNode: Rule.Node) {\n const element = ruleNode as unknown as Node\n const part = partOf(element)\n if (!part || !(FIELD_PARTS as readonly string[]).includes(part)) return\n if (part === 'Field') drawsAField = true\n for (let up = element.parent as Node | undefined; up; up = up.parent as Node | undefined) {\n if (up.type !== 'JSXElement') continue\n const around = partOf(up)\n if (around && (FORM_PARTS as readonly string[]).includes(around)) return\n if (around === 'Field') return\n }\n loose.push({ opening: child(element, 'openingElement') as Node, part })\n },\n 'Program:exit'() {\n for (const { opening, part } of loose) {\n if (part !== 'Field' && drawsAField) continue\n if (isEscaped(context, opening)) continue\n context.report({ loc: opening.loc as NonNullable<Rule.Node['loc']>, messageId: 'loose', data: { part } })\n }\n },\n }\n },\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\nimport { bindingOfTag, partsOfFile, type Node, type Parser, type PartBinding } from './no-restyled-part'\n\n/**\n * The parts whose `title` is their own: the words of a heading or a dialog,\n * drawn on the page. Every other part hands a `title` on to its element, and\n * the browser shows it as its tooltip. `no-native-title.test.ts` holds this\n * list to the catalogue: a part that gains a `title` of its own joins it.\n */\nexport const PARTS_WITH_A_TITLE = ['CollapsibleSection', 'ConfirmDialog', 'ContainerHeader', 'DialogShell', 'ListColumn', 'NavTree', 'NavTreeSection', 'Panel', 'SectionHeader'] as const\n\nconst child = (node: Node, key: string) => node[key] as Node | null | undefined\nconst nameOf = (node: Node | null | undefined): string | undefined =>\n node?.type === 'JSXIdentifier' || node?.type === 'Identifier' ? (node.name as string) : undefined\n\n/**\n * UIG-24: the browser's tooltip where ours belongs.\n *\n * A `title` on an element is the browser's hover box: grey, in the system's\n * font, after a delay nobody chose, and never on a touch screen. The package's\n * `WithTooltip` is the tooltip here (and `IconButton`'s `tooltip`, which draws\n * it). The rule reads the attribute, never the page: a tooltip's words are not\n * on the page until it opens.\n *\n * Judged: a `title` on a plain element, and on a part of the package (or an\n * app's wrapper that hands all its props on to one) whose `title` is not its\n * own \u2014 `<Button title>` reaches the `<button>`. Not judged, on purpose:\n *\n * - the `<title>` **element**, in an `<svg>` (a label for a screen reader) or\n * a document's head: an element, not an attribute, so the rule never sees it;\n * - a part whose `title` is its own heading (`PARTS_WITH_A_TITLE`);\n * - the app's own components: what one does with a `title` is its own business,\n * and its elements are judged where it draws them;\n * - a story's `title` (`meta = { title: 'Group/Name' }`): an object key, not an\n * attribute.\n */\nexport const noNativeTitle: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: \"A title attribute: the browser's tooltip where WithTooltip is the part\" },\n schema: [],\n messages: {\n native:\n \"`title` is the browser's tooltip, not ours. Wrap it in `WithTooltip` from @estiva-app/ui, or use `IconButton`'s `tooltip`: its page (Primitives/Tooltip) says when it shows and how.\",\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const parser = (context.languageOptions?.parser ?? {}) as Parser\n let locals: Map<string, PartBinding | 'namespace'> | undefined\n return {\n Program(program) {\n locals = partsOfFile(context.filename, program as unknown as Node, parser)\n },\n JSXAttribute(ruleNode: Rule.Node) {\n const attribute = ruleNode as unknown as Node\n if (nameOf(child(attribute, 'name')) !== 'title') return\n const opening = attribute.parent as Node\n const tag = child(opening, 'name')\n const name = nameOf(tag)\n if (!(name && /^[a-z]/.test(name))) {\n const binding = locals && bindingOfTag(tag, locals)\n if (!binding || binding.props !== 'all') return\n if ((PARTS_WITH_A_TITLE as readonly string[]).includes(binding.part)) return\n }\n if (isEscaped(context, opening)) return\n context.report({ loc: attribute.loc as NonNullable<Rule.Node['loc']>, messageId: 'native' })\n },\n }\n },\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\ninterface JSXAttributeValue {\n type: string\n value?: unknown\n expression?: { type: string; value?: unknown; expressions?: unknown[]; quasis?: { value: { cooked: string | null } }[] }\n}\n\ninterface JSXAttribute {\n type: 'JSXAttribute'\n name: { type: string; name?: string }\n value: JSXAttributeValue | null\n}\n\ninterface JSXOpeningElement {\n name: { type: string; name?: string }\n attributes: (JSXAttribute | { type: 'JSXSpreadAttribute' })[]\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n}\n\n/**\n * What the package has instead of one raw element: the component the message\n * names, and where one element does more than one job, the others after it.\n * `null` is an element the package has no part for yet.\n */\nexport interface RawElementPart {\n use: string\n more?: string\n}\n\n/**\n * The mapping (UIG-7), derived from the package's exports: every interactive\n * element in the HTML standard's list (\"interactive content\"), plus `<dialog>`,\n * `<form>` and `<progress>`, which have a part here. docs/GATES.md prints it.\n *\n * Not here, on purpose: `<summary>` (it lives inside a `<details>`, which is\n * reported), `<option>`, `<optgroup>` and `<datalist>` (they live inside a\n * `<select>` or beside an input), `<fieldset>` and `<legend>` (a group's frame,\n * no control of its own), and `<img>` without `usemap`, `<hr>`, `<kbd>`, which\n * are not controls. An `<audio>` or `<video>` is a control only with `controls`.\n */\nexport const RAW_ELEMENT_PARTS: Record<string, RawElementPart | null> = {\n a: { use: 'Link', more: ' For a chip, `InlineChip`; for a whole card, `Card` with `href`.' },\n button: { use: 'Button' },\n textarea: { use: 'Textarea' },\n select: { use: 'Select' },\n dialog: { use: 'DialogShell', more: ' To ask yes or no, `ConfirmDialog`.' },\n label: { use: 'Field', more: ' For words beside a tick box, `Checkbox` with `label`.' },\n details: { use: 'CollapsibleSection' },\n progress: { use: 'ProgressBar' },\n form: { use: 'Form' },\n meter: null,\n iframe: null,\n embed: null,\n object: null,\n audio: null,\n video: null,\n img: null,\n}\n\n/**\n * An `<input>` is as many controls as its `type`. A type missing from here\n * (text, email, password, url, tel, number, or one the browser does not know)\n * is a text box.\n */\nexport const RAW_INPUT_PARTS: Record<string, RawElementPart | null> = {\n search: { use: 'SearchInput' },\n checkbox: { use: 'Checkbox' },\n file: { use: 'FilePicker' },\n submit: { use: 'Button' },\n button: { use: 'Button' },\n reset: { use: 'Button' },\n image: { use: 'Button' },\n radio: null,\n range: null,\n color: null,\n date: null,\n 'datetime-local': null,\n month: null,\n week: null,\n time: null,\n}\n\nconst TEXT_INPUT: RawElementPart = { use: 'TextInput' }\nconst ANY_INPUT: RawElementPart = {\n use: 'TextInput',\n more: ' For a search, `SearchInput`; for a tick box, `Checkbox`; to pick files, `FilePicker`.',\n}\n\nfunction attribute(element: JSXOpeningElement, name: string): JSXAttribute | undefined {\n return element.attributes.find((a): a is JSXAttribute => a.type === 'JSXAttribute' && a.name.name === name)\n}\n\n/** An attribute's value when the code spells it out, `undefined` when it is computed. */\nfunction literal(attr: JSXAttribute): string | boolean | undefined {\n const value = attr.value\n if (value === null) return true\n if (value.type === 'Literal') return typeof value.value === 'string' ? value.value : undefined\n if (value.type !== 'JSXExpressionContainer' || !value.expression) return undefined\n const expression = value.expression\n if (expression.type === 'Literal' && (typeof expression.value === 'string' || typeof expression.value === 'boolean')) return expression.value\n if (expression.type === 'TemplateLiteral' && expression.expressions?.length === 0) return expression.quasis?.[0]?.value.cooked ?? undefined\n return undefined\n}\n\n/** Present, and not written as `={false}`. */\nfunction isOn(element: JSXOpeningElement, name: string): boolean {\n const attr = attribute(element, name)\n return attr !== undefined && literal(attr) !== false\n}\n\ntype Found = { report: 'raw'; element: string; part: RawElementPart } | { report: 'noPart'; element: string } | { report: 'clickable'; element: string } | null\n\n/** The pointer's press, as a handler on a plain element makes it a control (R5). */\nconst CLICK_HANDLERS = ['onClick', 'onMouseDown', 'onMouseUp', 'onPointerDown', 'onPointerUp', 'onDoubleClick']\n\ninterface Expression {\n type: string\n [key: string]: unknown\n}\n\n/** `e.stopPropagation()` or `e.preventDefault()`: a handler that only keeps the click from what is behind. */\nfunction onlyStops(handler: Expression | undefined): boolean {\n if (!handler || (handler.type !== 'ArrowFunctionExpression' && handler.type !== 'FunctionExpression')) return false\n const body = handler.body as Expression\n const calls = body.type === 'BlockStatement' ? (body.body as Expression[]).map((s) => (s.type === 'ExpressionStatement' ? (s.expression as Expression) : s)) : [body]\n return (\n calls.length > 0 &&\n calls.every((call) => {\n if (call.type !== 'CallExpression') return false\n const callee = call.callee as Expression\n const property = callee.type === 'MemberExpression' ? (callee.property as Expression) : undefined\n return property?.type === 'Identifier' && (property.name === 'stopPropagation' || property.name === 'preventDefault')\n })\n )\n}\n\n/** A plain element made clickable by hand: the first press handler that does more than stop the click. */\nfunction clickHandler(element: JSXOpeningElement): string | undefined {\n for (const name of CLICK_HANDLERS) {\n const attr = attribute(element, name)\n if (!attr) continue\n const value = attr.value\n const handler = value?.type === 'JSXExpressionContainer' ? (value.expression as Expression | undefined) : undefined\n if (!onlyStops(handler)) return name\n }\n return undefined\n}\n\n/** What this element is to the rule: a raw element with a part, one with none yet, or none of its business. */\nexport function classify(element: JSXOpeningElement): Found {\n if (element.name.type !== 'JSXIdentifier' || !element.name.name) return null\n const name = element.name.name\n\n if (name === 'input') {\n const attr = attribute(element, 'type')\n const type = attr ? literal(attr) : 'text'\n if (typeof type !== 'string') return { report: 'raw', element: '<input>', part: ANY_INPUT }\n const key = type.toLowerCase()\n // A hidden input draws nothing and takes no focus: it is data, not a control.\n if (key === 'hidden') return null\n if (!(key in RAW_INPUT_PARTS)) return { report: 'raw', element: '<input>', part: TEXT_INPUT }\n const part = RAW_INPUT_PARTS[key]\n const shown = `<input type=\"${key}\">`\n return part ? { report: 'raw', element: shown, part } : { report: 'noPart', element: shown }\n }\n\n if (!Object.hasOwn(RAW_ELEMENT_PARTS, name)) {\n // A plain element with a press handler is a button drawn by hand (Katerina's ruling R5,\n // 25 September): no focus, no keys, no look anybody keeps in step. `<option>` and\n // `<summary>` live inside a control the rule already reads.\n if (!/^[a-z][a-z0-9]*$/.test(name) || name === 'option' || name === 'summary') return null\n const handler = clickHandler(element)\n return handler ? { report: 'clickable', element: `<${name} ${handler}>` } : null\n }\n if ((name === 'audio' || name === 'video') && !isOn(element, 'controls')) return null\n if (name === 'img' && !attribute(element, 'usemap') && !attribute(element, 'useMap')) return null\n\n const part = RAW_ELEMENT_PARTS[name]\n return part ? { report: 'raw', element: `<${name}>`, part } : { report: 'noPart', element: `<${name}>` }\n}\n\n/**\n * A raw interactive element in an app, where the package has a part for it\n * (UIG-3 began it with `<button>`; UIG-7 made it every element). A control\n * the app writes itself has a look, a focus ring and keys that nobody else\n * keeps in step with \u2014 and it looks nearly right, which is why nobody catches\n * it by eye. Every message names the part to use.\n *\n * An element the package has no part for yet is refused too, with a message\n * that says so: the part is made in the package, not by hand in an app\n * (Katerina, 16 September).\n *\n * A plain element with a press handler (`<div onClick>`) is a control too, and\n * is refused naming `Button` (R5, 25 September); a handler that only stops the\n * click reaching what is behind passes.\n *\n * Only a JSX element written with a lowercase name. `<Button>`,\n * `<Foo.button>` and `createElement('button')` are not this rule's business.\n */\nexport const noRawElement: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'A raw interactive element where @estiva-app/ui has a part, or where it needs one' },\n schema: [],\n messages: {\n raw: 'Use `{{use}}` from @estiva-app/ui instead of a raw {{element}}.{{more}}',\n clickable:\n 'A clickable {{element}} is a button made by hand: it takes no focus and answers no key. Use `Button` from @estiva-app/ui; for a whole card that opens something, `Card` with `href`. A handler that only stops the click (`e.stopPropagation()`) is fine.',\n noPart: '@estiva-app/ui has no part for a raw {{element}} yet. Do not build one here: ask Katerina, and it gets made in @estiva-app/ui.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n return {\n // ESLint's types know ESTree's nodes, not JSX's; the parser hands this one over.\n JSXOpeningElement(node: Rule.Node) {\n const element = node as unknown as JSXOpeningElement\n const found = classify(element)\n if (!found) return\n if (isEscaped(context, element)) return\n if (found.report === 'clickable') context.report({ loc: element.loc, messageId: 'clickable', data: { element: found.element } })\n else if (found.report === 'noPart') context.report({ loc: element.loc, messageId: 'noPart', data: { element: found.element } })\n else context.report({ loc: element.loc, messageId: 'raw', data: { element: found.element, use: found.part.use, more: found.part.more ?? '' } })\n },\n }\n },\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\n/**\n * Behaviour the package already owns, rebuilt by hand in an app (UIG-8, \"forbid\n * the reach\"). A hand-made dropdown, dialog, list or scrolling box does not look\n * wrong in review; it shows itself when somebody uses a keyboard, or has 81\n * folders. Every message names the part that already does it.\n *\n * What it reads is derived from the package source: which `@base-ui/react` part\n * each component imports, and so what it owns (`OWNED_BEHAVIOURS`, printed in\n * docs/GATES.md and reused by UIG-12's registry). `no-rebuilt-behaviour.test.ts`\n * holds the tables to the source, so a new part cannot be added without them.\n *\n * What it deliberately does not read, and why:\n *\n * - **A box that should scroll and does not.** A class rule finds the scrolling\n * box built by hand; it cannot find the one that was never built. Peek's\n * Folders column (fixed in peek 3dc663b) had no overflow class at all. Only a\n * check that opens the page can find that.\n * - **Enter and Escape** compared by hand. In a field or an editor they are\n * typing, and `Form` and `EditableText` own the ones that send or cancel.\n * Escape and every other key taken for the whole page are read, through the\n * listener.\n * - **aria-expanded, aria-pressed and the other states** written on a package\n * component: the component is already the package's (UIG-14's usage rules).\n * - **Measuring arithmetic**, for the reason UIG-5 gave: `Popover` takes a\n * rectangle to hang from, and a rule that guessed at arithmetic would report it.\n * - A listener on a variable that happens to hold the document.\n *\n * A place that keeps one says why on the line above: `// @estiva-escape: <why>`.\n * An escape above a statement, an element or an object property covers what the\n * rule found there.\n */\n\n/** The part a message names, and where one behaviour has more owners, the others after it. `null`: no part yet. */\nexport interface OwnerPart {\n use: string\n more?: string\n}\n\n/**\n * Every Base UI module, and the package component built on it. Read from the\n * package's imports (`src/*.tsx`); the test fails if a component imports a\n * module this does not name, or names a component that does not import it.\n * A module no component uses has no part yet, and neither do Base UI's utilities.\n */\nexport const BASE_UI_PARTS: Record<string, OwnerPart | null> = {\n 'alert-dialog': { use: 'DialogShell', more: ' To ask yes or no, `ConfirmDialog`.' },\n autocomplete: { use: 'CommandPalette' },\n avatar: { use: 'Avatar' },\n button: { use: 'Button', more: ' Icon only, `IconButton`.' },\n checkbox: { use: 'Checkbox' },\n collapsible: { use: 'CollapsibleSection' },\n combobox: { use: 'ChipInput' },\n dialog: { use: 'DialogShell', more: ' To search and act, `CommandPalette`.' },\n field: { use: 'Field' },\n fieldset: { use: 'Form' },\n form: { use: 'Form' },\n input: { use: 'TextInput', more: ' For a search, `SearchInput`.' },\n menu: { use: 'Menu' },\n popover: { use: 'Popover' },\n 'preview-card': { use: 'PreviewCard' },\n progress: { use: 'ProgressBar' },\n 'scroll-area': { use: 'ScrollArea' },\n select: { use: 'Select' },\n separator: { use: 'Divider' },\n tabs: { use: 'Tabs' },\n toast: { use: 'Toast' },\n toggle: { use: 'Reaction' },\n toolbar: { use: 'Toolbar' },\n tooltip: { use: 'Tooltip', more: ' Around a control, `WithTooltip`.' },\n accordion: null,\n 'checkbox-group': null,\n 'context-menu': null,\n drawer: null,\n menubar: null,\n meter: null,\n 'navigation-menu': null,\n 'number-field': null,\n 'otp-field': null,\n radio: null,\n 'radio-group': null,\n slider: null,\n switch: null,\n 'toggle-group': null,\n}\n\nconst LIST_PART: OwnerPart = {\n use: 'Select',\n more: ' To pick several, `ChipInput`; to search and act, `CommandPalette`; to tick several in a list, `Checkbox` with `row`; for the list a text editor opens as you type, `SuggestionMenu`.',\n}\n\nconst MESSAGE_PART: OwnerPart = { use: 'FieldLine', more: ' For a notice, `Banner`; for a message that comes and goes, `Toast`.' }\n\n/**\n * A role written by hand, and the part that sets it. Base UI's parts set most of\n * these; `tooltip` (Base UI's Tooltip sets none), `alert`, `status` and `link` are\n * the package's own. A role Base UI has a part for and this package has not got\n * yet is `null`. Not here, on purpose: `img`, `group`, `presentation`, `none`,\n * `region` and every landmark \u2014 they describe, they do not behave.\n */\nexport const ROLE_PARTS: Record<string, { thing: string; part: OwnerPart | null }> = {\n dialog: { thing: 'dialog', part: { use: 'DialogShell', more: ' To ask yes or no, `ConfirmDialog`.' } },\n alertdialog: { thing: 'dialog', part: { use: 'ConfirmDialog' } },\n menu: { thing: 'menu', part: { use: 'Menu' } },\n menuitem: { thing: 'menu', part: { use: 'Menu' } },\n menuitemcheckbox: { thing: 'menu', part: { use: 'Menu' } },\n menuitemradio: { thing: 'menu', part: { use: 'Menu' } },\n listbox: { thing: 'list', part: LIST_PART },\n option: { thing: 'list', part: LIST_PART },\n combobox: { thing: 'list', part: LIST_PART },\n tablist: { thing: 'set of tabs', part: { use: 'Tabs' } },\n tab: { thing: 'set of tabs', part: { use: 'Tabs' } },\n tabpanel: { thing: 'set of tabs', part: { use: 'Tabs' } },\n toolbar: { thing: 'toolbar', part: { use: 'Toolbar' } },\n progressbar: { thing: 'progress bar', part: { use: 'ProgressBar' } },\n checkbox: { thing: 'tick box', part: { use: 'Checkbox' } },\n separator: { thing: 'divider', part: { use: 'Divider' } },\n button: { thing: 'button', part: { use: 'Button', more: ' Icon only, `IconButton`.' } },\n link: { thing: 'link', part: { use: 'Link' } },\n tooltip: { thing: 'tooltip', part: { use: 'Tooltip', more: ' Around a control, `WithTooltip`.' } },\n alert: { thing: 'message', part: MESSAGE_PART },\n status: { thing: 'message', part: MESSAGE_PART },\n menubar: { thing: 'menu bar', part: null },\n switch: { thing: 'switch', part: null },\n radio: { thing: 'radio button', part: null },\n radiogroup: { thing: 'radio group', part: null },\n slider: { thing: 'slider', part: null },\n spinbutton: { thing: 'number field', part: null },\n meter: { thing: 'meter', part: null },\n}\n\n/** The keys a list, a menu, tabs and a toolbar move with. Enter and Escape are not here (see above). */\nexport const WALKING_KEYS = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown']\n\n/**\n * A listener on the whole page, by what it is for. The events Base UI's own\n * parts listen to on the document (useDismiss, FloatingFocusManager, the\n * Positioner's autoUpdate): a floating part closes, holds focus and follows its\n * anchor with these. `focus`, `blur`, `visibilitychange` and `storage` are not\n * here: an app refreshing when the window comes back is not a floating part.\n */\nexport const PAGE_EVENTS: Record<string, 'press' | 'key' | 'focus' | 'follow'> = {\n mousedown: 'press',\n pointerdown: 'press',\n click: 'press',\n touchstart: 'press',\n keydown: 'key',\n keyup: 'key',\n keypress: 'key',\n focusin: 'focus',\n focusout: 'focus',\n scroll: 'follow',\n resize: 'follow',\n}\n\n/** Elements that are reachable with Tab by themselves; `tabIndex` on these is not a Tab stop made by hand. */\nexport const INTERACTIVE_ELEMENTS = new Set(['a', 'button', 'input', 'select', 'textarea', 'summary', 'iframe', 'embed', 'object', 'audio', 'video'])\n\n/** `overflow-auto`, `overflow-y-scroll`\u2026: a box that scrolls with the browser's scrollbar. */\nexport const SCROLL_CLASS = /^overflow(?:-[xy])?-(?:auto|scroll)$/\n\n/** One row of the enumeration (UIG-8's acceptance; the shape UIG-12's registry reads). */\nexport interface OwnedBehaviour {\n id: string\n /** What a person notices the part doing. */\n behaviour: string\n /** The Base UI parts that do it, read from their source (1.8.0). */\n baseUi: string[]\n /** The package components an error names. */\n owners: string[]\n /** What the rule reads in an app to find it rebuilt. */\n reads: string\n}\n\nconst uses = (parts: (OwnerPart | null)[]) => [\n ...new Set(parts.flatMap((p) => (p ? [p.use, ...[...(p.more ?? '').matchAll(/`([A-Z]\\w+)`/g)].map((m) => m[1])] : []))),\n]\n\nexport const OWNED_BEHAVIOURS: OwnedBehaviour[] = [\n {\n id: 'base-ui',\n behaviour: 'Is built on Base UI',\n baseUi: Object.keys(BASE_UI_PARTS),\n owners: uses(Object.values(BASE_UI_PARTS)),\n reads: 'an import from @base-ui/react (and the old @base-ui-components spelling)',\n },\n {\n id: 'portal',\n behaviour: 'Floats on top of the page',\n baseUi: ['Dialog', 'AlertDialog', 'Popover', 'Menu', 'Select', 'Combobox', 'Autocomplete', 'Tooltip', 'PreviewCard', 'Toast'],\n owners: ['DialogShell', 'ConfirmDialog', 'CommandPalette', 'Lightbox', 'Popover', 'Menu', 'Select', 'ChipInput', 'Tooltip', 'PreviewCard', 'Toast'],\n reads: 'createPortal, called, or imported and never called',\n },\n {\n id: 'press-outside',\n behaviour: 'Closes on a press outside',\n baseUi: ['Dialog', 'AlertDialog', 'Popover', 'Menu', 'Select', 'Combobox', 'Tooltip', 'PreviewCard'],\n owners: ['DialogShell', 'Popover', 'Menu', 'Select', 'PreviewCard'],\n reads: 'a mousedown, pointerdown, click or touchstart listener on window or document',\n },\n {\n id: 'page-keys',\n behaviour: 'Takes its keys by itself',\n baseUi: ['Dialog', 'AlertDialog', 'Popover', 'Menu', 'Select', 'Combobox', 'Tooltip', 'PreviewCard', 'Toast'],\n owners: ['DialogShell', 'Lightbox', 'Popover', 'Menu', 'Select', 'Tabs', 'Toolbar'],\n reads: 'a keydown, keyup or keypress listener on window or document',\n },\n {\n id: 'focus',\n behaviour: 'Holds focus inside while open, and gives it back',\n baseUi: ['Dialog', 'AlertDialog', 'Popover', 'Menu', 'Select', 'Combobox'],\n owners: ['DialogShell', 'CommandPalette', 'Lightbox'],\n reads: 'a focusin or focusout listener on window or document; the Tab key compared by hand',\n },\n {\n id: 'scroll-lock',\n behaviour: 'Stops the page behind it scrolling',\n baseUi: ['Dialog', 'AlertDialog'],\n owners: ['DialogShell', 'Lightbox'],\n reads: 'overflow written into the style of document.body or document.documentElement',\n },\n {\n id: 'follow',\n behaviour: 'Stays attached to its anchor on scroll and resize',\n baseUi: ['Popover', 'Menu', 'Select', 'Combobox', 'Tooltip', 'PreviewCard', 'Toast'],\n owners: ['Popover', 'Menu', 'Select', 'Tooltip', 'PreviewCard'],\n reads: 'a scroll or resize listener on window or document',\n },\n {\n id: 'walking',\n behaviour: 'Moves through its items with the arrow keys',\n baseUi: ['Menu', 'Select', 'Combobox', 'Autocomplete', 'Tabs', 'Toolbar'],\n owners: ['Menu', 'Select', 'ChipInput', 'CommandPalette', 'SuggestionMenu', 'Tabs', 'Toolbar'],\n reads: `a key compared by hand with ${WALKING_KEYS.join(', ')}`,\n },\n {\n id: 'role',\n behaviour: 'Says what it is to assistive technology',\n baseUi: ['Dialog', 'AlertDialog', 'Menu', 'Select', 'Combobox', 'Tabs', 'Toolbar', 'Progress', 'Checkbox', 'Separator', 'Button'],\n owners: uses(Object.values(ROLE_PARTS).map((r) => r.part)),\n reads: `role written by hand: ${Object.keys(ROLE_PARTS).join(', ')}`,\n },\n {\n id: 'tab-stop',\n behaviour: 'Is reachable with Tab',\n baseUi: ['Button', 'Toggle', 'Checkbox', 'Tabs', 'Toolbar', 'ScrollArea'],\n owners: ['Button', 'IconButton', 'Link'],\n reads: 'tabIndex that can be 0 or more, on an element that is not a control',\n },\n {\n id: 'scroll',\n behaviour: 'Scrolls with our scrollbar',\n baseUi: ['ScrollArea'],\n owners: ['ScrollArea'],\n reads: 'overflow-auto or overflow-scroll (x or y, behind any variant) in a string, or overflow auto or scroll in a style',\n },\n]\n\ninterface Node {\n type: string\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n parent?: Node\n [key: string]: unknown\n}\n\nconst PAGE_TARGETS = new Set(['window', 'document', 'globalThis', 'self', 'document.body', 'document.documentElement', 'window.document'])\n\n/** Where an escape for this node is written: its object property, its element, its array item, or its statement. */\nfunction anchorOf(node: Node): Node {\n if (node.type === 'FunctionDeclaration') {\n return node.parent && /^Export/.test(node.parent.type) ? node.parent : node\n }\n let child = node\n for (let p = node.parent; p; child = p, p = p.parent) {\n if (p.type === 'JSXOpeningElement' || p.type === 'Property' || p.type === 'MethodDefinition' || p.type === 'PropertyDefinition') return p\n if (p.type === 'ArrayExpression') return child\n if (p.type !== 'BlockStatement' && /(Statement|Declaration)$/.test(p.type)) return p\n }\n return node\n}\n\nfunction enclosingFunction(node: Node): Node | undefined {\n for (let p = node.parent; p; p = p.parent) {\n if (p.type === 'FunctionDeclaration' || p.type === 'FunctionExpression' || p.type === 'ArrowFunctionExpression') return p\n }\n return undefined\n}\n\nfunction stringOf(node: Node | undefined | null): string | undefined {\n if (!node) return undefined\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value\n const quasis = node.quasis as { value: { cooked: string | null } }[] | undefined\n const expressions = node.expressions as unknown[] | undefined\n if (node.type === 'TemplateLiteral' && expressions?.length === 0) return quasis?.[0]?.value.cooked ?? undefined\n return undefined\n}\n\n/** Every string a JSX attribute's value can be: `\"x\"`, `{'x'}`, `{a ? 'x' : 'y'}`, `{a && 'x'}`. */\nfunction stringsOf(node: Node | undefined | null): string[] {\n if (!node) return []\n if (node.type === 'JSXExpressionContainer') return stringsOf(node.expression as Node)\n const s = stringOf(node)\n if (s !== undefined) return [s]\n if (node.type === 'ConditionalExpression') return [...stringsOf(node.consequent as Node), ...stringsOf(node.alternate as Node)]\n if (node.type === 'LogicalExpression') return [...stringsOf(node.left as Node), ...stringsOf(node.right as Node)]\n return []\n}\n\n/** Whether a `tabIndex` value can be 0 or more, as far as the code spells it out. */\nfunction canBeTabStop(node: Node | undefined | null): boolean {\n if (!node) return false\n if (node.type === 'JSXExpressionContainer') return canBeTabStop(node.expression as Node)\n if (node.type === 'Literal') {\n if (typeof node.value === 'number') return node.value >= 0\n if (typeof node.value === 'string') return /^\\s*\\d+\\s*$/.test(node.value)\n return false\n }\n if (node.type === 'ConditionalExpression') return canBeTabStop(node.consequent as Node) || canBeTabStop(node.alternate as Node)\n if (node.type === 'LogicalExpression') return canBeTabStop(node.left as Node) || canBeTabStop(node.right as Node)\n if (node.type === 'TSAsExpression' || node.type === 'TSNonNullExpression') return canBeTabStop(node.expression as Node)\n return false\n}\n\n/** A class token's utility, past its variants: `[&_pre]:overflow-x-auto` \u2192 `overflow-x-auto`. */\nexport function utilityOf(token: string): string {\n let depth = 0\n let last = -1\n for (let i = 0; i < token.length; i++) {\n const c = token[i]\n if (c === '[') depth++\n else if (c === ']') depth--\n else if (c === ':' && depth === 0) last = i\n }\n return token.slice(last + 1).replace(/^!/, '').replace(/!$/, '')\n}\n\n/** The Base UI module an import names, or `undefined` when it is not Base UI. `''` is the package root. */\nexport function baseUiModule(source: string): string | undefined {\n const m = /^@base-ui(?:-components)?\\/([^/]+)(?:\\/(.+))?$/.exec(source)\n if (!m) return undefined\n const [, pkg, sub] = m\n return pkg === 'react' ? (sub ?? '') : `${pkg}${sub ? `/${sub}` : ''}`\n}\n\nfunction isKeySubject(node: Node | undefined): boolean {\n if (!node) return false\n if (node.type === 'Identifier') return node.name === 'key' || node.name === 'code'\n if (node.type !== 'MemberExpression' || node.computed) return false\n const property = node.property as Node\n return property.type === 'Identifier' && (property.name === 'key' || property.name === 'code')\n}\n\nfunction pageTarget(node: Node, text: string): boolean {\n return (node.type === 'Identifier' || node.type === 'MemberExpression') && PAGE_TARGETS.has(text)\n}\n\nexport const noRebuiltBehaviour: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'Behaviour @estiva-app/ui already owns, rebuilt by hand in an app' },\n schema: [],\n messages: {\n baseUi: 'Only @estiva-app/ui imports Base UI (`{{module}}`). Use `{{use}}` from @estiva-app/ui.{{more}}',\n baseUiNoPart:\n 'Only @estiva-app/ui imports Base UI (`{{module}}`), and it has no part built on it yet. Do not build one here: ask Katerina, and it gets made in @estiva-app/ui.',\n portal:\n 'A layer put on top of the page by hand (`createPortal`). Every floating part of @estiva-app/ui carries its own: `DialogShell` for a dialog, `Popover` for a panel, `Menu`, `Select`, `Tooltip`, `PreviewCard`, `Toast`.',\n press:\n 'A `{{event}}` listener on `{{target}}`: closing on a press outside, by hand. `Popover`, `Menu`, `Select`, `DialogShell` and `PreviewCard` from @estiva-app/ui close themselves.',\n key: 'A `{{event}}` listener on `{{target}}`: keys taken for the whole page, by hand. `DialogShell`, `Popover`, `Menu` and `Select` from @estiva-app/ui close on Escape themselves; `Menu`, `Select`, `Tabs` and `Toolbar` move with the arrow keys.',\n focus:\n 'A `{{event}}` listener on `{{target}}`: focus held by hand. `DialogShell` and `CommandPalette` from @estiva-app/ui keep focus inside and give it back.',\n follow:\n 'A `{{event}}` listener on `{{target}}`: following an anchor by hand. `Popover`, `Menu`, `Select`, `Tooltip` and `PreviewCard` from @estiva-app/ui stay attached to theirs.',\n scrollLock: \"The page's scroll locked by hand. `DialogShell` from @estiva-app/ui stops the page scrolling while it is open, and gives it back.\",\n walking:\n 'Arrow keys handled by hand (`{{key}}`). `Menu`, `Select`, `ChipInput`, `CommandPalette`, `Tabs` and `Toolbar` from @estiva-app/ui move through their items themselves.',\n tabKey: 'The Tab key handled by hand. `DialogShell` and `CommandPalette` from @estiva-app/ui keep focus inside themselves.',\n role: 'A hand-written `role=\"{{role}}\"` is a hand-made {{thing}}. Use `{{use}}` from @estiva-app/ui.{{more}}',\n roleNoPart:\n 'A hand-written `role=\"{{role}}\"` is a hand-made {{thing}}, and @estiva-app/ui has no part for one yet. Do not build one here: ask Katerina, and it gets made in @estiva-app/ui.',\n tabStop:\n '`tabIndex={{value}}` makes a `<{{element}}>` a Tab stop by hand. Use `Button`, `IconButton` or `Link` from @estiva-app/ui, which are reachable already.',\n scrollClass: \"`{{token}}` scrolls with the browser's scrollbar. Use `ScrollArea` from @estiva-app/ui, which draws ours.\",\n scrollStyle: \"`{{style}}` scrolls with the browser's scrollbar. Use `ScrollArea` from @estiva-app/ui, which draws ours.\",\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const { sourceCode } = context\n const text = (node: Node) => sourceCode.getText(node as unknown as Rule.Node)\n\n // One escape covers what the rule found at its anchor, and is counted once.\n const escapes = new Map<Node, boolean>()\n const escaped = (anchor: Node) => {\n if (!escapes.has(anchor)) escapes.set(anchor, isEscaped(context, anchor))\n return escapes.get(anchor) === true\n }\n const seen = new Set<string>()\n const report = (anchor: Node, at: Node, messageId: string, data: Record<string, string> = {}, once = `${at.range[0]}`) => {\n const key = `${anchor.range[0]}|${messageId}|${once}`\n if (seen.has(key)) return\n seen.add(key)\n if (escaped(anchor)) return\n context.report({ loc: at.loc, messageId, data })\n }\n\n const importSource = (node: Node, source: Node | undefined | null) => {\n const value = stringOf(source)\n if (value === undefined) return\n const module = baseUiModule(value)\n if (module === undefined) return\n const part = Object.hasOwn(BASE_UI_PARTS, module) ? BASE_UI_PARTS[module] : null\n const anchor = anchorOf(node)\n if (part) report(anchor, node, 'baseUi', { module: value, use: part.use, more: part.more ?? '' })\n else report(anchor, node, 'baseUiNoPart', { module: value })\n }\n\n const keyCompared = (node: Node, key: string | undefined) => {\n if (key === undefined) return\n const fn = enclosingFunction(node)\n const anchor = anchorOf(fn ?? node)\n if (WALKING_KEYS.includes(key)) report(anchor, node, 'walking', { key }, `walking@${fn?.range[0] ?? node.range[0]}`)\n else if (key === 'Tab') report(anchor, node, 'tabKey', {}, `tab@${fn?.range[0] ?? node.range[0]}`)\n }\n\n const classTokens = (node: Node, value: string) => {\n for (const token of value.split(/\\s+/)) {\n if (token && SCROLL_CLASS.test(utilityOf(token))) report(anchorOf(node), node, 'scrollClass', { token }, `class@${token}`)\n }\n }\n\n // `createPortal` imported: reported where it is called, or at the import when it never is.\n const portalImports = new Map<string, Node>()\n let portalCalled = false\n\n return {\n ImportDeclaration(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n importSource(node, node.source as Node)\n if (stringOf(node.source as Node) !== 'react-dom') return\n for (const specifier of node.specifiers as Node[]) {\n const imported = specifier.imported as Node | undefined\n if (specifier.type === 'ImportSpecifier' && imported?.name === 'createPortal') portalImports.set((specifier.local as Node).name as string, node)\n }\n },\n ExportNamedDeclaration(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n if (node.source) importSource(node, node.source as Node)\n },\n ExportAllDeclaration(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n importSource(node, node.source as Node)\n },\n ImportExpression(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n importSource(node, node.source as Node)\n },\n\n CallExpression(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n const callee = node.callee as Node\n const args = node.arguments as Node[]\n\n if (callee.type === 'Identifier' && callee.name === 'require') importSource(node, args[0])\n\n if (callee.type === 'Identifier' && portalImports.has(callee.name as string)) {\n portalCalled = true\n report(anchorOf(node), node, 'portal')\n }\n if (callee.type !== 'MemberExpression') return\n const object = callee.object as Node\n const property = callee.property as Node\n if (property.type !== 'Identifier') return\n\n if (property.name === 'createPortal') {\n report(anchorOf(node), node, 'portal')\n return\n }\n\n if (property.name === 'addEventListener') {\n const target = text(object)\n if (!pageTarget(object, target)) return\n const event = stringOf(args[0])\n const group = event === undefined ? undefined : PAGE_EVENTS[event]\n if (!event || !group) return\n report(anchorOf(node), node, group, { event, target })\n return\n }\n\n // ['ArrowUp', 'ArrowDown'].includes(event.key)\n if (property.name === 'includes' && object.type === 'ArrayExpression' && isKeySubject(args[0])) {\n for (const element of object.elements as Node[]) keyCompared(node, stringOf(element))\n }\n },\n\n AssignmentExpression(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n const left = node.left as Node\n if (left.type !== 'MemberExpression') return\n const property = left.property as Node\n const object = left.object as Node\n const handler = property.type === 'Identifier' ? /^on([a-z]+)$/.exec(property.name as string) : null\n if (handler && pageTarget(object, text(object)) && PAGE_EVENTS[handler[1]]) {\n report(anchorOf(node), node, PAGE_EVENTS[handler[1]], { event: handler[1], target: text(object) })\n return\n }\n if (/^document\\.(?:body|documentElement)\\.style\\.overflow[XY]?$/.test(text(left))) report(anchorOf(node), node, 'scrollLock')\n },\n\n BinaryExpression(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n if (!['===', '==', '!==', '!='].includes(node.operator as string)) return\n const left = node.left as Node\n const right = node.right as Node\n if (isKeySubject(left)) keyCompared(node, stringOf(right))\n else if (isKeySubject(right)) keyCompared(node, stringOf(left))\n },\n\n SwitchCase(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n const statement = node.parent as Node\n if (node.test && isKeySubject(statement.discriminant as Node)) keyCompared(node, stringOf(node.test as Node))\n },\n\n JSXAttribute(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n const nameNode = node.name as Node\n if (nameNode.type !== 'JSXIdentifier') return\n const name = nameNode.name as string\n const element = node.parent as Node\n const value = node.value as Node | null\n\n if (name === 'role') {\n for (const role of stringsOf(value).flatMap((v) => v.trim().split(/\\s+/))) {\n if (!Object.hasOwn(ROLE_PARTS, role)) continue\n const { thing, part } = ROLE_PARTS[role]\n if (part) report(element, node, 'role', { role, thing, use: part.use, more: part.more ?? '' })\n else report(element, node, 'roleNoPart', { role, thing })\n return\n }\n return\n }\n\n if (name === 'tabIndex' || name === 'tabindex') {\n const tag = element.name as Node\n if (tag.type !== 'JSXIdentifier' || !/^[a-z]/.test(tag.name as string) || INTERACTIVE_ELEMENTS.has(tag.name as string)) return\n const attributes = element.attributes as Node[]\n const editable = attributes.some((a) => a.type === 'JSXAttribute' && /^contenteditable$/i.test(((a.name as Node).name as string) ?? ''))\n if (editable || !canBeTabStop(value)) return\n report(element, node, 'tabStop', { value: value ? text(value).replace(/^\\{|\\}$/g, '') : '', element: tag.name as string })\n return\n }\n\n if (name === 'style' && value?.type === 'JSXExpressionContainer') {\n const object = value.expression as Node\n if (object.type !== 'ObjectExpression') return\n for (const property of object.properties as Node[]) {\n if (property.type !== 'Property') continue\n const key = property.key as Node\n const keyName = key.type === 'Identifier' ? (key.name as string) : stringOf(key)\n if (!keyName || !/^overflow[XY]?$/.test(keyName)) continue\n const setting = stringOf(property.value as Node)\n if (setting === 'auto' || setting === 'scroll') report(element, property, 'scrollStyle', { style: `${keyName}: '${setting}'` }, `style@${keyName}`)\n }\n }\n },\n\n Literal(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n if (typeof node.value !== 'string') return\n const parent = node.parent\n if (parent && /^(Import|Export)/.test(parent.type)) return\n if (parent?.type === 'TSLiteralType' || parent?.type === 'TSExternalModuleReference') return\n classTokens(node, node.value)\n },\n\n TemplateElement(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n const cooked = (node.value as { cooked: string | null }).cooked\n if (cooked && node.parent) classTokens(node.parent, cooked)\n },\n\n 'Program:exit'() {\n if (portalCalled) return\n for (const declaration of new Set(portalImports.values())) report(anchorOf(declaration), declaration, 'portal')\n },\n }\n },\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\ninterface JSXOpeningElement {\n type: string\n name: { type: string; name?: string }\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n parent?: Parent\n}\n\ninterface Parent {\n type: string\n name?: { name?: string }\n openingElement?: unknown\n parent?: Parent\n}\n\n/**\n * The elements this package writes by hand. The set the count used (UIG-1,\n * docs/GATES.md \u00A75 and \u00A77): every element that carries behaviour or a role of\n * its own. A `div` or a `span` is layout and is nobody's business here.\n */\nexport const RAW_ELEMENTS = new Set(['a', 'button', 'input', 'textarea', 'select', 'dialog', 'form', 'label'])\n\n/**\n * A raw element nested inside another element, in the package itself (UIG-5,\n * the inward tracer).\n *\n * The package is allowed to write raw elements \u2014 that is what a primitive is.\n * Two shapes are right, and both are facts about the code rather than a\n * judgement:\n *\n * - **the component's own outermost element.** `NavItem` is an `<a>`, `Link` is\n * an `<a>`, a `MenuItem` outside a `Menu` is a `<button>`. A primitive owning\n * its element is the whole point of it.\n * - **handed to a Base UI `render` prop.** `render={<button type=\"button\" />}`\n * tells a Base UI part which element to be; the behaviour stays Base UI's.\n *\n * Anything else is an element buried inside a bigger component, where its look\n * and its behaviour are kept in step by nobody \u2014 the package's own version of\n * the rule the apps get from UIG-3 and UIG-7.\n *\n * It keeps its reason on the line above if it stays: `// @estiva-escape: <why>`.\n */\nexport const rawElementOutsideAWrapper: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'A raw element nested inside a component, rather than the component itself' },\n schema: [],\n messages: {\n nested:\n 'A raw <{{name}}> inside another element. In this package a raw element is either the component\\'s own outermost element or handed to a Base UI `render` prop; one buried inside belongs in a component of its own (Link, Button, MenuItem...).',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n return {\n // ESLint's types know ESTree's nodes, not JSX's; the parser hands this one over.\n JSXOpeningElement(node: Rule.Node) {\n const element = node as unknown as JSXOpeningElement\n const name = element.name.name\n if (element.name.type !== 'JSXIdentifier' || !name || !RAW_ELEMENTS.has(name)) return\n\n // An opening tag's own parent is its JSXElement: that is this element,\n // not an element around it.\n let parent = element.parent\n if (parent?.type === 'JSXElement' && parent.openingElement === (element as unknown)) parent = parent.parent\n\n // Whichever comes first going outward decides: an element around it\n // means it is nested; a `render` prop means Base UI draws it.\n for (let p = parent; p; p = p.parent) {\n if (p.type === 'JSXAttribute') {\n if (p.name?.name === 'render') return\n continue\n }\n if (p.type !== 'JSXElement' && p.type !== 'JSXFragment') continue\n if (isEscaped(context, element)) return\n context.report({ loc: element.loc, messageId: 'nested', data: { name } })\n return\n }\n },\n }\n },\n}\n", "/**\n * The names of the app rules, with nothing imported.\n *\n * `create-estiva-app` needs these names to write a new app's count at zero, and\n * nothing else of the plugin. It runs from `npx` in an empty folder, where only\n * this package's own dependencies are installed, so it must never load the\n * rules themselves: since `no-copied-look` (UIG-25, 0.34.0) they import\n * TypeScript, and that import stopped the command before it wrote a file\n * (UIG-10, reopened 27 September). `index.ts` holds its rule table to exactly\n * these names, so the two cannot drift.\n */\n\n/** The name the configs register the plugin under, so every rule id is `estiva/<rule>`. */\nexport const PLUGIN_KEY = 'estiva'\n\nexport const APP_RULE_NAMES = [\n 'no-raw-element',\n 'no-rebuilt-behaviour',\n 'no-restyled-part',\n 'no-handmade-header',\n 'no-handmade-empty-state',\n 'no-native-title',\n 'no-copied-look',\n 'no-field-outside-a-form',\n] as const\n\nexport type AppRuleName = (typeof APP_RULE_NAMES)[number]\n\n/** The ids `recommended` and `strict` carry \u2014 what an app's gate runs and counts. */\nexport const APP_RULE_IDS = APP_RULE_NAMES.map((name) => `${PLUGIN_KEY}/${name}`)\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/// <reference types=\"node\" />\n/**\n * `@estiva-app/ui/eslint` \u2014 the UI Guardrails' lint rules, as a plugin (UIG-3,\n * seam S1 in docs/GATES.md \u00A716).\n *\n * A plugin rather than config, so every app \u2014 Peek, Ship, Leaf \u2014 gets a new\n * rule through an ordinary version bump, and an app's editor hook runs the\n * very rule code its CI runs.\n *\n * import estiva from '@estiva-app/ui/eslint'\n * export default [{ files: ['src/**\\/*.tsx'], ...estiva.configs.recommended }]\n *\n * Register it under `estiva` (the configs do): the rule ids are\n * `estiva/<rule>`, and `countGates` counts those ids.\n *\n * Built on its own by build.mjs, for Node, into `dist/eslint/`; nothing here\n * reaches the components' browser bundle.\n */\nimport { createRequire } from 'node:module'\nimport type { ESLint, Linter } from 'eslint'\nimport { componentHasAPage, componentHasAStory } from './has-a-page-and-a-story'\nimport { noHandRolledBehaviour } from './no-hand-rolled-behaviour'\nimport { noHandmadeEmptyState } from './no-handmade-empty-state'\nimport { noHandmadeHeader } from './no-handmade-header'\nimport { noCopiedLook } from './no-copied-look'\nimport { noFieldOutsideAForm } from './no-field-outside-a-form'\nimport { noNativeTitle } from './no-native-title'\nimport { noRawElement } from './no-raw-element'\nimport { noRebuiltBehaviour } from './no-rebuilt-behaviour'\nimport { noRestyledPart } from './no-restyled-part'\nimport { rawElementOutsideAWrapper } from './raw-element-outside-a-wrapper'\nimport { APP_RULE_IDS, PLUGIN_KEY, type AppRuleName } from './rule-ids'\n\nexport { ESCAPE_MARKER, MIN_REASON, SETTINGS_KEY, isEscaped, type EstivaSettings } from './escape'\nexport { OWNED_BEHAVIOURS, type OwnedBehaviour } from './no-rebuilt-behaviour'\nexport { PART_LOOK_PROPS, PLACEMENT } from './no-restyled-part'\nexport { PARTS_WITH_A_TITLE } from './no-native-title'\nexport { MIN_COVER, MIN_SHARED } from './looks-of'\nexport { FIELD_PARTS } from './no-field-outside-a-form'\n\nconst { version } = createRequire(import.meta.url)('../../package.json') as { version: string }\n\nexport { APP_RULE_IDS, PLUGIN_KEY }\n\n/**\n * The rules an **app** runs: they say an app must not build what the package\n * already has \u2014 a raw control (UIG-7), or a behaviour one of its parts owns\n * (UIG-8) \u2014 nor restyle a part it uses (UIG-9). `recommended` and `strict`\n * carry these and only these. Their names live in `rule-ids.ts`, which\n * `create-estiva-app` reads without loading a rule; `satisfies` fails the\n * typecheck when a rule is missing from either.\n */\nconst appRules = {\n 'no-raw-element': noRawElement,\n 'no-rebuilt-behaviour': noRebuiltBehaviour,\n 'no-restyled-part': noRestyledPart,\n 'no-handmade-header': noHandmadeHeader,\n 'no-handmade-empty-state': noHandmadeEmptyState,\n 'no-native-title': noNativeTitle,\n 'no-copied-look': noCopiedLook,\n 'no-field-outside-a-form': noFieldOutsideAForm,\n} satisfies Record<AppRuleName, unknown>\n\n/**\n * The rules the **package itself** runs, pointed inward (UIG-5): don't bury a\n * raw element inside a component, don't rebuild what Base UI owns, don't ship a\n * component without a page or a story.\n *\n * They are in `configs.package`, never in `recommended`, on purpose. Peek and\n * Ship spread `recommended`, so a rule added here must not arrive in an app\n * with the next version bump: an app's components are not primitives, so\n * \"buried inside a component\" means nothing there (`no-raw-element` is the\n * app's version, UIG-7), and an app has no `.mdx` pages at all. `index.test.ts` holds the\n * apps' list to exactly the app rules.\n *\n * Five rules are in both sets: `no-restyled-part` (UIG-9), and the\n * fingerprints `no-handmade-header` (UIG-22), `no-handmade-empty-state`\n * (UIG-23), `no-native-title` (UIG-24) and `no-copied-look` (UIG-25, a\n * warning). The package restyles none of its own parts either (Katerina, 17\n * September), and \"my review isn't enough\" (23 September).\n */\nconst packageRules = {\n 'raw-element-outside-a-wrapper': rawElementOutsideAWrapper,\n 'no-hand-rolled-behaviour': noHandRolledBehaviour,\n 'component-has-a-page': componentHasAPage,\n 'component-has-a-story': componentHasAStory,\n 'no-restyled-part': noRestyledPart,\n 'no-handmade-header': noHandmadeHeader,\n 'no-handmade-empty-state': noHandmadeEmptyState,\n 'no-native-title': noNativeTitle,\n 'no-copied-look': noCopiedLook,\n}\n\nconst rules = { ...appRules, ...packageRules }\n\nconst plugin = {\n meta: { name: '@estiva-app/ui/eslint', version },\n rules,\n configs: {} as { recommended: Linter.Config; strict: Linter.Config; package: Linter.Config },\n} satisfies ESLint.Plugin\n\n/** The ids `package` carries \u2014 what this package's own gate runs and counts (UIG-5). */\nexport const PACKAGE_RULE_IDS = Object.keys(packageRules).map((name) => `${PLUGIN_KEY}/${name}`)\n\n/**\n * `recommended` switches every **app** rule on at the level it was ruled at: an\n * error blocks, a warning is reported and never blocks. `strict` makes every app\n * rule an error. They part at the first warning-level rule, `no-copied-look`\n * (UIG-25): `recommended` warns on it, `strict` blocks on it.\n *\n * `package` is the inward set (UIG-5), which only this package runs.\n */\nplugin.configs.recommended = {\n name: '@estiva-app/ui/recommended',\n plugins: { [PLUGIN_KEY]: plugin },\n rules: {\n [`${PLUGIN_KEY}/no-raw-element`]: 'error',\n [`${PLUGIN_KEY}/no-rebuilt-behaviour`]: 'error',\n [`${PLUGIN_KEY}/no-restyled-part`]: 'error',\n [`${PLUGIN_KEY}/no-handmade-header`]: 'error',\n [`${PLUGIN_KEY}/no-handmade-empty-state`]: 'error',\n [`${PLUGIN_KEY}/no-native-title`]: 'error',\n // A warning, never an error (Katerina, 13 September): likeness is a judgement.\n [`${PLUGIN_KEY}/no-copied-look`]: 'warn',\n [`${PLUGIN_KEY}/no-field-outside-a-form`]: 'error',\n },\n}\nplugin.configs.strict = {\n name: '@estiva-app/ui/strict',\n plugins: { [PLUGIN_KEY]: plugin },\n rules: Object.fromEntries(APP_RULE_IDS.map((id) => [id, 'error'])),\n}\nplugin.configs.package = {\n name: '@estiva-app/ui/package',\n plugins: { [PLUGIN_KEY]: plugin },\n // Every inward rule blocks, but the copied look, which warns here too (UIG-25).\n rules: Object.fromEntries(PACKAGE_RULE_IDS.map((id) => [id, id === `${PLUGIN_KEY}/no-copied-look` ? 'warn' : 'error'])),\n}\n\nexport default plugin\n\nexport interface GateRuleCount {\n errors: number\n warnings: number\n escapes: number\n}\n\nexport interface GateCount {\n /** Per rule id, including rules with nothing to report. */\n rules: Record<string, GateRuleCount>\n /**\n * Reports of these rules that an `eslint-disable` directive silenced. Not\n * an escape: a gate fails on any of these (docs/GATES.md \u00A716, S4).\n */\n disabled: { filePath: string; line: number; ruleId: string }[]\n}\n\n/**\n * Count what a lint of these rules found, for `.gates-count.json` (seam S3).\n *\n * Run the lint with `settings: { estiva: { reportEscapes: true } }` for the\n * escapes to be counted; without it they are silent and count 0. A marker\n * with no reason, or inside a directive, counts as an error of its rule.\n *\n * `seed` is which rules the count lists when they found nothing, and it is the\n * app rules unless a caller says otherwise: an app's count file must not gain\n * rows for the inward rules (UIG-5) that its gate does not run. This package's\n * own count script passes `PACKAGE_RULE_IDS`.\n */\nexport function countGates(results: ESLint.LintResult[], seed: readonly string[] = APP_RULE_IDS): GateCount {\n const counts: Record<string, GateRuleCount> = Object.fromEntries(seed.map((id) => [id, { errors: 0, warnings: 0, escapes: 0 }]))\n const disabled: GateCount['disabled'] = []\n const ours = (ruleId: string | null | undefined): ruleId is string => typeof ruleId === 'string' && ruleId.startsWith(`${PLUGIN_KEY}/`)\n for (const result of results) {\n for (const message of result.messages) {\n // Seeded or not: every rule of this plugin that reported is counted, so a\n // lint of a set the caller did not name is still counted in full.\n if (!ours(message.ruleId)) continue\n const count = (counts[message.ruleId] ??= { errors: 0, warnings: 0, escapes: 0 })\n if (message.messageId === 'escaped') count.escapes += 1\n else if (message.severity === 2) count.errors += 1\n else count.warnings += 1\n }\n for (const message of result.suppressedMessages ?? []) {\n if (ours(message.ruleId)) disabled.push({ filePath: result.filePath, line: message.line, ruleId: message.ruleId })\n }\n }\n return { rules: counts, disabled }\n}\n", "import { existsSync } from 'node:fs'\nimport type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\n/**\n * A component of the package with no page, and one with no story (UIG-5, P2 and\n * P3).\n *\n * A component nobody can read about is a component nobody uses correctly, and\n * one nobody can look at is one nobody reviews. Both were at zero when these\n * were switched on; they are here so the next component cannot arrive without\n * them.\n *\n * The pair is by file name, beside the component, which is how this package is\n * laid out: `Button.tsx`, `Button.mdx`, `Button.stories.tsx`, `Button.test.tsx`\n * side by side in `src/`.\n *\n * **The false positive to avoid** (UIG-1 confirmed it is real): `FieldLine` and\n * `MenuItem` have a page and a story but no `.tsx` of their own \u2014 they are\n * exported from a sibling. These rules read a component file and ask for its\n * page and its story, never the other way round, so a page without a component\n * is not this rule's business.\n *\n * A file that stays without one says why at its top: `// @estiva-escape: <why>`.\n */\ninterface ProgramNode {\n body: { loc?: Rule.Node['loc']; range?: [number, number] }[]\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n}\n\n/** A component file: a `.tsx` in the package's source that is not a story or a test. */\nfunction componentFile(filename: string): boolean {\n return filename.endsWith('.tsx') && !/\\.(stories|test)\\.tsx$/.test(filename)\n}\n\nfunction sibling(filename: string, extension: string): string {\n return filename.replace(/\\.tsx$/, extension)\n}\n\n/**\n * Report on the file's first statement, so the escape is a comment at the top of\n * the file \u2014 the only place a reason for a missing page could go.\n */\nfunction reportOnFile(context: Rule.RuleContext, program: ProgramNode, messageId: string, data: Record<string, string>): void {\n const anchor = program.body[0] ?? program\n if (anchor.loc && anchor.range && isEscaped(context, { loc: anchor.loc, range: anchor.range })) return\n context.report({ loc: anchor.loc ?? program.loc, messageId, data })\n}\n\nexport const componentHasAPage: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'Every component of the package has a usage page beside it' },\n schema: [],\n messages: {\n missing: '{{name}} has no page. Write {{page}} beside it \u2014 what it is, when, when not, how, and what it owns \u2014 or say why not at the top of the file.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n return {\n Program(node) {\n const filename = context.filename\n if (!componentFile(filename)) return\n const page = sibling(filename, '.mdx')\n if (existsSync(page)) return\n const name = filename.split(/[\\\\/]/).pop() ?? filename\n reportOnFile(context, node as unknown as ProgramNode, 'missing', { name, page: page.split(/[\\\\/]/).pop() ?? page })\n },\n }\n },\n}\n\nexport const componentHasAStory: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'Every component of the package has a story beside it' },\n schema: [],\n messages: {\n missing: '{{name}} has no story. Write {{story}} beside it, so it can be seen and reviewed, or say why not at the top of the file.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n return {\n Program(node) {\n const filename = context.filename\n if (!componentFile(filename)) return\n const story = sibling(filename, '.stories.tsx')\n if (existsSync(story)) return\n const name = filename.split(/[\\\\/]/).pop() ?? filename\n reportOnFile(context, node as unknown as ProgramNode, 'missing', { name, story: story.split(/[\\\\/]/).pop() ?? story })\n },\n }\n },\n}\n", "import type { AST, Rule } from 'eslint'\n\n/**\n * The escape marker (UIG-3, seam S4 in docs/GATES.md \u00A716): one written reason\n * why one element stays as it is.\n *\n * A line comment directly above the element, naming the rule it keeps off,\n *\n * // @estiva-escape(no-raw-element): <reason>\n *\n * or, where the element is a JSX child, the JSX comment on the line above,\n *\n * {/* @estiva-escape(no-raw-element): <reason> *\\/}\n *\n * with at least ten characters of reason, spaces not counted. It escapes only\n * the rules it names (Katerina's ruling B3, 25 September: one reason used to\n * switch off every rule on the element, so a raw button that also wrote a\n * dialog's role by hand passed under one reason). Two rules on one element are\n * named together, `@estiva-escape(no-raw-element, no-rebuilt-behaviour)`, each\n * on purpose. A marker that names no rule escapes nothing, and says which name\n * to write.\n *\n * Not `eslint-disable`. A directive switches a rule off without saying it was\n * meant, and the count of escapes (`.gates-count.json`) could not see it. A\n * marker written inside a directive that switches one of these rules off is\n * reported for that reason.\n *\n * The token lint's older notes (`eslint-disable-next-line <rule> -- @estiva-escape:\n * <reason>`, Katerina's ruling A2 of 15 September) are not read here: they\n * escape the token lint's rules, which are not this plugin's, and they stay as\n * they are (Katerina, 15 September).\n */\nexport const ESCAPE_MARKER = '@estiva-escape'\n\n/** Characters of reason, spaces not counted. */\nexport const MIN_REASON = 10\n\n/** The key under ESLint's `settings` this plugin reads. */\nexport const SETTINGS_KEY = 'estiva'\n\n/**\n * Every rule spreads these into its `meta.messages`, because `isEscaped`\n * reports through the rule that called it.\n */\nexport const ESCAPE_MESSAGES = {\n escapeWithoutReason: `An escape needs its reason, at least ${MIN_REASON} characters: \\`// ${ESCAPE_MARKER}({{rule}}): <why this stays>\\`. An escape with no reason hides nothing.`,\n escapeInDirective: `Write the escape as its own comment on the line above: \\`// ${ESCAPE_MARKER}({{rule}}): <reason>\\`. Inside an eslint-disable comment it switches the rule off instead of recording why.`,\n escapeWithoutRule: `Name the rule this escape keeps off: \\`${ESCAPE_MARKER}({{rule}}): <reason>\\`. An escape now keeps off only the rules it names.`,\n escaped: 'Escaped: {{reason}}',\n} as const\n\n/** A rule's name as a marker writes it: `no-raw-element` for `estiva/no-raw-element`. */\nexport const shortRuleName = (id: string) => id.slice(id.lastIndexOf('/') + 1)\n\n/**\n * What a marker says, read from a comment's text: the rules it names (none when\n * it names none) and its reason. Null when the comment carries no marker.\n */\nexport function readMarker(text: string): { rules: string[]; reason: string } | null {\n const at = text.indexOf(ESCAPE_MARKER)\n if (at === -1) return null\n const rest = text.slice(at + ESCAPE_MARKER.length)\n const named = /^\\s*\\(([^)]*)\\)/.exec(rest)\n const rules = named ? named[1].split(/[\\s,]+/).filter(Boolean).map(shortRuleName) : []\n const reason = (named ? rest.slice(named[0].length) : rest).replace(/^\\s*:/, '').trim()\n return { rules, reason }\n}\n\nexport interface EstivaSettings {\n /**\n * Report every sanctioned escape as a message with the id `escaped`, so a\n * count can read them. Off in the lint anyone runs; on only in the count.\n */\n reportEscapes?: boolean\n}\n\ninterface Located {\n loc?: AST.SourceLocation | null\n range?: [number, number]\n}\n\nconst DIRECTIVE = /^\\s*eslint-disable(?:-next-line|-line)?(?=\\s|$)([^]*)$/\n\n/** The rules a directive names: what comes before its ` -- ` description. None means every rule. */\nfunction directiveRules(rest: string): string[] {\n const dashes = rest.search(/(?:^|\\s)--(?:\\s|$)/)\n return (dashes === -1 ? rest : rest.slice(0, dashes)).split(/[\\s,]+/).filter(Boolean)\n}\n\n/** Only spaces and a JSX expression's closing brace between the marker and the element. */\nconst BETWEEN = /^[\\s}]*$/\n\n/**\n * Whether the element at `node` carries a valid escape on the line above.\n *\n * Every rule of this plugin calls it before it reports. It reports, through\n * that rule, a marker with too short a reason and a marker inside an\n * eslint-disable directive for this rule; either way the element is not\n * escaped, so the rule reports it too.\n */\nexport function isEscaped(context: Rule.RuleContext, node: Located): boolean {\n const { sourceCode } = context\n if (!node.loc || !node.range) return false\n const line = node.loc.start.line\n const nodeStart = node.range[0]\n\n const comment = sourceCode\n .getAllComments()\n .find((c) => c.loc && c.range && c.loc.end.line === line - 1 && BETWEEN.test(sourceCode.text.slice(c.range[1], nodeStart)))\n if (!comment?.loc) return false\n\n const marker = readMarker(comment.value)\n if (!marker) return false\n const rule = shortRuleName(context.id)\n\n const directive = DIRECTIVE.exec(comment.value)\n if (directive) {\n const rules = directiveRules(directive[1])\n // A directive for other rules (the token lint's notes) is not an escape of this one.\n if (rules.length > 0 && !rules.includes(context.id)) return false\n context.report({ loc: comment.loc, messageId: 'escapeInDirective', data: { rule } })\n return false\n }\n\n // Named, but not this rule: another rule on the element may be the one it keeps off.\n if (marker.rules.length > 0 && !marker.rules.includes(rule)) return false\n if (marker.rules.length === 0) {\n context.report({ loc: comment.loc, messageId: 'escapeWithoutRule', data: { rule } })\n return false\n }\n\n const { reason } = marker\n if (reason.replace(/\\s/g, '').length < MIN_REASON) {\n context.report({ loc: comment.loc, messageId: 'escapeWithoutReason', data: { rule } })\n return false\n }\n\n const settings = context.settings[SETTINGS_KEY] as EstivaSettings | undefined\n if (settings?.reportEscapes) context.report({ loc: comment.loc, messageId: 'escaped', data: { reason } })\n return true\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\n/**\n * Behaviour Base UI already owns, written by hand inside the package (UIG-5,\n * P1 \u2014 the migration's standing rule D6 as a machine).\n *\n * This is the rule with the most to lose. A hand-made portal or a global\n * listener inside `DialogShell` is inherited by every caller in every app, and\n * nobody sees it from there.\n *\n * Two facts, both mechanical, both the signature of a floating part rebuilt by\n * hand:\n *\n * - **`createPortal`**, or importing it from `react-dom`. Base UI's parts carry\n * their own portal.\n * - **a listener on `window` or `document`** for the events a floating part\n * lives on \u2014 resize, scroll, an outside press, a key. Base UI's Positioner\n * follows the anchor and its Root closes on an outside press and on Escape.\n *\n * What it deliberately does not try to read: measuring arithmetic. `Popover`\n * hands Base UI a virtual anchor with a `getBoundingClientRect`, which is the\n * documented way to anchor to a rectangle rather than an element, and a rule\n * that guessed at arithmetic would report it. Anything that shape is caught by\n * a reader, not by this.\n *\n * A place that keeps one says why on the line above: `// @estiva-escape: <why>`.\n */\nconst FLOATING_EVENTS = new Set(['resize', 'scroll', 'mousedown', 'pointerdown', 'keydown', 'keyup', 'focusin', 'focusout', 'click'])\n\ninterface Node {\n type: string\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n}\n\ninterface Identifier extends Node {\n name: string\n}\n\ninterface ImportDeclaration extends Node {\n source: { value: unknown }\n specifiers: { type: string; imported?: { name?: string }; local?: { name?: string }; loc?: Rule.Node['loc']; range?: [number, number] }[]\n}\n\ninterface CallExpression extends Node {\n callee: { type: string; name?: string; object?: { type: string; name?: string }; property?: { type: string; name?: string } }\n arguments: { type: string; value?: unknown }[]\n parent?: { type: string; loc?: Rule.Node['loc']; range?: [number, number]; parent?: CallExpression['parent'] }\n}\n\n/**\n * The statement a call sits in, which is what an escape is written above:\n * `return createPortal(\u2026)` puts the call in the middle of its line, and a\n * comment above the line is above the statement.\n */\nfunction statement(node: { loc: NonNullable<Rule.Node['loc']>; range: [number, number]; parent?: CallExpression['parent'] }): {\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n} {\n for (let p = node.parent; p; p = p.parent) {\n if (!/(Statement|Declaration)$/.test(p.type)) continue\n if (p.loc && p.range) return { loc: p.loc, range: p.range }\n break\n }\n return { loc: node.loc, range: node.range }\n}\n\nexport const noHandRolledBehaviour: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'Overlay behaviour written by hand where Base UI has a part (D6)' },\n schema: [],\n messages: {\n portal:\n 'A portal written by hand. Base UI\\'s parts carry their own (Popover, Menu, Select, Tooltip, Dialog, Toast): use the part, or say why this one stays.',\n listener:\n 'A `{{event}}` listener on `{{target}}`. A floating part follows its anchor and closes on an outside press and on Escape by itself (Base UI Positioner and Root): use the part, or say why this one stays.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n return {\n ImportDeclaration(node: Rule.Node) {\n const declaration = node as unknown as ImportDeclaration\n if (declaration.source.value !== 'react-dom') return\n for (const specifier of declaration.specifiers) {\n if (specifier.type !== 'ImportSpecifier' || specifier.imported?.name !== 'createPortal') continue\n // The escape goes above the import line, not above the name inside it.\n if (isEscaped(context, declaration)) return\n context.report({ loc: declaration.loc, messageId: 'portal' })\n return\n }\n },\n CallExpression(node: Rule.Node) {\n const call = node as unknown as CallExpression\n const { callee } = call\n\n if (callee.type === 'Identifier' && callee.name === 'createPortal') {\n if (isEscaped(context, statement(call))) return\n context.report({ loc: call.loc, messageId: 'portal' })\n return\n }\n\n if (callee.type !== 'MemberExpression' || callee.property?.name !== 'addEventListener') return\n const target = callee.object?.type === 'Identifier' ? callee.object.name : undefined\n if (target !== 'window' && target !== 'document') return\n const [first] = call.arguments\n const event = first?.type === 'Literal' && typeof first.value === 'string' ? first.value : undefined\n if (!event || !FLOATING_EVENTS.has(event)) return\n if (isEscaped(context, statement(call))) return\n context.report({ loc: call.loc, messageId: 'listener', data: { event, target } })\n },\n }\n },\n}\n", "import { statSync } from 'node:fs'\nimport type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\nimport {\n bindingOfTag,\n classesOf,\n functionComponents,\n parseFile,\n partsOfFile,\n resolveModule,\n walk,\n type Node,\n type Parser,\n type PartBinding,\n} from './no-restyled-part'\n\ntype Locals = Map<string, PartBinding | 'namespace'>\n\nconst child = (node: Node, key: string) => node[key] as Node | null | undefined\nconst children = (node: Node, key: string) => ((node[key] as (Node | null)[] | undefined) ?? []).filter((n): n is Node => !!n)\nconst nameOf = (node: Node | null | undefined): string | undefined =>\n node?.type === 'Identifier' || node?.type === 'JSXIdentifier' ? (node.name as string) : undefined\nconst tagName = (element: Node) => nameOf(child(child(element, 'openingElement') as Node, 'name'))\n/**\n * Whether a name is the part itself: imported, re-exported, or an app wrapper\n * that hands everything on (Peek's `EmptyState`). A component that only hands\n * its `className` to one (Ship's `Activity`) is the app's own, and is followed.\n */\nconst isPart = (binding: PartBinding | undefined, part: string) => binding?.part === part && binding.props === 'all'\nconst attributeOf = (opening: Node, name: string) => children(opening, 'attributes').find((a) => a.type === 'JSXAttribute' && nameOf(child(a, 'name')) === name)\n\n// ---------------------------------------------------------------- shape 1: a line drawn by hand\n\n/**\n * An empty state is a line, not a paragraph of prose. The words are not read:\n * UIG-1's pass on words alone fired on a hint and a status note, and words\n * missed four of Peek's dialogs (\"There is nowhere else to move it\u2026\", \"Every\n * topic is already in your Open work.\"). Where the line sits decides.\n */\nconst SHORT = 120\n\n/**\n * The element's words, when words are all it holds: text, a string, a name\n * dropped into a sentence (\"There is nowhere else in {teamName} to put it.\").\n * A line with no words of its own \u2014 a count, a message's body \u2014 is not one.\n */\nfunction onlyWords(element: Node): string | undefined {\n let line = ''\n let own = ''\n for (const kid of children(element, 'children')) {\n let piece: string\n if (kid.type === 'JSXText') piece = String(kid.value)\n else if (kid.type === 'JSXExpressionContainer') {\n const e = child(kid, 'expression') as Node\n if (e.type === 'JSXEmptyExpression') continue\n if (e.type === 'Literal' && typeof e.value === 'string') piece = e.value\n else if (e.type === 'TemplateLiteral' && children(e, 'expressions').length === 0) piece = children(e, 'quasis').map((q) => (q.value as { cooked: string }).cooked).join('')\n else if (e.type === 'Identifier' || e.type === 'MemberExpression') {\n line += 'x'\n continue\n } else return undefined\n } else return undefined\n own += piece\n line += piece\n }\n if (!/[a-z]{2,}/i.test(own)) return undefined\n return line.replace(/\\s+/g, ' ').trim()\n}\n\nconst isCount = (node: Node | null | undefined): boolean => {\n if (node?.type === 'ChainExpression') return isCount(child(node, 'expression'))\n return node?.type === 'MemberExpression' && !node.computed && /^(?:length|size)$/.test(nameOf(child(node, 'property')) ?? '')\n}\nconst isNumber = (node: Node | null | undefined, n: number) => node?.type === 'Literal' && node.value === n\n\n/**\n * What a condition says about a list: `empty` when it is true for an empty one\n * (`rows.length === 0`, `!rows.length`, `isEmpty(rows)`), `full` when it is\n * true for a list with rows (`rows.length > 0`, `rows.length`), nothing when it\n * does not ask. `a && b` says what either side says.\n */\nfunction whenTrue(test: Node | null | undefined): 'empty' | 'full' | undefined {\n if (!test) return undefined\n if (isCount(test)) return 'full'\n switch (test.type) {\n case 'UnaryExpression': {\n if (test.operator !== '!') return undefined\n const inner = whenTrue(child(test, 'argument'))\n return inner === 'empty' ? 'full' : inner === 'full' ? 'empty' : undefined\n }\n case 'LogicalExpression':\n if (test.operator !== '&&') return undefined\n return whenTrue(child(test, 'left')) ?? whenTrue(child(test, 'right'))\n case 'BinaryExpression': {\n let [count, other, op] = [child(test, 'left'), child(test, 'right'), String(test.operator)]\n if (!isCount(count)) [count, other, op] = [other, count, ({ '<': '>', '>': '<', '<=': '>=', '>=': '<=' } as Record<string, string>)[op] ?? op]\n if (!isCount(count)) return undefined\n if (isNumber(other, 0)) return op === '===' || op === '==' || op === '<=' ? 'empty' : op === '>' || op === '!==' || op === '!=' ? 'full' : undefined\n if (isNumber(other, 1)) return op === '<' ? 'empty' : op === '>=' ? 'full' : undefined\n return undefined\n }\n case 'CallExpression': {\n const callee = child(test, 'callee')\n const name = callee?.type === 'MemberExpression' ? nameOf(child(callee, 'property')) : nameOf(callee)\n return name && /^is(?:Empty|Blank)$/.test(name) ? 'empty' : undefined\n }\n default:\n return undefined\n }\n}\n\nconst isMapCall = (node: Node | null | undefined) => {\n const callee = node?.type === 'CallExpression' ? child(node, 'callee') : undefined\n return callee?.type === 'MemberExpression' && nameOf(child(callee, 'property')) === 'map'\n}\n\n/**\n * Whether a branch **is** a list: a `.map(\u2026)`, or a box that holds only that \u2014\n * `<ul>{rows.map(\u2026)}</ul>`. A branch that shows something else and lists a few\n * things inside it (an answer with its sources) is not the list the line stands\n * in for.\n */\nfunction isAList(branch: Node | null | undefined, depth = 0): boolean {\n if (!branch || depth > 2) return false\n if (isMapCall(branch)) return true\n if (branch.type !== 'JSXElement' && branch.type !== 'JSXFragment') return false\n if (branch.type === 'JSXElement' && !/^[a-z]/.test(tagName(branch) ?? '')) return false\n const kids = children(branch, 'children').filter((k) => !(k.type === 'JSXText' && !String(k.value).trim()) && !(k.type === 'JSXExpressionContainer' && (child(k, 'expression') as Node).type === 'JSXEmptyExpression'))\n return kids.length === 1 && (kids[0].type === 'JSXExpressionContainer' ? isMapCall(child(kids[0], 'expression')) : isAList(kids[0], depth + 1))\n}\n\n/** A box around one thing and nothing else: a wrapper that pads or places the line. */\nfunction soleChildOf(parent: Node | undefined, element: Node): boolean {\n if (parent?.type !== 'JSXElement' || !/^[a-z]/.test(tagName(parent) ?? '')) return false\n const kids = children(parent, 'children').filter((k) => !(k.type === 'JSXText' && !String(k.value).trim()) && !(k.type === 'JSXExpressionContainer' && (child(k, 'expression') as Node).type === 'JSXEmptyExpression'))\n return kids.length === 1 && kids[0] === element\n}\n\n/**\n * Whether the element stands where a list's rows would be: one side of a\n * condition whose other side maps a list, or under a condition that asks if\n * something is empty \u2014 `cond && \u2026`, `cond ? \u2026 : \u2026`, `if (cond) return \u2026`.\n */\nfunction standsInForAList(element: Node): boolean {\n let at = element\n for (let depth = 0; depth < 3 && soleChildOf(at.parent, at); depth += 1) at = at.parent as Node\n const parent = at.parent\n if (!parent) return false\n if (parent.type === 'ConditionalExpression' && parent.test !== at) {\n const consequent = parent.consequent === at\n const other = child(parent, consequent ? 'alternate' : 'consequent')\n return whenTrue(child(parent, 'test')) === (consequent ? 'empty' : 'full') || isAList(other)\n }\n if (parent.type === 'LogicalExpression' && parent.operator === '&&' && parent.right === at) return whenTrue(child(parent, 'left')) === 'empty'\n if (parent.type === 'ReturnStatement') {\n let holder = parent.parent\n if (holder?.type === 'BlockStatement' && children(holder, 'body').length === 1) holder = holder.parent\n return holder?.type === 'IfStatement' && child(holder, 'consequent') !== undefined && whenTrue(child(holder, 'test')) === 'empty'\n }\n return false\n}\n\n// ---------------------------------------------------------------- shape 2: the right part at the wrong scope\n\n/** A content box that fills its viewport: `min-h-full` or `h-full` on `contentClassName`. */\nconst FILLS = /^(?:min-h-full|h-full)$/\n\n/** What a box does that a page-scope EmptyState already does itself: centre, or leave room round it. */\nconst CENTRES = /^(?:justify-center|items-center|content-center|place-(?:items|content)-center)$/\nconst PADS = /^p[xytrblse]?-/\n\n/** The only element a box holds, when it holds one and nothing else but blank space. */\nfunction onlyElement(box: Node): Node | undefined {\n const kids = children(box, 'children').filter((kid) => !(kid.type === 'JSXText' && !String(kid.value).trim()))\n return kids.length === 1 && kids[0].type === 'JSXElement' ? kids[0] : undefined\n}\n\nfunction isPageScope(opening: Node): boolean {\n const scope = attributeOf(opening, 'scope')\n if (!scope) return true\n const value = child(scope, 'value')\n return value?.type === 'Literal' && value.value === 'page'\n}\n\ninterface FileFacts {\n file: string\n locals: Locals\n components: Map<string, Node>\n /** A local name imported from the app's own files: where from, and under what name. */\n imports: Map<string, { file: string; name: string }>\n}\n\nconst factsCache = new Map<string, { mtime: number; facts: FileFacts | null }>()\n\nfunction factsOf(file: string, program: Node, parser: Parser): FileFacts {\n const imports = new Map<string, { file: string; name: string }>()\n for (const statement of children(program, 'body')) {\n if (statement.type !== 'ImportDeclaration' || statement.importKind === 'type') continue\n const target = resolveModule(file, String((child(statement, 'source') as Node).value))\n if (!target) continue\n for (const specifier of children(statement, 'specifiers')) {\n if (specifier.type !== 'ImportSpecifier' || specifier.importKind === 'type') continue\n const local = nameOf(child(specifier, 'local'))\n const imported = nameOf(child(specifier, 'imported'))\n if (local && imported) imports.set(local, { file: target, name: imported })\n }\n }\n return { file, locals: partsOfFile(file, program, parser), components: functionComponents(program), imports }\n}\n\nfunction factsOfFile(file: string, parser: Parser): FileFacts | null {\n const mtime = statSync(file).mtimeMs\n const cached = factsCache.get(file)\n if (cached && cached.mtime === mtime) return cached.facts\n factsCache.set(file, { mtime, facts: null })\n const program = parseFile(parser, file)\n const facts = program ? factsOf(file, program, parser) : null\n factsCache.set(file, { mtime, facts })\n return facts\n}\n\ninterface PageState {\n file: string\n line: number\n}\n\n/**\n * Every page-scope `EmptyState` a component can draw, following the app's own\n * components it draws in turn, in its file and in the files it imports from,\n * four deep.\n */\nfunction pageStatesOf(facts: FileFacts, name: string, parser: Parser, depth: number, seen: Set<string>): PageState[] {\n const key = `${facts.file}#${name}`\n if (depth > 4 || seen.has(key)) return []\n seen.add(key)\n const local = facts.components.get(name)\n if (!local) {\n const from = facts.imports.get(name)\n const there = from ? factsOfFile(from.file, parser) : null\n return there && from ? pageStatesOf(there, from.name, parser, depth + 1, seen) : []\n }\n const found: PageState[] = []\n walk(local, (node) => {\n if (node.type !== 'JSXOpeningElement') return\n const tag = child(node, 'name')\n const binding = bindingOfTag(tag, facts.locals)\n if (isPart(binding, 'EmptyState')) {\n if (isPageScope(node)) found.push({ file: facts.file, line: node.loc?.start.line ?? 0 })\n return\n }\n const component = binding?.props === 'all' ? undefined : nameOf(tag)\n if (component && /^[A-Z]/.test(component)) found.push(...pageStatesOf(facts, component, parser, depth + 1, seen))\n })\n return found\n}\n\nconst fileName = (file: string) => file.replace(/\\\\/g, '/').split('/').pop()\n\n/**\n * UIG-23: an empty state drawn by hand, or the right part at the wrong scope.\n *\n * **A line drawn by hand.** A plain box whose only content is a short line\n * saying there is nothing (\"No tickets yet.\") where a list's rows would be: one\n * side of a condition whose other side maps the list, or under a condition that\n * asks if something is empty. Both halves are needed. The words alone fire on a\n * hint and a status note (UIG-1 measured it); the place alone fires on any\n * line a list shows beside itself.\n *\n * **The wrong scope.** A `page`-scope `EmptyState` centres in the room a flex\n * column gives it. Inside a `ScrollArea` the content box is only as tall as\n * what is in it, so the state sits at the top of its pane. The rule looks at\n * the `ScrollArea`'s content and at every component of the app's own placed in\n * it, following them into their files, because that is how four of them\n * arrived on Folders in one merge (peek `7f22e5e`): the state was drawn in one\n * file and scrolled in another. A `contentClassName` with `min-h-full` or\n * `h-full` gives the state its room, and passes.\n *\n * **A box that places it** (UIG-42). A plain box holding only a page-scope\n * `EmptyState` and centring or padding it does the part's own job, and a box\n * like that pinned the starter's home page 64px from the top (UIG-10). A box\n * that is only the flex column the state asks for passes, and so does any box\n * round a `section` state, which takes its inset from the box (Katerina, 14\n * September).\n *\n * Not judged: the package's `EmptyState` and a part's own lines (a\n * `FieldLine`, a palette's empty row) \u2014 a part is already a part.\n */\nexport const noHandmadeEmptyState: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'An empty state drawn by hand, or a page-scope EmptyState that cannot centre' },\n schema: [],\n messages: {\n handmade:\n 'A line saying there is nothing is an EmptyState. Use `EmptyState` from @estiva-app/ui: `scope=\"section\"` inside a section, `scope=\"page\"` for a whole page.',\n wrongScope:\n 'A page-scope EmptyState inside a ScrollArea sits at the top of its pane, not the middle: the ScrollArea\\'s content is only as tall as what is in it. Use `scope=\"section\"` when the pane has anything else on it; when the whole pane is empty, draw the page EmptyState in place of the ScrollArea, not inside it.',\n boxedPage:\n 'This box {{what}} a page-scope EmptyState, which centres itself in the room a flex column gives it and takes no padding. A box that places it can push it out of the middle, as the starter\\'s home page did (UIG-10). Draw the EmptyState straight into the column, with `className=\"h-full\"` outside a flex column.',\n wrongScopeVia:\n '`{{component}}` draws a page-scope EmptyState ({{where}}) inside this ScrollArea, where it sits at the top of its pane, not the middle: the ScrollArea\\'s content is only as tall as what is in it. Use `scope=\"section\"` there when the pane has anything else on it; when the whole pane is empty, draw the page EmptyState in place of the ScrollArea, not inside it.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const parser = (context.languageOptions?.parser ?? {}) as Parser\n const file = context.filename\n let facts: FileFacts | undefined\n // A ScrollArea inside another is walked by both; each state is reported once.\n const reported = new Set<Node>()\n const scopeOf = (node: Node) => context.sourceCode.getScope(node as unknown as Parameters<typeof context.sourceCode.getScope>[0])\n\n return {\n Program(program) {\n facts = factsOf(file, program as unknown as Node, parser)\n },\n JSXElement(ruleNode: Rule.Node) {\n const element = ruleNode as unknown as Node\n const opening = child(element, 'openingElement') as Node\n const tag = tagName(element)\n\n if (tag && /^[a-z]/.test(tag)) {\n // Shape 3 (UIG-42): a plain box around a page-scope EmptyState that centres or pads it.\n const only = facts && onlyElement(element)\n const inner = only && (child(only, 'openingElement') as Node)\n // Props spread in (`{...args}`) may carry the scope, so it is not judged.\n const spread = inner && children(inner, 'attributes').some((a) => a.type === 'JSXSpreadAttribute')\n if (inner && !spread && isPart(bindingOfTag(child(inner, 'name'), facts!.locals), 'EmptyState') && isPageScope(inner)) {\n const className = attributeOf(opening, 'className')\n const own = className ? classesOf(child(className, 'value'), scopeOf).map((c) => c.replace(/^(?:[^:\\s[\\]]+:)+/, '')) : []\n const centres = own.some((c) => CENTRES.test(c))\n const pads = own.some((c) => PADS.test(c))\n if ((centres || pads) && !isEscaped(context, opening)) {\n const what = centres && pads ? 'centres and pads' : centres ? 'centres' : 'pads'\n context.report({ loc: opening.loc as NonNullable<Rule.Node['loc']>, messageId: 'boxedPage', data: { what } })\n }\n return\n }\n\n // Shape 1: a plain box holding only a \"nothing\" line, where a list would be.\n const words = onlyWords(element)\n if (!words || words.length > SHORT) return\n if (!standsInForAList(element)) return\n if (isEscaped(context, opening)) return\n context.report({ loc: opening.loc as NonNullable<Rule.Node['loc']>, messageId: 'handmade' })\n return\n }\n\n // Shape 2: a page-scope EmptyState in a ScrollArea that does not fill.\n if (!facts || !isPart(bindingOfTag(child(opening, 'name'), facts.locals), 'ScrollArea')) return\n const content = attributeOf(opening, 'contentClassName')\n if (content && classesOf(child(content, 'value'), scopeOf).some((c) => FILLS.test(c.replace(/^(?:[^:\\s[\\]]+:)+/, '')))) return\n const here = facts\n for (const kid of children(element, 'children')) {\n walk(kid, (node) => {\n if (node.type !== 'JSXOpeningElement') return\n const name = child(node, 'name')\n const binding = bindingOfTag(name, here.locals)\n if (isPart(binding, 'EmptyState')) {\n if (!isPageScope(node) || reported.has(node) || isEscaped(context, node)) return\n reported.add(node)\n context.report({ loc: node.loc as NonNullable<Rule.Node['loc']>, messageId: 'wrongScope' })\n return\n }\n const component = binding?.props === 'all' ? undefined : nameOf(name)\n if (!component || !/^[A-Z]/.test(component)) return\n const states = pageStatesOf(here, component, parser, 0, new Set())\n if (!states.length || reported.has(node) || isEscaped(context, node)) return\n reported.add(node)\n // In reading order: file, then line.\n for (const state of [...states].sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line)) {\n const where = state.file === file ? `line ${state.line}` : `${fileName(state.file)}:${state.line}`\n context.report({ loc: node.loc as NonNullable<Rule.Node['loc']>, messageId: 'wrongScopeVia', data: { component, where } })\n }\n })\n }\n },\n }\n },\n}\n", "import { existsSync, readFileSync, statSync } from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\nimport type { Rule, Scope } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\n/**\n * A part of the package is placed from outside, never restyled (UIG-9; Katerina's\n * ruling B8 of 13 September, \"only position and spacing pass into our\n * components\").\n *\n * Every part takes `className`, and some take a second class prop for an inner\n * box (`contentClassName`, `bodyClassName`\u2026). Through either, an app could push\n * a colour, a text size or a border into a part and quietly undo it: the token\n * lint only asks whether a class is a real token, never whether the part should\n * take it. This rule reads every class passed into a part and lets through only\n * placement \u2014 where the part sits and how much room it takes.\n *\n * **Which elements are parts: by where they come from, never by name.** No list\n * of names is kept, so a part added to the package later is covered the day it\n * is added.\n *\n * - In an app: anything imported from `@estiva-app/ui`, and anything imported\n * from the app's own files that is one of those \u2014 a re-export (Peek's\n * `components/ui/Button.tsx`), a wrapper that hands its props on to a part\n * (`{...rest}`), or a component that hands its own `className` on to a part\n * (Peek's `ConversationCard` into `Card`). Relative imports and the apps' `@/`\n * alias are followed; `@/` is the `src` folder beside the nearest\n * `package.json`.\n * - Inside the package (Katerina, 17 September): a name `src/index.ts` exports,\n * imported from a sibling file or declared in the same file.\n *\n * **What it reads:** a string, a template, `cn()`/`clsx()` and their arguments,\n * both sides of a condition, a `const` in the same file and the values of a\n * class map read from one. A class the code works out while it runs passes: the\n * rule cannot read it.\n *\n * `EmptyState` takes no padding either (Katerina's ruling 6 of 14 September):\n * its room comes from the box its rows live in.\n *\n * `Form` takes no layout for its fields (Katerina, 28 September): it stacks\n * them 24px apart itself, so every form reads the same. A form that is not a\n * list of fields says `layout=\"free\"`, and then lays itself out.\n */\n\n// ---------------------------------------------------------------- the classes\n\n/** Where a part sits and how much room it takes. Read on the utility, after its variants. */\nexport const PLACEMENT: { what: string; pattern: RegExp }[] = [\n { what: 'space around', pattern: /^m[xytrblse]?-/ },\n { what: 'space inside', pattern: /^p[xytrblse]?-/ },\n { what: 'width and height', pattern: /^(?:w|h|size|min-w|min-h|max-w|max-h)-/ },\n { what: 'shown, and how it lays out', pattern: /^(?:hidden|block|inline|inline-block|inline-flex|inline-grid|flex|grid|contents|flow-root)$/ },\n { what: 'its place in a row or a grid', pattern: /^(?:grow|shrink)$|^(?:flex|basis|grow|shrink|order|gap|gap-x|gap-y|space-x|space-y|col|row|grid-cols|grid-rows|grid-flow|auto-cols|auto-rows)-/ },\n { what: 'alignment', pattern: /^(?:self|justify|justify-items|justify-self|items|place-content|place-items|place-self)-|^content-(?!\\[)/ },\n { what: 'position', pattern: /^(?:static|relative|absolute|fixed|sticky)$|^(?:inset|inset-x|inset-y|top|right|bottom|left|start|end|z)-/ },\n // Draws nothing: it names the part, so what is inside can answer its hover (`group-hover:`).\n { what: 'a name for hover', pattern: /^(?:group|peer)(?:\\/[\\w-]+)?$/ },\n]\n\n/**\n * The same, as `style` keys (Katerina's ruling B6, 25 September): `style` on a\n * part is read like its `className`, so a radius, a weight or an opacity cannot\n * go in by the other door. CSS's own names for space, size, flex and grid, and\n * position; `transform` and `translate` move a part without changing its look.\n * A custom property (`--name`) passes: the part decides what it means.\n */\nexport const PLACEMENT_STYLE =\n /^(?:margin|padding|inset|scrollMargin)(?:Top|Right|Bottom|Left|Block|Inline|BlockStart|BlockEnd|InlineStart|InlineEnd)?$|^(?:width|height|minWidth|minHeight|maxWidth|maxHeight|inlineSize|blockSize|minInlineSize|minBlockSize|maxInlineSize|maxBlockSize)$|^(?:display|flex|flexGrow|flexShrink|flexBasis|order|gap|rowGap|columnGap|alignSelf|justifySelf|placeSelf|gridArea|gridColumn|gridColumnStart|gridColumnEnd|gridRow|gridRowStart|gridRowEnd)$|^(?:position|top|right|bottom|left|zIndex|transform|translate)$/\n\n/**\n * A variant that draws another box or reaches inside the part: `before:`,\n * `after:`, `[&>*]:`, `*:`\u2026 A placement class behind one of these is not the\n * part's placement.\n */\nconst REACHING_VARIANT = /^\\[|^(?:before|after|placeholder|file|marker|selection|first-letter|first-line|backdrop|\\*|\\*\\*)$/\n\n/** A class list's variants and its utility: `sm:[&>*]:shrink-0` \u2192 `['sm', '[&>*]']`, `shrink-0`. */\nexport function splitClass(token: string): { variants: string[]; utility: string } {\n const variants: string[] = []\n let current = ''\n let depth = 0\n for (const character of token) {\n if (character === '[') depth += 1\n if (character === ']') depth -= 1\n if (character === ':' && depth === 0) {\n variants.push(current)\n current = ''\n } else current += character\n }\n return { variants, utility: current.replace(/^!/, '').replace(/!$/, '').replace(/^-/, '') }\n}\n\n/** Whether a class only places the part. */\nexport function isPlacement(token: string): boolean {\n const { variants, utility } = splitClass(token)\n if (variants.some((variant) => REACHING_VARIANT.test(variant))) return false\n return PLACEMENT.some(({ pattern }) => pattern.test(utility))\n}\n\n/** How a form's fields are laid out: its display, direction, gaps and alignment. */\nconst FIELDS_LAYOUT = /^(?:block|flex|grid|inline-flex|inline-grid|contents|flow-root)$|^(?:gap|gap-x|gap-y|space-x|space-y|grid-cols|grid-rows|grid-flow|auto-cols|auto-rows|items|justify|justify-items|place-content|place-items)-|^flex-(?:row|col|wrap|nowrap)|^content-(?!\\[)/\n\nconst isFieldsLayout = (token: string) => {\n const { variants, utility } = splitClass(token)\n return !variants.some((variant) => REACHING_VARIANT.test(variant)) && FIELDS_LAYOUT.test(utility)\n}\n\n/** Room between a box's children, down the page or across it: what spaces a Form from its neighbours. */\nconst isSpacing = (token: string) => {\n const { variants, utility } = splitClass(token)\n return !variants.some((variant) => REACHING_VARIANT.test(variant)) && /^(?:gap|gap-x|gap-y|space-x|space-y)-/.test(utility)\n}\n\nconst isPadding = (token: string) => {\n const { variants, utility } = splitClass(token)\n return !variants.some((variant) => REACHING_VARIANT.test(variant)) && /^p[xytrblse]?-/.test(utility)\n}\n\n/**\n * The props a part has for how it looks, named in the message. Held to the\n * package's source by `no-restyled-part.test.ts`: every prop here exists, and\n * every look prop an exported part has is here. A part missing from this table\n * has none, and the message says to ask for one.\n */\nexport const PART_LOOK_PROPS: Record<string, string[]> = {\n AppShell: ['variant'],\n Avatar: ['size'],\n AvatarGroup: ['size'],\n Banner: ['tone'],\n Button: ['variant', 'size'],\n Card: ['fill', 'hover', 'attention', 'selected', 'active', 'hovered', 'quietUntilHover', 'unreadable', 'clip'],\n Checkbox: ['row'],\n Chip: ['type'],\n CollapsibleSection: ['look'],\n Divider: ['tone', 'orientation'],\n EmptyState: ['scope'],\n FieldLine: ['tone'],\n IconButton: ['variant', 'pressed', 'glow'],\n InputChip: ['truncate'],\n Kbd: ['tone'],\n Link: ['variant', 'truncate', 'cover'],\n MenuItem: ['size', 'selected', 'destructive'],\n MenuSub: ['selected'],\n NavItem: ['active'],\n Person: ['size'],\n ProgressBar: ['variant'],\n Property: ['layout'],\n RailItem: ['active'],\n Reaction: ['pressed'],\n ReactionPicker: ['surface'],\n RichText: ['size'],\n SectionHeader: ['hover', 'look'],\n SectionLabel: ['tone', 'truncate'],\n ShowMore: ['surface'],\n Select: ['size'],\n Tabs: ['size'],\n TextInput: ['size'],\n Toast: ['type'],\n Toolbar: ['surface'],\n ToolbarButton: ['variant', 'pressed', 'glow'],\n TopBar: ['variant'],\n}\n\n/** The class props of a part: `className`, and the ones for an inner box. */\nconst CLASS_PROP = /^(?:className|[a-z][A-Za-z]*ClassName)$/\n\n// ---------------------------------------------------------------- the nodes\n\ninterface Node {\n type: string\n range: [number, number]\n loc?: NonNullable<Rule.Node['loc']>\n parent?: Node\n [key: string]: unknown\n}\n\nconst child = (node: Node, key: string) => node[key] as Node | null | undefined\nconst children = (node: Node, key: string) => (node[key] as (Node | null)[] | undefined) ?? []\nconst nameOf = (node: Node | null | undefined): string | undefined =>\n node?.type === 'Identifier' || node?.type === 'JSXIdentifier' ? (node.name as string) : node?.type === 'Literal' && typeof node.value === 'string' ? node.value : undefined\n\n/** Walk every node under `root`, skipping the parser's bookkeeping keys. */\nfunction walk(root: Node, visit: (node: Node) => void): void {\n const stack: Node[] = [root]\n while (stack.length) {\n const node = stack.pop() as Node\n visit(node)\n for (const key of Object.keys(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range' || key === 'tokens' || key === 'comments') continue\n const value = node[key]\n if (Array.isArray(value)) for (const item of value) { if (item && typeof (item as Node).type === 'string') stack.push(item as Node) }\n else if (value && typeof (value as Node).type === 'string') stack.push(value as Node)\n }\n }\n}\n\n// ---------------------------------------------------------------- the parts\n\n/**\n * What a name is to this rule: the part it draws, and which of the caller's\n * class props reach which of the part's (`all` for a part, a re-export or a\n * wrapper; a map for a component that hands on its own `className`). `via` is\n * the app's own component in between, for the message.\n */\nexport interface PartBinding {\n part: string\n props: 'all' | Record<string, string>\n via?: string\n}\n\ninterface Parser {\n parseForESLint?: (code: string, options: unknown) => { ast: Node }\n parse?: (code: string, options: unknown) => Node\n}\n\ninterface ModuleFacts {\n mtime: number\n exports: Map<string, PartBinding>\n}\n\nconst PACKAGE = '@estiva-app/ui'\nconst moduleCache = new Map<string, ModuleFacts>()\nconst packageDirCache = new Map<string, string | null>()\nconst packagePartsCache = new Map<string, { mtime: number; parts: Set<string> }>()\n\nfunction parseFile(parser: Parser, filePath: string): Node | null {\n const code = readFileSync(filePath, 'utf8')\n const options = { filePath, ecmaVersion: 'latest', sourceType: 'module', ecmaFeatures: { jsx: filePath.endsWith('x') }, range: true, loc: true }\n try {\n if (parser.parseForESLint) return parser.parseForESLint(code, options).ast\n if (parser.parse) return parser.parse(code, options)\n } catch {\n // A file that does not parse is its own lint's business; it hands on no parts.\n }\n return null\n}\n\n/** The nearest folder holding a `package.json`, from a file. */\nfunction packageDirOf(file: string): string | null {\n const start = dirname(resolve(file))\n if (packageDirCache.has(start)) return packageDirCache.get(start) ?? null\n let dir = start\n for (;;) {\n if (existsSync(join(dir, 'package.json'))) break\n const up = dirname(dir)\n if (up === dir) {\n dir = ''\n break\n }\n dir = up\n }\n packageDirCache.set(start, dir || null)\n return dir || null\n}\n\nfunction resolveModule(fromFile: string, specifier: string): string | null {\n let base: string\n if (specifier.startsWith('.')) base = resolve(dirname(fromFile), specifier)\n else if (specifier.startsWith('@/')) {\n const dir = packageDirOf(fromFile)\n if (!dir) return null\n base = join(dir, 'src', specifier.slice(2))\n } else return null\n for (const candidate of [base, `${base}.tsx`, `${base}.ts`, join(base, 'index.tsx'), join(base, 'index.ts')]) {\n if (existsSync(candidate) && statSync(candidate).isFile()) return candidate\n }\n return null\n}\n\n/** The names this package's `src/index.ts` exports, when the file lives in `@estiva-app/ui` itself. */\nfunction packagePartsFor(file: string, parser: Parser): Set<string> | null {\n const dir = packageDirOf(file)\n if (!dir) return null\n let name: string | undefined\n try {\n name = (JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as { name?: string }).name\n } catch {\n return null\n }\n if (name !== PACKAGE) return null\n const index = join(dir, 'src', 'index.ts')\n if (!existsSync(index)) return null\n const mtime = statSync(index).mtimeMs\n const cached = packagePartsCache.get(index)\n if (cached && cached.mtime === mtime) return cached.parts\n const parts = new Set<string>()\n const ast = parseFile(parser, index)\n for (const statement of ast ? children(ast, 'body') : []) {\n if (statement?.type !== 'ExportNamedDeclaration' || statement.exportKind === 'type') continue\n for (const specifier of children(statement, 'specifiers')) {\n const exported = nameOf(child(specifier as Node, 'exported'))\n if (specifier?.exportKind !== 'type' && exported && /^[A-Z][a-z]/.test(exported)) parts.add(exported)\n }\n }\n packagePartsCache.set(index, { mtime, parts })\n return parts\n}\n\n/** A function component declared in a module: its name, and the function. */\nfunction functionComponents(program: Node): Map<string, Node> {\n const found = new Map<string, Node>()\n const unwrap = (node: Node | null | undefined): Node | null => {\n let current = node\n while (current?.type === 'CallExpression' && children(current, 'arguments').length) {\n const callee = child(current, 'callee')\n const text = callee?.type === 'Identifier' ? nameOf(callee) : callee?.type === 'MemberExpression' ? nameOf(child(callee, 'property')) : undefined\n if (text !== 'forwardRef' && text !== 'memo') return null\n current = children(current, 'arguments')[0]\n }\n return current?.type === 'ArrowFunctionExpression' || current?.type === 'FunctionExpression' ? current : null\n }\n walk(program, (node) => {\n if (node.type === 'FunctionDeclaration') {\n const name = nameOf(child(node, 'id'))\n if (name && /^[A-Z]/.test(name)) found.set(name, node)\n } else if (node.type === 'VariableDeclarator') {\n const name = nameOf(child(node, 'id'))\n const fn = unwrap(child(node, 'init'))\n if (name && /^[A-Z]/.test(name) && fn) found.set(name, fn)\n }\n })\n return found\n}\n\n/**\n * The parts a module's names stand for. `ownFile` is the file being linted: its\n * imports are read the same way, so a wrapper declared beside its use counts.\n */\nfunction moduleParts(file: string, program: Node, parser: Parser, stack: Set<string>): { locals: Map<string, PartBinding | 'namespace'>; exports: Map<string, PartBinding> } {\n const locals = new Map<string, PartBinding | 'namespace'>()\n const packageParts = packagePartsFor(file, parser)\n const body = children(program, 'body')\n\n const exportsOf = (specifier: string): Map<string, PartBinding> | 'package' | null => {\n if (specifier === PACKAGE) return 'package'\n const target = resolveModule(file, specifier)\n if (!target) return null\n if (packageParts) return 'package'\n return moduleExports(target, parser, stack)\n }\n\n for (const statement of body) {\n if (statement?.type !== 'ImportDeclaration' || statement.importKind === 'type') continue\n const source = exportsOf(String((child(statement, 'source') as Node).value))\n if (!source) continue\n for (const specifier of children(statement, 'specifiers')) {\n if (!specifier || specifier.importKind === 'type') continue\n const local = nameOf(child(specifier, 'local'))\n if (!local) continue\n if (specifier.type === 'ImportNamespaceSpecifier') {\n if (source === 'package' && !packageParts) locals.set(local, 'namespace')\n continue\n }\n const imported = specifier.type === 'ImportDefaultSpecifier' ? 'default' : nameOf(child(specifier, 'imported'))\n if (!imported) continue\n if (source === 'package') {\n const isPart = packageParts ? packageParts.has(imported) : /^[A-Z]/.test(imported)\n if (isPart) locals.set(local, { part: imported, props: 'all' })\n } else if (source.has(imported)) locals.set(local, source.get(imported) as PartBinding)\n }\n }\n\n // Inside the package, a part used in the file that declares it.\n const components = functionComponents(program)\n if (packageParts) for (const name of components.keys()) if (packageParts.has(name) && !locals.has(name)) locals.set(name, { part: name, props: 'all' })\n\n // In an app, a component that hands its props, or its own className, on to a part.\n if (!packageParts) {\n let changed = true\n for (let round = 0; changed && round < 10; round += 1) {\n changed = false\n for (const [name, fn] of components) {\n const binding = handsOnTo(fn, (tag) => bindingOfTag(tag, locals))\n if (!binding) continue\n const next = { ...binding, via: name }\n const previous = locals.get(name)\n if (!previous || JSON.stringify(previous) !== JSON.stringify(next)) {\n if (previous && previous !== 'namespace' && !previous.via) continue\n locals.set(name, next)\n changed = true\n }\n }\n }\n }\n\n const exports = new Map<string, PartBinding>()\n const localBinding = (name: string | undefined) => {\n const binding = name ? locals.get(name) : undefined\n return binding && binding !== 'namespace' ? binding : undefined\n }\n for (const statement of body) {\n if (!statement) continue\n if (statement.type === 'ExportNamedDeclaration') {\n const declaration = child(statement, 'declaration')\n if (declaration?.type === 'FunctionDeclaration') {\n const name = nameOf(child(declaration, 'id'))\n const binding = localBinding(name)\n if (name && binding) exports.set(name, binding)\n } else if (declaration?.type === 'VariableDeclaration') {\n for (const declarator of children(declaration, 'declarations')) {\n const name = nameOf(child(declarator as Node, 'id'))\n const init = child(declarator as Node, 'init')\n const binding = localBinding(name) ?? (init?.type === 'Identifier' ? localBinding(nameOf(init)) : undefined)\n if (name && binding) exports.set(name, binding)\n }\n }\n const source = child(statement, 'source')\n const from = source ? exportsOf(String(source.value)) : null\n for (const specifier of children(statement, 'specifiers')) {\n if (!specifier || specifier.exportKind === 'type') continue\n const local = nameOf(child(specifier, 'local'))\n const exported = nameOf(child(specifier, 'exported'))\n if (!local || !exported) continue\n if (!source) {\n const binding = localBinding(local)\n if (binding) exports.set(exported, binding)\n } else if (from === 'package') {\n if (/^[A-Z]/.test(local)) exports.set(exported, { part: local, props: 'all' })\n } else if (from?.has(local)) exports.set(exported, from.get(local) as PartBinding)\n }\n } else if (statement.type === 'ExportAllDeclaration' && !child(statement, 'exported')) {\n const from = exportsOf(String((child(statement, 'source') as Node).value))\n if (from && from !== 'package') for (const [name, binding] of from) exports.set(name, binding)\n } else if (statement.type === 'ExportDefaultDeclaration') {\n const declaration = child(statement, 'declaration')\n const name = declaration?.type === 'Identifier' ? nameOf(declaration) : nameOf(child(declaration as Node, 'id'))\n const binding = localBinding(name)\n if (binding) exports.set('default', binding)\n }\n }\n return { locals, exports }\n}\n\n/**\n * What a file's names stand for, found the way this rule finds them: for a rule\n * that asks whether a tag is one particular part, through an app's wrapper too\n * (UIG-23 asks for `EmptyState` and `ScrollArea`).\n */\nexport function partsOfFile(file: string, program: Node, parser: Parser): Map<string, PartBinding | 'namespace'> {\n return moduleParts(file, program, parser, new Set([file])).locals\n}\n\nexport { bindingOfTag, functionComponents, parseFile, resolveModule, walk, type Node, type Parser }\n\nfunction moduleExports(file: string, parser: Parser, stack: Set<string>): Map<string, PartBinding> {\n const mtime = statSync(file).mtimeMs\n const cached = moduleCache.get(file)\n if (cached && cached.mtime === mtime) return cached.exports\n if (stack.has(file)) return new Map()\n stack.add(file)\n const program = parseFile(parser, file)\n const exports = program ? moduleParts(file, program, parser, stack).exports : new Map<string, PartBinding>()\n stack.delete(file)\n moduleCache.set(file, { mtime, exports })\n return exports\n}\n\nfunction bindingOfTag(tag: Node | null | undefined, locals: Map<string, PartBinding | 'namespace'>): PartBinding | undefined {\n if (!tag) return undefined\n if (tag.type === 'JSXIdentifier') {\n const binding = locals.get(tag.name as string)\n return binding && binding !== 'namespace' ? binding : undefined\n }\n if (tag.type === 'JSXMemberExpression') {\n const object = child(tag, 'object')\n const property = nameOf(child(tag, 'property'))\n if (object?.type === 'JSXIdentifier' && locals.get(object.name as string) === 'namespace' && property) return { part: property, props: 'all' }\n }\n return undefined\n}\n\n/**\n * Whether a function component hands its props on to a part: its rest or its\n * whole props spread onto one (a wrapper), or its own class props passed into\n * one's class props (a component that places a part by its caller's word).\n */\nfunction handsOnTo(fn: Node, bindingOf: (tag: Node | null | undefined) => PartBinding | undefined): PartBinding | undefined {\n const param = children(fn, 'params')[0]\n if (!param) return undefined\n let restName: string | undefined\n let propsName: string | undefined\n const classParams = new Map<string, string>()\n if (param.type === 'ObjectPattern') {\n for (const property of children(param, 'properties')) {\n if (!property) continue\n if (property.type === 'RestElement') restName = nameOf(child(property, 'argument'))\n else if (property.type === 'Property') {\n const key = nameOf(child(property, 'key'))\n let value = child(property, 'value')\n if (value?.type === 'AssignmentPattern') value = child(value, 'left')\n const local = nameOf(value)\n if (key && local && CLASS_PROP.test(key)) classParams.set(local, key)\n }\n }\n } else if (param.type === 'Identifier') propsName = nameOf(param)\n\n let wrapper: PartBinding | undefined\n const forwarded: { part?: string; props: Record<string, string> } = { props: {} }\n const body = child(fn, 'body')\n if (!body) return undefined\n walk(body, (node) => {\n if (wrapper || node.type !== 'JSXOpeningElement') return\n const binding = bindingOf(child(node, 'name'))\n if (!binding) return\n for (const attribute of children(node, 'attributes')) {\n if (!attribute) continue\n if (attribute.type === 'JSXSpreadAttribute') {\n const argument = nameOf(child(attribute, 'argument'))\n if (argument && (argument === restName || argument === propsName)) wrapper = { part: binding.part, props: binding.props }\n continue\n }\n const prop = nameOf(child(attribute, 'name'))\n if (!prop || !CLASS_PROP.test(prop)) continue\n const partProp = binding.props === 'all' ? prop : binding.props[prop]\n if (!partProp) continue\n walk(attribute, (inner) => {\n let callerProp: string | undefined\n if (inner.type === 'Identifier') callerProp = classParams.get(inner.name as string)\n if (inner.type === 'MemberExpression' && nameOf(child(inner, 'object')) === propsName) {\n const key = nameOf(child(inner, 'property'))\n if (key && CLASS_PROP.test(key)) callerProp = key\n }\n if (!callerProp) return\n if (forwarded.part && forwarded.part !== binding.part) return\n forwarded.part = binding.part\n forwarded.props[callerProp] = partProp\n })\n }\n })\n if (wrapper) return wrapper\n return forwarded.part ? { part: forwarded.part, props: forwarded.props } : undefined\n}\n\n// ---------------------------------------------------------------- reading a class list\n\nconst CLASS_FUNCTIONS = new Set(['cn', 'clsx', 'cx', 'twMerge', 'classNames'])\n\n/** The `const` a name stands for in this file, if it is one. */\nfunction constantOf(identifier: Node, scope: Scope.Scope | null): Node | undefined {\n let current = scope\n while (current) {\n const variable = current.set.get(identifier.name as string)\n if (variable) {\n const definition = variable.defs[0] as unknown as { type: string; node: Node; parent?: Node } | undefined\n if (variable.defs.length !== 1 || definition?.type !== 'Variable') return undefined\n if ((definition.parent as Node | undefined)?.kind !== 'const') return undefined\n return child(definition.node, 'init') ?? undefined\n }\n current = current.upper\n }\n return undefined\n}\n\n/**\n * Every class the code spells out for a value, as far as it can be read in this\n * file. `asMap` reads an object as a class map (its values) rather than as a\n * `clsx` object (its keys).\n */\nexport function classesOf(value: Node | null | undefined, scopeOf: (node: Node) => Scope.Scope | null, asMap = false, seen = new Set<Node>()): string[] {\n if (!value || seen.has(value) || seen.size > 200) return []\n seen.add(value)\n const read = (node: Node | null | undefined, map = false) => classesOf(node, scopeOf, map, seen)\n const words = (text: unknown) => (typeof text === 'string' ? text.split(/\\s+/).filter(Boolean) : [])\n switch (value.type) {\n case 'Literal':\n return words(value.value)\n case 'TemplateLiteral':\n return [...children(value, 'quasis').flatMap((quasi) => words((quasi?.value as { cooked?: string }).cooked)), ...children(value, 'expressions').flatMap((e) => read(e))]\n case 'JSXExpressionContainer':\n case 'TSAsExpression':\n case 'TSSatisfiesExpression':\n case 'TSNonNullExpression':\n case 'ChainExpression':\n return read(child(value, 'expression'), asMap)\n case 'ConditionalExpression':\n return [...read(child(value, 'consequent')), ...read(child(value, 'alternate'))]\n case 'LogicalExpression':\n return value.operator === '&&' ? read(child(value, 'right')) : [...read(child(value, 'left')), ...read(child(value, 'right'))]\n case 'BinaryExpression':\n return value.operator === '+' ? [...read(child(value, 'left')), ...read(child(value, 'right'))] : []\n case 'ArrayExpression':\n return children(value, 'elements').flatMap((e) => read(e))\n case 'ObjectExpression':\n return children(value, 'properties').flatMap((property) => {\n if (property?.type !== 'Property') return []\n return asMap ? read(child(property, 'value'), true) : property.computed ? [] : words(nameOf(child(property, 'key')))\n })\n case 'CallExpression': {\n const callee = child(value, 'callee')\n return callee?.type === 'Identifier' && CLASS_FUNCTIONS.has(callee.name as string) ? children(value, 'arguments').flatMap((a) => read(a)) : []\n }\n case 'Identifier': {\n const constant = constantOf(value, scopeOf(value))\n return constant ? read(constant, asMap) : []\n }\n case 'MemberExpression': {\n const object = child(value, 'object')\n const target = object?.type === 'Identifier' ? constantOf(object, scopeOf(object)) : object\n const map = target?.type === 'TSAsExpression' || target?.type === 'TSSatisfiesExpression' ? child(target, 'expression') : target\n if (map?.type !== 'ObjectExpression') return []\n const property = child(value, 'property')\n const key = value.computed ? (property?.type === 'Literal' ? String(property.value) : undefined) : nameOf(property)\n return children(map, 'properties').flatMap((entry) => {\n if (entry?.type !== 'Property') return []\n if (key !== undefined && nameOf(child(entry, 'key')) !== key) return []\n return read(child(entry, 'value'), true)\n })\n }\n default:\n return []\n }\n}\n\n// ---------------------------------------------------------------- the rule\n\nconst code = (items: string[]) => items.map((item) => `\\`${item}\\``).join(' ')\nconst or = (items: string[]) => (items.length === 1 ? code(items) : `${items.slice(0, -1).map((i) => `\\`${i}\\``).join(', ')} or \\`${items[items.length - 1]}\\``)\n\nexport const noRestyledPart: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'Only placement passes into a part of @estiva-app/ui through a class prop' },\n schema: [],\n messages: {\n restyled:\n '{{classes}} on {{where}} changes how it looks. A part of @estiva-app/ui is placed from outside, never restyled: only space, size, flex and grid, and position pass in.{{use}} A look for what is around it goes on your own element around it.',\n restyledStyle:\n '{{keys}} in the `style` of {{where}} changes how it looks. A part of @estiva-app/ui is placed from outside, never restyled, by class or by style: only space, size, flex and grid, and position pass in.{{use}} A look for what is around it goes on your own element around it.',\n emptyStatePadding:\n '{{classes}} pads {{where}}. EmptyState takes no padding (Katerina, 14 September): its room comes from the box its rows live in, so put the padding on that box.',\n formLayout:\n '{{classes}} lays out the fields of {{where}}. A Form places its own fields, 24px apart (Katerina, 28 September), so every form reads the same: remove it. A form that is not a list of fields (a field and its button, a composer) says `layout=\"free\"` and lays itself out.',\n formSpacedFromOutside:\n '{{classes}} on the box around `Form` spaces the form from what is beside it, so the gap above its first field is not the form\u2019s 24px. Put what is beside it inside the `Form`, as one block before the fields, and drop the box: the Form puts 24px between them (Katerina, 1 October; MoveDialog in Peek does this).',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const parser = (context.languageOptions?.parser ?? {}) as Parser\n const file = context.filename\n const sourceCode = context.sourceCode\n const scopeOf = (node: Node) => sourceCode.getScope(node as unknown as Parameters<typeof sourceCode.getScope>[0])\n let locals: Map<string, PartBinding | 'namespace'> | undefined\n const escapes = new Map<Node, boolean>()\n const escaped = (anchor: Node) => {\n if (!escapes.has(anchor)) escapes.set(anchor, isEscaped(context, anchor))\n return escapes.get(anchor) === true\n }\n\n /** A `Form` lays out its own fields unless it says `layout=\"free\"`; a layout the rule cannot read passes. */\n const placesItsFields = (element: Node) =>\n !children(element, 'attributes').some((attribute) => {\n if (attribute?.type !== 'JSXAttribute' || nameOf(child(attribute, 'name')) !== 'layout') return false\n const value = child(attribute, 'value')\n const literal = value?.type === 'JSXExpressionContainer' ? child(value, 'expression') : value\n return !(literal?.type === 'Literal' && literal.value === 'fields')\n })\n\n const check = (element: Node, binding: PartBinding, prop: string, value: Node | null | undefined, at: Node) => {\n const partProp = binding.props === 'all' ? prop : binding.props[prop]\n if (!partProp || !value) return\n const classes = classesOf(value, scopeOf)\n const handedOn = binding.props === 'all' ? 'its props' : `its \\`${prop}\\``\n const via = binding.via && binding.via !== binding.part ? `\\`${binding.via}\\` (it hands ${handedOn} to \\`${binding.part}\\`)` : `\\`${binding.part}\\``\n const where = `${via}${partProp === 'className' ? '' : `'s \\`${partProp}\\``}`\n const restyled = [...new Set(classes.filter((token) => !isPlacement(token)))]\n const padding = binding.part === 'EmptyState' && binding.props === 'all' ? [...new Set(classes.filter(isPadding))] : []\n const layout = binding.part === 'Form' && partProp === 'className' && placesItsFields(element) ? [...new Set(classes.filter(isFieldsLayout))] : []\n if (!restyled.length && !padding.length && !layout.length) return\n if (escaped(element)) return\n if (restyled.length) {\n const props = PART_LOOK_PROPS[binding.part]\n const use = props ? ` Use its ${or(props)}.` : ` \\`${binding.part}\\` has no prop for this yet: ask Katerina, and it gets made in @estiva-app/ui.`\n context.report({ loc: at.loc as NonNullable<Rule.Node['loc']>, messageId: 'restyled', data: { classes: code(restyled), where, use } })\n }\n if (padding.length) context.report({ loc: at.loc as NonNullable<Rule.Node['loc']>, messageId: 'emptyStatePadding', data: { classes: code(padding), where } })\n if (layout.length) context.report({ loc: at.loc as NonNullable<Rule.Node['loc']>, messageId: 'formLayout', data: { classes: code(layout), where } })\n }\n\n /** `style` on a part: every key it can read must be placement (B6). */\n const checkStyle = (element: Node, binding: PartBinding, value: Node | null | undefined, at: Node) => {\n if (binding.props !== 'all' || value?.type !== 'JSXExpressionContainer') return\n let object = child(value, 'expression')\n if (object?.type === 'Identifier') object = constantOf(object, scopeOf(object))\n while (object?.type === 'TSAsExpression' || object?.type === 'TSSatisfiesExpression') object = child(object, 'expression')\n if (object?.type !== 'ObjectExpression') return\n const keys = children(object, 'properties')\n .map((property) => (property?.type === 'Property' && !property.computed ? nameOf(child(property, 'key')) : undefined))\n .filter((key): key is string => !!key && !key.startsWith('--') && !PLACEMENT_STYLE.test(key))\n if (!keys.length || escaped(element)) return\n const props = PART_LOOK_PROPS[binding.part]\n const use = props ? ` Use its ${or(props)}.` : ` \\`${binding.part}\\` has no prop for this yet: ask Katerina, and it gets made in @estiva-app/ui.`\n const where = binding.via && binding.via !== binding.part ? `\\`${binding.via}\\` (it hands its props to \\`${binding.part}\\`)` : `\\`${binding.part}\\``\n context.report({ loc: at.loc as NonNullable<Rule.Node['loc']>, messageId: 'restyledStyle', data: { keys: code([...new Set(keys)]), where, use } })\n }\n\n /**\n * A Form with something beside it, in a box that spaces them: the gap\n * above the first field is then the box's, not the Form's 24px (Peek's and\n * Ship's ArchiveDialog, 1 October: 12px). Read on the box's own class\n * props, `className` or a part's `bodyClassName`; a box with only the Form\n * in it spaces nothing.\n */\n const checkSpacedFromOutside = (opening: Node) => {\n const form = opening.parent as Node | undefined\n const box = form?.parent as Node | undefined\n if (form?.type !== 'JSXElement' || box?.type !== 'JSXElement') return\n const beside = children(box, 'children').filter((node) => {\n if (!node || node === form) return false\n if (node.type === 'JSXText') return String(node.value).trim() !== ''\n if (node.type === 'JSXExpressionContainer') return child(node, 'expression')?.type !== 'JSXEmptyExpression'\n return true\n })\n if (!beside.length) return\n const boxOpening = child(box, 'openingElement') as Node\n const spacing = children(boxOpening, 'attributes').flatMap((attribute) => {\n if (attribute?.type !== 'JSXAttribute') return []\n const prop = nameOf(child(attribute, 'name'))\n return prop === 'className' || prop === 'bodyClassName' ? classesOf(child(attribute, 'value'), scopeOf).filter(isSpacing) : []\n })\n if (!spacing.length || escaped(opening)) return\n context.report({ loc: opening.loc as NonNullable<Rule.Node['loc']>, messageId: 'formSpacedFromOutside', data: { classes: code([...new Set(spacing)]) } })\n }\n\n return {\n Program(program) {\n locals = moduleParts(file, program as unknown as Node, parser, new Set([file])).locals\n },\n JSXOpeningElement(ruleNode: Rule.Node) {\n const element = ruleNode as unknown as Node\n const binding = locals && bindingOfTag(child(element, 'name'), locals)\n if (!binding) return\n if (binding.part === 'Form' && binding.props === 'all' && placesItsFields(element)) checkSpacedFromOutside(element)\n for (const attribute of children(element, 'attributes')) {\n if (!attribute) continue\n if (attribute.type === 'JSXAttribute') {\n const prop = nameOf(child(attribute, 'name'))\n if (prop && CLASS_PROP.test(prop)) check(element, binding, prop, child(attribute, 'value'), attribute)\n else if (prop === 'style') checkStyle(element, binding, child(attribute, 'value'), attribute)\n continue\n }\n // `{...{ className }}`, or a `const` object spread onto the part.\n let spread = child(attribute, 'argument')\n if (spread?.type === 'Identifier') spread = constantOf(spread, scopeOf(spread))\n while (spread?.type === 'TSAsExpression' || spread?.type === 'TSSatisfiesExpression') spread = child(spread, 'expression')\n if (spread?.type !== 'ObjectExpression') continue\n for (const property of children(spread, 'properties')) {\n const key = property?.type === 'Property' && !property.computed ? nameOf(child(property, 'key')) : undefined\n if (key && CLASS_PROP.test(key)) check(element, binding, key, child(property as Node, 'value'), property as Node)\n }\n }\n },\n }\n },\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\n/** The JSX an element is made of, as far as this rule reads it. */\ninterface Node {\n type: string\n [key: string]: unknown\n}\n\ninterface JSXElement extends Node {\n type: 'JSXElement'\n openingElement: {\n name: { type: string; name?: string; object?: { name?: string }; property?: { name?: string } }\n attributes: { type: string; name?: { name?: string }; value?: Node | null }[]\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n }\n children: Node[]\n}\n\nconst isElement = (n: unknown): n is JSXElement => typeof n === 'object' && n !== null && (n as Node).type === 'JSXElement'\n\nfunction tagOf(el: JSXElement): string {\n const n = el.openingElement.name\n if (n.type === 'JSXIdentifier') return n.name ?? ''\n if (n.type === 'JSXMemberExpression') return `${n.object?.name ?? ''}.${n.property?.name ?? ''}`\n return ''\n}\n\nfunction attribute(el: JSXElement, name: string) {\n return el.openingElement.attributes.find((a) => a.type === 'JSXAttribute' && a.name?.name === name)\n}\n\n/** Every string literal under a node: a `cn()` call, a template, a ternary. */\nfunction strings(node: Node | null | undefined, out: string[] = []): string[] {\n if (!node || typeof node !== 'object') return out\n if (node.type === 'Literal' && typeof node.value === 'string') out.push(node.value)\n else if (node.type === 'TemplateLiteral') for (const q of node.quasis as { value: { cooked: string | null } }[]) out.push(q.value.cooked ?? '')\n for (const [key, value] of Object.entries(node)) {\n if (key === 'parent' || key === 'loc' || key === 'range') continue\n if (Array.isArray(value)) for (const v of value) strings(v as Node, out)\n else if (value && typeof value === 'object' && (value as Node).type) strings(value as Node, out)\n }\n return out\n}\n\n/** The classes an element is given, variants taken off: `md:px-3` is `px-3`. */\nfunction classesOf(el: JSXElement): string[] {\n const value = attribute(el, 'className')?.value\n if (!value) return []\n const text = value.type === 'Literal' ? String(value.value) : strings(value.expression as Node).join(' ')\n return text\n .split(/\\s+/)\n .filter(Boolean)\n .map((c) => c.replace(/^(?:[^:\\s[\\]]+:)+/, ''))\n}\n\n/**\n * An element's children as a reader sees them: whitespace and comments gone,\n * `{open && <X />}` read as `<X />`.\n */\nfunction meaningful(el: JSXElement): Node[] {\n const out: Node[] = []\n for (const child of el.children) {\n if (child.type === 'JSXText') {\n if (String(child.value).trim()) out.push(child)\n } else if (child.type === 'JSXExpressionContainer') {\n const e = child.expression as Node\n if (e.type === 'JSXEmptyExpression') continue\n if (e.type === 'LogicalExpression' && isElement(e.right)) out.push(e.right as Node)\n else if (isElement(e)) out.push(e)\n else out.push(child)\n } else if (child.type === 'JSXElement' || child.type === 'JSXFragment') out.push(child)\n }\n return out\n}\n\n/** Parts that draw a line of text: a title made of one is still a title. */\nconst TEXT_PARTS = new Set(['EditableText', 'Person', 'Breadcrumb', 'Link', 'SectionLabel', 'InlineChip'])\n/** What a title written as an expression looks like: a name, a field, a template, a fallback. */\nconst VALUE_EXPRESSIONS = new Set(['Identifier', 'MemberExpression', 'TemplateLiteral', 'Literal', 'LogicalExpression', 'ConditionalExpression', 'ChainExpression', 'CallExpression'])\n\n/** Whether the row carries a title: text, a value, a heading, or a part that draws text, three boxes deep at most. */\nfunction carriesTitle(el: JSXElement, depth = 0): boolean {\n if (depth > 3) return false\n for (const child of meaningful(el)) {\n if (child.type === 'JSXText') return true\n if (child.type === 'JSXExpressionContainer') {\n if (VALUE_EXPRESSIONS.has((child.expression as Node).type)) return true\n continue\n }\n if (!isElement(child)) continue\n const tag = tagOf(child)\n // `Dialog.Title`, `Parts.Title`: a part's title, named as one.\n if (/^h[1-6]$/.test(tag) || TEXT_PARTS.has(tag) || /\\.(?:Title|Heading)$/.test(tag)) return true\n // A part's own words are its label, a Button's \"Save\": only plain boxes are looked into.\n if (/^[a-z]/.test(tag) && carriesTitle(child, depth + 1)) return true\n }\n return false\n}\n\nconst ROW = (c: string[]) => c.includes('flex') && !c.includes('flex-col')\nconst OWN_SIDE_PADDING = (c: string[]) => c.some((x) => /^-?(?:p|px|pl|pr|ps|pe)-/.test(x))\n/** A column that takes the height it is given: the pane a header bar tops. */\nconst FILLS = (c: string[]) => c.includes('flex-col') && c.some((x) => /^(?:h-full|h-screen|flex-1|grow|min-h-0|h-dvh)$/.test(x))\n/** A header bar's own geometry: a column bar's height, or the hairline under it. */\nconst BAR = (c: string[]) => c.some((x) => /^(?:h|min-h)-(?:10|11|12|13|14|\\[(?:4[0-9]|5[0-6])px\\])$/.test(x)) || c.some((x) => /^border-b(?:-|$)/.test(x))\n/** A row a person presses is a row of its own kind, not a header. */\nconst INTERACTIVE = ['onClick', 'href', 'role', 'onKeyDown', 'onPointerDown']\n\n/**\n * UIG-22: a column's header bar built by hand.\n *\n * The general rules cannot see this one: a hand-made header is made entirely of\n * legal parts, a box, some text, some padding. So this rule reads the shape.\n * A row, first in a column, with side padding of its own and a title in it,\n * where the column fills the height it is given, or the row has a header bar's\n * height or the hairline under one. `ContainerHeader` is that bar: 48px, the\n * title, the column's buttons at the right edge, a hairline under it.\n *\n * What it leaves alone, on purpose: a group heading inside a list (the row one\n * section starts with), a label strip on a card, and a row a person presses.\n * Only a lowercase element is judged: a part is already a part.\n *\n * And the package's `ContainerHeader` on its own in an app (26 September): a\n * header over a box of the app's own is a panel made by hand, and the box is\n * what forgot to scroll \u2014 Peek's widget panel cut off a long description. The\n * message names `Panel`, whose body always scrolls.\n */\nexport const noHandmadeHeader: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: \"A column's header bar drawn by hand, or the package's header on its own in an app, where Panel is the part\" },\n schema: [],\n messages: {\n handmade:\n \"A column's header bar drawn by hand. Use `Panel` from @estiva-app/ui: its header (48px, the title, the column's buttons at the right edge in `actions`, a hairline under it) and a body under it that scrolls. For a list beside the page, `ListColumn`.\",\n bare:\n \"A panel put together by hand: `ContainerHeader` over a box of your own, which cuts off whatever does not fit. Use `Panel` from @estiva-app/ui: the same header (`title`, `actions`), a body that scrolls whenever it is taller, and a `footer` that stays put. For a list beside the page, `ListColumn`.\",\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n // The package's header, imported by name in an app (Katerina, 26 September): in an\n // app it comes with Panel or ListColumn, whose body scrolls. The package's own parts\n // import it from their sibling file, so this never reads them.\n const bare = new Set<string>()\n return {\n ImportDeclaration(node: Rule.Node) {\n const declaration = node as unknown as { source: { value: unknown }; specifiers: { type: string; imported?: { name?: string }; local: { name: string } }[] }\n if (declaration.source.value !== '@estiva-app/ui') return\n for (const specifier of declaration.specifiers) if (specifier.type === 'ImportSpecifier' && specifier.imported?.name === 'ContainerHeader') bare.add(specifier.local.name)\n },\n JSXOpeningElement(node: Rule.Node) {\n const element = node as unknown as JSXElement['openingElement']\n if (element.name.type !== 'JSXIdentifier' || !bare.has(element.name.name ?? '')) return\n if (isEscaped(context, element)) return\n context.report({ loc: element.loc, messageId: 'bare' })\n },\n JSXElement(node: Rule.Node) {\n const column = node as unknown as JSXElement\n const kids = meaningful(column)\n const first = kids[0]\n if (kids.length < 2 || !isElement(first) || !/^[a-z]/.test(tagOf(first))) return\n const own = classesOf(first)\n if (!ROW(own) || !OWN_SIDE_PADDING(own)) return\n if (INTERACTIVE.some((name) => attribute(first, name))) return\n if (!FILLS(classesOf(column)) && !BAR(own)) return\n if (!carriesTitle(first)) return\n if (isEscaped(context, first.openingElement)) return\n context.report({ loc: first.openingElement.loc, messageId: 'handmade' })\n },\n }\n },\n}\n", "import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'\nimport { dirname, join, relative, resolve } from 'node:path'\nimport type { Rule } from 'eslint'\nimport type ts from 'typescript'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\nimport { classUnits, componentsOf, copies, looksOf, parseForLooks, sharedLooksOf, type ClassUnit } from './looks-of'\n\n/**\n * UIG-25: a component's look typed again by hand. **A warning, never an error**\n * (Katerina, 13 September): a copy is found by how alike two lists are, and\n * likeness is a judgement \u2014 a warning gets read, a guess that blocks gets\n * switched off.\n *\n * Every class list in the file (see `looks-of.ts` for where one is read) is\n * compared, by its look words alone, against the looks of every catalogued\n * part in another file. A list is a copy when it shares `MIN_SHARED` look words\n * with one of a part's looks, covering `MIN_COVER` of the shorter of the two.\n *\n * - **In an app**, the parts are the package's \u2014 read from the catalogue the\n * installed package ships (`@estiva-app/ui/registry.json`, its `looks`) \u2014 and\n * the app's own exported components, read from its `src`. So a part added to\n * either is covered the day it is added, with no list kept here. The fix:\n * use the part.\n * - **In the package**, the parts are its own. The fix: write the look once in\n * `src/looks.ts` and use it in both.\n *\n * Left alone: a part's look in its own file, and a component named like the\n * part it wraps (Peek's `Avatar` over the package's). A constant imported from\n * another file is a look written once, not a copy. Peek and Ship copying each\n * other is not seen here \u2014 each app knows only itself and the package \u2014 and\n * is counted by `gates:status`.\n */\n\ninterface Look {\n part: string\n file: string\n look: string[]\n /** The installed package's part, this repo's own part, or a shared look (`\u2026_CLASSES`) this repo writes once. */\n from: 'package' | 'own' | 'shared'\n}\n\nconst packageDirCache = new Map<string, string | null>()\nfunction packageDirOf(file: string): string | null {\n const start = dirname(resolve(file))\n if (packageDirCache.has(start)) return packageDirCache.get(start) ?? null\n let dir = start\n for (;;) {\n if (existsSync(join(dir, 'package.json'))) break\n const up = dirname(dir)\n if (up === dir) {\n dir = ''\n break\n }\n dir = up\n }\n packageDirCache.set(start, dir || null)\n return dir || null\n}\n\nconst PACKAGE = '@estiva-app/ui'\nconst nameOf = (dir: string) => {\n try {\n return (JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as { name?: string }).name\n } catch {\n return undefined\n }\n}\n\n/** The installed package's parts and their looks, from the catalogue it ships. */\nconst shippedCache = new Map<string, { mtime: number; looks: Look[] }>()\nfunction shippedLooks(appDir: string): Look[] {\n for (let dir = appDir; ; dir = dirname(dir)) {\n const file = join(dir, 'node_modules', PACKAGE, 'registry.json')\n if (existsSync(file)) {\n const mtime = statSync(file).mtimeMs\n const cached = shippedCache.get(file)\n if (cached && cached.mtime === mtime) return cached.looks\n let looks: Look[] = []\n try {\n const registry = JSON.parse(readFileSync(file, 'utf8')) as { entries: { name: string; sourceFile: string; looks?: string[] }[] }\n looks = registry.entries.flatMap((e) => (e.looks ?? []).map((l) => ({ part: e.name, file: e.sourceFile, look: l.split(' '), from: 'package' as const })))\n } catch {\n // A catalogue that does not parse is its own check's business.\n }\n shippedCache.set(file, { mtime, looks })\n return looks\n }\n if (dirname(dir) === dir) return []\n }\n}\n\n/** The names a file exports. */\nfunction exportedNames(source: ts.SourceFile): Set<string> {\n const names = new Set<string>()\n const text = source.text\n for (const m of text.matchAll(/export\\s+(?:default\\s+)?(?:function|const)\\s+([A-Z]\\w*)/g)) names.add(m[1])\n for (const m of text.matchAll(/export\\s*\\{([^}]*)\\}/g)) for (const part of m[1].split(',')) {\n const name = part.trim().split(/\\s+as\\s+/).pop()\n if (name && /^[A-Z]/.test(name)) names.add(name)\n }\n return names\n}\n\n/** A repo's own exported components and their looks, from its `src`. */\nconst ownCache = new Map<string, { mtime: number; looks: Look[] }>()\nfunction ownLooks(repoDir: string): Look[] {\n const out: Look[] = []\n const walk = (dir: string) => {\n let names: string[] = []\n try {\n names = readdirSync(dir)\n } catch {\n return\n }\n for (const name of names) {\n if (name === 'node_modules' || name === 'dist') continue\n const path = join(dir, name)\n if (statSync(path).isDirectory()) walk(path)\n else if (/\\.tsx?$/.test(name) && !/\\.(?:stories|test)\\.tsx?$/.test(name) && !name.endsWith('.d.ts')) {\n const mtime = statSync(path).mtimeMs\n let cached = ownCache.get(path)\n if (!cached || cached.mtime !== mtime) {\n const text = readFileSync(path, 'utf8')\n const source = parseForLooks(path, text)\n const exported = name.endsWith('.tsx') ? [...componentsOf(source).keys()].filter((n) => exportedNames(source).has(n)) : []\n const file = relative(repoDir, path).replace(/\\\\/g, '/')\n const looks: Look[] = [...looksOf(source, exported)].flatMap(([part, lists]) => lists.map((l) => ({ part, file, look: l.split(' '), from: 'own' as const })))\n // A shared look written once (`\u2026_CLASSES`): a copy of it is told to use it.\n if (text.includes('_CLASSES')) for (const [part, lists] of sharedLooksOf(source)) for (const l of lists) looks.push({ part, file, look: l.split(' '), from: 'shared' })\n cached = { mtime, looks }\n ownCache.set(path, cached)\n }\n out.push(...cached.looks)\n }\n }\n }\n walk(join(repoDir, 'src'))\n return out\n}\n\nexport const noCopiedLook: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n docs: { description: \"A part's look typed again by hand, where the part (or a shared look) should be used\" },\n schema: [],\n messages: {\n usePart:\n \"This class list is `{{part}}`'s look, typed again ({{count}} words: {{words}}). Use `{{part}}` from {{from}}: a copy looks right today and stays behind the day `{{part}}` changes.\",\n shareIt:\n 'This look is also written in `{{part}}` ({{file}}): {{words}}. Write it once in src/looks.ts and use it in both, so the two cannot drift apart.',\n useShared:\n 'This class list is `{{part}}` ({{file}}), typed again: {{words}}. Use `{{part}}`: a look written once cannot drift apart.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const file = context.filename\n const repoDir = packageDirOf(file)\n if (!repoDir) return {}\n const inPackage = nameOf(repoDir) === PACKAGE\n return {\n Program() {\n const here = relative(repoDir, file).replace(/\\\\/g, '/')\n const source = parseForLooks(file, context.sourceCode.text)\n const declared = new Set(componentsOf(source).keys())\n const looks = [...(inPackage ? [] : shippedLooks(repoDir)), ...ownLooks(repoDir)].filter((l) => l.file !== here && !declared.has(l.part))\n if (!looks.length) return\n const units = classUnits(source)\n // A string inside a className is read with it; report the className once.\n const within = (u: ClassUnit) => units.some((o) => o !== u && o.via === 'attribute' && u.via === 'literal' && u.start >= o.start && u.end <= o.end)\n const reported = new Set<number>()\n for (const unit of units) {\n if (within(unit) || reported.has(unit.start)) continue\n let best: { look: Look; shared: string[] } | null = null\n for (const look of looks) {\n // A shared look is compared with the package's parts only: the parts here that use it are not its copies.\n if (unit.shared && look.from !== 'package') continue\n const shared = copies(unit.look, look.look)\n // On a tie, the shared look: using it is the whole fix.\n if (shared && (!best || shared.length > best.shared.length || (shared.length === best.shared.length && look.from === 'shared'))) best = { look, shared }\n }\n if (!best) continue\n // A className built from a constant of this file is reported once, at the constant.\n const found = best\n if (unit.via === 'attribute' && units.some((o) => o.via === 'literal' && !within(o) && found.shared.every((w) => o.look.includes(w)) && looks.some((l) => copies(o.look, l.look)))) continue\n const loc = { start: context.sourceCode.getLocFromIndex(unit.start), end: context.sourceCode.getLocFromIndex(unit.end) }\n const at = { start: context.sourceCode.getLocFromIndex(unit.anchor), end: loc.end }\n if (isEscaped(context, { loc: at, range: [unit.anchor, unit.end] })) continue\n reported.add(unit.start)\n const words = best.shared.map((w) => `\\`${w}\\``).join(' ')\n if (best.look.from === 'shared') context.report({ loc, messageId: 'useShared', data: { part: best.look.part, file: best.look.file, words } })\n else if (inPackage) context.report({ loc, messageId: 'shareIt', data: { part: best.look.part, file: best.look.file, words } })\n else\n context.report({\n loc,\n messageId: 'usePart',\n data: { part: best.look.part, count: String(best.shared.length), words, from: best.look.from === 'package' ? PACKAGE : `\\`${best.look.file}\\`` },\n })\n }\n },\n }\n },\n}\n", "import { existsSync, readFileSync } from 'node:fs'\nimport { dirname, join, resolve as resolvePath } from 'node:path'\nimport ts from 'typescript'\n\n/**\n * What a component looks like, read from its source: every class list it\n * writes (UIG-25). Shared by the catalogue, which records each part's looks in\n * `registry.json`, and by `estiva/no-copied-look`, which compares a class list\n * typed by hand against them \u2014 so the two always mean the same thing by \"look\".\n *\n * A class list is read wherever it is written: a `className` (or any\n * `\u2026ClassName`), through `cn()`/`clsx()`, a ternary, a `&&`, a template, a\n * `const` in the file, or a class map indexed by a key; and every string that\n * is a class list on its own. A constant imported from another file is not\n * followed: a look written once and imported is not a copy.\n *\n * Only the **look words** count \u2014 colour, text, border, corner, shadow.\n * Placement (where it sits, how much room it takes) is everyone's and says\n * nothing about which part a list is copied from.\n */\n\n/** Where a thing sits and how much room it takes: never part of a look (the same list as `no-restyled-part`'s PLACEMENT). */\nconst PLACEMENT = [\n /^m[xytrblse]?-/,\n /^p[xytrblse]?-/,\n /^(?:w|h|size|min-w|min-h|max-w|max-h)-/,\n /^(?:hidden|block|inline|inline-block|inline-flex|inline-grid|flex|grid|contents|flow-root)$/,\n /^(?:grow|shrink)$|^(?:flex|basis|grow|shrink|order|gap|gap-x|gap-y|space-x|space-y|col|row|grid-cols|grid-rows|grid-flow|auto-cols|auto-rows)-/,\n /^(?:self|justify|justify-items|justify-self|items|place-content|place-items|place-self)-|^content-(?!\\[)/,\n /^(?:static|relative|absolute|fixed|sticky)$|^(?:inset|inset-x|inset-y|top|right|bottom|left|start|end|z)-/,\n /^(?:group|peer)(?:\\/[\\w-]+)?$/,\n]\nconst bare = (token: string) => token.replace(/^(?:[^:\\s[\\]]+:)+/, '')\nexport const isPlacementWord = (token: string) => PLACEMENT.some((pattern) => pattern.test(bare(token)))\n\n/** A word that could be a Tailwind class: lower case, dashes, variants, arbitrary values. */\nconst CLASSY = /^!?(?:[a-z0-9-]+:|\\[[^\\]\\s]+\\]:)*-?[a-z@][a-z0-9-]*(?:-\\[[^\\]\\s]+\\]|\\/[\\w.[\\]-]+|-[\\w.]+)*$|^\\[[^\\]\\s]+\\]$/\nconst words = (text: string) => text.split(/\\s+/).filter(Boolean)\nconst CLASS_FUNCTIONS = new Set(['cn', 'clsx', 'cx', 'twMerge', 'classNames'])\nconst CLASS_PROP = /^(?:className|[a-z][A-Za-z]*ClassName)$/\n\n/** A string is a class list on its own when every word could be a class, and two at least have a dash or a variant. */\nfunction isClassList(text: string): boolean {\n const list = words(text)\n return list.length >= 3 && list.every((w) => CLASSY.test(w)) && list.filter((w) => /[-:[]/.test(w)).length >= 2\n}\n\nexport interface ClassUnit {\n /** Every class of the list, placement included, as written. */\n tokens: string[]\n /** Its look words only. */\n look: string[]\n /** Offsets in the file, for a report. */\n start: number\n end: number\n /** A `className` (resolved through the file), or a string that is a class list on its own. */\n via: 'attribute' | 'literal'\n /** Where an escape for it is read: the element a `className` is on, or the string itself. */\n anchor: number\n /** The value of an exported `\u2026_CLASSES` constant: a shared look, where it is written once. */\n shared: boolean\n}\n\nconst CAP = 24\n\n/**\n * Every class list a file writes. `follow` resolves a name the file imports,\n * for a part's own look: what it draws includes a look it takes from a shared\n * file. A list being checked is never followed \u2014 using a shared look is not\n * copying it.\n */\nexport function classUnits(source: ts.SourceFile, follow?: (name: string) => ts.Expression | undefined): ClassUnit[] {\n const consts = new Map<string, ts.Expression>()\n const collect = (node: ts.Node) => {\n if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer && ts.isVariableDeclarationList(node.parent) && node.parent.flags & ts.NodeFlags.Const) {\n consts.set(node.name.text, node.initializer)\n }\n ts.forEachChild(node, collect)\n }\n collect(source)\n\n const product = (lists: string[][][]): string[][] => {\n let out: string[][] = [[]]\n for (const alternatives of lists) {\n const next: string[][] = []\n for (const a of out) for (const b of alternatives) if (next.length < CAP) next.push([...a, ...b])\n out = next\n }\n return out\n }\n const resolve = (node: ts.Node | undefined, depth = 0): string[][] => {\n if (!node || depth > 8) return [[]]\n if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return [words(node.text)]\n if (ts.isTemplateExpression(node)) return product([[words(node.head.text)], ...node.templateSpans.flatMap((span) => [resolve(span.expression, depth + 1), [words(span.literal.text)]])])\n if (ts.isParenthesizedExpression(node) || ts.isAsExpression(node) || ts.isSatisfiesExpression(node) || ts.isNonNullExpression(node)) return resolve(node.expression, depth + 1)\n if (ts.isJsxExpression(node)) return resolve(node.expression, depth + 1)\n if (ts.isCallExpression(node)) return ts.isIdentifier(node.expression) && CLASS_FUNCTIONS.has(node.expression.text) ? product(node.arguments.map((a) => resolve(a, depth + 1))) : [[]]\n if (ts.isConditionalExpression(node)) return [...resolve(node.whenTrue, depth + 1), ...resolve(node.whenFalse, depth + 1)].slice(0, CAP)\n if (ts.isBinaryExpression(node)) {\n // Off first: a look is the part at rest, with each option taken one at a time, never all at once.\n if (node.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) return [[], ...resolve(node.right, depth + 1)]\n if (node.operatorToken.kind === ts.SyntaxKind.BarBarToken || node.operatorToken.kind === ts.SyntaxKind.QuestionQuestionToken) return [...resolve(node.left, depth + 1), ...resolve(node.right, depth + 1)].slice(0, CAP)\n return [[]]\n }\n if (ts.isArrayLiteralExpression(node)) return product(node.elements.map((e) => resolve(e, depth + 1)))\n if (ts.isObjectLiteralExpression(node)) return [[], node.properties.flatMap((p) => (p.name && (ts.isIdentifier(p.name) || ts.isStringLiteral(p.name)) ? words(p.name.text) : []))]\n if (ts.isIdentifier(node)) {\n const init = consts.get(node.text) ?? follow?.(node.text)\n return init ? resolve(init, depth + 1) : [[]]\n }\n if (ts.isPropertyAccessExpression(node) || ts.isElementAccessExpression(node)) {\n let target: ts.Expression | undefined = node.expression\n if (ts.isIdentifier(target)) target = consts.get(target.text) ?? follow?.(target.text)\n while (target && (ts.isAsExpression(target) || ts.isSatisfiesExpression(target) || ts.isParenthesizedExpression(target))) target = target.expression\n if (!target || !ts.isObjectLiteralExpression(target)) return [[]]\n const key = ts.isPropertyAccessExpression(node) ? node.name.text : ts.isStringLiteral(node.argumentExpression) ? node.argumentExpression.text : null\n return target.properties\n .filter((p): p is ts.PropertyAssignment => ts.isPropertyAssignment(p) && (key === null || (!!p.name && (ts.isIdentifier(p.name) || ts.isStringLiteral(p.name)) && p.name.text === key)))\n .flatMap((p) => resolve(p.initializer, depth + 1))\n .slice(0, CAP)\n }\n return [[]]\n }\n\n const units: ClassUnit[] = []\n const seen = new Set<string>()\n const sharedAt = (node: ts.Node) => {\n for (let at: ts.Node | undefined = node; at; at = at.parent) {\n if (ts.isVariableDeclaration(at)) return ts.isIdentifier(at.name) && /_CLASSES$/.test(at.name.text) && !!at.parent?.parent && ts.isVariableStatement(at.parent.parent) && !!at.parent.parent.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)\n }\n return false\n }\n // A string's escape is read above the line it starts: the widest thing that starts on that line.\n const lineStart = (node: ts.Node) => {\n const line = source.getLineAndCharacterOfPosition(node.getStart(source)).line\n let at = node\n while (at.parent && !ts.isSourceFile(at.parent) && source.getLineAndCharacterOfPosition(at.parent.getStart(source)).line === line) at = at.parent\n return at.getStart(source)\n }\n const add = (tokens: string[], node: ts.Node, via: ClassUnit['via'], anchor = via === 'literal' ? lineStart(node) : node.getStart(source)) => {\n const list = [...new Set(tokens.filter((t) => CLASSY.test(t)))]\n const look = list.filter((t) => !isPlacementWord(t))\n if (look.length === 0) return\n const key = `${via}:${node.getStart(source)}:${[...list].sort().join(' ')}`\n if (seen.has(key)) return\n seen.add(key)\n units.push({ tokens: list, look, start: node.getStart(source), end: node.getEnd(), via, anchor, shared: via === 'literal' && sharedAt(node) })\n }\n const visit = (node: ts.Node) => {\n if (ts.isJsxAttribute(node) && ts.isIdentifier(node.name) && CLASS_PROP.test(node.name.text) && node.initializer) {\n // An escape goes on the line above the element, as it does for every rule of the plugin.\n const element = node.parent.parent\n for (const alternative of resolve(node.initializer)) add(alternative, node, 'attribute', element.getStart(source))\n }\n if ((ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) && isClassList(node.text)) add(words(node.text), node, 'literal')\n ts.forEachChild(node, visit)\n }\n visit(source)\n return units\n}\n\n/** The function components a file declares, by name, with where each one's body is. */\nexport function componentsOf(source: ts.SourceFile): Map<string, { start: number; end: number }> {\n const found = new Map<string, { start: number; end: number }>()\n const fn = (node: ts.Expression | undefined): ts.Node | undefined => {\n let current = node\n while (current && ts.isCallExpression(current) && current.arguments.length) current = current.arguments[0]\n return current && (ts.isArrowFunction(current) || ts.isFunctionExpression(current)) ? current : undefined\n }\n for (const statement of source.statements) {\n if (ts.isFunctionDeclaration(statement) && statement.name && /^[A-Z]/.test(statement.name.text)) found.set(statement.name.text, { start: statement.getStart(source), end: statement.getEnd() })\n if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n const body = fn(declaration.initializer)\n if (ts.isIdentifier(declaration.name) && /^[A-Z]/.test(declaration.name.text) && body) found.set(declaration.name.text, { start: body.getStart(source), end: body.getEnd() })\n }\n }\n }\n return found\n}\n\n/** A look is worth comparing when it has this many look words at least: fewer is a text style, not a part. */\nexport const MIN_LOOK_WORDS = 4\n\n/**\n * Each named component's looks: its class lists' look words, one space-joined\n * string per list, those with `MIN_LOOK_WORDS` or more. A list written outside\n * every component of the file (a top-level constant, a class map) belongs to\n * every component in it.\n */\nexport function looksOf(source: ts.SourceFile, names?: Iterable<string>): Map<string, string[]> {\n const components = componentsOf(source)\n const units = classUnits(source, importedConstants(source)).filter((u) => u.look.length >= MIN_LOOK_WORDS)\n const inside = (u: ClassUnit, r: { start: number; end: number }) => u.start >= r.start && u.start < r.end\n const out = new Map<string, string[]>()\n for (const name of names ?? components.keys()) {\n const range = components.get(name)\n const mine = units.filter((u) => (range ? inside(u, range) : false) || ![...components.values()].some((r) => inside(u, r)))\n out.set(name, [...new Set(mine.map((u) => u.look.join(' ')))])\n }\n return out\n}\n\n/** Read and parse a file for looks. */\nexport function parseForLooks(fileName: string, text: string): ts.SourceFile {\n return ts.createSourceFile(fileName, text, ts.ScriptTarget.Latest, true, fileName.endsWith('x') ? ts.ScriptKind.TSX : ts.ScriptKind.TS)\n}\n\n/** How much of a look a class list must share to be a copy of it (UIG-25, Katerina 24 September). */\nexport const MIN_SHARED = 4\nexport const MIN_COVER = 0.8\n\n/** The look words a list shares with a look, when it is a copy of it; otherwise null. */\nexport function copies(list: string[], look: string[]): string[] | null {\n const mine = new Set(list)\n const shared = look.filter((word) => mine.has(word))\n if (shared.length < MIN_SHARED) return null\n return shared.length / Math.min(list.length, look.length) >= MIN_COVER ? shared : null\n}\n\n/** The file a relative or `@/` import names, from the file that imports it. */\nfunction importTarget(fromFile: string, specifier: string): string | null {\n let base: string\n if (specifier.startsWith('.')) base = resolvePath(dirname(fromFile), specifier)\n else if (specifier.startsWith('@/')) {\n let dir = dirname(resolvePath(fromFile))\n while (!existsSync(join(dir, 'package.json')) && dirname(dir) !== dir) dir = dirname(dir)\n base = join(dir, 'src', specifier.slice(2))\n } else return null\n for (const candidate of [`${base}.ts`, `${base}.tsx`, join(base, 'index.ts')]) if (existsSync(candidate)) return candidate\n return null\n}\n\nconst constantsCache = new Map<string, Map<string, ts.Expression>>()\n/** A file's top-level `const`s, by name. */\nfunction constantsOf(file: string): Map<string, ts.Expression> {\n const cached = constantsCache.get(file)\n if (cached) return cached\n const found = new Map<string, ts.Expression>()\n const source = parseForLooks(file, readFileSync(file, 'utf8'))\n for (const statement of source.statements) {\n if (!ts.isVariableStatement(statement)) continue\n for (const d of statement.declarationList.declarations) if (ts.isIdentifier(d.name) && d.initializer) found.set(d.name.text, d.initializer)\n }\n constantsCache.set(file, found)\n return found\n}\n\n/** A resolver for the class constants a file imports from its own repo: `FIELD_BOX_CLASSES` from `./looks`. */\nexport function importedConstants(source: ts.SourceFile): (name: string) => ts.Expression | undefined {\n const imported = new Map<string, { file: string; name: string }>()\n for (const statement of source.statements) {\n if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) continue\n const bindings = statement.importClause?.namedBindings\n if (!bindings || !ts.isNamedImports(bindings)) continue\n const target = importTarget(source.fileName, statement.moduleSpecifier.text)\n if (!target) continue\n for (const element of bindings.elements) {\n const local = element.name.text\n if (/_CLASSES$/.test(element.propertyName?.text ?? local)) imported.set(local, { file: target, name: element.propertyName?.text ?? local })\n }\n }\n return (name) => {\n const from = imported.get(name)\n if (!from) return undefined\n try {\n return constantsOf(from.file).get(from.name)\n } catch {\n return undefined\n }\n }\n}\n\n/**\n * The shared looks a file declares: each exported `\u2026_CLASSES` constant, a string\n * or a map of strings, by name (`FIELD_SIZE_CLASSES.small`). A hand-typed copy of\n * one is told to use it.\n */\nexport function sharedLooksOf(source: ts.SourceFile): Map<string, string[]> {\n const out = new Map<string, string[]>()\n const lookWords = (text: string) => words(text).filter((w) => CLASSY.test(w) && !isPlacementWord(w))\n for (const statement of source.statements) {\n if (!ts.isVariableStatement(statement) || !statement.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) continue\n for (const d of statement.declarationList.declarations) {\n if (!ts.isIdentifier(d.name) || !/_CLASSES$/.test(d.name.text) || !d.initializer) continue\n let init: ts.Expression = d.initializer\n while (ts.isAsExpression(init) || ts.isSatisfiesExpression(init) || ts.isParenthesizedExpression(init)) init = init.expression\n if (ts.isStringLiteral(init) || ts.isNoSubstitutionTemplateLiteral(init)) {\n const look = lookWords(init.text)\n if (look.length >= MIN_LOOK_WORDS) out.set(d.name.text, [look.join(' ')])\n } else if (ts.isObjectLiteralExpression(init)) {\n for (const p of init.properties) {\n if (!ts.isPropertyAssignment(p) || !p.name || !(ts.isIdentifier(p.name) || ts.isStringLiteral(p.name))) continue\n if (!(ts.isStringLiteral(p.initializer) || ts.isNoSubstitutionTemplateLiteral(p.initializer))) continue\n const look = lookWords(p.initializer.text)\n if (look.length >= MIN_LOOK_WORDS) out.set(`${d.name.text}.${p.name.text}`, [look.join(' ')])\n }\n }\n }\n }\n return out\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\nimport { bindingOfTag, partsOfFile, type Node, type Parser, type PartBinding } from './no-restyled-part'\n\n/**\n * The parts a person types into to send something. `Field` is the labelled\n * row; `TextInput` and `Textarea` are judged on their own only in a file that\n * draws no `Field`, so a field is reported once, at its label.\n */\nexport const FIELD_PARTS = ['Field', 'TextInput', 'Textarea'] as const\n\n/** The parts that are a `Form`: the package's own, and the palette's form level, which is one (UIG-29). */\nexport const FORM_PARTS = ['Form', 'CommandPaletteForm'] as const\n\nconst child = (node: Node, key: string) => node[key] as Node | null | undefined\nconst nameOf = (node: Node | null | undefined): string | undefined =>\n node?.type === 'JSXIdentifier' || node?.type === 'Identifier' ? (node.name as string) : undefined\n\n/**\n * A field outside a `Form` (Katerina, 1 October, after Peek's and Ship's\n * Archive dialog: a resolution typed into a `ConfirmDialog`, sent by its\n * button, with no form around it \u2014 Ctrl+Enter did nothing, and the field\n * stayed open while it archived).\n *\n * `Form` owns what a field needs to be sent: Enter and Ctrl+Enter, `busy`\n * switching every field off at once, and where focus goes after. A field\n * outside one has none of it, and the dialog around it is the wrong one: a\n * question with a field in it is a `DialogShell` with a `Form`\n * (ConfirmDialog's page, **When not**).\n *\n * Judged: a `Field`, a `TextInput` or a `Textarea` of the package (or an\n * app's re-export or wrapper of one) with no `Form` around it in the same\n * file. Not judged, on purpose:\n *\n * - `EditableText` and `SearchInput`: one saves itself as you leave it, the\n * other filters a list, and neither is sent (Form's page, **When not**);\n * - a `TextInput` or `Textarea` in a file that draws a `Field`: the `Field`\n * is reported, and a control handed to it from a function of its own (a\n * `switch` over field kinds) cannot be followed to it;\n * - the app's own components: a component that draws a field for a form its\n * caller holds says so with an escape on the field, naming that caller.\n */\nexport const noFieldOutsideAForm: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'A field with no Form around it' },\n schema: [],\n messages: {\n loose:\n '`{{part}}` has no `Form` around it, so nothing owns sending it: Enter and Ctrl+Enter, `busy`, and focus after. Put it in `Form` from @estiva-app/ui; in a dialog, that is `DialogShell` with a `Form`, never `ConfirmDialog` (Primitives/Form says how).',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const parser = (context.languageOptions?.parser ?? {}) as Parser\n let locals: Map<string, PartBinding | 'namespace'> | undefined\n const loose: { opening: Node; part: string }[] = []\n let drawsAField = false\n const partOf = (element: Node): string | undefined => {\n const tag = child(child(element, 'openingElement') as Node, 'name')\n const name = nameOf(tag)\n if (!name || /^[a-z]/.test(name)) return undefined\n const binding = locals && bindingOfTag(tag, locals)\n return binding && binding.props === 'all' ? binding.part : undefined\n }\n return {\n Program(program) {\n locals = partsOfFile(context.filename, program as unknown as Node, parser)\n },\n JSXElement(ruleNode: Rule.Node) {\n const element = ruleNode as unknown as Node\n const part = partOf(element)\n if (!part || !(FIELD_PARTS as readonly string[]).includes(part)) return\n if (part === 'Field') drawsAField = true\n for (let up = element.parent as Node | undefined; up; up = up.parent as Node | undefined) {\n if (up.type !== 'JSXElement') continue\n const around = partOf(up)\n if (around && (FORM_PARTS as readonly string[]).includes(around)) return\n if (around === 'Field') return\n }\n loose.push({ opening: child(element, 'openingElement') as Node, part })\n },\n 'Program:exit'() {\n for (const { opening, part } of loose) {\n if (part !== 'Field' && drawsAField) continue\n if (isEscaped(context, opening)) continue\n context.report({ loc: opening.loc as NonNullable<Rule.Node['loc']>, messageId: 'loose', data: { part } })\n }\n },\n }\n },\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\nimport { bindingOfTag, partsOfFile, type Node, type Parser, type PartBinding } from './no-restyled-part'\n\n/**\n * The parts whose `title` is their own: the words of a heading or a dialog,\n * drawn on the page. Every other part hands a `title` on to its element, and\n * the browser shows it as its tooltip. `no-native-title.test.ts` holds this\n * list to the catalogue: a part that gains a `title` of its own joins it.\n */\nexport const PARTS_WITH_A_TITLE = ['CollapsibleSection', 'ConfirmDialog', 'ContainerHeader', 'DialogShell', 'ListColumn', 'NavTree', 'NavTreeSection', 'Panel', 'SectionHeader'] as const\n\nconst child = (node: Node, key: string) => node[key] as Node | null | undefined\nconst nameOf = (node: Node | null | undefined): string | undefined =>\n node?.type === 'JSXIdentifier' || node?.type === 'Identifier' ? (node.name as string) : undefined\n\n/**\n * UIG-24: the browser's tooltip where ours belongs.\n *\n * A `title` on an element is the browser's hover box: grey, in the system's\n * font, after a delay nobody chose, and never on a touch screen. The package's\n * `WithTooltip` is the tooltip here (and `IconButton`'s `tooltip`, which draws\n * it). The rule reads the attribute, never the page: a tooltip's words are not\n * on the page until it opens.\n *\n * Judged: a `title` on a plain element, and on a part of the package (or an\n * app's wrapper that hands all its props on to one) whose `title` is not its\n * own \u2014 `<Button title>` reaches the `<button>`. Not judged, on purpose:\n *\n * - the `<title>` **element**, in an `<svg>` (a label for a screen reader) or\n * a document's head: an element, not an attribute, so the rule never sees it;\n * - a part whose `title` is its own heading (`PARTS_WITH_A_TITLE`);\n * - the app's own components: what one does with a `title` is its own business,\n * and its elements are judged where it draws them;\n * - a story's `title` (`meta = { title: 'Group/Name' }`): an object key, not an\n * attribute.\n */\nexport const noNativeTitle: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: \"A title attribute: the browser's tooltip where WithTooltip is the part\" },\n schema: [],\n messages: {\n native:\n \"`title` is the browser's tooltip, not ours. Wrap it in `WithTooltip` from @estiva-app/ui, or use `IconButton`'s `tooltip`: its page (Primitives/Tooltip) says when it shows and how.\",\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const parser = (context.languageOptions?.parser ?? {}) as Parser\n let locals: Map<string, PartBinding | 'namespace'> | undefined\n return {\n Program(program) {\n locals = partsOfFile(context.filename, program as unknown as Node, parser)\n },\n JSXAttribute(ruleNode: Rule.Node) {\n const attribute = ruleNode as unknown as Node\n if (nameOf(child(attribute, 'name')) !== 'title') return\n const opening = attribute.parent as Node\n const tag = child(opening, 'name')\n const name = nameOf(tag)\n if (!(name && /^[a-z]/.test(name))) {\n const binding = locals && bindingOfTag(tag, locals)\n if (!binding || binding.props !== 'all') return\n if ((PARTS_WITH_A_TITLE as readonly string[]).includes(binding.part)) return\n }\n if (isEscaped(context, opening)) return\n context.report({ loc: attribute.loc as NonNullable<Rule.Node['loc']>, messageId: 'native' })\n },\n }\n },\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\ninterface JSXAttributeValue {\n type: string\n value?: unknown\n expression?: { type: string; value?: unknown; expressions?: unknown[]; quasis?: { value: { cooked: string | null } }[] }\n}\n\ninterface JSXAttribute {\n type: 'JSXAttribute'\n name: { type: string; name?: string }\n value: JSXAttributeValue | null\n}\n\ninterface JSXOpeningElement {\n name: { type: string; name?: string }\n attributes: (JSXAttribute | { type: 'JSXSpreadAttribute' })[]\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n}\n\n/**\n * What the package has instead of one raw element: the component the message\n * names, and where one element does more than one job, the others after it.\n * `null` is an element the package has no part for yet.\n */\nexport interface RawElementPart {\n use: string\n more?: string\n}\n\n/**\n * The mapping (UIG-7), derived from the package's exports: every interactive\n * element in the HTML standard's list (\"interactive content\"), plus `<dialog>`,\n * `<form>` and `<progress>`, which have a part here. docs/GATES.md prints it.\n *\n * Not here, on purpose: `<summary>` (it lives inside a `<details>`, which is\n * reported), `<option>`, `<optgroup>` and `<datalist>` (they live inside a\n * `<select>` or beside an input), `<fieldset>` and `<legend>` (a group's frame,\n * no control of its own), and `<img>` without `usemap`, `<hr>`, `<kbd>`, which\n * are not controls. An `<audio>` or `<video>` is a control only with `controls`.\n */\nexport const RAW_ELEMENT_PARTS: Record<string, RawElementPart | null> = {\n a: { use: 'Link', more: ' For a chip, `InlineChip`; for a whole card, `Card` with `href`.' },\n button: { use: 'Button' },\n textarea: { use: 'Textarea' },\n select: { use: 'Select' },\n dialog: { use: 'DialogShell', more: ' To ask yes or no, `ConfirmDialog`.' },\n label: { use: 'Field', more: ' For words beside a tick box, `Checkbox` with `label`.' },\n details: { use: 'CollapsibleSection' },\n progress: { use: 'ProgressBar' },\n form: { use: 'Form' },\n meter: null,\n iframe: null,\n embed: null,\n object: null,\n audio: null,\n video: null,\n img: null,\n}\n\n/**\n * An `<input>` is as many controls as its `type`. A type missing from here\n * (text, email, password, url, tel, number, or one the browser does not know)\n * is a text box.\n */\nexport const RAW_INPUT_PARTS: Record<string, RawElementPart | null> = {\n search: { use: 'SearchInput' },\n checkbox: { use: 'Checkbox' },\n file: { use: 'FilePicker' },\n submit: { use: 'Button' },\n button: { use: 'Button' },\n reset: { use: 'Button' },\n image: { use: 'Button' },\n radio: null,\n range: null,\n color: null,\n date: null,\n 'datetime-local': null,\n month: null,\n week: null,\n time: null,\n}\n\nconst TEXT_INPUT: RawElementPart = { use: 'TextInput' }\nconst ANY_INPUT: RawElementPart = {\n use: 'TextInput',\n more: ' For a search, `SearchInput`; for a tick box, `Checkbox`; to pick files, `FilePicker`.',\n}\n\nfunction attribute(element: JSXOpeningElement, name: string): JSXAttribute | undefined {\n return element.attributes.find((a): a is JSXAttribute => a.type === 'JSXAttribute' && a.name.name === name)\n}\n\n/** An attribute's value when the code spells it out, `undefined` when it is computed. */\nfunction literal(attr: JSXAttribute): string | boolean | undefined {\n const value = attr.value\n if (value === null) return true\n if (value.type === 'Literal') return typeof value.value === 'string' ? value.value : undefined\n if (value.type !== 'JSXExpressionContainer' || !value.expression) return undefined\n const expression = value.expression\n if (expression.type === 'Literal' && (typeof expression.value === 'string' || typeof expression.value === 'boolean')) return expression.value\n if (expression.type === 'TemplateLiteral' && expression.expressions?.length === 0) return expression.quasis?.[0]?.value.cooked ?? undefined\n return undefined\n}\n\n/** Present, and not written as `={false}`. */\nfunction isOn(element: JSXOpeningElement, name: string): boolean {\n const attr = attribute(element, name)\n return attr !== undefined && literal(attr) !== false\n}\n\ntype Found = { report: 'raw'; element: string; part: RawElementPart } | { report: 'noPart'; element: string } | { report: 'clickable'; element: string } | null\n\n/** The pointer's press, as a handler on a plain element makes it a control (R5). */\nconst CLICK_HANDLERS = ['onClick', 'onMouseDown', 'onMouseUp', 'onPointerDown', 'onPointerUp', 'onDoubleClick']\n\ninterface Expression {\n type: string\n [key: string]: unknown\n}\n\n/** `e.stopPropagation()` or `e.preventDefault()`: a handler that only keeps the click from what is behind. */\nfunction onlyStops(handler: Expression | undefined): boolean {\n if (!handler || (handler.type !== 'ArrowFunctionExpression' && handler.type !== 'FunctionExpression')) return false\n const body = handler.body as Expression\n const calls = body.type === 'BlockStatement' ? (body.body as Expression[]).map((s) => (s.type === 'ExpressionStatement' ? (s.expression as Expression) : s)) : [body]\n return (\n calls.length > 0 &&\n calls.every((call) => {\n if (call.type !== 'CallExpression') return false\n const callee = call.callee as Expression\n const property = callee.type === 'MemberExpression' ? (callee.property as Expression) : undefined\n return property?.type === 'Identifier' && (property.name === 'stopPropagation' || property.name === 'preventDefault')\n })\n )\n}\n\n/** A plain element made clickable by hand: the first press handler that does more than stop the click. */\nfunction clickHandler(element: JSXOpeningElement): string | undefined {\n for (const name of CLICK_HANDLERS) {\n const attr = attribute(element, name)\n if (!attr) continue\n const value = attr.value\n const handler = value?.type === 'JSXExpressionContainer' ? (value.expression as Expression | undefined) : undefined\n if (!onlyStops(handler)) return name\n }\n return undefined\n}\n\n/** What this element is to the rule: a raw element with a part, one with none yet, or none of its business. */\nexport function classify(element: JSXOpeningElement): Found {\n if (element.name.type !== 'JSXIdentifier' || !element.name.name) return null\n const name = element.name.name\n\n if (name === 'input') {\n const attr = attribute(element, 'type')\n const type = attr ? literal(attr) : 'text'\n if (typeof type !== 'string') return { report: 'raw', element: '<input>', part: ANY_INPUT }\n const key = type.toLowerCase()\n // A hidden input draws nothing and takes no focus: it is data, not a control.\n if (key === 'hidden') return null\n if (!(key in RAW_INPUT_PARTS)) return { report: 'raw', element: '<input>', part: TEXT_INPUT }\n const part = RAW_INPUT_PARTS[key]\n const shown = `<input type=\"${key}\">`\n return part ? { report: 'raw', element: shown, part } : { report: 'noPart', element: shown }\n }\n\n if (!Object.hasOwn(RAW_ELEMENT_PARTS, name)) {\n // A plain element with a press handler is a button drawn by hand (Katerina's ruling R5,\n // 25 September): no focus, no keys, no look anybody keeps in step. `<option>` and\n // `<summary>` live inside a control the rule already reads.\n if (!/^[a-z][a-z0-9]*$/.test(name) || name === 'option' || name === 'summary') return null\n const handler = clickHandler(element)\n return handler ? { report: 'clickable', element: `<${name} ${handler}>` } : null\n }\n if ((name === 'audio' || name === 'video') && !isOn(element, 'controls')) return null\n if (name === 'img' && !attribute(element, 'usemap') && !attribute(element, 'useMap')) return null\n\n const part = RAW_ELEMENT_PARTS[name]\n return part ? { report: 'raw', element: `<${name}>`, part } : { report: 'noPart', element: `<${name}>` }\n}\n\n/**\n * A raw interactive element in an app, where the package has a part for it\n * (UIG-3 began it with `<button>`; UIG-7 made it every element). A control\n * the app writes itself has a look, a focus ring and keys that nobody else\n * keeps in step with \u2014 and it looks nearly right, which is why nobody catches\n * it by eye. Every message names the part to use.\n *\n * An element the package has no part for yet is refused too, with a message\n * that says so: the part is made in the package, not by hand in an app\n * (Katerina, 16 September).\n *\n * A plain element with a press handler (`<div onClick>`) is a control too, and\n * is refused naming `Button` (R5, 25 September); a handler that only stops the\n * click reaching what is behind passes.\n *\n * Only a JSX element written with a lowercase name. `<Button>`,\n * `<Foo.button>` and `createElement('button')` are not this rule's business.\n */\nexport const noRawElement: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'A raw interactive element where @estiva-app/ui has a part, or where it needs one' },\n schema: [],\n messages: {\n raw: 'Use `{{use}}` from @estiva-app/ui instead of a raw {{element}}.{{more}}',\n clickable:\n 'A clickable {{element}} is a button made by hand: it takes no focus and answers no key. Use `Button` from @estiva-app/ui; for a whole card that opens something, `Card` with `href`. A handler that only stops the click (`e.stopPropagation()`) is fine.',\n noPart: '@estiva-app/ui has no part for a raw {{element}} yet. Do not build one here: ask Katerina, and it gets made in @estiva-app/ui.',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n return {\n // ESLint's types know ESTree's nodes, not JSX's; the parser hands this one over.\n JSXOpeningElement(node: Rule.Node) {\n const element = node as unknown as JSXOpeningElement\n const found = classify(element)\n if (!found) return\n if (isEscaped(context, element)) return\n if (found.report === 'clickable') context.report({ loc: element.loc, messageId: 'clickable', data: { element: found.element } })\n else if (found.report === 'noPart') context.report({ loc: element.loc, messageId: 'noPart', data: { element: found.element } })\n else context.report({ loc: element.loc, messageId: 'raw', data: { element: found.element, use: found.part.use, more: found.part.more ?? '' } })\n },\n }\n },\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\n/**\n * Behaviour the package already owns, rebuilt by hand in an app (UIG-8, \"forbid\n * the reach\"). A hand-made dropdown, dialog, list or scrolling box does not look\n * wrong in review; it shows itself when somebody uses a keyboard, or has 81\n * folders. Every message names the part that already does it.\n *\n * What it reads is derived from the package source: which `@base-ui/react` part\n * each component imports, and so what it owns (`OWNED_BEHAVIOURS`, printed in\n * docs/GATES.md and reused by UIG-12's registry). `no-rebuilt-behaviour.test.ts`\n * holds the tables to the source, so a new part cannot be added without them.\n *\n * What it deliberately does not read, and why:\n *\n * - **A box that should scroll and does not.** A class rule finds the scrolling\n * box built by hand; it cannot find the one that was never built. Peek's\n * Folders column (fixed in peek 3dc663b) had no overflow class at all. Only a\n * check that opens the page can find that.\n * - **Enter and Escape** compared by hand. In a field or an editor they are\n * typing, and `Form` and `EditableText` own the ones that send or cancel.\n * Escape and every other key taken for the whole page are read, through the\n * listener.\n * - **aria-expanded, aria-pressed and the other states** written on a package\n * component: the component is already the package's (UIG-14's usage rules).\n * - **Measuring arithmetic**, for the reason UIG-5 gave: `Popover` takes a\n * rectangle to hang from, and a rule that guessed at arithmetic would report it.\n * - A listener on a variable that happens to hold the document.\n *\n * A place that keeps one says why on the line above: `// @estiva-escape: <why>`.\n * An escape above a statement, an element or an object property covers what the\n * rule found there.\n */\n\n/** The part a message names, and where one behaviour has more owners, the others after it. `null`: no part yet. */\nexport interface OwnerPart {\n use: string\n more?: string\n}\n\n/**\n * Every Base UI module, and the package component built on it. Read from the\n * package's imports (`src/*.tsx`); the test fails if a component imports a\n * module this does not name, or names a component that does not import it.\n * A module no component uses has no part yet, and neither do Base UI's utilities.\n */\nexport const BASE_UI_PARTS: Record<string, OwnerPart | null> = {\n 'alert-dialog': { use: 'DialogShell', more: ' To ask yes or no, `ConfirmDialog`.' },\n autocomplete: { use: 'CommandPalette' },\n avatar: { use: 'Avatar' },\n button: { use: 'Button', more: ' Icon only, `IconButton`.' },\n checkbox: { use: 'Checkbox' },\n collapsible: { use: 'CollapsibleSection' },\n combobox: { use: 'ChipInput' },\n dialog: { use: 'DialogShell', more: ' To search and act, `CommandPalette`.' },\n field: { use: 'Field' },\n fieldset: { use: 'Form' },\n form: { use: 'Form' },\n input: { use: 'TextInput', more: ' For a search, `SearchInput`.' },\n menu: { use: 'Menu' },\n popover: { use: 'Popover' },\n 'preview-card': { use: 'PreviewCard' },\n progress: { use: 'ProgressBar' },\n 'scroll-area': { use: 'ScrollArea' },\n select: { use: 'Select' },\n separator: { use: 'Divider' },\n tabs: { use: 'Tabs' },\n toast: { use: 'Toast' },\n toggle: { use: 'Reaction' },\n toolbar: { use: 'Toolbar' },\n tooltip: { use: 'Tooltip', more: ' Around a control, `WithTooltip`.' },\n accordion: null,\n 'checkbox-group': null,\n 'context-menu': null,\n drawer: null,\n menubar: null,\n meter: null,\n 'navigation-menu': null,\n 'number-field': null,\n 'otp-field': null,\n radio: null,\n 'radio-group': null,\n slider: null,\n switch: null,\n 'toggle-group': null,\n}\n\nconst LIST_PART: OwnerPart = {\n use: 'Select',\n more: ' To pick several, `ChipInput`; to search and act, `CommandPalette`; to tick several in a list, `Checkbox` with `row`; for the list a text editor opens as you type, `SuggestionMenu`.',\n}\n\nconst MESSAGE_PART: OwnerPart = { use: 'FieldLine', more: ' For a notice, `Banner`; for a message that comes and goes, `Toast`.' }\n\n/**\n * A role written by hand, and the part that sets it. Base UI's parts set most of\n * these; `tooltip` (Base UI's Tooltip sets none), `alert`, `status` and `link` are\n * the package's own. A role Base UI has a part for and this package has not got\n * yet is `null`. Not here, on purpose: `img`, `group`, `presentation`, `none`,\n * `region` and every landmark \u2014 they describe, they do not behave.\n */\nexport const ROLE_PARTS: Record<string, { thing: string; part: OwnerPart | null }> = {\n dialog: { thing: 'dialog', part: { use: 'DialogShell', more: ' To ask yes or no, `ConfirmDialog`.' } },\n alertdialog: { thing: 'dialog', part: { use: 'ConfirmDialog' } },\n menu: { thing: 'menu', part: { use: 'Menu' } },\n menuitem: { thing: 'menu', part: { use: 'Menu' } },\n menuitemcheckbox: { thing: 'menu', part: { use: 'Menu' } },\n menuitemradio: { thing: 'menu', part: { use: 'Menu' } },\n listbox: { thing: 'list', part: LIST_PART },\n option: { thing: 'list', part: LIST_PART },\n combobox: { thing: 'list', part: LIST_PART },\n tablist: { thing: 'set of tabs', part: { use: 'Tabs' } },\n tab: { thing: 'set of tabs', part: { use: 'Tabs' } },\n tabpanel: { thing: 'set of tabs', part: { use: 'Tabs' } },\n toolbar: { thing: 'toolbar', part: { use: 'Toolbar' } },\n progressbar: { thing: 'progress bar', part: { use: 'ProgressBar' } },\n checkbox: { thing: 'tick box', part: { use: 'Checkbox' } },\n separator: { thing: 'divider', part: { use: 'Divider' } },\n button: { thing: 'button', part: { use: 'Button', more: ' Icon only, `IconButton`.' } },\n link: { thing: 'link', part: { use: 'Link' } },\n tooltip: { thing: 'tooltip', part: { use: 'Tooltip', more: ' Around a control, `WithTooltip`.' } },\n alert: { thing: 'message', part: MESSAGE_PART },\n status: { thing: 'message', part: MESSAGE_PART },\n menubar: { thing: 'menu bar', part: null },\n switch: { thing: 'switch', part: null },\n radio: { thing: 'radio button', part: null },\n radiogroup: { thing: 'radio group', part: null },\n slider: { thing: 'slider', part: null },\n spinbutton: { thing: 'number field', part: null },\n meter: { thing: 'meter', part: null },\n}\n\n/** The keys a list, a menu, tabs and a toolbar move with. Enter and Escape are not here (see above). */\nexport const WALKING_KEYS = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown']\n\n/**\n * A listener on the whole page, by what it is for. The events Base UI's own\n * parts listen to on the document (useDismiss, FloatingFocusManager, the\n * Positioner's autoUpdate): a floating part closes, holds focus and follows its\n * anchor with these. `focus`, `blur`, `visibilitychange` and `storage` are not\n * here: an app refreshing when the window comes back is not a floating part.\n */\nexport const PAGE_EVENTS: Record<string, 'press' | 'key' | 'focus' | 'follow'> = {\n mousedown: 'press',\n pointerdown: 'press',\n click: 'press',\n touchstart: 'press',\n keydown: 'key',\n keyup: 'key',\n keypress: 'key',\n focusin: 'focus',\n focusout: 'focus',\n scroll: 'follow',\n resize: 'follow',\n}\n\n/** Elements that are reachable with Tab by themselves; `tabIndex` on these is not a Tab stop made by hand. */\nexport const INTERACTIVE_ELEMENTS = new Set(['a', 'button', 'input', 'select', 'textarea', 'summary', 'iframe', 'embed', 'object', 'audio', 'video'])\n\n/** `overflow-auto`, `overflow-y-scroll`\u2026: a box that scrolls with the browser's scrollbar. */\nexport const SCROLL_CLASS = /^overflow(?:-[xy])?-(?:auto|scroll)$/\n\n/** One row of the enumeration (UIG-8's acceptance; the shape UIG-12's registry reads). */\nexport interface OwnedBehaviour {\n id: string\n /** What a person notices the part doing. */\n behaviour: string\n /** The Base UI parts that do it, read from their source (1.8.0). */\n baseUi: string[]\n /** The package components an error names. */\n owners: string[]\n /** What the rule reads in an app to find it rebuilt. */\n reads: string\n}\n\nconst uses = (parts: (OwnerPart | null)[]) => [\n ...new Set(parts.flatMap((p) => (p ? [p.use, ...[...(p.more ?? '').matchAll(/`([A-Z]\\w+)`/g)].map((m) => m[1])] : []))),\n]\n\nexport const OWNED_BEHAVIOURS: OwnedBehaviour[] = [\n {\n id: 'base-ui',\n behaviour: 'Is built on Base UI',\n baseUi: Object.keys(BASE_UI_PARTS),\n owners: uses(Object.values(BASE_UI_PARTS)),\n reads: 'an import from @base-ui/react (and the old @base-ui-components spelling)',\n },\n {\n id: 'portal',\n behaviour: 'Floats on top of the page',\n baseUi: ['Dialog', 'AlertDialog', 'Popover', 'Menu', 'Select', 'Combobox', 'Autocomplete', 'Tooltip', 'PreviewCard', 'Toast'],\n owners: ['DialogShell', 'ConfirmDialog', 'CommandPalette', 'Lightbox', 'Popover', 'Menu', 'Select', 'ChipInput', 'Tooltip', 'PreviewCard', 'Toast'],\n reads: 'createPortal, called, or imported and never called',\n },\n {\n id: 'press-outside',\n behaviour: 'Closes on a press outside',\n baseUi: ['Dialog', 'AlertDialog', 'Popover', 'Menu', 'Select', 'Combobox', 'Tooltip', 'PreviewCard'],\n owners: ['DialogShell', 'Popover', 'Menu', 'Select', 'PreviewCard'],\n reads: 'a mousedown, pointerdown, click or touchstart listener on window or document',\n },\n {\n id: 'page-keys',\n behaviour: 'Takes its keys by itself',\n baseUi: ['Dialog', 'AlertDialog', 'Popover', 'Menu', 'Select', 'Combobox', 'Tooltip', 'PreviewCard', 'Toast'],\n owners: ['DialogShell', 'Lightbox', 'Popover', 'Menu', 'Select', 'Tabs', 'Toolbar'],\n reads: 'a keydown, keyup or keypress listener on window or document',\n },\n {\n id: 'focus',\n behaviour: 'Holds focus inside while open, and gives it back',\n baseUi: ['Dialog', 'AlertDialog', 'Popover', 'Menu', 'Select', 'Combobox'],\n owners: ['DialogShell', 'CommandPalette', 'Lightbox'],\n reads: 'a focusin or focusout listener on window or document; the Tab key compared by hand',\n },\n {\n id: 'scroll-lock',\n behaviour: 'Stops the page behind it scrolling',\n baseUi: ['Dialog', 'AlertDialog'],\n owners: ['DialogShell', 'Lightbox'],\n reads: 'overflow written into the style of document.body or document.documentElement',\n },\n {\n id: 'follow',\n behaviour: 'Stays attached to its anchor on scroll and resize',\n baseUi: ['Popover', 'Menu', 'Select', 'Combobox', 'Tooltip', 'PreviewCard', 'Toast'],\n owners: ['Popover', 'Menu', 'Select', 'Tooltip', 'PreviewCard'],\n reads: 'a scroll or resize listener on window or document',\n },\n {\n id: 'walking',\n behaviour: 'Moves through its items with the arrow keys',\n baseUi: ['Menu', 'Select', 'Combobox', 'Autocomplete', 'Tabs', 'Toolbar'],\n owners: ['Menu', 'Select', 'ChipInput', 'CommandPalette', 'SuggestionMenu', 'Tabs', 'Toolbar'],\n reads: `a key compared by hand with ${WALKING_KEYS.join(', ')}`,\n },\n {\n id: 'role',\n behaviour: 'Says what it is to assistive technology',\n baseUi: ['Dialog', 'AlertDialog', 'Menu', 'Select', 'Combobox', 'Tabs', 'Toolbar', 'Progress', 'Checkbox', 'Separator', 'Button'],\n owners: uses(Object.values(ROLE_PARTS).map((r) => r.part)),\n reads: `role written by hand: ${Object.keys(ROLE_PARTS).join(', ')}`,\n },\n {\n id: 'tab-stop',\n behaviour: 'Is reachable with Tab',\n baseUi: ['Button', 'Toggle', 'Checkbox', 'Tabs', 'Toolbar', 'ScrollArea'],\n owners: ['Button', 'IconButton', 'Link'],\n reads: 'tabIndex that can be 0 or more, on an element that is not a control',\n },\n {\n id: 'scroll',\n behaviour: 'Scrolls with our scrollbar',\n baseUi: ['ScrollArea'],\n owners: ['ScrollArea'],\n reads: 'overflow-auto or overflow-scroll (x or y, behind any variant) in a string, or overflow auto or scroll in a style',\n },\n]\n\ninterface Node {\n type: string\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n parent?: Node\n [key: string]: unknown\n}\n\nconst PAGE_TARGETS = new Set(['window', 'document', 'globalThis', 'self', 'document.body', 'document.documentElement', 'window.document'])\n\n/** Where an escape for this node is written: its object property, its element, its array item, or its statement. */\nfunction anchorOf(node: Node): Node {\n if (node.type === 'FunctionDeclaration') {\n return node.parent && /^Export/.test(node.parent.type) ? node.parent : node\n }\n let child = node\n for (let p = node.parent; p; child = p, p = p.parent) {\n if (p.type === 'JSXOpeningElement' || p.type === 'Property' || p.type === 'MethodDefinition' || p.type === 'PropertyDefinition') return p\n if (p.type === 'ArrayExpression') return child\n if (p.type !== 'BlockStatement' && /(Statement|Declaration)$/.test(p.type)) return p\n }\n return node\n}\n\nfunction enclosingFunction(node: Node): Node | undefined {\n for (let p = node.parent; p; p = p.parent) {\n if (p.type === 'FunctionDeclaration' || p.type === 'FunctionExpression' || p.type === 'ArrowFunctionExpression') return p\n }\n return undefined\n}\n\nfunction stringOf(node: Node | undefined | null): string | undefined {\n if (!node) return undefined\n if (node.type === 'Literal' && typeof node.value === 'string') return node.value\n const quasis = node.quasis as { value: { cooked: string | null } }[] | undefined\n const expressions = node.expressions as unknown[] | undefined\n if (node.type === 'TemplateLiteral' && expressions?.length === 0) return quasis?.[0]?.value.cooked ?? undefined\n return undefined\n}\n\n/** Every string a JSX attribute's value can be: `\"x\"`, `{'x'}`, `{a ? 'x' : 'y'}`, `{a && 'x'}`. */\nfunction stringsOf(node: Node | undefined | null): string[] {\n if (!node) return []\n if (node.type === 'JSXExpressionContainer') return stringsOf(node.expression as Node)\n const s = stringOf(node)\n if (s !== undefined) return [s]\n if (node.type === 'ConditionalExpression') return [...stringsOf(node.consequent as Node), ...stringsOf(node.alternate as Node)]\n if (node.type === 'LogicalExpression') return [...stringsOf(node.left as Node), ...stringsOf(node.right as Node)]\n return []\n}\n\n/** Whether a `tabIndex` value can be 0 or more, as far as the code spells it out. */\nfunction canBeTabStop(node: Node | undefined | null): boolean {\n if (!node) return false\n if (node.type === 'JSXExpressionContainer') return canBeTabStop(node.expression as Node)\n if (node.type === 'Literal') {\n if (typeof node.value === 'number') return node.value >= 0\n if (typeof node.value === 'string') return /^\\s*\\d+\\s*$/.test(node.value)\n return false\n }\n if (node.type === 'ConditionalExpression') return canBeTabStop(node.consequent as Node) || canBeTabStop(node.alternate as Node)\n if (node.type === 'LogicalExpression') return canBeTabStop(node.left as Node) || canBeTabStop(node.right as Node)\n if (node.type === 'TSAsExpression' || node.type === 'TSNonNullExpression') return canBeTabStop(node.expression as Node)\n return false\n}\n\n/** A class token's utility, past its variants: `[&_pre]:overflow-x-auto` \u2192 `overflow-x-auto`. */\nexport function utilityOf(token: string): string {\n let depth = 0\n let last = -1\n for (let i = 0; i < token.length; i++) {\n const c = token[i]\n if (c === '[') depth++\n else if (c === ']') depth--\n else if (c === ':' && depth === 0) last = i\n }\n return token.slice(last + 1).replace(/^!/, '').replace(/!$/, '')\n}\n\n/** The Base UI module an import names, or `undefined` when it is not Base UI. `''` is the package root. */\nexport function baseUiModule(source: string): string | undefined {\n const m = /^@base-ui(?:-components)?\\/([^/]+)(?:\\/(.+))?$/.exec(source)\n if (!m) return undefined\n const [, pkg, sub] = m\n return pkg === 'react' ? (sub ?? '') : `${pkg}${sub ? `/${sub}` : ''}`\n}\n\nfunction isKeySubject(node: Node | undefined): boolean {\n if (!node) return false\n if (node.type === 'Identifier') return node.name === 'key' || node.name === 'code'\n if (node.type !== 'MemberExpression' || node.computed) return false\n const property = node.property as Node\n return property.type === 'Identifier' && (property.name === 'key' || property.name === 'code')\n}\n\nfunction pageTarget(node: Node, text: string): boolean {\n return (node.type === 'Identifier' || node.type === 'MemberExpression') && PAGE_TARGETS.has(text)\n}\n\nexport const noRebuiltBehaviour: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'Behaviour @estiva-app/ui already owns, rebuilt by hand in an app' },\n schema: [],\n messages: {\n baseUi: 'Only @estiva-app/ui imports Base UI (`{{module}}`). Use `{{use}}` from @estiva-app/ui.{{more}}',\n baseUiNoPart:\n 'Only @estiva-app/ui imports Base UI (`{{module}}`), and it has no part built on it yet. Do not build one here: ask Katerina, and it gets made in @estiva-app/ui.',\n portal:\n 'A layer put on top of the page by hand (`createPortal`). Every floating part of @estiva-app/ui carries its own: `DialogShell` for a dialog, `Popover` for a panel, `Menu`, `Select`, `Tooltip`, `PreviewCard`, `Toast`.',\n press:\n 'A `{{event}}` listener on `{{target}}`: closing on a press outside, by hand. `Popover`, `Menu`, `Select`, `DialogShell` and `PreviewCard` from @estiva-app/ui close themselves.',\n key: 'A `{{event}}` listener on `{{target}}`: keys taken for the whole page, by hand. `DialogShell`, `Popover`, `Menu` and `Select` from @estiva-app/ui close on Escape themselves; `Menu`, `Select`, `Tabs` and `Toolbar` move with the arrow keys.',\n focus:\n 'A `{{event}}` listener on `{{target}}`: focus held by hand. `DialogShell` and `CommandPalette` from @estiva-app/ui keep focus inside and give it back.',\n follow:\n 'A `{{event}}` listener on `{{target}}`: following an anchor by hand. `Popover`, `Menu`, `Select`, `Tooltip` and `PreviewCard` from @estiva-app/ui stay attached to theirs.',\n scrollLock: \"The page's scroll locked by hand. `DialogShell` from @estiva-app/ui stops the page scrolling while it is open, and gives it back.\",\n walking:\n 'Arrow keys handled by hand (`{{key}}`). `Menu`, `Select`, `ChipInput`, `CommandPalette`, `Tabs` and `Toolbar` from @estiva-app/ui move through their items themselves.',\n tabKey: 'The Tab key handled by hand. `DialogShell` and `CommandPalette` from @estiva-app/ui keep focus inside themselves.',\n role: 'A hand-written `role=\"{{role}}\"` is a hand-made {{thing}}. Use `{{use}}` from @estiva-app/ui.{{more}}',\n roleNoPart:\n 'A hand-written `role=\"{{role}}\"` is a hand-made {{thing}}, and @estiva-app/ui has no part for one yet. Do not build one here: ask Katerina, and it gets made in @estiva-app/ui.',\n tabStop:\n '`tabIndex={{value}}` makes a `<{{element}}>` a Tab stop by hand. Use `Button`, `IconButton` or `Link` from @estiva-app/ui, which are reachable already.',\n scrollClass: \"`{{token}}` scrolls with the browser's scrollbar. Use `ScrollArea` from @estiva-app/ui, which draws ours.\",\n scrollStyle: \"`{{style}}` scrolls with the browser's scrollbar. Use `ScrollArea` from @estiva-app/ui, which draws ours.\",\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n const { sourceCode } = context\n const text = (node: Node) => sourceCode.getText(node as unknown as Rule.Node)\n\n // One escape covers what the rule found at its anchor, and is counted once.\n const escapes = new Map<Node, boolean>()\n const escaped = (anchor: Node) => {\n if (!escapes.has(anchor)) escapes.set(anchor, isEscaped(context, anchor))\n return escapes.get(anchor) === true\n }\n const seen = new Set<string>()\n const report = (anchor: Node, at: Node, messageId: string, data: Record<string, string> = {}, once = `${at.range[0]}`) => {\n const key = `${anchor.range[0]}|${messageId}|${once}`\n if (seen.has(key)) return\n seen.add(key)\n if (escaped(anchor)) return\n context.report({ loc: at.loc, messageId, data })\n }\n\n const importSource = (node: Node, source: Node | undefined | null) => {\n const value = stringOf(source)\n if (value === undefined) return\n const module = baseUiModule(value)\n if (module === undefined) return\n const part = Object.hasOwn(BASE_UI_PARTS, module) ? BASE_UI_PARTS[module] : null\n const anchor = anchorOf(node)\n if (part) report(anchor, node, 'baseUi', { module: value, use: part.use, more: part.more ?? '' })\n else report(anchor, node, 'baseUiNoPart', { module: value })\n }\n\n const keyCompared = (node: Node, key: string | undefined) => {\n if (key === undefined) return\n const fn = enclosingFunction(node)\n const anchor = anchorOf(fn ?? node)\n if (WALKING_KEYS.includes(key)) report(anchor, node, 'walking', { key }, `walking@${fn?.range[0] ?? node.range[0]}`)\n else if (key === 'Tab') report(anchor, node, 'tabKey', {}, `tab@${fn?.range[0] ?? node.range[0]}`)\n }\n\n const classTokens = (node: Node, value: string) => {\n for (const token of value.split(/\\s+/)) {\n if (token && SCROLL_CLASS.test(utilityOf(token))) report(anchorOf(node), node, 'scrollClass', { token }, `class@${token}`)\n }\n }\n\n // `createPortal` imported: reported where it is called, or at the import when it never is.\n const portalImports = new Map<string, Node>()\n let portalCalled = false\n\n return {\n ImportDeclaration(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n importSource(node, node.source as Node)\n if (stringOf(node.source as Node) !== 'react-dom') return\n for (const specifier of node.specifiers as Node[]) {\n const imported = specifier.imported as Node | undefined\n if (specifier.type === 'ImportSpecifier' && imported?.name === 'createPortal') portalImports.set((specifier.local as Node).name as string, node)\n }\n },\n ExportNamedDeclaration(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n if (node.source) importSource(node, node.source as Node)\n },\n ExportAllDeclaration(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n importSource(node, node.source as Node)\n },\n ImportExpression(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n importSource(node, node.source as Node)\n },\n\n CallExpression(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n const callee = node.callee as Node\n const args = node.arguments as Node[]\n\n if (callee.type === 'Identifier' && callee.name === 'require') importSource(node, args[0])\n\n if (callee.type === 'Identifier' && portalImports.has(callee.name as string)) {\n portalCalled = true\n report(anchorOf(node), node, 'portal')\n }\n if (callee.type !== 'MemberExpression') return\n const object = callee.object as Node\n const property = callee.property as Node\n if (property.type !== 'Identifier') return\n\n if (property.name === 'createPortal') {\n report(anchorOf(node), node, 'portal')\n return\n }\n\n if (property.name === 'addEventListener') {\n const target = text(object)\n if (!pageTarget(object, target)) return\n const event = stringOf(args[0])\n const group = event === undefined ? undefined : PAGE_EVENTS[event]\n if (!event || !group) return\n report(anchorOf(node), node, group, { event, target })\n return\n }\n\n // ['ArrowUp', 'ArrowDown'].includes(event.key)\n if (property.name === 'includes' && object.type === 'ArrayExpression' && isKeySubject(args[0])) {\n for (const element of object.elements as Node[]) keyCompared(node, stringOf(element))\n }\n },\n\n AssignmentExpression(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n const left = node.left as Node\n if (left.type !== 'MemberExpression') return\n const property = left.property as Node\n const object = left.object as Node\n const handler = property.type === 'Identifier' ? /^on([a-z]+)$/.exec(property.name as string) : null\n if (handler && pageTarget(object, text(object)) && PAGE_EVENTS[handler[1]]) {\n report(anchorOf(node), node, PAGE_EVENTS[handler[1]], { event: handler[1], target: text(object) })\n return\n }\n if (/^document\\.(?:body|documentElement)\\.style\\.overflow[XY]?$/.test(text(left))) report(anchorOf(node), node, 'scrollLock')\n },\n\n BinaryExpression(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n if (!['===', '==', '!==', '!='].includes(node.operator as string)) return\n const left = node.left as Node\n const right = node.right as Node\n if (isKeySubject(left)) keyCompared(node, stringOf(right))\n else if (isKeySubject(right)) keyCompared(node, stringOf(left))\n },\n\n SwitchCase(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n const statement = node.parent as Node\n if (node.test && isKeySubject(statement.discriminant as Node)) keyCompared(node, stringOf(node.test as Node))\n },\n\n JSXAttribute(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n const nameNode = node.name as Node\n if (nameNode.type !== 'JSXIdentifier') return\n const name = nameNode.name as string\n const element = node.parent as Node\n const value = node.value as Node | null\n\n if (name === 'role') {\n for (const role of stringsOf(value).flatMap((v) => v.trim().split(/\\s+/))) {\n if (!Object.hasOwn(ROLE_PARTS, role)) continue\n const { thing, part } = ROLE_PARTS[role]\n if (part) report(element, node, 'role', { role, thing, use: part.use, more: part.more ?? '' })\n else report(element, node, 'roleNoPart', { role, thing })\n return\n }\n return\n }\n\n if (name === 'tabIndex' || name === 'tabindex') {\n const tag = element.name as Node\n if (tag.type !== 'JSXIdentifier' || !/^[a-z]/.test(tag.name as string) || INTERACTIVE_ELEMENTS.has(tag.name as string)) return\n const attributes = element.attributes as Node[]\n const editable = attributes.some((a) => a.type === 'JSXAttribute' && /^contenteditable$/i.test(((a.name as Node).name as string) ?? ''))\n if (editable || !canBeTabStop(value)) return\n report(element, node, 'tabStop', { value: value ? text(value).replace(/^\\{|\\}$/g, '') : '', element: tag.name as string })\n return\n }\n\n if (name === 'style' && value?.type === 'JSXExpressionContainer') {\n const object = value.expression as Node\n if (object.type !== 'ObjectExpression') return\n for (const property of object.properties as Node[]) {\n if (property.type !== 'Property') continue\n const key = property.key as Node\n const keyName = key.type === 'Identifier' ? (key.name as string) : stringOf(key)\n if (!keyName || !/^overflow[XY]?$/.test(keyName)) continue\n const setting = stringOf(property.value as Node)\n if (setting === 'auto' || setting === 'scroll') report(element, property, 'scrollStyle', { style: `${keyName}: '${setting}'` }, `style@${keyName}`)\n }\n }\n },\n\n Literal(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n if (typeof node.value !== 'string') return\n const parent = node.parent\n if (parent && /^(Import|Export)/.test(parent.type)) return\n if (parent?.type === 'TSLiteralType' || parent?.type === 'TSExternalModuleReference') return\n classTokens(node, node.value)\n },\n\n TemplateElement(ruleNode: Rule.Node) {\n const node = ruleNode as unknown as Node\n const cooked = (node.value as { cooked: string | null }).cooked\n if (cooked && node.parent) classTokens(node.parent, cooked)\n },\n\n 'Program:exit'() {\n if (portalCalled) return\n for (const declaration of new Set(portalImports.values())) report(anchorOf(declaration), declaration, 'portal')\n },\n }\n },\n}\n", "import type { Rule } from 'eslint'\nimport { ESCAPE_MESSAGES, isEscaped } from './escape'\n\ninterface JSXOpeningElement {\n type: string\n name: { type: string; name?: string }\n loc: NonNullable<Rule.Node['loc']>\n range: [number, number]\n parent?: Parent\n}\n\ninterface Parent {\n type: string\n name?: { name?: string }\n openingElement?: unknown\n parent?: Parent\n}\n\n/**\n * The elements this package writes by hand. The set the count used (UIG-1,\n * docs/GATES.md \u00A75 and \u00A77): every element that carries behaviour or a role of\n * its own. A `div` or a `span` is layout and is nobody's business here.\n */\nexport const RAW_ELEMENTS = new Set(['a', 'button', 'input', 'textarea', 'select', 'dialog', 'form', 'label'])\n\n/**\n * A raw element nested inside another element, in the package itself (UIG-5,\n * the inward tracer).\n *\n * The package is allowed to write raw elements \u2014 that is what a primitive is.\n * Two shapes are right, and both are facts about the code rather than a\n * judgement:\n *\n * - **the component's own outermost element.** `NavItem` is an `<a>`, `Link` is\n * an `<a>`, a `MenuItem` outside a `Menu` is a `<button>`. A primitive owning\n * its element is the whole point of it.\n * - **handed to a Base UI `render` prop.** `render={<button type=\"button\" />}`\n * tells a Base UI part which element to be; the behaviour stays Base UI's.\n *\n * Anything else is an element buried inside a bigger component, where its look\n * and its behaviour are kept in step by nobody \u2014 the package's own version of\n * the rule the apps get from UIG-3 and UIG-7.\n *\n * It keeps its reason on the line above if it stays: `// @estiva-escape: <why>`.\n */\nexport const rawElementOutsideAWrapper: Rule.RuleModule = {\n meta: {\n type: 'problem',\n docs: { description: 'A raw element nested inside a component, rather than the component itself' },\n schema: [],\n messages: {\n nested:\n 'A raw <{{name}}> inside another element. In this package a raw element is either the component\\'s own outermost element or handed to a Base UI `render` prop; one buried inside belongs in a component of its own (Link, Button, MenuItem...).',\n ...ESCAPE_MESSAGES,\n },\n },\n create(context) {\n return {\n // ESLint's types know ESTree's nodes, not JSX's; the parser hands this one over.\n JSXOpeningElement(node: Rule.Node) {\n const element = node as unknown as JSXOpeningElement\n const name = element.name.name\n if (element.name.type !== 'JSXIdentifier' || !name || !RAW_ELEMENTS.has(name)) return\n\n // An opening tag's own parent is its JSXElement: that is this element,\n // not an element around it.\n let parent = element.parent\n if (parent?.type === 'JSXElement' && parent.openingElement === (element as unknown)) parent = parent.parent\n\n // Whichever comes first going outward decides: an element around it\n // means it is nested; a `render` prop means Base UI draws it.\n for (let p = parent; p; p = p.parent) {\n if (p.type === 'JSXAttribute') {\n if (p.name?.name === 'render') return\n continue\n }\n if (p.type !== 'JSXElement' && p.type !== 'JSXFragment') continue\n if (isEscaped(context, element)) return\n context.report({ loc: element.loc, messageId: 'nested', data: { name } })\n return\n }\n },\n }\n },\n}\n", "/**\n * The names of the app rules, with nothing imported.\n *\n * `create-estiva-app` needs these names to write a new app's count at zero, and\n * nothing else of the plugin. It runs from `npx` in an empty folder, where only\n * this package's own dependencies are installed, so it must never load the\n * rules themselves: since `no-copied-look` (UIG-25, 0.34.0) they import\n * TypeScript, and that import stopped the command before it wrote a file\n * (UIG-10, reopened 27 September). `index.ts` holds its rule table to exactly\n * these names, so the two cannot drift.\n */\n\n/** The name the configs register the plugin under, so every rule id is `estiva/<rule>`. */\nexport const PLUGIN_KEY = 'estiva'\n\nexport const APP_RULE_NAMES = [\n 'no-raw-element',\n 'no-rebuilt-behaviour',\n 'no-restyled-part',\n 'no-handmade-header',\n 'no-handmade-empty-state',\n 'no-native-title',\n 'no-copied-look',\n 'no-field-outside-a-form',\n] as const\n\nexport type AppRuleName = (typeof APP_RULE_NAMES)[number]\n\n/** The ids `recommended` and `strict` carry \u2014 what an app's gate runs and counts. */\nexport const APP_RULE_IDS = APP_RULE_NAMES.map((name) => `${PLUGIN_KEY}/${name}`)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["rules", "statSync", "existsSync", "code", "existsSync", "statement", "isPart", "attribute", "words", "literal", "child", "children", "nameOf", "statement", "statSync", "words", "classesOf", "child", "FILLS", "bare", "existsSync", "readFileSync", "statSync", "dirname", "join", "resolve", "existsSync", "readFileSync", "dirname", "join", "PLACEMENT", "CLASS_FUNCTIONS", "CLASS_PROP", "resolve", "statement", "fileName", "packageDirCache", "packageDirOf", "dirname", "resolve", "existsSync", "join", "PACKAGE", "nameOf", "readFileSync", "statSync", "walk", "words", "child", "nameOf", "child", "nameOf", "attribute", "attribute", "part", "child", "statement"]
|
|
7
7
|
}
|