@estiva-app/ui 0.44.1 → 0.45.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.
Files changed (54) hide show
  1. package/dist/SelectionToolbar.d.ts +62 -0
  2. package/dist/SelectionToolbar.d.ts.map +1 -0
  3. package/dist/SuggestionMenu.d.ts +75 -0
  4. package/dist/SuggestionMenu.d.ts.map +1 -0
  5. package/dist/editor.d.ts +12 -0
  6. package/dist/editor.d.ts.map +1 -0
  7. package/dist/editor.js +357 -0
  8. package/dist/editor.js.map +7 -0
  9. package/dist/eslint/index.js +2 -2
  10. package/dist/eslint/index.js.map +2 -2
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +201 -99
  14. package/dist/index.js.map +4 -4
  15. package/dist/registry/{app-YMABQII6.js → app-LDGOH6UW.js} +3 -3
  16. package/dist/registry/{build-3EANARLQ.js → build-P6X3PTZP.js} +6 -2
  17. package/dist/registry/build.d.ts +4 -0
  18. package/dist/registry/build.d.ts.map +1 -1
  19. package/dist/registry/{chunk-SIB44CES.js → chunk-P55P2QFD.js} +9 -4
  20. package/dist/registry/chunk-P55P2QFD.js.map +7 -0
  21. package/dist/registry/{chunk-EVJW26UR.js → chunk-TQ6UQER3.js} +10 -10
  22. package/dist/registry/chunk-TQ6UQER3.js.map +7 -0
  23. package/dist/registry/cli.js +2 -2
  24. package/dist/registry/index.js +2 -2
  25. package/dist/shortcuts.d.ts +27 -0
  26. package/dist/shortcuts.d.ts.map +1 -0
  27. package/dist/suggestionPopup.d.ts +41 -0
  28. package/dist/suggestionPopup.d.ts.map +1 -0
  29. package/package.json +27 -2
  30. package/registry.json +341 -3
  31. package/src/SelectionToolbar.mdx +78 -0
  32. package/src/SelectionToolbar.stories.tsx +63 -0
  33. package/src/SelectionToolbar.test.ts +105 -0
  34. package/src/SelectionToolbar.tsx +487 -0
  35. package/src/SuggestionMenu.mdx +107 -0
  36. package/src/SuggestionMenu.stories.tsx +202 -0
  37. package/src/SuggestionMenu.test.tsx +128 -0
  38. package/src/SuggestionMenu.tsx +189 -0
  39. package/src/editor.ts +11 -0
  40. package/src/eslint/no-rebuilt-behaviour.test.ts +1 -1
  41. package/src/eslint/no-rebuilt-behaviour.ts +2 -2
  42. package/src/how.test.ts +1 -1
  43. package/src/index.ts +2 -0
  44. package/src/keptSelection.test.ts +67 -0
  45. package/src/registry/app.ts +8 -8
  46. package/src/registry/build.ts +10 -2
  47. package/src/registry/registry.test.ts +14 -9
  48. package/src/shortcuts.ts +40 -0
  49. package/src/suggestionPopup.tsx +119 -0
  50. package/stories/Choosing.mdx +2 -0
  51. package/dist/registry/chunk-EVJW26UR.js.map +0 -7
  52. package/dist/registry/chunk-SIB44CES.js.map +0 -7
  53. /package/dist/registry/{app-YMABQII6.js.map → app-LDGOH6UW.js.map} +0 -0
  54. /package/dist/registry/{build-3EANARLQ.js.map → build-P6X3PTZP.js.map} +0 -0
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  buildAppRegistry
4
- } from "./chunk-EVJW26UR.js";
5
- import "./chunk-SIB44CES.js";
4
+ } from "./chunk-TQ6UQER3.js";
5
+ import "./chunk-P55P2QFD.js";
6
6
  import "./chunk-PZO4BVV3.js";
7
7
  export {
8
8
  buildAppRegistry
9
9
  };
10
- //# sourceMappingURL=app-YMABQII6.js.map
10
+ //# sourceMappingURL=app-LDGOH6UW.js.map
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ EDITOR_IMPORT,
3
4
  PACKAGE_IMPORT,
4
5
  buildRegistry,
5
6
  firstSentence,
7
+ isPackageImport,
6
8
  pageOpening,
7
9
  readIndexExports,
8
10
  readModule,
@@ -10,12 +12,14 @@ import {
10
12
  sanitize,
11
13
  serializeRegistry,
12
14
  toId
13
- } from "./chunk-SIB44CES.js";
15
+ } from "./chunk-P55P2QFD.js";
14
16
  import "./chunk-PZO4BVV3.js";
15
17
  export {
18
+ EDITOR_IMPORT,
16
19
  PACKAGE_IMPORT,
17
20
  buildRegistry,
18
21
  firstSentence,
22
+ isPackageImport,
19
23
  pageOpening,
20
24
  readIndexExports,
21
25
  readModule,
@@ -24,4 +28,4 @@ export {
24
28
  serializeRegistry,
25
29
  toId
26
30
  };
27
- //# sourceMappingURL=build-3EANARLQ.js.map
31
+ //# sourceMappingURL=build-P6X3PTZP.js.map
@@ -26,6 +26,10 @@ interface Declared {
26
26
  propsType?: ts.TypeNode;
27
27
  }
28
28
  export declare const PACKAGE_IMPORT = "@estiva-app/ui";
29
+ /** The editor corner (UIG-31): parts that import Tiptap, kept off the main entry. */
30
+ export declare const EDITOR_IMPORT = "@estiva-app/ui/editor";
31
+ /** Whether an import names the package: its main entry, or its editor corner. */
32
+ export declare const isPackageImport: (specifier: string) => specifier is "@estiva-app/ui" | "@estiva-app/ui/editor";
29
33
  /**
30
34
  * Storybook's own `sanitize`, which is what turns a title and a story's export
31
35
  * name into the id in the URL. Copied rather than imported: `storybook` is a
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/registry/build.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,MAAM,YAAY,CAAA;AAI3B,OAAO,EAAuD,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAsB,MAAM,UAAU,CAAA;AAEpJ,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,yCAAyC;AACzC,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,uEAAuE;AACvE,UAAU,QAAQ;IAChB,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAA;CACxB;AAED,eAAO,MAAM,cAAc,mBAAmB,CAAA;AAE9C;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO7C;AAsBD,eAAO,MAAM,IAAI,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,WAAiE,CAAA;AAEjH,8FAA8F;AAC9F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CAa5D;AAgCD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAanD;AAED,+FAA+F;AAC/F,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiB/C;AAwCD,uFAAuF;AACvF,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,QAAQ,EAAE,YAAY,EAAE,CAAA;CACzB;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,QAAQ,GAAG,SAAS,CAAA;AAEnF,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,OAAyB,EAAE,EAAE,gBAAuB,EAAE,GAAE,WAAgB;;;yBAuQ9F,EAAE,CAAC,QAAQ,GAAG,SAAS,KAAG,QAAQ;wBAOwD,MAAM;EAC7H;AAYD,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAuBvF;AAeD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,EAAE,IAAoB,EAAE,IAAkB,EAAE,GAAE,YAAiB,GAAG,QAAQ,CA+IvG;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE5D"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/registry/build.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,MAAM,YAAY,CAAA;AAI3B,OAAO,EAAuD,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,KAAK,QAAQ,EAAsB,MAAM,UAAU,CAAA;AAEpJ,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,yCAAyC;AACzC,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,OAAO,CAAA;CAChB;AAED,uEAAuE;AACvE,UAAU,QAAQ;IAChB,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAA;CACxB;AAED,eAAO,MAAM,cAAc,mBAAmB,CAAA;AAC9C,qFAAqF;AACrF,eAAO,MAAM,aAAa,0BAA0B,CAAA;AACpD,iFAAiF;AACjF,eAAO,MAAM,eAAe,GAAI,WAAW,MAAM,4DAAgE,CAAA;AAEjH;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAO7C;AAsBD,eAAO,MAAM,IAAI,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,WAAiE,CAAA;AAEjH,8FAA8F;AAC9F,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CAa5D;AAgCD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAanD;AAED,+FAA+F;AAC/F,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiB/C;AAwCD,uFAAuF;AACvF,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,QAAQ,EAAE,YAAY,EAAE,CAAA;CACzB;AAED;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,QAAQ,GAAG,SAAS,CAAA;AAEnF,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,OAAyB,EAAE,EAAE,gBAAuB,EAAE,GAAE,WAAgB;;;yBAuQ9F,EAAE,CAAC,QAAQ,GAAG,SAAS,KAAG,QAAQ;wBAOwD,MAAM;EAC7H;AAYD,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAuBvF;AAeD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,EAAE,IAAoB,EAAE,IAAkB,EAAE,GAAE,YAAiB,GAAG,QAAQ,CAmJvG;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE5D"}
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-PZO4BVV3.js";
5
5
 
6
6
  // src/registry/build.ts
7
- import { readFileSync as readFileSync2, readdirSync } from "node:fs";
7
+ import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync } from "node:fs";
8
8
  import { join as join2 } from "node:path";
9
9
  import ts3 from "typescript";
10
10
  import { OWNED_BEHAVIOURS as OWNED_BEHAVIOURS2 } from "../eslint/index.js";
@@ -348,6 +348,8 @@ function importedConstants(source) {
348
348
 
349
349
  // src/registry/build.ts
350
350
  var PACKAGE_IMPORT = "@estiva-app/ui";
351
+ var EDITOR_IMPORT = "@estiva-app/ui/editor";
352
+ var isPackageImport = (specifier) => specifier === PACKAGE_IMPORT || specifier === EDITOR_IMPORT;
351
353
  function sanitize(name) {
352
354
  return name.toLowerCase().replace(/[ ’–—―′¿'`~!@#$%^&*()_|+\-=?;:'",.<>{}[\]\\/]/g, "-").replace(/-+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
353
355
  }
@@ -636,7 +638,8 @@ function buildRegistry({ root = process.cwd(), repo = "estiva-ui" } = {}) {
636
638
  const src = join2(root, "src");
637
639
  const manifest = JSON.parse(readFileSync2(join2(root, "package.json"), "utf8"));
638
640
  const files = new Set(readdirSync(src));
639
- const exported = readIndexExports(readFileSync2(join2(src, "index.ts"), "utf8"));
641
+ const fromEntry = (file, importPath) => existsSync2(join2(src, file)) ? readIndexExports(readFileSync2(join2(src, file), "utf8")).map((entry) => ({ ...entry, importPath })) : [];
642
+ const exported = [...fromEntry("index.ts", PACKAGE_IMPORT), ...fromEntry("editor.ts", EDITOR_IMPORT)];
640
643
  const values = exported.filter((entry) => !entry.isType);
641
644
  const modules = /* @__PURE__ */ new Map();
642
645
  const moduleOf = (name) => {
@@ -679,7 +682,7 @@ function buildRegistry({ root = process.cwd(), repo = "estiva-ui" } = {}) {
679
682
  name: value.name,
680
683
  repo,
681
684
  kind: kindOf(value.name),
682
- importPath: PACKAGE_IMPORT,
685
+ importPath: value.importPath,
683
686
  sourceFile: module.file,
684
687
  purpose,
685
688
  purposeFrom: fromPage ? "page" : "comment",
@@ -768,6 +771,8 @@ export {
768
771
  looksOf,
769
772
  parseForLooks,
770
773
  PACKAGE_IMPORT,
774
+ EDITOR_IMPORT,
775
+ isPackageImport,
771
776
  sanitize,
772
777
  toId,
773
778
  readIndexExports,
@@ -778,4 +783,4 @@ export {
778
783
  buildRegistry,
779
784
  serializeRegistry
780
785
  };
781
- //# sourceMappingURL=chunk-SIB44CES.js.map
786
+ //# sourceMappingURL=chunk-P55P2QFD.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/registry/build.ts", "../../src/registry/behaviours.ts", "../../src/eslint/looks-of.ts"],
4
+ "sourcesContent": ["/// <reference types=\"node\" />\n/**\n * The catalogue's builder (UIG-12): it reads the code and writes\n * `registry.json`. Nothing here is kept by hand, and CI rebuilds it and fails\n * on a difference, so the file cannot drift from what it describes.\n *\n * **Why a parser and not a regex.** This package's components are flat in\n * `src/`, with `.tsx`, `.mdx`, `.stories.tsx` and sometimes `.test.tsx` side by\n * side, and **a file is not a component**: eleven files export more than one\n * name \u2014 `Menu.tsx` alone exports seven \u2014 and `Skeleton.tsx` exports no\n * `Skeleton` at all. Pairing by filename gets `FieldLine`, `MenuItem` and every\n * one of those wrong. The target set is what `src/index.ts` exports, read with\n * TypeScript's own parser, and everything else is looked up from there.\n *\n * TypeScript is the app's own install, as it is for the gate pieces\n * (`build.mjs`): every package this names stays external.\n */\nimport { existsSync, readFileSync, readdirSync } from 'node:fs'\nimport { join } from 'node:path'\nimport ts from 'typescript'\nimport { OWNED_BEHAVIOURS } from '../eslint/index'\nimport { asBehaviours, baseUiBehaviours, drawnIn, handedOn, importsOf, isBaseUi, rootsIn, splitTag } from './behaviours'\nimport { looksOf, parseForLooks } from '../eslint/looks-of'\nimport { SCHEMA_VERSION, type EntryBehaviour, type EntryKind, type EntryProp, type EntryVariant, type Registry, type RegistryEntry } from './schema'\n\nexport interface BuildOptions {\n /** The repository's top folder. */\n root?: string\n /** The name this registry's entries are recorded under. */\n repo?: string\n}\n\n/** One name as `index.ts` exports it. */\ninterface RawExport {\n name: string\n /** The sibling it comes from, without `./`. */\n module: string\n isType: boolean\n}\n\n/** What the parser found above and about one top-level declaration. */\ninterface Declared {\n /** The doc comment, cleaned, or `''`. */\n doc: string\n deprecated: boolean\n /**\n * Its first parameter's type, as written. Kept as the node and resolved after\n * the whole file is walked: a props interface is often declared *below* the\n * component that takes it.\n */\n propsType?: ts.TypeNode\n}\n\nexport const PACKAGE_IMPORT = '@estiva-app/ui'\n/** The editor corner (UIG-31): parts that import Tiptap, kept off the main entry. */\nexport const EDITOR_IMPORT = '@estiva-app/ui/editor'\n/** Whether an import names the package: its main entry, or its editor corner. */\nexport const isPackageImport = (specifier: string) => specifier === PACKAGE_IMPORT || specifier === EDITOR_IMPORT\n\n/**\n * Storybook's own `sanitize`, which is what turns a title and a story's export\n * name into the id in the URL. Copied rather than imported: `storybook` is a\n * dev dependency of this repo and must not become a runtime dependency of the\n * builder, which apps run. A test holds this to the ids a real Storybook build\n * produces.\n */\nexport function sanitize(name: string): string {\n return name\n .toLowerCase()\n .replace(/[ \u2019\u2013\u2014\u2015\u2032\u00BF'`~!@#$%^&*()_|+\\-=?;:'\",.<>{}[\\]\\\\/]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-+/, '')\n .replace(/-+$/, '')\n}\n\n/**\n * Storybook's `storyNameFromExport`, which is lodash's `startCase`: an export\n * called `WithCounts` is the story \"With Counts\", and its id is\n * `navigation-tabs--with-counts`, not `--withcounts`.\n *\n * Measured against a real `storybook build` (2026-09-18): without this, 11 of\n * the 81 ids resolved nowhere \u2014 every export whose name is more than one word.\n * Written out rather than pulled from lodash or `@storybook/csf`, neither of\n * which may become a runtime dependency of a builder that apps run.\n */\nfunction storyNameFromExport(key: string): string {\n return key\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/([a-zA-Z])([0-9])/g, '$1 $2')\n .replace(/([0-9])([a-zA-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .trim()\n}\n\nexport const toId = (title: string, name: string) => `${sanitize(title)}--${sanitize(storyNameFromExport(name))}`\n\n/** Read `src/index.ts`. Its `export { \u2026 } from './Sibling'` statements are the target set. */\nexport function readIndexExports(source: string): RawExport[] {\n const file = ts.createSourceFile('index.ts', source, ts.ScriptTarget.Latest, true)\n const found: RawExport[] = []\n for (const statement of file.statements) {\n if (!ts.isExportDeclaration(statement)) continue\n const from = statement.moduleSpecifier\n const clause = statement.exportClause\n if (!from || !ts.isStringLiteral(from) || !clause || !ts.isNamedExports(clause)) continue\n for (const element of clause.elements) {\n found.push({ name: element.name.text, module: from.text.replace(/^\\.\\//, ''), isType: statement.isTypeOnly || element.isTypeOnly })\n }\n }\n return found\n}\n\n/**\n * The doc comment immediately above a declaration, cleaned of its markers.\n * `''` when there is none.\n *\n * `headerPos` is where the **file's** own header comment starts, and a\n * declaration never gets to claim it. Measured: `Skeleton.tsx` opens with a\n * paragraph about the whole family and `export function SkeletonBar` follows it\n * directly, so the bar was given the family's description \u2014 right-looking, and\n * wrong. Refusing it turns that into a build failure with the export's name in\n * it, which is a line somebody then writes.\n */\nfunction docAbove(source: string, node: ts.Node, headerPos: number | null = null): string {\n const ranges = ts.getLeadingCommentRanges(source, node.getFullStart()) ?? []\n const jsdoc = ranges.filter((range) => source.slice(range.pos, range.pos + 3) === '/**').pop()\n if (!jsdoc) return ''\n if (headerPos !== null && jsdoc.pos === headerPos) return ''\n // Only a comment that sits against the declaration describes it: anything\n // with another statement between them is about something else. A `//` line\n // between is still its own \u2014 the written note an escape needs sits there, and\n // TypeScript attaches the doc comment through it too.\n const between = source.slice(jsdoc.end, node.getStart())\n if (between.replace(/\\/\\/[^\\n]*/g, '').trim() !== '') return ''\n return source\n .slice(jsdoc.pos, jsdoc.end)\n .split(/\\r?\\n/)\n .map((line) => line.trim().replace(/^\\/\\*\\*/, '').replace(/\\*\\/$/, '').replace(/^\\*/, '').trim())\n .join('\\n')\n .trim()\n}\n\n/**\n * The first sentence of a block of prose, which is the purpose.\n *\n * A sentence ends at `.`, `!` or `?` followed by a space and something that\n * starts a new one. A very short first sentence takes the next as well \u2014\n * \"A list of actions from a trigger.\" is a purpose; \"One row, two parts.\" is\n * not, on its own.\n */\nexport function firstSentence(prose: string): string {\n const flat = prose\n .split(/\\n\\s*\\n/)[0]\n .split('\\n')\n .filter((line) => !line.trim().startsWith('@'))\n .join(' ')\n .replace(/\\*\\*/g, '')\n .replace(/\\s+/g, ' ')\n .trim()\n const parts = flat.split(/(?<=[.!?])\\s+(?=[A-Z`'\"\u2018\u201C])/)\n let line = parts[0] ?? ''\n if (line.length < 40 && parts[1]) line = `${line} ${parts[1]}`\n return line.trim()\n}\n\n/** A page's opening paragraph: everything between its `# Heading` and the first blank line. */\nexport function pageOpening(mdx: string): string {\n const lines = mdx.split(/\\r?\\n/)\n const heading = lines.findIndex((line) => /^#\\s+\\S/.test(line))\n if (heading < 0) return ''\n const paragraph: string[] = []\n for (const line of lines.slice(heading + 1)) {\n const text = line.trim()\n if (text === '') {\n if (paragraph.length) break\n continue\n }\n // A canvas, an import or the next heading: the opening paragraph is over,\n // or there never was one.\n if (text.startsWith('<') || text.startsWith('#')) break\n paragraph.push(text)\n }\n return paragraph.join(' ')\n}\n\n/**\n * A property's name, however it is written.\n *\n * **A quoted name is a name.** `'aria-label'?: string` cannot be written as an\n * identifier, so a reader that takes identifiers only drops it \u2014 and with it\n * every accessible name this package declares. Found by comparing against\n * `react-docgen`, a parser with none of this one's assumptions: 13 props over\n * 10 files, two of them required (`Reaction`, `Toolbar`).\n */\nfunction propName(member: ts.TypeElement): string | null {\n if (!member.name) return null\n if (ts.isIdentifier(member.name) || ts.isStringLiteral(member.name)) return member.name.text\n return null\n}\n\n/** A union of string literals, following one local type alias if the property points at one. */\nfunction literalUnion(type: ts.TypeNode | undefined, aliases: Map<string, ts.TypeNode>, seen = new Set<string>()): string[] | null {\n if (!type) return null\n if (ts.isTypeReferenceNode(type) && ts.isIdentifier(type.typeName)) {\n const name = type.typeName.text\n if (seen.has(name)) return null\n seen.add(name)\n const alias = aliases.get(name)\n return alias ? literalUnion(alias, aliases, seen) : null\n }\n if (ts.isLiteralTypeNode(type) && ts.isStringLiteral(type.literal)) return [type.literal.text]\n if (!ts.isUnionTypeNode(type)) return null\n const values: string[] = []\n for (const member of type.types) {\n // `'small' | 'default' | undefined` is still a set of two words.\n if (member.kind === ts.SyntaxKind.UndefinedKeyword || member.kind === ts.SyntaxKind.NullKeyword) continue\n const inner = literalUnion(member, aliases, seen)\n if (!inner) return null\n values.push(...inner)\n }\n return values.length > 1 ? values : null\n}\n\n/** A type\u2019s finished props and word-choices, read by the module that declares them. */\nexport interface Resolved {\n props: EntryProp[]\n variants: EntryVariant[]\n}\n\n/**\n * Ask another file for a type it declares, already resolved. `specifier` is the\n * import as written (`./IconButton`, `@/lib/types`); the caller decides what it\n * points at, and answers `undefined` for anything outside the library it reads.\n */\nexport type Sibling = (specifier: string, typeName: string) => Resolved | undefined\n\nexport interface ReadOptions {\n /**\n * Whether a file with no comment of its own at the top lends the comment on\n * its first declaration to the file. The package: yes \u2014 `Skeleton.tsx`'s\n * family paragraph sits there, and taking it as `SkeletonBar`'s was wrong. An\n * app: no \u2014 a comment directly above a part is that part's, which is what a\n * person writing one expects; a file's own goes at the very top.\n */\n lendFirstComment?: boolean\n}\n\nexport function readModule(source: string, sibling: Sibling = () => undefined, { lendFirstComment = true }: ReadOptions = {}) {\n const file = ts.createSourceFile('module.tsx', source, ts.ScriptTarget.Latest, true)\n const declarations = new Map<string, Declared>()\n const aliases = new Map<string, ts.TypeNode>()\n const shapes = new Map<string, ts.TypeElement[]>()\n /** What each interface extends, as written \u2014 `Omit<IdentityMenuProps, 'compact'>` and all. */\n const bases = new Map<string, ts.ExpressionWithTypeArguments[]>()\n /** Which module each imported name came from. */\n const importedFrom = new Map<string, { specifier: string; imported: string }>()\n\n const propsTypeOf = (parameters: readonly ts.ParameterDeclaration[]): ts.TypeNode | undefined => parameters[0]?.type\n\n /**\n * The props type of `const X = \u2026`.\n *\n * A plain function expression carries it on its first parameter. `forwardRef`\n * carries it as its **second type argument** and leaves the inner function's\n * parameter bare \u2014 `TextInput`, whose `size` was missed until this read it.\n */\n const propsOfInitializer = (initializer: ts.Expression | undefined): ts.TypeNode | undefined => {\n if (!initializer) return undefined\n if (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer)) return propsTypeOf(initializer.parameters)\n if (ts.isCallExpression(initializer)) {\n const callee = ts.isPropertyAccessExpression(initializer.expression) ? initializer.expression.name.text : ts.isIdentifier(initializer.expression) ? initializer.expression.text : ''\n if (callee === 'forwardRef' && initializer.typeArguments?.[1]) return initializer.typeArguments[1]\n // `memo(function X({ \u2026 }: Props) { \u2026 })` and anything else that wraps a\n // function written out at the call.\n const wrapped = initializer.arguments.find((argument) => ts.isArrowFunction(argument) || ts.isFunctionExpression(argument))\n if (wrapped) return propsTypeOf((wrapped as ts.ArrowFunction | ts.FunctionExpression).parameters)\n }\n return undefined\n }\n\n /**\n * `const Row: FC<RowProps> = ({ \u2026 }) => \u2026` leaves the parameter bare: the\n * props are the annotation's type argument \u2014 `FC`, `FunctionComponent`,\n * `React.FC`, `React.FunctionComponent`.\n */\n const propsOfAnnotation = (type: ts.TypeNode | undefined): ts.TypeNode | undefined => {\n if (!type || !ts.isTypeReferenceNode(type)) return undefined\n const named = ts.isIdentifier(type.typeName) ? type.typeName.text : type.typeName.right.text\n return named === 'FC' || named === 'FunctionComponent' ? type.typeArguments?.[0] : undefined\n }\n\n // The file's header comment: the first `/**` above the first thing that is\n // not an import. It belongs to the file, whatever export happens to follow it.\n const opening = file.statements.find((statement) => !ts.isImportDeclaration(statement))\n const headerPos = opening ? ((ts.getLeadingCommentRanges(source, opening.getFullStart()) ?? []).find((range) => source.slice(range.pos, range.pos + 3) === '/**')?.pos ?? null) : null\n // A file that opens with its own comment, above its imports \u2014 Peek's and Ship's\n // way \u2014 has its header there, so the comment on its first declaration is that\n // declaration's own. Only a file with no such comment lends the first one it has.\n const topPos = file.statements[0] ? ((ts.getLeadingCommentRanges(source, file.statements[0].getFullStart()) ?? []).find((range) => source.slice(range.pos, range.pos + 3) === '/**')?.pos ?? null) : null\n // An app lends no comment to the file but one above its imports: in a file\n // with no imports the first comment sits on the first part, and is the part's.\n const aboveImports = !!file.statements[0] && ts.isImportDeclaration(file.statements[0])\n const refused = lendFirstComment ? (topPos ?? headerPos) : aboveImports ? topPos : null\n\n for (const statement of file.statements) {\n if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {\n const bindings = statement.importClause?.namedBindings\n if (bindings && ts.isNamedImports(bindings)) {\n for (const element of bindings.elements) importedFrom.set(element.name.text, { specifier: statement.moduleSpecifier.text, imported: (element.propertyName ?? element.name).text })\n }\n }\n // `export type { TopicRowProps } from './TopicRow'` hands a type on without\n // declaring it: a file that asks this one for it is sent on to the next.\n if (ts.isExportDeclaration(statement) && statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier) && statement.exportClause && ts.isNamedExports(statement.exportClause)) {\n for (const element of statement.exportClause.elements) importedFrom.set(element.name.text, { specifier: statement.moduleSpecifier.text, imported: (element.propertyName ?? element.name).text })\n }\n if (ts.isTypeAliasDeclaration(statement)) aliases.set(statement.name.text, statement.type)\n if (ts.isInterfaceDeclaration(statement)) {\n shapes.set(statement.name.text, [...statement.members])\n // The whole clause, not its name: `extends Omit<IdentityMenuProps,\n // 'compact'>` reads as the name `Omit` and loses both the type it wraps\n // and the key it drops.\n const extended = (statement.heritageClauses ?? []).flatMap((clause) => [...clause.types])\n if (extended.length) bases.set(statement.name.text, extended)\n }\n if (ts.isTypeAliasDeclaration(statement) && ts.isTypeLiteralNode(statement.type)) shapes.set(statement.name.text, [...statement.type.members])\n\n // Every top-level function, class and constant, exported or not. The package\n // exports at the declaration, so for it the two are the same; an app also\n // writes `function Row() {\u2026}` and `export { Row }` or `export default Row`\n // further down, and the name is still read here, with its comment and props.\n if (ts.isClassDeclaration(statement)) {\n // `class ErrorBoundary extends Component<Props, State>`: its props are the\n // first type argument of what it extends. `export default class extends \u2026`\n // has no name of its own, and is kept under `default`.\n const base = (statement.heritageClauses ?? []).find((clause) => clause.token === ts.SyntaxKind.ExtendsKeyword)?.types[0]\n const name = statement.name?.text ?? (ts.getModifiers(statement)?.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword) ? 'default' : null)\n if (name) declarations.set(name, { doc: docAbove(source, statement, refused), deprecated: false, propsType: base?.typeArguments?.[0] })\n continue\n }\n // `export default memo(() => \u2026)` and `export default function () {\u2026}`: a part\n // an app writes as its file's default, with no name of its own. Kept under\n // `default`, with its comment and its props.\n if (ts.isExportAssignment(statement) && !statement.isExportEquals && !ts.isIdentifier(statement.expression)) {\n declarations.set('default', { doc: docAbove(source, statement, refused), deprecated: false, propsType: propsOfInitializer(statement.expression) })\n continue\n }\n if (ts.isFunctionDeclaration(statement) && !statement.name && ts.getModifiers(statement)?.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword)) {\n declarations.set('default', { doc: docAbove(source, statement, refused), deprecated: false, propsType: propsTypeOf(statement.parameters) })\n continue\n }\n if (!ts.isFunctionDeclaration(statement) && !ts.isVariableStatement(statement)) continue\n const doc = docAbove(source, statement, refused)\n const deprecated = /(^|\\n)@deprecated\\b/.test(doc) || /\\*\\s*@deprecated\\b/.test(source.slice(Math.max(0, statement.getFullStart()), statement.getStart()))\n\n if (ts.isFunctionDeclaration(statement) && statement.name) {\n // Overloads: the first signature carries the comment and the props a caller\n // sees; a later one, or the body, only fills in a comment the first lacks.\n const held = declarations.get(statement.name.text)\n if (held) {\n if (!held.doc && doc) held.doc = doc\n continue\n }\n declarations.set(statement.name.text, { doc, deprecated, propsType: propsTypeOf(statement.parameters) })\n continue\n }\n if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name)) continue\n declarations.set(declaration.name.text, { doc, deprecated, propsType: propsOfInitializer(declaration.initializer) ?? propsOfAnnotation(declaration.type) })\n }\n }\n }\n /**\n * A type's props and its word-choices, **resolved in the file that declares\n * them**.\n *\n * This is the whole shape of the thing, and the reason for it is a bug that\n * looked like nothing: a `ts.TypeElement` carries positions into *its own*\n * source text, so handing a sibling's node to this file's `getText`, `aliases`\n * and `docAbove` reads the wrong file at those offsets. `ToolbarButton` came\n * out with `variant: \"ats over what it a\"` and `children: \"omeAndEndK\"` \u2014\n * real prop names, and slices of another file for their types. Nothing caught\n * it: the names were right, and the cross-check against `react-docgen`\n * compared names.\n *\n * So a sibling never returns nodes. It returns finished props, read by the\n * module that owns them, and this file only merges them.\n */\n const EMPTY: Resolved = { props: [], variants: [] }\n\n /** The keys named by an `Omit`/`Pick` argument: `'a'` or `'a' | 'b'`. */\n const keysOf = (type: ts.TypeNode | undefined): string[] | null => {\n if (!type) return null\n if (ts.isLiteralTypeNode(type) && ts.isStringLiteral(type.literal)) return [type.literal.text]\n if (!ts.isUnionTypeNode(type)) return null\n const keys: string[] = []\n for (const member of type.types) {\n if (!ts.isLiteralTypeNode(member) || !ts.isStringLiteral(member.literal)) return null\n keys.push(member.literal.text)\n }\n return keys\n }\n\n /** `Omit` drops the keys it names, `Pick` keeps only them. Unreadable keys change nothing. */\n const narrow = (resolved: Resolved, how: 'Omit' | 'Pick', keys: string[] | null): Resolved => {\n if (!keys) return resolved\n const named = new Set(keys)\n const keep = (name: string) => (how === 'Omit' ? !named.has(name) : named.has(name))\n return { props: resolved.props.filter((prop) => keep(prop.name)), variants: resolved.variants.filter((variant) => keep(variant.prop)) }\n }\n\n /** The first of each name wins, so what a type declares itself beats what it inherits. */\n const merge = (parts: Resolved[]): Resolved => {\n const props: EntryProp[] = []\n const variants: EntryVariant[] = []\n const seenProp = new Set<string>()\n const seenVariant = new Set<string>()\n for (const part of parts) {\n for (const prop of part.props) if (!seenProp.has(prop.name)) (seenProp.add(prop.name), props.push(prop))\n for (const variant of part.variants) if (!seenVariant.has(variant.prop)) (seenVariant.add(variant.prop), variants.push(variant))\n }\n return { props, variants }\n }\n\n /**\n * What a prop takes, in a word a person reads. The type as written is the\n * fallback, not the answer: `(next: string) => void` tells a reader nothing\n * they cannot guess, and \"a handler\" tells them what to pass.\n */\n const takes = (type: ts.TypeNode | undefined, values: string[] | null): string => {\n if (values) return values.join(' | ')\n if (!type) return 'anything'\n const written = type.getText(file).replace(/\\s+/g, ' ').trim()\n if (written === 'boolean') return 'true/false'\n if (written === 'number') return 'number'\n if (written === 'string') return 'text'\n if (/^React(Node|Element)\\b/.test(written)) return 'anything'\n if (written.includes('=>')) return 'a handler'\n return written.length > 60 ? `${written.slice(0, 57)}\u2026` : written\n }\n\n /** Members of this file, read with this file's text and aliases. */\n const fromMembers = (members: readonly ts.TypeElement[]): Resolved => {\n const props: EntryProp[] = []\n const variants: EntryVariant[] = []\n for (const member of members) {\n const name = propName(member)\n if (name === null || !ts.isPropertySignature(member)) continue\n const values = literalUnion(member.type, aliases)\n const note = firstSentence(docAbove(source, member))\n props.push({ name, takes: takes(member.type, values), required: !member.questionToken, note: note || null })\n if (values) variants.push({ prop: name, values })\n }\n return { props, variants }\n }\n\n const resolveNode = (type: ts.TypeNode | undefined, seen: Set<string>): Resolved => {\n if (!type || seen.size > 12) return EMPTY\n // `{ tone?: 'primary' | 'secondary' }` written out at the parameter.\n if (ts.isTypeLiteralNode(type)) return fromMembers(type.members)\n if (ts.isIntersectionTypeNode(type)) return merge(type.types.map((side) => resolveNode(side, seen)))\n if (ts.isTypeReferenceNode(type) && ts.isIdentifier(type.typeName)) {\n const named = type.typeName.text\n if (named === 'Omit' || named === 'Pick') {\n return narrow(resolveNode(type.typeArguments?.[0], seen), named, keysOf(type.typeArguments?.[1]))\n }\n return resolveName(named, seen)\n }\n return EMPTY\n }\n\n /** A heritage clause is not a `TypeNode`, and carries the same `Omit<\u2026>` shapes. */\n const resolveBase = (base: ts.ExpressionWithTypeArguments, seen: Set<string>): Resolved => {\n if (!ts.isIdentifier(base.expression)) return EMPTY\n const named = base.expression.text\n if (named === 'Omit' || named === 'Pick') {\n return narrow(resolveNode(base.typeArguments?.[0], seen), named, keysOf(base.typeArguments?.[1]))\n }\n return resolveName(named, seen)\n }\n\n /**\n * A named type: its own props, plus everything it extends **within this\n * package**.\n *\n * It stops at React and Base UI on purpose. `ToolbarButtonProps extends\n * IconButtonProps` is ours, and `variant`, `pressed` and `tooltip` are things\n * `ToolbarButton` genuinely takes; `ButtonProps extends\n * ComponentPropsWithRef<'button'>` is the DOM, and listing `onCopy` and\n * `spellCheck` would bury the answer. The rule is where the type is declared,\n * not what it is called.\n */\n function resolveName(name: string, seen: Set<string>): Resolved {\n if (seen.has(name) || seen.size > 12) return EMPTY\n seen.add(name)\n const own = shapes.get(name)\n if (own) {\n const inherited = (bases.get(name) ?? []).map((base) => resolveBase(base, seen))\n return merge([fromMembers(own), ...inherited])\n }\n // `type ToolbarInputProps = TextInputProps` \u2014 an alias, not an interface.\n const alias = aliases.get(name)\n if (alias) return resolveNode(alias, seen)\n // Not declared here at all. Follow the import; the caller says where it may go.\n const from = importedFrom.get(name)\n return (from ? sibling(from.specifier, from.imported) : undefined) ?? EMPTY\n }\n\n /** What one declaration's first parameter takes. */\n const resolve = (propsType: ts.TypeNode | undefined): Resolved => resolveNode(propsType, new Set())\n\n // The file's own description, for an app's file of one part: the first `/**`\n // at the very top, above the imports \u2014 where Peek and Ship write it \u2014 or else\n // the one directly above the first thing that is not an import.\n const jsdocAt = (node: ts.Node | undefined) => (node ? (ts.getLeadingCommentRanges(source, node.getFullStart()) ?? []).find((range) => source.slice(range.pos, range.pos + 3) === '/**') : undefined)\n const headerRange = jsdocAt(file.statements[0]) ?? jsdocAt(opening)\n return { declarations, headerDoc: headerRange ? headerComment(source, headerRange) : '', resolve, resolveName: (name: string) => resolveName(name, new Set()) }\n}\n\n/** The file's own header comment, cleaned the way `docAbove` cleans a declaration's. */\nfunction headerComment(source: string, range: ts.CommentRange): string {\n return source\n .slice(range.pos, range.end)\n .split(/\\r?\\n/)\n .map((line) => line.trim().replace(/^\\/\\*\\*/, '').replace(/\\*\\/$/, '').replace(/^\\*/, '').trim())\n .join('\\n')\n .trim()\n}\n\n/** The `title` a stories file gives Storybook, and the stories it exports. */\nexport function readStories(source: string): { title: string | null; stories: string[] } {\n const file = ts.createSourceFile('x.stories.tsx', source, ts.ScriptTarget.Latest, true)\n let title: string | null = null\n const stories: string[] = []\n for (const statement of file.statements) {\n if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (!ts.isIdentifier(declaration.name)) continue\n const initializer = declaration.initializer\n const object = initializer && ts.isSatisfiesExpression(initializer) ? initializer.expression : initializer\n if (declaration.name.text === 'meta' && object && ts.isObjectLiteralExpression(object)) {\n for (const property of object.properties) {\n if (ts.isPropertyAssignment(property) && ts.isIdentifier(property.name) && property.name.text === 'title' && ts.isStringLiteral(property.initializer)) {\n title = property.initializer.text\n }\n }\n }\n const exported = ts.getModifiers(statement)?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)\n if (exported && declaration.name.text !== 'meta') stories.push(declaration.name.text)\n }\n }\n }\n return { title, stories }\n}\n\nconst isAllCaps = (name: string) => /^[A-Z0-9_]+$/.test(name)\n\n/** What a name is. A constant and a function are both helpers; only a `use\u2026` is a hook. */\nfunction kindOf(name: string): EntryKind {\n if (/^use[A-Z]/.test(name)) return 'hook'\n return /^[A-Z]/.test(name) && !isAllCaps(name) ? 'component' : 'helper'\n}\n\n/** What UIG-8's enumeration says this component owns. */\nfunction behavioursOf(name: string): EntryBehaviour[] {\n return OWNED_BEHAVIOURS.filter((owned) => owned.owners.includes(name)).map((owned) => ({ id: owned.id, behaviour: owned.behaviour }))\n}\n\n/**\n * Read the repository and return the catalogue.\n *\n * Throws on anything it cannot explain \u2014 a missing sibling, a name with no\n * purpose anywhere. A registry that quietly drops what it could not read is\n * worse than no registry, because a reader cannot tell the difference between\n * \"we have nothing for that\" and \"the builder gave up\".\n */\nexport function buildRegistry({ root = process.cwd(), repo = 'estiva-ui' }: BuildOptions = {}): Registry {\n const src = join(root, 'src')\n const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')) as { name: string; version: string }\n const files = new Set(readdirSync(src))\n // Two entries: the main one, and the editor corner beside it (UIG-31), whose\n // parts are imported from their own path.\n const fromEntry = (file: string, importPath: string) =>\n existsSync(join(src, file)) ? readIndexExports(readFileSync(join(src, file), 'utf8')).map((entry) => ({ ...entry, importPath })) : []\n const exported = [...fromEntry('index.ts', PACKAGE_IMPORT), ...fromEntry('editor.ts', EDITOR_IMPORT)]\n const values = exported.filter((entry) => !entry.isType)\n\n type Module = ReturnType<typeof readModule> & { file: string }\n const modules = new Map<string, Module>()\n const moduleOf = (name: string): Module => {\n const held = modules.get(name)\n if (held) return held\n const file = ['.tsx', '.ts'].map((extension) => `${name}${extension}`).find((candidate) => files.has(candidate))\n if (!file) throw new Error(`src/index.ts exports from './${name}', which is not a file in src/`)\n // The callback lets one file's props type reach a type declared in another\n // \u2014 `ToolbarButtonProps extends IconButtonProps`. It is only called later,\n // by which time this module is in the cache, so the recursion terminates.\n const read = { ...readModule(readFileSync(join(src, file), 'utf8'), (specifier, typeName) => (specifier.startsWith('./') ? moduleOf(specifier.slice(2)).resolveName(typeName) : undefined)), file: `src/${file}` }\n modules.set(name, read)\n return read\n }\n\n const problems: string[] = []\n const entries: RegistryEntry[] = []\n // What each part looks like (UIG-25), read once per file.\n const looksCache = new Map<string, ReturnType<typeof parseForLooks>>()\n const looksFor = (file: string, name: string) => {\n if (!looksCache.has(file)) looksCache.set(file, parseForLooks(join(src, file.replace(/^src\\//, '')), readFileSync(join(src, file.replace(/^src\\//, '')), 'utf8')))\n return looksOf(looksCache.get(file)!, [name]).get(name) ?? []\n }\n\n for (const value of values) {\n const module = moduleOf(value.module)\n const declared = module.declarations.get(value.name)\n if (!declared) {\n problems.push(`${value.name} is exported from './${value.module}' but is not declared there`)\n continue\n }\n\n // A name with a page of its own takes its purpose from the page; the rest\n // are documented on a sibling's page, and take it from the comment above\n // the export. Every one of them has one \u2014 the build fails below if not.\n const pageFile = files.has(`${value.name}.mdx`) ? `src/${value.name}.mdx` : null\n const fromPage = pageFile ? firstSentence(pageOpening(readFileSync(join(root, pageFile), 'utf8'))) : ''\n const fromComment = firstSentence(declared.doc)\n const purpose = fromPage || fromComment\n if (!purpose) {\n problems.push(`${value.name} has no purpose: no opening paragraph on its page, and no doc comment above it in ${module.file}`)\n continue\n }\n\n // A name with stories of its own uses them; otherwise the sibling's, which\n // is the page that documents it.\n const storiesFile = files.has(`${value.name}.stories.tsx`) ? `${value.name}.stories.tsx` : files.has(`${value.module}.stories.tsx`) ? `${value.module}.stories.tsx` : null\n const stories = storiesFile ? readStories(readFileSync(join(src, storiesFile), 'utf8')) : { title: null, stories: [] }\n const title = stories.title\n const story = stories.stories.includes(value.name) ? value.name : stories.stories[0]\n\n const shape = module.resolve(declared.propsType)\n\n entries.push({\n name: value.name,\n repo,\n kind: kindOf(value.name),\n importPath: value.importPath,\n sourceFile: module.file,\n purpose,\n purposeFrom: fromPage ? 'page' : 'comment',\n props: shape.props,\n variants: shape.variants,\n ownsBehaviours: behavioursOf(value.name),\n status: declared.deprecated ? 'deprecated' : 'stable',\n migrationStage: null,\n docsId: title ? `${sanitize(title)}--docs` : null,\n storyId: title && story ? toId(title, story) : null,\n docPage: pageFile,\n app: null,\n looks: kindOf(value.name) === 'component' ? looksFor(module.file, value.name) : [],\n })\n }\n\n if (problems.length) throw new Error(`the registry cannot be built:\\n ${problems.join('\\n ')}`)\n\n // What each part owns, from what it draws (B9): the Base UI parts in it, and\n // every part of the package inside it, followed; UIG-8's list is the floor.\n const moduleByName = new Map(values.map((v) => [v.name, v.module]))\n const drawing = new Map<string, { drawn: Map<string, Set<string>>; roots: Map<string, Set<string>>; imports: ReturnType<typeof importsOf> }>()\n const drawingOf = (moduleName: string) => {\n if (!drawing.has(moduleName)) {\n const file = moduleOf(moduleName).file\n const sf = ts.createSourceFile(file, readFileSync(join(root, file), 'utf8'), ts.ScriptTarget.Latest, true, file.endsWith('x') ? ts.ScriptKind.TSX : ts.ScriptKind.TS)\n drawing.set(moduleName, { drawn: drawnIn(sf), roots: rootsIn(sf), imports: importsOf(sf) })\n }\n return drawing.get(moduleName)!\n }\n const owns = (name: string, seen: Set<string>): Set<string> => {\n const out = new Set(behavioursOf(name).map((b) => b.id))\n const moduleName = moduleByName.get(name)\n if (!moduleName || seen.has(name)) return out\n seen.add(name)\n const { drawn, roots, imports } = drawingOf(moduleName)\n // The Base UI parts it draws, anywhere in it.\n for (const tag of drawn.get(name) ?? []) {\n const [local, piece] = splitTag(tag)\n const from = imports.get(local)\n if (from && isBaseUi(from.specifier)) for (const id of baseUiBehaviours(from.imported, piece)) out.add(id)\n }\n // The parts it is: what it hands back at its root.\n for (const tag of roots.get(name) ?? []) {\n const [local] = splitTag(tag)\n const from = imports.get(local)\n const part = from?.specifier.startsWith('./') ? from.imported : !from && local !== name ? local : undefined\n if (part && moduleByName.has(part)) for (const id of handedOn(part, owns(part, seen))) out.add(id)\n }\n return out\n }\n for (const entry of entries) if (entry.kind === 'component') entry.ownsBehaviours = asBehaviours(owns(entry.name, new Set()))\n\n entries.sort((a, b) => a.name.localeCompare(b.name))\n\n return {\n schemaVersion: SCHEMA_VERSION,\n builtFrom: {\n kind: 'package',\n repo,\n package: manifest.name,\n packageVersion: manifest.version,\n exports: values.length,\n typeExports: exported.length - values.length,\n files: null,\n },\n storybook: {\n docsPath: '/?path=/docs/{docsId}',\n storyPath: '/?path=/story/{storyId}',\n devUrl: 'http://localhost:6008',\n },\n entries,\n // Nothing is excluded: every value export is an entry, helpers and the one\n // hook included, each marked by `kind`. The field stays because the count\n // has to reconcile out loud \u2014 see validateRegistry.\n excluded: [],\n filesWithoutParts: [],\n }\n}\n\n/** The committed file's text, so a check and a write produce the same bytes. */\nexport function serializeRegistry(registry: Registry): string {\n return `${JSON.stringify(registry, null, 2)}\\n`\n}\n", "/**\n * What a part owns, worked out from what it draws (Katerina's ruling B9,\n * 25 September).\n *\n * The plan's Gate 0 asked for \"the behaviours it owns \u2014 derived from which Base\n * UI parts it imports\". Until 0.36.0 only \"is built on Base UI\" was; the rest\n * was UIG-8's hand list of owners, which is right for the part that does the\n * work and silent for every part built from it: ConfirmDialog draws DialogShell,\n * whose page says it keeps focus inside, and the catalogue listed no focus for\n * ConfirmDialog. Every app entry listed nothing at all.\n *\n * Now a part owns:\n *\n * - what the Base UI parts it draws do, from UIG-8's enumeration (`baseUi` on\n * each behaviour, read from Base UI's source): all of it for a whole part\n * (`Menu.Root`), what it is for a piece (`Menu.Item`);\n * - what the whole of the part it **is** does (floating, focus, keys, scroll):\n * the part it hands back at its root, followed through parts inside parts, in\n * the package and in an app. ConfirmDialog returns a DialogShell, so it keeps\n * focus inside; a page with a menu somewhere in it does not float, and a\n * tooltip's floating stays the tooltip's;\n * - and, in the package, what UIG-8's list says (the floor: a part like `Link`\n * is reachable with Tab without any Base UI in it).\n *\n * Read from the code: a JSX tag inside the part's own declaration, or inside a\n * function of the same file it draws. A root on one branch of a condition\n * still counts, so the list says what a part can be, not what one screen shows.\n */\nimport ts from 'typescript'\nimport { OWNED_BEHAVIOURS } from '../eslint/index'\nimport type { EntryBehaviour } from './schema'\n\n/** `@base-ui/react`, its sub-paths, and the old `@base-ui-components/react` spelling. */\nexport const isBaseUi = (specifier: string) => /^@base-ui(?:-components)?\\/react(?:\\/|$)/.test(specifier)\n\n/**\n * What drawing a Base UI part gives, by behaviour id. The whole part (`Menu.Root`,\n * or a part of one piece: `<Separator>`, `<Toggle>`) does all UIG-8 lists for it;\n * a piece of one (`Menu.Item`, `Toolbar.Button`) only says what it is.\n */\nexport function baseUiBehaviours(part: string, piece?: string): string[] {\n const whole = !piece || piece === 'Root' || piece === 'Provider'\n return OWNED_BEHAVIOURS.filter((owned) => owned.id === 'base-ui' || (owned.baseUi.includes(part) && (whole || owned.id === 'role'))).map((owned) => owned.id)\n}\n\n/**\n * What a part hands on to the parts drawn around it: what the whole thing does.\n * Being built on Base UI, a role and a Tab stop stay the inner part's: a banner\n * with a button in it is not itself reachable with Tab.\n */\nexport const HANDED_ON = new Set(['portal', 'press-outside', 'page-keys', 'focus', 'scroll-lock', 'follow', 'scroll'])\n\n/** A hint drawn beside a part: its floating is its own, never the part's. */\nexport const HINTS = new Set(['Tooltip', 'WithTooltip', 'TooltipProvider', 'PreviewCard'])\n\n/** What a part drawn inside another hands on to it. */\nexport const handedOn = (name: string, owned: Iterable<string>) => (HINTS.has(name) ? [] : [...owned].filter((id) => HANDED_ON.has(id)))\n\n/** Behaviour ids as the catalogue writes them: in UIG-8's order, each once. */\nexport function asBehaviours(ids: Iterable<string>): EntryBehaviour[] {\n const held = new Set(ids)\n return OWNED_BEHAVIOURS.filter((owned) => held.has(owned.id)).map((owned) => ({ id: owned.id, behaviour: owned.behaviour }))\n}\n\n/** A tag as written: `Dialog.Popup`, `Button`. */\nfunction tagText(tag: ts.JsxTagNameExpression): string | null {\n if (ts.isIdentifier(tag)) return tag.text\n if (ts.isPropertyAccessExpression(tag)) {\n const inner = tagText(tag.expression as ts.JsxTagNameExpression)\n return inner && `${inner}.${tag.name.text}`\n }\n return null\n}\n\n/** A tag's name and its piece: `['Dialog', 'Popup']`, `['Button', undefined]`. */\nexport const splitTag = (tag: string): [string, string | undefined] => {\n const [root, piece] = tag.split('.')\n return [root, piece]\n}\n\n/** Every tag drawn anywhere under `node`, as written. */\nfunction tagsUnder(node: ts.Node): Set<string> {\n const found = new Set<string>()\n const visit = (n: ts.Node) => {\n if (ts.isJsxOpeningElement(n) || ts.isJsxSelfClosingElement(n)) {\n const tag = tagText(n.tagName)\n if (tag && /^[A-Z]/.test(tag)) found.add(tag)\n }\n ts.forEachChild(n, visit)\n }\n visit(node)\n return found\n}\n\n/**\n * For each name a file declares at its top (a function, a `const`, a class):\n * the tags drawn inside it, with the file's own functions it draws followed, so\n * what is left are names the file imports or declares without a body.\n */\nexport function drawnIn(sf: ts.SourceFile): Map<string, Set<string>> {\n const direct = new Map<string, Set<string>>()\n for (const statement of sf.statements) {\n if ((ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name) direct.set(statement.name.text, tagsUnder(statement))\n else if (ts.isVariableStatement(statement)) {\n for (const d of statement.declarationList.declarations) if (ts.isIdentifier(d.name) && d.initializer) direct.set(d.name.text, tagsUnder(d.initializer))\n }\n }\n const closed = new Map<string, Set<string>>()\n for (const name of direct.keys()) {\n const out = new Set<string>()\n const seen = new Set([name])\n const stack = [name]\n while (stack.length) {\n for (const tag of direct.get(stack.pop() as string) ?? []) {\n out.add(tag)\n if (direct.has(tag) && !seen.has(tag)) {\n seen.add(tag)\n stack.push(tag)\n }\n }\n }\n closed.set(name, out)\n }\n return closed\n}\n\n/** The tags an expression hands back at its top: both sides of a condition, never a fragment's children. */\nfunction rootsOfExpression(e: ts.Node | undefined, out: Set<string>): void {\n if (!e) return\n if (ts.isParenthesizedExpression(e) || ts.isAsExpression(e) || ts.isSatisfiesExpression(e) || ts.isNonNullExpression(e)) return rootsOfExpression(e.expression, out)\n if (ts.isConditionalExpression(e)) {\n rootsOfExpression(e.whenTrue, out)\n rootsOfExpression(e.whenFalse, out)\n return\n }\n if (ts.isBinaryExpression(e)) {\n if (e.operatorToken.kind !== ts.SyntaxKind.AmpersandAmpersandToken) rootsOfExpression(e.left, out)\n rootsOfExpression(e.right, out)\n return\n }\n // A fragment is several things side by side (a page and the dialog it opens):\n // the part is none of them alone.\n if (ts.isJsxFragment(e)) return\n const tag = ts.isJsxElement(e) ? tagText(e.openingElement.tagName) : ts.isJsxSelfClosingElement(e) ? tagText(e.tagName) : null\n if (tag && /^[A-Z]/.test(tag)) out.add(tag)\n}\n\n/** The tags a function hands back: every `return`, or an arrow's body, never a nested function's. */\nfunction rootsOfFunction(fn: ts.Node): Set<string> {\n const out = new Set<string>()\n if (ts.isArrowFunction(fn) && !ts.isBlock(fn.body)) rootsOfExpression(fn.body, out)\n const visit = (n: ts.Node) => {\n if (n !== fn && (ts.isFunctionLike(n) || ts.isClassLike(n))) return\n if (ts.isReturnStatement(n)) rootsOfExpression(n.expression, out)\n ts.forEachChild(n, visit)\n }\n visit(fn)\n return out\n}\n\n/** The function a declaration's value is: itself, or the one inside `forwardRef(\u2026)`, `memo(\u2026)`. */\nfunction functionOf(node: ts.Node | undefined): ts.Node | undefined {\n if (!node) return undefined\n if (ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node) || ts.isArrowFunction(node)) return node\n if (ts.isParenthesizedExpression(node) || ts.isAsExpression(node) || ts.isSatisfiesExpression(node)) return functionOf(node.expression)\n if (ts.isCallExpression(node)) for (const argument of node.arguments) {\n const fn = functionOf(argument)\n if (fn) return fn\n }\n return undefined\n}\n\n/**\n * For each function a file declares at its top: the parts it **is** \u2014 the tags it\n * hands back at its root, following the file's own functions it hands back.\n * `ConfirmDialog` returns a `DialogShell`, so it is one; a page with a menu\n * somewhere in it is not a menu.\n */\nexport function rootsIn(sf: ts.SourceFile): Map<string, Set<string>> {\n const direct = new Map<string, Set<string>>()\n for (const statement of sf.statements) {\n if (ts.isFunctionDeclaration(statement) && statement.name) direct.set(statement.name.text, rootsOfFunction(statement))\n else if (ts.isVariableStatement(statement)) {\n for (const d of statement.declarationList.declarations) {\n const fn = functionOf(d.initializer)\n if (ts.isIdentifier(d.name) && fn) direct.set(d.name.text, rootsOfFunction(fn))\n }\n }\n }\n const closed = new Map<string, Set<string>>()\n for (const name of direct.keys()) {\n const out = new Set<string>()\n const seen = new Set([name])\n const stack = [name]\n while (stack.length) {\n for (const tag of direct.get(stack.pop() as string) ?? []) {\n if (direct.has(tag)) {\n if (!seen.has(tag)) {\n seen.add(tag)\n stack.push(tag)\n }\n } else out.add(tag)\n }\n }\n closed.set(name, out)\n }\n return closed\n}\n\n/** Each imported value name \u2192 where it came from. */\nexport function importsOf(sf: ts.SourceFile): Map<string, { specifier: string; imported: string }> {\n const out = new Map<string, { specifier: string; imported: string }>()\n for (const statement of sf.statements) {\n if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) continue\n const clause = statement.importClause\n if (!clause || clause.isTypeOnly) continue\n const specifier = statement.moduleSpecifier.text\n if (clause.name) out.set(clause.name.text, { specifier, imported: 'default' })\n const bindings = clause.namedBindings\n if (bindings && ts.isNamedImports(bindings)) for (const e of bindings.elements) if (!e.isTypeOnly) out.set(e.name.text, { specifier, imported: (e.propertyName ?? e.name).text })\n }\n return out\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"],
5
+ "mappings": "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",
6
+ "names": ["existsSync", "readFileSync", "join", "ts", "OWNED_BEHAVIOURS", "ts", "ts", "ts", "line", "OWNED_BEHAVIOURS", "join", "readFileSync", "existsSync"]
7
+ }
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- PACKAGE_IMPORT,
4
3
  asBehaviours,
5
4
  baseUiBehaviours,
6
5
  drawnIn,
7
6
  firstSentence,
8
7
  handedOn,
9
8
  isBaseUi,
9
+ isPackageImport,
10
10
  looksOf,
11
11
  pageOpening,
12
12
  parseForLooks,
@@ -15,7 +15,7 @@ import {
15
15
  sanitize,
16
16
  splitTag,
17
17
  toId
18
- } from "./chunk-SIB44CES.js";
18
+ } from "./chunk-P55P2QFD.js";
19
19
  import {
20
20
  SCHEMA_VERSION
21
21
  } from "./chunk-PZO4BVV3.js";
@@ -510,7 +510,7 @@ function buildAppRegistry({ root = process.cwd(), repo, packageRegistry, package
510
510
  const held = modules.get(file);
511
511
  if (held) return held;
512
512
  const read = readModule(facts.get(file).source, (specifier, typeName) => {
513
- if (specifier === PACKAGE_IMPORT) {
513
+ if (isPackageImport(specifier)) {
514
514
  const part = typeName.endsWith("Props") ? theRegistry?.entries.find((entry) => entry.name === typeName.slice(0, -"Props".length)) : void 0;
515
515
  return part ? { props: part.props, variants: part.variants } : void 0;
516
516
  }
@@ -537,7 +537,7 @@ function buildAppRegistry({ root = process.cwd(), repo, packageRegistry, package
537
537
  if (held) return held;
538
538
  const out = /* @__PURE__ */ new Set();
539
539
  if (p.from) {
540
- if (p.from.specifier === PACKAGE_IMPORT) for (const id of packageOwns.get(p.from.name) ?? []) out.add(id);
540
+ if (isPackageImport(p.from.specifier)) for (const id of packageOwns.get(p.from.name) ?? []) out.add(id);
541
541
  return out;
542
542
  }
543
543
  const f = facts.get(p.file);
@@ -555,7 +555,7 @@ function buildAppRegistry({ root = process.cwd(), repo, packageRegistry, package
555
555
  const from = imported.get(splitTag(tag)[0]);
556
556
  if (!from) continue;
557
557
  let inner = [];
558
- if (from.link.specifier === PACKAGE_IMPORT) inner = handedOn(from.imported, packageOwns.get(from.imported) ?? []);
558
+ if (isPackageImport(from.link.specifier)) inner = handedOn(from.imported, packageOwns.get(from.imported) ?? []);
559
559
  else if (from.link.target && from.link.target !== "?") {
560
560
  const part = origin(from.link.target, from.imported);
561
561
  if (part) inner = handedOn(part.from?.name ?? part.name, ownsOf(part, seen));
@@ -582,7 +582,7 @@ function buildAppRegistry({ root = process.cwd(), repo, packageRegistry, package
582
582
  let purposeFrom = "comment";
583
583
  if (pass) {
584
584
  const as = pass.name === p.name ? "" : ` as ${p.name}`;
585
- purpose = pass.specifier === PACKAGE_IMPORT ? `The package's ${pass.name}, handed on${as} so the app can import it from ${importPathOf(p.file)}.` : `${pass.name} from ${pass.specifier}, handed on${as} so the app can import it from ${importPathOf(p.file)}.`;
585
+ purpose = isPackageImport(pass.specifier) ? `The package's ${pass.name}, handed on${as} so the app can import it from ${importPathOf(p.file)}.` : `${pass.name} from ${pass.specifier}, handed on${as} so the app can import it from ${importPathOf(p.file)}.`;
586
586
  purposeFrom = "package";
587
587
  } else if (firstSentence(pageText)) {
588
588
  purpose = firstSentence(pageText);
@@ -604,7 +604,7 @@ function buildAppRegistry({ root = process.cwd(), repo, packageRegistry, package
604
604
  let written = false;
605
605
  if (pass) {
606
606
  cls = "re-export";
607
- reason = `Its file only hands on ${pass.specifier === PACKAGE_IMPORT ? `the package's ${pass.name}` : `${pass.name} from ${pass.specifier}`}.`;
607
+ reason = `Its file only hands on ${isPackageImport(pass.specifier) ? `the package's ${pass.name}` : `${pass.name} from ${pass.specifier}`}.`;
608
608
  if (writtenLine) problems.push(`${p.name} in ${p.file} is a pass-on, so its kind is read from the file: remove "@registry ${writtenLine[1]}"`);
609
609
  } else if (writtenLine) {
610
610
  const said = writtenLine[1];
@@ -633,10 +633,10 @@ function buildAppRegistry({ root = process.cwd(), repo, packageRegistry, package
633
633
  class: cls,
634
634
  reason,
635
635
  written,
636
- handsOn: pass ? pass.specifier === PACKAGE_IMPORT ? pass.name : `${pass.name} from ${pass.specifier}` : null,
636
+ handsOn: pass ? isPackageImport(pass.specifier) ? pass.name : `${pass.name} from ${pass.specifier}` : null,
637
637
  usedIn,
638
638
  tiedTo: ties,
639
- packageNamesake: namesakes.has(p.name) && !(pass && pass.specifier === PACKAGE_IMPORT && pass.name === p.name) ? p.name : null,
639
+ packageNamesake: namesakes.has(p.name) && !(pass && isPackageImport(pass.specifier) && pass.name === p.name) ? p.name : null,
640
640
  defaultExport: p.defaultExport
641
641
  };
642
642
  const found2 = pass ? { docsId: null, storyId: null } : storyOf(p);
@@ -697,4 +697,4 @@ function buildAppRegistry({ root = process.cwd(), repo, packageRegistry, package
697
697
  export {
698
698
  buildAppRegistry
699
699
  };
700
- //# sourceMappingURL=chunk-EVJW26UR.js.map
700
+ //# sourceMappingURL=chunk-TQ6UQER3.js.map