{"version":3,"sources":["../src/index.ts","../src/validate.ts","../src/generate-site.ts","../src/doclet.ts","../src/class-view.ts","../src/mdast/class-view.ts","../src/mdast/builders.ts","../src/embed.ts","../src/mdast/from-html.ts","../src/playground.ts","../src/slots.ts","../src/mdast/doclet.ts","../src/mdast/link-tags.ts","../src/mdx.ts","../src/link-registry.ts","../src/guide-view.ts","../src/source-view.ts"],"sourcesContent":["import { validateCollectionOrThrow } from './validate';\nimport {\n  assembleNav,\n  buildGlobalsView,\n  computeBuildId,\n  enumerateLongnamesByKind,\n  makePlaygroundResolver,\n  renderContainerPage,\n  splitLongnameForSlug,\n  type MenuItem,\n  type PlaygroundSiteConfig,\n} from './generate-site';\nimport { getContainerView, mergeContainerViews, type ContainerView } from './class-view';\nimport {\n  resolveCollapsibleSections,\n  slugifyPath,\n  topLevelSectionLabels,\n  type CollapsibleSidebarSections,\n} from '@clean-jsdoc-theme/utils';\nimport { makeLinkResolver, registerContainerView, type LinkRegistry } from './link-registry';\nimport {\n  buildDocPages,\n  buildReadmePage,\n  buildTutorialPages,\n  composeResolvers,\n  makeDocResolver,\n  makeTutorialResolver,\n  type DocInput,\n  type TutorialInput,\n} from './guide-view';\nimport { buildSourceModel, type SourceFileInput } from './source-view';\nimport { SlotCollector, makeSlotTranslator, type SlotResolver } from './slots';\nimport type { NavNode, Page, PageKind, SiteManifest, TDoclet } from '@clean-jsdoc-theme/utils';\n\n/**\n * API container kinds that each get a standalone page, in nav display order.\n * Iterating module→namespace→class→interface→mixin→typedef means a documented\n * container (e.g. a module) wins a slug collision over a later kind. Typedefs\n * are mechanically identical to other containers: they go through the same\n * `buildContainerPage`/`getContainerView` path. A typedef's body (its `@type`,\n * `@property` list, and `@param`/`@returns` for function-signature typedefs)\n * renders via `containerViewToMdast`'s class-level `docletBlocks` call, which\n * only skips params/returns for the `class` kind.\n */\nconst CONTAINER_KINDS: readonly PageKind[] = [\n  'module',\n  'namespace',\n  'class',\n  'interface',\n  'mixin',\n  'typedef',\n];\n\n/**\n * A surviving container page from the dedup pass: its kind, source longname, the\n * already-built {@link ContainerView}, and its computed slug. Carried from pass 1\n * (dedup + registry) into pass 3 (render) so the view is built exactly once and\n * the registry's slugs always match the emitted pages.\n */\ninterface ContainerSpec {\n  kind: PageKind;\n  longname: string;\n  view: ContainerView;\n  slug: string;\n  /**\n   * Longnames of later same-slug containers whose views were merged into this\n   * one. Registered as aliases so the merged-away namepath still resolves to\n   * this page (see the registry pass).\n   */\n  aliases: string[];\n}\n\n/** Build-side options. */\nexport interface GenerateSiteOptions {\n  /**\n   * Document-model flavor. `'jsdoc'` (default) keeps the JSDoc container/member\n   * model — enums/functions/variables stay members or land on the Globals page,\n   * sidebar kind labels are the JSDoc ones (`Typedefs`, …). `'typedoc'` matches\n   * default TypeDoc: enums, top-level functions, variables, and type aliases each\n   * get a standalone page in their own kind-section, with TypeDoc labels. Only\n   * the TypeDoc bridge passes `'typedoc'`, so JSDoc output is byte-identical.\n   */\n  flavor?: 'jsdoc' | 'typedoc';\n  /** Optional package metadata to embed in the manifest. */\n  pkg?: SiteManifest['pkg'];\n  /**\n   * Project README as HTML (JSDoc renders it from Markdown into `opts.readme`).\n   * Rendered as the site home page (`index.html`).\n   */\n  readme?: string;\n  /**\n   * Tutorial tree, normalized from JSDoc's `--tutorials` resolver. Rendered as\n   * guide pages under \"Tutorials\", preserving the resolved order.\n   */\n  tutorials?: TutorialInput[];\n  /**\n   * Doc inputs from the bridge's docs-directory walk (already read off disk;\n   * setu does no I/O). Each becomes a prose page at its clean (unprefixed) slug\n   * via {@link buildDocPages}, grouped by its frontmatter/directory group. A root\n   * `index.md` (`path === 'index'`) becomes the home page, overriding the README\n   * home. A doc whose slug would shadow the home or an existing API/source/\n   * tutorial page is skipped (see the collision handling in `generateSite`).\n   */\n  docs?: DocInput[];\n  /**\n   * Top-level doc-group display order — the doc-group slice of the generalized\n   * sidebar `sectionOrder`. Threaded into {@link assembleNav} so the doc-group\n   * sidebar sections render in this order (after the API sections). The\n   * companion sidebar plan generalizes this; here it simply orders the doc\n   * groups consistently with how `sectionOrder` orders the rest.\n   */\n  docGroups?: string[];\n  /**\n   * Group label assigned to a doc page that carries no frontmatter/directory\n   * group. Forwarded to {@link buildDocPages}.\n   */\n  defaultDocGroup?: string;\n  /**\n   * Project source files to render as read-only `kind: 'source'` viewer pages.\n   * When supplied, each class member + the class itself gets a \"Source:\n   * file:line\" link resolved against these files.\n   */\n  sources?: SourceFileInput[];\n  /**\n   * When `true`, `Source: file:line` links point at the doclet's raw comment\n   * line instead of the first line of the declaration. Defaults to `false` (jump\n   * to the code). See {@link SourceModelOptions.linkToComment}.\n   */\n  sourceLinkToComment?: boolean;\n  /**\n   * Top-level sidebar group order — ONE unified list governing `@category`\n   * names, doc-group names, and kind labels together (e.g.\n   * `[\"Getting Started\", \"Core\", \"Classes\", \"Globals\"]`). For *kind* labels it\n   * acts as both a filter and an ordering — a kind section omitted here is\n   * dropped. Category/doc groups it omits are not dropped; they render after the\n   * listed labels, alphabetically. \"Home\" (when a README exists) and \"Source\n   * Files\" (when source pages are emitted) are always present and not controlled\n   * by this. Defaults to `DEFAULT_SECTION_ORDER` when absent or empty. Ignored\n   * when `menu` is set.\n   */\n  sectionOrder?: string[];\n  /**\n   * Full sidebar menu, in order. When set, takes precedence over `sectionOrder`\n   * and controls the entire sidebar: Home / Source Files appear only if their\n   * ids (`home` / `sourceFile`) are listed, sections only if named, and external\n   * links render inline. Each entry can carry an icon. See {@link MenuItem}.\n   */\n  menu?: MenuItem[];\n  /**\n   * Club related sidebar entries within each section into a one-level\n   * parent/child tree, grouping by the path segment before the first `/` (e.g.\n   * `queue`, `queue/Queue`, `queue/types` collapse under a `queue` parent). A\n   * prefix used by only one entry is left flat. Applies to every section,\n   * tutorials included. Off by default. See {@link clubNavTree}.\n   */\n  clubSidebarItems?: boolean;\n  /**\n   * Which top-level sidebar sections render as collapse toggles. `undefined`\n   * (default) or `true` → all present sections; `false` → none; `string[]` →\n   * only those exact labels. Resolved against the produced nav into\n   * {@link SiteManifest.collapsibleGroups}. See utils `resolveCollapsibleSections`.\n   */\n  collapsibleSidebarSections?: CollapsibleSidebarSections;\n  /**\n   * Site-wide code-playground enablement: `enableForAllExamples` opts every\n   * `@example` in, and `providers` is the default provider set + order a bare\n   * `@playground` (or `enableForAllExamples`) falls back to. The per-provider\n   * runtime options are NOT here — they're a dwar/browser concern. When omitted,\n   * `@playground` tags are ignored (feature off → byte-identical output). See\n   * {@link makePlaygroundResolver}.\n   */\n  playground?: PlaygroundSiteConfig;\n  /**\n   * Translatable-prose slot resolver (localization Phase 2). When omitted, the\n   * build is byte-identical to before but still emits the slot template in\n   * `manifest.slots`. When set with a `translate`, each API description/summary/\n   * example-caption is substituted for the active locale — this is the per-locale\n   * \"stamp\". A `collect` hook is added internally regardless, to populate the\n   * template; a caller's own `collect` (if any) also fires. See {@link stampSite}.\n   */\n  slots?: SlotResolver;\n}\n\n/**\n * Build a `SiteManifest` from a JSDoc salty collection. This is the boundary\n * setu→dwar entry point. API pages cover the container kinds in\n * {@link CONTAINER_KINDS} (module/namespace/class/interface/mixin/typedef) plus\n * one aggregated \"Globals\" page for global-scope symbols that don't get their\n * own page; the README (home page) and tutorials are rendered when supplied via\n * {@link GenerateSiteOptions}.\n */\nexport function generateSite(collection: unknown, opts?: GenerateSiteOptions): SiteManifest {\n  validateCollectionOrThrow(collection);\n\n  // Document-model flavor. `'jsdoc'` (default) keeps the container/member model;\n  // `'typedoc'` gives enums/functions/variables their own pages with TypeDoc\n  // labels. Gated everywhere below, so the JSDoc path is byte-identical.\n  const flavor = opts?.flavor ?? 'jsdoc';\n\n  // Source viewer model (pages + nav + the doclet→source link resolver). Built\n  // first so its `resolve` can be threaded into each class page's mdast.\n  const sourceModel = opts?.sources?.length\n    ? buildSourceModel(opts.sources, { linkToComment: opts.sourceLinkToComment ?? false })\n    : null;\n  // `resolve` keys off a doclet's `meta`; adapt it to the `(doclet) => link`\n  // shape `sourceLink` expects.\n  const sourceLink = sourceModel\n    ? (doclet: TDoclet) => sourceModel.resolve(doclet.meta)\n    : undefined;\n\n  // --- Pass 1: collect specs (single dedup pass) ---------------------------\n  //\n  // Iterate CONTAINER_KINDS in order, building each container's view + slug.\n  // When a later container collides on slug with one already seen (e.g. a\n  // `@module` symbol JSDoc emits as both `~Name` and `.Name` class doclets), we\n  // MERGE the colliding view into the existing spec instead of dropping it (see\n  // `mergeContainerViews`) — so neither doclet's classdesc, constructor params,\n  // relations, nor members are lost. The first-seen kind/slug/longname win; the\n  // merged-away longname is recorded in `aliases` for registry aliasing. This is\n  // the ONE place dedup happens: the surviving specs drive both the registry\n  // build and the render pass, so the registry's slugs can never diverge from\n  // the emitted pages.\n  const specs: ContainerSpec[] = [];\n  const specsBySlug = new Map<string, ContainerSpec>();\n  for (const kind of CONTAINER_KINDS) {\n    for (const longname of enumerateLongnamesByKind(collection, kind)) {\n      const view = getContainerView(collection, longname, kind);\n      if (!view) continue;\n      const slug = slugifyPath(splitLongnameForSlug(longname));\n      const existing = specsBySlug.get(slug);\n      if (existing) {\n        // Merge into the existing page (mutated in place so both `specs` and\n        // `specsBySlug` see it); record the merged-away longname as an alias.\n        existing.view = mergeContainerViews(existing.view, view);\n        existing.aliases.push(longname);\n        continue;\n      }\n      const spec: ContainerSpec = { kind, longname, view, slug, aliases: [] };\n      specsBySlug.set(slug, spec);\n      specs.push(spec);\n    }\n  }\n\n  // --- Pass 1b: standalone leaf pages (typedoc flavor only) ----------------\n  //\n  // TypeDoc treats enums, top-level functions, and module/global variables as\n  // first-class entities with their own pages. Enumerate them AFTER the\n  // container pass (so a container always wins a slug collision) and build a\n  // single-symbol page for each. A function/variable that is a MEMBER of a\n  // class/interface/mixin/enum is skipped — it stays inside its owner's page.\n  // The JSDoc flavor never enters this block, so its page set is unchanged.\n  if (flavor === 'typedoc') {\n    const memberOwners = new Set<string>();\n    for (const k of ['class', 'interface', 'mixin', 'enum'] as PageKind[]) {\n      for (const ln of enumerateLongnamesByKind(collection, k)) memberOwners.add(ln);\n    }\n    for (const kind of ['enum', 'function', 'variable'] as PageKind[]) {\n      for (const longname of enumerateLongnamesByKind(collection, kind)) {\n        const view = getContainerView(collection, longname, kind);\n        if (!view) continue;\n        const owner = view.doclet.memberof;\n        if (owner && memberOwners.has(owner)) continue; // a member, not a page\n        const slug = slugifyPath(splitLongnameForSlug(longname));\n        if (specsBySlug.has(slug)) continue; // a container already claimed it\n        const spec: ContainerSpec = { kind, longname, view, slug, aliases: [] };\n        specsBySlug.set(slug, spec);\n        specs.push(spec);\n      }\n    }\n  }\n\n  // One aggregated \"Globals\" page: every global-scope symbol that doesn't get\n  // its own container/typedef page, each rendered as a member section. Appended\n  // to the spec list. Globals is synthetic, so it must NOT merge into a real\n  // container — if its slug ('global') somehow collides with one, skip it.\n  const globals = buildGlobalsView(collection, flavor);\n  if (globals && !specsBySlug.has(globals.slug)) {\n    const spec: ContainerSpec = {\n      kind: 'global',\n      longname: 'Globals',\n      view: globals.view,\n      slug: globals.slug,\n      aliases: [],\n    };\n    specsBySlug.set(globals.slug, spec);\n    specs.push(spec);\n  }\n\n  // --- Pass 2: registry, then resolver -------------------------------------\n  //\n  // Populate the link registry from the EXACT surviving spec set (so registry\n  // slugs always match real output), THEN build the resolver. The registry is\n  // fully populated before any page body renders, so forward references (page A\n  // → symbol B enumerated after A) resolve. Mirrors how `sourceLink` is built\n  // first and threaded into pages.\n  const registry: LinkRegistry = new Map();\n  // Under the typedoc flavor, enums/functions/variables/classes/interfaces each\n  // own a standalone page yet also appear in a module/namespace's member buckets.\n  // Pre-seed every page's OWN longname → its slug before the member walks, so a\n  // symbol that has its own page always resolves there (and never to a stale\n  // `module#member` anchor — which no longer exists, since a typedoc module page\n  // is a links index). Page keys only; member anchors are still added below. The\n  // JSDoc path skips this, so its registry build is byte-identical.\n  if (flavor === 'typedoc') {\n    for (const s of specs) {\n      const key = s.view.doclet.longname;\n      if (key && !registry.has(key)) registry.set(key, { slug: s.slug });\n    }\n  }\n  for (const s of specs) {\n    registerContainerView(registry, s.view, s.slug);\n    // Merged-away longnames resolve to the surviving page (first-wins guard).\n    for (const alias of s.aliases) if (!registry.has(alias)) registry.set(alias, { slug: s.slug });\n  }\n  const resolveLink = makeLinkResolver(registry);\n\n  // `@tutorial <name>` resolver. Tutorials resolve by their tutorial name; docs\n  // resolve by their slug (e.g. `@tutorial guides/advanced`). Both are derived\n  // from the raw inputs here so the resolver threads into every API page's\n  // render alongside `resolveLink`; the guide/doc pages themselves are built\n  // further below. Tutorials are tried first, so a tutorial name wins a\n  // collision with a doc slug (backward compatible).\n  const resolveTutorial = composeResolvers(\n    opts?.tutorials?.length ? makeTutorialResolver(opts.tutorials) : undefined,\n    opts?.docs?.length ? makeDocResolver(opts.docs) : undefined\n  );\n\n  // Slot template: always collect translatable API prose into `manifest.slots`,\n  // and (when the caller supplied one) substitute the active locale's text via\n  // `translate` — the per-locale stamp. The internal collector populates the\n  // template; a caller's own `collect`, if any, still fires alongside it.\n  const slotCollector = new SlotCollector();\n  const slots: SlotResolver = {\n    collect: (entry) => {\n      slotCollector.collect(entry);\n      opts?.slots?.collect?.(entry);\n    },\n    translate: opts?.slots?.translate,\n  };\n\n  // Per-doclet `@playground` resolver (undefined when the feature is off, so the\n  // output stays byte-identical). Built once and threaded into every API page.\n  const playgroundFor = makePlaygroundResolver(opts?.playground);\n\n  // --- Pass 3: render -------------------------------------------------------\n  //\n  // Render each surviving spec from its already-built view (views are not\n  // rebuilt), threading `sourceLink`, the registry-backed `resolveLink`, the\n  // `@tutorial` resolver, the slot resolver (collect + per-locale translate), and\n  // the `@playground` resolver.\n  const apiPages: Page[] = specs.map((s) =>\n    renderContainerPage(s.view, s.kind, s.longname, s.slug, {\n      sourceLink,\n      resolveLink,\n      resolveTutorial,\n      slots,\n      playgroundFor,\n      flavor,\n    })\n  );\n\n  const pages: Page[] = [];\n  // Slugs already claimed by API + globals pages. Doc pages may not shadow these\n  // (nor the home slug, nor tutorial/source slugs added below). On a clash a doc\n  // is skipped — setu stays resilient and never throws (mirrors how a colliding\n  // synthetic globals page is skipped above, and how the bridge logs skips).\n  const claimedSlugs = new Set<string>(apiPages.map((p) => p.slug));\n\n  // Build doc pages (the docs directory) up front — BEFORE choosing the home\n  // page — because a root `index.md` produces a `kind: 'index'` page at slug ''\n  // that overrides the README home. Built with the same resolver as tutorials/\n  // README so prose cross-references resolve. The home page (if any) is split out\n  // and handled alongside the README below; the rest are filtered for slug\n  // collisions and merged into the page set + a `docNav` for the sidebar.\n  let docHome: Page | undefined;\n  const docPages: Page[] = [];\n  let docNav: NavNode[] = [];\n  if (opts?.docs && opts.docs.length > 0) {\n    const built = buildDocPages(opts.docs, { defaultDocGroup: opts.defaultDocGroup }, resolveLink);\n    const droppedSlugs = new Set<string>();\n    for (const page of built.pages) {\n      if (page.slug === '' && page.frontmatter.kind === 'index') {\n        // Root index.md → the home page (overrides the README home, below).\n        docHome = page;\n        continue;\n      }\n      // A doc may not shadow the home or an already-claimed API/source slug.\n      if (page.slug === '' || claimedSlugs.has(page.slug)) {\n        droppedSlugs.add(page.slug);\n        // Non-fatal: skip deterministically and warn (the bridge surfaces logs).\n        console.warn(\n          `[setu] skipping doc page: slug \"${page.slug}\" collides with an existing page`\n        );\n        continue;\n      }\n      claimedSlugs.add(page.slug);\n      docPages.push(page);\n    }\n    // Drop nav entries for the skipped doc pages so the sidebar matches the\n    // emitted pages (a dropped slug never reaches the manifest).\n    docNav = built.nav.filter((n) => n.slug !== undefined && !droppedSlugs.has(n.slug));\n  }\n\n  // README → home page (slug ''), the always-first ungrouped \"Home\" link. A root\n  // `index.md` (docHome) takes precedence over the README home when present.\n  // Rendered with the same resolver so prose cross-references resolve too.\n  const readmeHome = opts?.readme ? buildReadmePage(opts.readme, opts.pkg, resolveLink) : null;\n  const home = docHome ?? readmeHome;\n  let homeNav: NavNode | undefined;\n  if (home) {\n    pages.push(home);\n    homeNav = { label: 'Home', slug: home.slug };\n  }\n\n  // API pages, grouped into sidebar sections by kind.\n  pages.push(...apiPages);\n\n  // Tutorials → guide pages under \"Tutorials\". Same resolver for cross-refs.\n  let tutorialNav: NavNode[] = [];\n  if (opts?.tutorials && opts.tutorials.length > 0) {\n    const built = buildTutorialPages(opts.tutorials, resolveLink);\n    // Tutorials slug under `tutorials/<name>`; on the off chance one collides\n    // with an API/doc page, skip it (keep slugs unique across the manifest).\n    for (const page of built.pages) {\n      if (claimedSlugs.has(page.slug)) continue;\n      claimedSlugs.add(page.slug);\n      pages.push(page);\n    }\n    tutorialNav = built.nav.filter((n) => n.slug === undefined || claimedSlugs.has(n.slug));\n  }\n\n  // Doc pages → prose pages grouped by their doc-group (added after tutorials,\n  // matching the prose-page ordering).\n  pages.push(...docPages);\n\n  // Source files → hidden viewer pages + a \"Source Files\" index in the nav.\n  let sourceNav: NavNode | undefined;\n  if (sourceModel) {\n    pages.push(...sourceModel.pages, sourceModel.indexPage);\n    sourceNav = sourceModel.navNode;\n  }\n\n  // Assemble the sidebar: Home first, then the API/Tutorials/doc-group sections\n  // in the configured (or default) order, then Source Files last. `sectionOrder`\n  // both filters and orders the API/Tutorials sections; `docGroups` orders the\n  // doc-group sections (appended after the API sections).\n  const nav = assembleNav({\n    apiPages,\n    tutorials: tutorialNav,\n    docs: docNav,\n    docGroups: opts?.docGroups,\n    home: homeNav,\n    source: sourceNav,\n    sectionOrder: opts?.sectionOrder,\n    menu: opts?.menu,\n    clubSidebarItems: opts?.clubSidebarItems ?? false,\n    flavor,\n  });\n\n  const manifest: SiteManifest = {\n    pages,\n    nav,\n    buildId: computeBuildId(pages),\n    // The locale-independent template: every translatable API slot, deduped in\n    // first-seen order. Present on every build (possibly empty); dwar ignores it.\n    slots: slotCollector.list(),\n  };\n  manifest.collapsibleGroups = resolveCollapsibleSections(\n    opts?.collapsibleSidebarSections,\n    topLevelSectionLabels(nav)\n  );\n  if (opts?.pkg) manifest.pkg = opts.pkg;\n  return manifest;\n}\n\n/**\n * Stamp a site for one locale: re-run {@link generateSite} with a slot resolver\n * that substitutes the locale's translations (`messages`, keyed by `apiSlotKey`),\n * falling back to the source text for any gap. This is the per-locale half of the\n * two-phase build — the same doclet walk, re-serialized with translated prose.\n * `messages` carries the `api.*` slot translations for the locale; chrome strings\n * are handled separately by rang/bhasha at render time.\n */\nexport function stampSite(\n  collection: unknown,\n  messages: Readonly<Record<string, string>>,\n  opts?: GenerateSiteOptions\n): SiteManifest {\n  return generateSite(collection, {\n    ...opts,\n    slots: { ...opts?.slots, translate: makeSlotTranslator(messages) },\n  });\n}\n\n/**\n * Backwards-compatible thin wrapper around `generateSite` that returns each\n * page body as a string. Kept so the legacy `generateMdx` test/import surface\n * keeps working until callers are migrated.\n */\nexport function generateMdx(collection: unknown): string[] {\n  return generateSite(collection).pages.map((p) => p.body);\n}\n\nexport {\n  assembleNav,\n  buildClassPage,\n  buildContainerPage,\n  buildGlobalsPage,\n  buildGlobalsView,\n  buildNav,\n  clubNavTree,\n  computeBuildId,\n  DEFAULT_SECTION_ORDER,\n  DOCS_SECTION,\n  enumerateClassLongnames,\n  enumerateLongnamesByKind,\n  extractHeadings,\n  HOME_MENU_ID,\n  makePlaygroundResolver,\n  renderContainerPage,\n  SOURCE_MENU_IDS,\n  splitLongnameForSlug,\n  TUTORIALS_SECTION,\n  type AssembleNavOptions,\n  type MenuItem,\n  type PlaygroundSiteConfig,\n} from './generate-site';\n\nexport {\n  KNOWN_PROVIDERS,\n  parsePlaygroundSpec,\n  resolvePlaygroundOpts,\n  type PlaygroundOpts,\n  type PlaygroundSpec,\n} from './playground';\n\nexport {\n  buildDocPages,\n  buildReadmePage,\n  buildTutorialPages,\n  composeResolvers,\n  makeDocResolver,\n  makeTutorialResolver,\n  parseFrontmatter,\n  tutorialsToDocInputs,\n  TUTORIALS_GROUP,\n  type BuildDocPagesOptions,\n  type CrossRefResolver,\n  type DocInput,\n  type ResolvedTutorial,\n  type TutorialInput,\n} from './guide-view';\n\nexport {\n  buildSourceModel,\n  detectLanguage,\n  firstCodeLine,\n  type SourceFileInput,\n  type SourceModel,\n  type SourceModelOptions,\n} from './source-view';\n\nexport { SlotCollector, makeSlotTranslator, resolveSlotText, type SlotResolver } from './slots';\n","import { DocletListSchema, TDoclet, TJSDocSaltyCollection } from '@clean-jsdoc-theme/utils';\n\nexport function validateCollectionOrThrow(\n  collection: unknown\n): asserts collection is TJSDocSaltyCollection<TDoclet> {\n  if (typeof collection !== 'function') {\n    throw new Error('Invalid collection: expected a function, got ' + typeof collection);\n  }\n\n  let data: unknown;\n  try {\n    data = collection().get();\n  } catch {\n    throw new Error('collection is not a valid @jsdoc/salty DB ');\n  }\n\n  const docletListSchemaResult = DocletListSchema.safeParse(data);\n  if (!docletListSchemaResult.success) {\n    throw new Error(\n      [\n        'Invalid doclet list.',\n        '@clean-jsdoc-theme/setu supports JSDoc 4, if you are using an older version consider upgrading to JSDoc 4 or higher.',\n        'The first issue is:',\n        // Not showing all the issues at once, as it is hard to read a long list of issues\n        JSON.stringify(docletListSchemaResult.error.issues[0], null, 2),\n      ].join('\\n')\n    );\n  }\n}\n","import { createHash } from 'node:crypto';\nimport type { Heading as MdastHeading, Root } from 'mdast';\nimport {\n  slugifyHeading,\n  slugifyPath,\n  type Frontmatter,\n  type Heading,\n  type NavNode,\n  type Page,\n  type PageKind,\n} from '@clean-jsdoc-theme/utils';\nimport type { TDoclet, TJSDocSaltyCollection } from '@clean-jsdoc-theme/utils';\nimport { bucketClassMembers, getContainerView, type ContainerView } from './class-view';\nimport { filterDoclets } from './doclet';\nimport { containerViewToMdast } from './mdast/class-view';\nimport type { DocletBlocksOptions } from './mdast/doclet';\nimport {\n  KNOWN_PROVIDERS,\n  parsePlaygroundSpec,\n  resolvePlaygroundOpts,\n  type PlaygroundOpts,\n} from './playground';\nimport { resolveLinkTags } from './mdast/link-tags';\nimport { resolveSlotText } from './slots';\nimport { toMdx } from './mdx';\n\n/** JSDoc separator characters that delimit name parts in a longname. */\nconst LONGNAME_SEPARATORS = /[.#~:]+/g;\n\n/**\n * Split a JSDoc longname into the parts used for path slugging. The separators\n * `.`, `#`, `~`, `:` are replaced with whitespace, then the string is split\n * and empties are dropped. This preserves distinctness — `module:Foo~Bar` and\n * `Foo.Bar` produce different part arrays even after slugification because\n * `module` becomes a leading segment in the former.\n */\nexport function splitLongnameForSlug(longname: string): string[] {\n  return longname\n    .replace(LONGNAME_SEPARATORS, ' ')\n    .split(/\\s+/)\n    .filter((p) => p.length > 0);\n}\n\n/**\n * Parse an API symbol's `@category` tag — the explicit sidebar group for its\n * page, optionally with `key=value` options. `@category Core/Parsing order=1`\n * arrives as `doclet.tags = [{ title:'category', text:'Core/Parsing order=1' }]`\n * (JSDoc keeps unknown block tags); the first one wins.\n *\n * The leading whitespace-delimited tokens form the `group` path (a `/`-path that\n * nests the symbol, `Core` ▸ `Parsing`); parsing switches to options at the first\n * token containing `=`. Today the only option is `order` — the within-group sort\n * key, mirroring a doc page's `frontmatter.order`: it positions the page among\n * its sibling leaves AND its subgroup among sibling branches (a branch sorts by\n * the min `order` of the pages inside it; see {@link buildGroupTree}).\n *\n * Returns `undefined` when the symbol carries no `@category` (the page then falls\n * back to its kind section, see {@link sectionForPage}) or the path is empty; a\n * missing/non-numeric `order` is left `undefined` (the page sorts last,\n * alphabetically, exactly as an untagged one would).\n */\nfunction parseCategory(doclet: {\n  tags?: { title?: string; text?: string }[];\n}): { group: string; order?: number } | undefined {\n  const tag = doclet.tags?.find((t) => t.title === 'category');\n  const text = tag?.text?.trim();\n  if (!text) return undefined;\n\n  const tokens = text.split(/\\s+/);\n  const pathTokens: string[] = [];\n  const options = new Map<string, string>();\n  for (const token of tokens) {\n    const eq = token.indexOf('=');\n    // The path is the leading run of plain tokens; the first `key=value` token\n    // (and everything after it) is options. A space in a category name therefore\n    // stays part of the path — `@category Getting Started order=1` groups under\n    // \"Getting Started\" — as long as it precedes the first option.\n    if (eq > 0 && pathTokens.length > 0) {\n      options.set(token.slice(0, eq).toLowerCase(), token.slice(eq + 1));\n    } else {\n      pathTokens.push(token);\n    }\n  }\n\n  const group = pathTokens.join(' ').trim();\n  if (!group) return undefined;\n\n  const orderText = options.get('order');\n  const orderNum = orderText !== undefined ? Number(orderText) : NaN;\n  const order = Number.isFinite(orderNum) ? orderNum : undefined;\n  return order !== undefined ? { group, order } : { group };\n}\n\n/**\n * Read a standalone `@order N` block tag → a finite sort key, or `undefined`.\n *\n * Unlike the inline `@category … order=` option (which only a symbol carrying a\n * category can use), `@order` positions ANY documented symbol — including a\n * plain `@module`/`@class`/`@namespace` that lives in its kind section\n * (Modules, Classes, …) rather than a `@category` group. It is an unknown tag\n * (needs `tags.allowUnknownTags`, exactly as `@category` already relies on), so\n * JSDoc hands us its text untouched; the built-in name-bearing tags can't carry\n * the same `key=value` (trailing text pollutes the name or is dropped). A\n * missing/non-numeric value is left `undefined` (the page sorts last,\n * alphabetically), exactly as an untagged one would.\n */\nfunction readOrder(doclet: { tags?: { title?: string; text?: string }[] }): number | undefined {\n  const tag = doclet.tags?.find((t) => t.title === 'order');\n  const text = tag?.text?.trim();\n  if (!text) return undefined;\n  const num = Number(text);\n  return Number.isFinite(num) ? num : undefined;\n}\n\n/** Site-wide playground enablement passed into {@link generateSite}. */\nexport interface PlaygroundSiteConfig {\n  /** Opt every `@example` in (using {@link PlaygroundSiteConfig.providers}). */\n  enableForAllExamples?: boolean;\n  /** Default provider set + order for a bare `@playground` / `enableForAllExamples`. */\n  providers?: PlaygroundOpts['providers'];\n}\n\n/**\n * Build the per-doclet `@playground` resolver from the site-wide config — the\n * §3.3 resolution table. A doclet's `@playground` tag (parsed via\n * {@link parsePlaygroundSpec}) wins: an explicit provider list is used as-is, a\n * bare tag falls back to the default set, and `none`/`off` opts out (but still\n * wraps for a `filename`/`highlight`). With no tag, `enableForAllExamples` opts\n * the example in with the default set; otherwise no wrapper. Returns `undefined`\n * when there is no config at all (feature off → byte-identical output).\n */\nexport function makePlaygroundResolver(\n  config: PlaygroundSiteConfig | undefined\n): ((doclet: TDoclet) => PlaygroundOpts | null) | undefined {\n  if (!config) return undefined;\n  const defaults = config.providers && config.providers.length > 0 ? config.providers : [...KNOWN_PROVIDERS];\n  const enableAll = config.enableForAllExamples ?? false;\n  return (doclet: TDoclet) => {\n    const tag = doclet.tags?.find((t) => t.title === 'playground');\n    if (tag) {\n      const raw = typeof tag.value === 'string' ? tag.value : (tag.text ?? '');\n      return resolvePlaygroundOpts(parsePlaygroundSpec(raw), defaults);\n    }\n    if (enableAll) return { providers: [...defaults], highlight: [] };\n    return null;\n  };\n}\n\n/** Concatenate the text content of a heading node's inline children. */\nfunction headingText(node: MdastHeading): string {\n  let out = '';\n  for (const child of node.children) {\n    if (child.type === 'text' || child.type === 'inlineCode') {\n      out += child.value;\n    }\n  }\n  return out;\n}\n\n/** Read a string attribute off an mdast-mdx JSX element node. */\nfunction jsxAttr(\n  node: { attributes?: { name?: string; value?: unknown }[] },\n  name: string\n): string | undefined {\n  const attr = node.attributes?.find((a) => a.name === name);\n  return typeof attr?.value === 'string' ? attr.value : undefined;\n}\n\n/**\n * Walk an mdast tree and emit a `Heading` per h{minDepth}..h6 in document order,\n * with IDs slugified through a per-page registry so duplicates dedupe\n * consistently with what the renderer will produce.\n *\n * h1 handling is adaptive: a lone h1 is the page title and is skipped\n * (`minDepth` stays 2). But when a page has *two or more* h1s the author is\n * using h1 as section structure rather than as a title, so they're surfaced\n * like any other heading (`minDepth` drops to 1) and join the dedup registry.\n * dwar's slug pass makes the exact same count-then-decide choice, so the\n * `#id` numbering stays identical on both sides.\n *\n * `<MemberHeading>` JSX nodes (setu's signature headings) are also picked up:\n * their explicit `id`/`name`/`depth` attributes become the entry directly, and\n * they do NOT touch the dedup registry — mirroring dwar's slug pass, which skips\n * them (they carry an explicit id), so the `-1`/`-2` numbering of real markdown\n * headings stays in sync between the two. Members are never h1, so this branch\n * is unaffected by the adaptive `minDepth`.\n */\nexport function extractHeadings(tree: Root): Heading[] {\n  let h1Count = 0;\n  for (const node of tree.children) {\n    if (node.type === 'heading' && node.depth === 1) h1Count++;\n  }\n  const minDepth = h1Count >= 2 ? 1 : 2;\n\n  const registry = new Map<string, number>();\n  const out: Heading[] = [];\n  for (const node of tree.children) {\n    if (node.type === 'mdxJsxFlowElement' && (node as { name?: string }).name === 'MemberHeading') {\n      const id = jsxAttr(node, 'id');\n      const text = jsxAttr(node, 'name');\n      const depth = Number(jsxAttr(node, 'depth'));\n      if (id && text && depth >= 2 && depth <= 6) {\n        out.push({ depth: depth as 2 | 3 | 4 | 5 | 6, text, id });\n      }\n      continue;\n    }\n    if (node.type !== 'heading') continue;\n    if (node.depth < minDepth || node.depth > 6) continue;\n    const t = headingText(node).trim();\n    if (!t) continue;\n    out.push({\n      depth: node.depth as 1 | 2 | 3 | 4 | 5 | 6,\n      text: t,\n      id: slugifyHeading(t, registry),\n    });\n  }\n  return out;\n}\n\n/** Strip HTML tags from a string and collapse whitespace; cheap, not a parser. */\nfunction stripHtml(html: string): string {\n  return html\n    .replace(/<[^>]+>/g, ' ')\n    .replace(/\\s+/g, ' ')\n    .trim();\n}\n\n/**\n * Returns the unique longnames of the given `kind` in the collection that have\n * a documented doclet. Dedupes on longname and skips undocumented doclets.\n */\nexport function enumerateLongnamesByKind(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  kind: PageKind\n): string[] {\n  const doclets = collection({ kind }).get();\n  const seen = new Set<string>();\n  const out: string[] = [];\n  for (const d of doclets) {\n    if (!d.longname || seen.has(d.longname)) continue;\n    if (d.undocumented) continue;\n    seen.add(d.longname);\n    out.push(d.longname);\n  }\n  return out;\n}\n\n/** Returns the unique class longnames in the collection that have a canonical doclet. */\nexport function enumerateClassLongnames(collection: TJSDocSaltyCollection<TDoclet>): string[] {\n  return enumerateLongnamesByKind(collection, 'class');\n}\n\n/** Per-render threading options shared by every container/globals page. */\ninterface RenderOptions {\n  sourceLink?: DocletBlocksOptions['sourceLink'];\n  resolveLink?: DocletBlocksOptions['resolveLink'];\n  resolveTutorial?: DocletBlocksOptions['resolveTutorial'];\n  /** Translatable-prose slot resolver (collect + per-locale translate). */\n  slots?: DocletBlocksOptions['slots'];\n  /** Per-doclet `@playground` resolver (see {@link makePlaygroundResolver}). */\n  playgroundFor?: DocletBlocksOptions['playgroundFor'];\n  /** Document-model flavor; `'typedoc'` switches member sections + module index. */\n  flavor?: 'jsdoc' | 'typedoc';\n}\n\n/**\n * Render an already-built {@link ContainerView} into a {@link Page}. This is the\n * one place a container's mdast is assembled → link tags resolved → serialized,\n * so the two-pass build in `generateSite` can reuse the view from its dedup pass\n * (rather than rebuilding it). When `resolveLink` is provided, every `{@link}` /\n * `@see` reference in the tree is rewritten to a real anchor before `toMdx`;\n * without a resolver the output is byte-identical to the pre-link-resolution\n * builder.\n */\nexport function renderContainerPage(\n  view: ContainerView,\n  kind: PageKind,\n  longname: string,\n  slug: string,\n  { sourceLink, resolveLink, resolveTutorial, slots, playgroundFor, flavor }: RenderOptions = {}\n): Page {\n  const tree = containerViewToMdast(view, {\n    sourceLink,\n    resolveLink,\n    resolveTutorial,\n    slots,\n    playgroundFor,\n    flavor,\n  });\n  if (resolveLink) resolveLinkTags(tree, resolveLink);\n\n  const title = view.doclet.name ?? view.doclet.longname ?? longname;\n  // The frontmatter description (page <meta> + search excerpt) is derived from\n  // the same source as the body description, so it tracks the same `…#description`\n  // slot — a stamped locale localizes the excerpt too, not just the visible prose.\n  // Identity by default → byte-identical (stripHtml of the unchanged source). Key\n  // off `view.doclet.longname` (NOT the `longname` param fallback) so the\n  // frontmatter and the body's `descriptionBlocks` always resolve the SAME key —\n  // otherwise a doclet without a longname could localize the excerpt but not the\n  // body. Both short-circuit to the source when the longname is absent.\n  const descriptionSource = resolveSlotText(\n    slots,\n    view.doclet.longname,\n    'description',\n    view.doclet.classdesc ?? view.doclet.description\n  );\n  const description = descriptionSource ? stripHtml(descriptionSource) : undefined;\n\n  // `@category` (if any) becomes the sidebar group — possibly a `/`-path that\n  // nests the page (`Core/Parsing` → Core ▸ Parsing) — and its `order=` option\n  // (if any) the within-group sort key. Untagged symbols carry no group and fall\n  // back to their kind section in `sectionForPage`. The globals page's synthetic\n  // doclet has no tags, so it stays ungrouped as before.\n  const category = parseCategory(view.doclet);\n  // The within-group sort key. `@category … order=` wins when present (the more\n  // specific, co-located declaration); otherwise a standalone `@order N` tag\n  // applies — so a plain `@module`/`@class` with no category can still position\n  // itself in its kind section. Both feed the same `frontmatter.order`.\n  const order = category?.order ?? readOrder(view.doclet);\n\n  const frontmatter: Frontmatter = {\n    title,\n    kind,\n    longname: view.doclet.longname ?? longname,\n    ...(description ? { description } : {}),\n    ...(category ? { group: category.group } : {}),\n    ...(order !== undefined ? { order } : {}),\n  };\n\n  const body = toMdx(tree, { frontmatter });\n  const headings = extractHeadings(tree);\n\n  return { slug, frontmatter, body, mdast: tree, headings };\n}\n\n/**\n * Build a single container page (class/interface/mixin/module/namespace);\n * returns null if no container view of `kind` can be built for `longname`.\n * Delegates to {@link renderContainerPage}. The optional `resolveLink` resolves\n * cross-references; omit it for byte-identical legacy output.\n */\nexport function buildContainerPage(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  longname: string,\n  kind: PageKind,\n  sourceLink?: DocletBlocksOptions['sourceLink'],\n  resolveLink?: DocletBlocksOptions['resolveLink']\n): Page | null {\n  const view = getContainerView(collection, longname, kind);\n  if (!view) return null;\n  const slug = slugifyPath(splitLongnameForSlug(longname));\n  return renderContainerPage(view, kind, longname, slug, { sourceLink, resolveLink });\n}\n\n/**\n * Build a single class page; returns null if the class view cannot be built.\n * Thin alias over {@link buildContainerPage} with `kind: 'class'`.\n */\nexport function buildClassPage(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  longname: string,\n  sourceLink?: DocletBlocksOptions['sourceLink']\n): Page | null {\n  return buildContainerPage(collection, longname, 'class', sourceLink);\n}\n\n/** Kinds that already render as their own standalone page, excluded from the globals page. */\nconst GLOBALS_EXCLUDED_KINDS = new Set([\n  'class',\n  'interface',\n  'mixin',\n  'module',\n  'namespace',\n  'typedef',\n]);\n\n/** Stable slug for the aggregated globals page. */\nconst GLOBALS_SLUG = 'global';\n\n/**\n * Build the synthetic \"Globals\" {@link ContainerView} + its slug, or `null` when\n * there are no qualifying global-scope symbols. This is the view-building half of\n * {@link buildGlobalsPage}, split out so `generateSite` can register the globals\n * page into the link registry during its dedup pass before any body is rendered.\n */\nexport function buildGlobalsView(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  flavor: 'jsdoc' | 'typedoc' = 'jsdoc'\n): { view: ContainerView; slug: string } | null {\n  const globals = filterDoclets(collection({ scope: 'global' }).get());\n  // Under the typedoc flavor, enums/functions/variables each get their own\n  // standalone page, so they must NOT also land on the aggregated Globals page.\n  const excluded =\n    flavor === 'typedoc'\n      ? new Set([...GLOBALS_EXCLUDED_KINDS, 'enum', 'function', 'variable'])\n      : GLOBALS_EXCLUDED_KINDS;\n  const remainder = globals.filter((d) => !excluded.has(d.kind ?? ''));\n  if (remainder.length === 0) return null;\n\n  const buckets = bucketClassMembers(remainder);\n  const view: ContainerView = {\n    doclet: { kind: 'global', name: 'Globals' } as unknown as TDoclet,\n    kind: 'global',\n    augments: [],\n    constructorParams: [],\n    constructorParamNames: [],\n    ...buckets,\n  };\n  return { view, slug: GLOBALS_SLUG };\n}\n\n/**\n * Build the single aggregated \"Globals\" page: every global-scope symbol that\n * does not already get its own page (functions, members, constants, enums,\n * events) rendered as a member section on one synthetic container. Returns\n * `null` when there are no qualifying globals. Renders through\n * {@link renderContainerPage}; pass `resolveLink` to resolve cross-references in\n * the globals' prose.\n */\nexport function buildGlobalsPage(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  sourceLink?: DocletBlocksOptions['sourceLink'],\n  resolveLink?: DocletBlocksOptions['resolveLink']\n): Page | null {\n  const built = buildGlobalsView(collection);\n  if (!built) return null;\n  const page = renderContainerPage(built.view, 'global', 'Globals', built.slug, {\n    sourceLink,\n    resolveLink,\n  });\n  // The globals page carries no per-symbol longname in its frontmatter.\n  delete page.frontmatter.longname;\n  return page;\n}\n\n/**\n * API page kind → sidebar section label. Kinds without a mapping fall into the\n * \"Other\" section ({@link OTHER_SECTION}), appended after the ordered sections.\n */\nconst SECTION_FOR_KIND: Partial<Record<PageKind, string>> = {\n  class: 'Classes',\n  module: 'Modules',\n  namespace: 'Namespaces',\n  mixin: 'Mixins',\n  interface: 'Interfaces',\n  typedef: 'Typedefs',\n  enum: 'Enumerations',\n  function: 'Functions',\n  variable: 'Variables',\n  global: 'Globals',\n};\n\n/**\n * The kind → section label, flavor-aware. Only `typedef` differs: TypeDoc calls\n * it \"Type Aliases\" (matching default TypeDoc), JSDoc keeps \"Typedefs\". Every\n * other label is identical across flavors. Kinds with no mapping return\n * `undefined` (the caller falls back to {@link OTHER_SECTION}).\n */\nfunction sectionForKind(kind: PageKind, flavor: 'jsdoc' | 'typedoc'): string | undefined {\n  if (flavor === 'typedoc' && kind === 'typedef') return 'Type Aliases';\n  return SECTION_FOR_KIND[kind];\n}\n\n/** Catch-all section label for page kinds with no explicit mapping. */\nconst OTHER_SECTION = 'Other';\n\n/** Section label tutorial/guide nav entries are grouped under. */\nexport const TUTORIALS_SECTION = 'Tutorials';\n\n/**\n * Fallback section label for a doc page that carries no `group` (no frontmatter\n * group, no directory group, no `defaultDocGroup`). Docs that DO carry a group\n * become their own section under that group's label.\n */\nexport const DOCS_SECTION = 'Docs';\n\n/**\n * Default sidebar section order, used when the consumer supplies no\n * `sectionOrder`. Includes forward-looking sections (Externals, Events) that\n * have no pages yet; empty sections are simply skipped. A section absent from\n * the effective order is omitted from the sidebar entirely.\n */\nexport const DEFAULT_SECTION_ORDER: readonly string[] = [\n  'Classes',\n  'Modules',\n  'Externals',\n  'Events',\n  'Namespaces',\n  'Mixins',\n  'Interfaces',\n  'Typedefs',\n  'Globals',\n  'Tutorials',\n];\n\n/**\n * Default sidebar section order under the typedoc flavor — matching default\n * TypeDoc's module-index ordering (Enumerations, Classes, Interfaces, Type\n * Aliases, Functions, Variables, then containers). Used when the consumer\n * supplies no `sectionOrder`.\n */\nexport const TYPEDOC_SECTION_ORDER: readonly string[] = [\n  'Enumerations',\n  'Classes',\n  'Interfaces',\n  'Type Aliases',\n  'Functions',\n  'Variables',\n  'Namespaces',\n  'Mixins',\n  'Modules',\n  'Globals',\n  'Tutorials',\n];\n\n/**\n * Within-module member kind priority under the typedoc flavor — the exact order\n * default TypeDoc lists a module's members in the nav (verified against the\n * decoded stock-TypeDoc navigation tree): enums → classes → interfaces → type\n * aliases → variables → functions, then alphabetical by name. Container kinds\n * (module/namespace) nest as child nodes and are ordered separately (after the\n * member leaves, alphabetically), so they need no entry here. A kind not listed\n * sorts last among the leaves.\n */\nconst TYPEDOC_MEMBER_KIND_ORDER: Partial<Record<PageKind, number>> = {\n  enum: 0,\n  class: 1,\n  interface: 2,\n  typedef: 3,\n  variable: 4,\n  function: 5,\n};\n\n/** Kinds that act as a navigable-AND-expandable container node (module/namespace). */\nconst TYPEDOC_CONTAINER_KINDS = new Set<PageKind>(['module', 'namespace']);\n\n/**\n * The full `group` **path** a page belongs to. An explicit `frontmatter.group`\n * (from an API `@category` tag, or a doc/tutorial page's frontmatter) wins and\n * may be a `/`-path that nests the page; otherwise the page falls back to its\n * kind section label (today's behavior for untagged API symbols). The first\n * path segment is the top-level group (the bold sidebar title); see\n * {@link buildGroupTree}.\n */\nfunction sectionForPage(page: Page, flavor: 'jsdoc' | 'typedoc'): string {\n  return page.frontmatter.group ?? sectionForKind(page.frontmatter.kind, flavor) ?? OTHER_SECTION;\n}\n\n/** Built-in `id` for the home menu entry (resolved against the README home page). */\nexport const HOME_MENU_ID = 'home';\n/** Built-in `id`s for the source-files menu entry (`source` preferred, `sourceFile` accepted). */\nexport const SOURCE_MENU_IDS = ['source', 'sourceFile'] as const;\n\n// Default icons (prefixed `source:code`) when a menu entry supplies none.\nconst HOME_ICON = 'lucide:home';\nconst SOURCE_ICON = 'lucide:code-xml';\nconst EXTERNAL_ICON = 'lucide:external-link';\n\n/**\n * A single sidebar **menu** entry from the consumer's `menu` config. The menu is\n * a top region above the API sections (see {@link assembleNav}); each entry is a\n * built-in link (`home` / `source`) or an external link, and renders with an\n * icon.\n *\n * - `id === 'home'` → the README home page (icon defaults to `house`).\n * - `id === 'source'` (or `sourceFile`) → the Source Files index (icon defaults\n *   to `code-xml`).\n * - otherwise → an external link to `link` (or `href`), opening in a new tab.\n *\n * `icon` is a prefixed `source:code` string — `simpleicons:<slug>` (CDN) or\n * `lucide:<name>` (bundled set), see {@link NavNode.icon}. When omitted it\n * defaults by role: home→`lucide:home`, source→`lucide:code-xml`,\n * external→`lucide:external-link`.\n *\n * `target` and `class` are optional link presentation: `target` overrides the\n * link target (an external entry still defaults to `_blank`), and `class` adds\n * CSS class(es) to the rendered link.\n */\nexport interface MenuItem {\n  /** Built-in id (`home` / `source`), or — for an external link — its Simple Icons slug. */\n  id?: string;\n  /** Display text. Defaults to the built-in label or the link URL. */\n  title?: string;\n  /** External link URL. */\n  link?: string;\n  /** External link URL — accepted as an alias for {@link MenuItem.link}. */\n  href?: string;\n  /** Icon name/slug for the entry. */\n  icon?: string;\n  /**\n   * Link `target` attribute (e.g. `_blank`, `_self`). Overrides the default — an\n   * external link still defaults to `_blank` when this is omitted.\n   */\n  target?: string;\n  /** Extra CSS class(es) merged onto the rendered menu link. */\n  class?: string;\n}\n\n/** Inputs for {@link assembleNav}: the per-source nav pieces + the section order. */\nexport interface AssembleNavOptions {\n  /** API pages, grouped into sections by kind and alphabetized within each. */\n  apiPages?: readonly Page[];\n  /** Tutorial nav entries (kept in tree order under \"Tutorials\"). */\n  tutorials?: readonly NavNode[];\n  /**\n   * Doc nav entries (the docs directory). Each is bucketed into a section by its\n   * OWN `group` (a doc with no group falls into {@link DOCS_SECTION}); entries\n   * keep their input order within a section (not alphabetized), like tutorials.\n   * The doc-group section labels render in {@link AssembleNavOptions.docGroups}\n   * order — after the API sections, before Source Files — when those labels are\n   * not already pinned by `sectionOrder`.\n   */\n  docs?: readonly NavNode[];\n  /**\n   * Top-level doc-group display order — the doc-group slice of the generalized\n   * sidebar `sectionOrder`. Doc-group section labels listed here render in this\n   * order; doc groups not listed are appended after them in first-seen order.\n   * Folded into the effective section order alongside `sectionOrder` (which\n   * stays the authority for any label it lists).\n   */\n  docGroups?: readonly string[];\n  /** Home nav entry — always first, ungrouped, regardless of `sectionOrder`. */\n  home?: NavNode;\n  /** \"Source Files\" nav entry — always last, ungrouped, regardless of `sectionOrder`. */\n  source?: NavNode;\n  /**\n   * Top-level group labels to render, in order — one unified list mixing\n   * `@category` names, doc-group names, and kind labels (e.g.\n   * `[\"Getting Started\", \"Core\", \"Classes\", \"Globals\"]`). For *kind* labels this\n   * acts as BOTH a filter and an ordering (a kind label absent here is dropped).\n   * Category/doc groups it omits are NOT dropped — they render after the listed\n   * labels, alphabetically (doc groups pinned by `docGroups` keep that order).\n   * Defaults to {@link DEFAULT_SECTION_ORDER}. Ignored when\n   * {@link AssembleNavOptions.menu} is set.\n   */\n  sectionOrder?: readonly string[];\n  /**\n   * Top-region sidebar menu, in order — rendered above the API sections, with a\n   * divider between. When set, it OWNS the home/source links: the auto Home\n   * (first) and Source Files (last) entries are suppressed and render only if\n   * listed here (`id: 'home'` / `id: 'source'`). External links appear inline.\n   * The API sections below are still ordered by `sectionOrder`. Each entry\n   * carries an icon. See {@link MenuItem}.\n   */\n  menu?: readonly MenuItem[];\n  /**\n   * Club related entries within each section into a one-level parent/child tree,\n   * grouping by the path segment before the first `/` in their label (e.g.\n   * `queue`, `queue/Queue`, `queue/types` collapse under a `queue` parent). A\n   * prefix shared by only one entry is left flat (so a lone `strings/format`\n   * keeps its full label). See {@link clubNavTree}. Off by default.\n   */\n  clubSidebarItems?: boolean;\n  /**\n   * Document-model flavor. `'typedoc'` resolves kind labels with TypeDoc names\n   * (`Type Aliases`) and defaults to {@link TYPEDOC_SECTION_ORDER} when no\n   * `sectionOrder` is given; `'jsdoc'` (default) keeps the JSDoc labels +\n   * {@link DEFAULT_SECTION_ORDER}.\n   */\n  flavor?: 'jsdoc' | 'typedoc';\n}\n\n/** Child label for the entry that IS the bare prefix (e.g. the `queue` module). */\nconst CLUB_ROOT_CHILD_LABEL = 'index';\n\n/**\n * One flattened sidebar entry, before nested-group assembly. Carries the leaf\n * {@link NavNode} (the navigable page link), its **full** `group` path (`/`\n * separates nesting levels), and the within-bucket sort key. `path` drives both\n * the top-level group (its first segment → the bold sidebar title) and any\n * deeper branch nodes; `explicit` records whether the group came from an\n * `@category`/frontmatter group (vs. a kind-label fallback) so clubbing can skip\n * already-nested buckets (decision 6). `order` is `frontmatter.order` (sort key\n * within the deepest group); `sort` chooses between alphabetical (API symbols)\n * and input order (tutorials/docs, pre-ordered by their builder).\n */\ninterface GroupedEntry {\n  leaf: NavNode;\n  path: string;\n  explicit: boolean;\n  order?: number;\n  sort: 'alpha' | 'input';\n}\n\n/** Split a full `group` path into its non-empty `/`-separated segments. */\nfunction splitGroupPath(path: string): string[] {\n  return path\n    .split('/')\n    .map((s) => s.trim())\n    .filter((s) => s.length > 0);\n}\n\n/**\n * Order the leaf entries of a single deepest bucket. Alphabetical buckets (API\n * symbols and docs) sort by `frontmatter.order` (ascending; unset sorts last)\n * then title — so an untagged kind section stays purely alphabetical,\n * byte-identical to today, and a doc group honors its frontmatter `order`.\n * Input-order buckets (tutorials, already ordered by their builder's tree walk)\n * keep their emission order.\n */\nfunction orderLeafEntries(entries: GroupedEntry[]): GroupedEntry[] {\n  if (entries.every((e) => e.sort === 'input')) return entries;\n  return [...entries].sort((a, b) => {\n    const ao = a.order ?? Number.POSITIVE_INFINITY;\n    const bo = b.order ?? Number.POSITIVE_INFINITY;\n    if (ao !== bo) return ao - bo;\n    return a.leaf.label.localeCompare(b.leaf.label);\n  });\n}\n\n/**\n * Build the nested `children` tree for one top-level group from its entries.\n * Each entry's path beyond the top segment becomes a chain of non-navigable\n * **branch** nodes (`children`, no `slug`, label = segment); the entry's leaf\n * sits at the end of its chain. Sibling order: by effective `order` (a leaf's\n * own `order`, a branch's the min `order` of the pages inside it), then leaves\n * before branches, then bucket/first-seen order — so `@category Core/Schema\n * order=2` sorts its subgroup after `Core/Processing order=1`, and an unordered\n * group stays byte-identical to before. Returns the top group's nodes\n * (the array `groupNav` buckets under the bold title), each carrying\n * `group = topLabel` so the renderer's contiguous-run grouping keeps them\n * together. When every entry sits directly under the top group (depth 1, the\n * common/backward-compatible case), this returns a flat list of leaves.\n */\nfunction buildGroupTree(topLabel: string, entries: GroupedEntry[]): NavNode[] {\n  // A branch level: ordered child labels + their sub-entries, keyed by label.\n  interface Branch {\n    order: string[];\n    children: Map<string, GroupedEntry[]>;\n    leaves: GroupedEntry[];\n  }\n  const makeBranch = (): Branch => ({ order: [], children: new Map(), leaves: [] });\n\n  // Recursively place entries by their path segments (relative to `depth`).\n  function place(level: Branch, items: GroupedEntry[], depth: number): void {\n    for (const e of items) {\n      const segs = splitGroupPath(e.path);\n      if (depth >= segs.length) {\n        level.leaves.push(e);\n        continue;\n      }\n      const seg = segs[depth];\n      let bucket = level.children.get(seg);\n      if (!bucket) {\n        bucket = [];\n        level.children.set(seg, bucket);\n        level.order.push(seg);\n      }\n      bucket.push(e);\n    }\n  }\n\n  // A branch's effective order is the min `order` of the pages routed into it, so\n  // `order=1` on any page pulls its whole subgroup up among its siblings.\n  const minOrder = (items: GroupedEntry[]): number =>\n    items.reduce(\n      (m, e) => Math.min(m, e.order ?? Number.POSITIVE_INFINITY),\n      Number.POSITIVE_INFINITY\n    );\n\n  function emit(level: Branch, depth: number, group: string): NavNode[] {\n    interface Sibling {\n      node: NavNode;\n      order: number;\n      isLeaf: boolean;\n      seq: number;\n    }\n    const siblings: Sibling[] = [];\n    // Leaves at this level, pre-ordered by the bucket rule (order then label);\n    // `seq` preserves that as the tiebreak.\n    orderLeafEntries(level.leaves).forEach((e, i) => {\n      siblings.push({\n        // Propagate `order` onto the emitted node so order-aware clubbing\n        // (`clubNavTree`) can read it. Conditional so the no-order path adds no\n        // `order` key — the backward-compat boundary stays byte-identical.\n        node: { ...e.leaf, group, ...(e.order !== undefined ? { order: e.order } : {}) },\n        order: e.order ?? Number.POSITIVE_INFINITY,\n        isLeaf: true,\n        seq: i,\n      });\n    });\n    // Branch nodes (deeper segments); each sorts by the min order of its pages.\n    level.order.forEach((seg, i) => {\n      const items = level.children.get(seg)!;\n      const sub = makeBranch();\n      place(sub, items, depth + 1);\n      siblings.push({\n        node: { label: seg, group, children: emit(sub, depth + 1, group) },\n        order: minOrder(items),\n        isLeaf: false,\n        seq: i,\n      });\n    });\n    // By effective order; on a tie keep leaves before branches, then the\n    // pre-computed bucket/first-seen order — so an unordered group is unchanged.\n    siblings.sort((a, b) => {\n      if (a.order !== b.order) return a.order - b.order;\n      if (a.isLeaf !== b.isLeaf) return a.isLeaf ? -1 : 1;\n      return a.seq - b.seq;\n    });\n    return siblings.map((s) => s.node);\n  }\n\n  const root = makeBranch();\n  place(root, entries, 1); // segment 0 is the top label itself\n  return emit(root, 1, topLabel);\n}\n\n/**\n * Club a section's entries into a one-level parent/child tree by the path\n * segment before the first `/` in each label. A prefix shared by ≥2 entries\n * becomes a non-navigable parent branch whose children are the entries with\n * their prefix stripped (`queue/Queue` → `Queue`); the entry that IS the bare\n * prefix (`queue`) becomes an `index` child, sorted first. A prefix with a\n * single entry is NOT clubbed — it stays flat with its original label (so a lone\n * `strings/format` is untouched), but its `order` still participates in the\n * parent-level sort below.\n *\n * Order-aware (decisions 4/5): a clubbed parent sorts by the **min `order`** of\n * its members (so `@order 1` on any member floats the whole parent up), and\n * children sort by `order` then the `index`-first tiebreak then name (so\n * `@order` can pull a sibling ahead of the bare-prefix `index` child). With no\n * `@order`/`order=` anywhere every effective order is `+∞`, so parents fall back\n * to first-seen order and children to `index`-first-then-alphabetical — i.e. an\n * unordered section is byte-identical to before.\n */\nexport function clubNavTree(nodes: readonly NavNode[]): NavNode[] {\n  const groups = new Map<string, NavNode[]>();\n  const firstSeen = new Map<string, number>();\n  let seq = 0;\n  for (const node of nodes) {\n    const slash = node.label.indexOf('/');\n    const prefix = slash === -1 ? node.label : node.label.slice(0, slash);\n    const bucket = groups.get(prefix);\n    if (bucket) bucket.push(node);\n    else {\n      groups.set(prefix, [node]);\n      firstSeen.set(prefix, seq++);\n    }\n  }\n\n  // A parent's effective order is the min `order` of its members (unset → +∞),\n  // mirroring how `buildGroupTree` orders branch nodes.\n  const minOrder = (members: NavNode[]): number =>\n    members.reduce(\n      (m, n) => Math.min(m, n.order ?? Number.POSITIVE_INFINITY),\n      Number.POSITIVE_INFINITY\n    );\n\n  interface Parent {\n    node: NavNode;\n    order: number;\n    seq: number;\n  }\n  const parents: Parent[] = [];\n  for (const [prefix, members] of groups) {\n    const seqIdx = firstSeen.get(prefix)!;\n    if (members.length < 2) {\n      // Single entry under this prefix → never clubbed; keep it verbatim, but\n      // let its own order place it among the section's parents.\n      parents.push({\n        node: members[0],\n        order: members[0].order ?? Number.POSITIVE_INFINITY,\n        seq: seqIdx,\n      });\n      continue;\n    }\n    const children = members\n      .map((m) => ({\n        ...m,\n        label: m.label === prefix ? CLUB_ROOT_CHILD_LABEL : m.label.slice(prefix.length + 1),\n      }))\n      // By `order` (unset last); on a tie the bare-prefix `index` child leads,\n      // then alphabetical — so an explicit `@order` can pull a sibling ahead of\n      // `index`, but `index` keeps its pin among otherwise-unordered children.\n      .sort((a, b) => {\n        const ao = a.order ?? Number.POSITIVE_INFINITY;\n        const bo = b.order ?? Number.POSITIVE_INFINITY;\n        if (ao !== bo) return ao - bo;\n        if (a.label === CLUB_ROOT_CHILD_LABEL) return -1;\n        if (b.label === CLUB_ROOT_CHILD_LABEL) return 1;\n        return a.label.localeCompare(b.label);\n      });\n    // The parent is a label-only branch (no slug → not navigable).\n    parents.push({\n      node: { label: prefix, group: members[0].group, children },\n      order: minOrder(members),\n      seq: seqIdx,\n    });\n  }\n\n  // Parents by effective order (unset last), then first-seen order — so an\n  // unordered section keeps first-seen order (byte-identical) and `@order` on\n  // any member floats its parent up.\n  parents.sort((a, b) => (a.order !== b.order ? a.order - b.order : a.seq - b.seq));\n  return parents.map((p) => p.node);\n}\n\n/**\n * The owning-module path of an API page under the typedoc flavor, derived from\n * its JSDoc longname. A module/namespace page's longname is `module:<path>`\n * where `<path>` is the TypeDoc entry-point-relative name (e.g.\n * `module:components/base/Component`) — strip the `module:` prefix. A member's\n * longname is `<owner><sep><name>` (sep ∈ `.#~`); strip the trailing\n * `<sep><name>` to get its owner. Returns the raw path string (still `/`- and\n * possibly `.`-separated) or `undefined` when the longname is absent.\n */\nfunction typedocModulePath(longname: string | undefined): string | undefined {\n  if (!longname) return undefined;\n  return longname.startsWith('module:') ? longname.slice('module:'.length) : longname;\n}\n\n/**\n * One node under construction in the typedoc module tree. `pages` are the direct\n * member leaves owned by a module node at this path (empty for a pure folder);\n * `children` are the deeper path segments. `slug` is set only when a real\n * module/namespace page lives at this exact path (→ a navigable container node);\n * a folder segment leaves it undefined.\n */\ninterface ModuleTreeNode {\n  /** The single path segment this node represents (its display label pre-compaction). */\n  segment: string;\n  /** Module/namespace page slug when a container lives here; undefined for a folder. */\n  slug?: string;\n  /** Member leaves owned by the container at this path (already sorted at emit). */\n  members: { label: string; slug: string; kind: PageKind }[];\n  /** Child nodes keyed by their next path segment, in first-seen order. */\n  children: Map<string, ModuleTreeNode>;\n  order: string[];\n}\n\nconst makeModuleTreeNode = (segment: string): ModuleTreeNode => ({\n  segment,\n  members: [],\n  children: new Map(),\n  order: [],\n});\n\n/** Split a typedoc module path (`components/base/Component`) into `/`-segments. */\nfunction splitModulePath(path: string): string[] {\n  return path\n    .split('/')\n    .map((s) => s.trim())\n    .filter((s) => s.length > 0);\n}\n\n/**\n * Build the module/folder-hierarchy sidebar tree for the **typedoc flavor** —\n * mirroring default TypeDoc's navigation, replacing the kind buckets. Returns an\n * ordered list of top-level nodes (folders and root modules), each tagged with\n * `group = <its own label>` so the renderer groups it as its own contiguous\n * section (as the kind sections were). This path is only reachable under\n * `flavor === 'typedoc'` (see {@link assembleNav}); the JSDoc nav never calls it,\n * so JSDoc output is byte-identical.\n *\n * Rules (matched against the decoded stock-TypeDoc tree):\n * - **Group by owning module.** A member's nav position is under its owning\n *   module/namespace (derived from its longname, {@link typedocModulePath}); the\n *   kind label is NOT a group.\n * - **Module = branch WITH slug.** A module/namespace page becomes a single node\n *   carrying BOTH its `slug` (navigable) AND `children` (its members + nested\n *   containers). It is NOT also emitted as a separate leaf — exactly one nav\n *   entry per symbol.\n * - **Folders from shared dir segments.** Intermediate `/`-segments with no\n *   module page of their own become non-navigable folder branches (no slug).\n * - **compactFolders.** A folder node (no slug) with exactly one child merges\n *   into that child, prefixing the child's label with `folder/` (recursively) —\n *   so a `base/` folder holding only the `Component` module renders as one node\n *   labeled `base/Component` (slug intact). A module node never compacts.\n * - **Members flat + kind-ordered** ({@link TYPEDOC_MEMBER_KIND_ORDER}), then\n *   nested containers alphabetically; no per-kind sub-headings in the nav.\n * - **Top level alphabetical** (documents are added separately, first, by the\n *   caller).\n */\nexport function buildTypedocApiNav(apiPages: readonly Page[]): NavNode[] {\n  // Register every module/namespace longname so folder segments that ARE a real\n  // container become module nodes, and members can find their owner by walking up.\n  const moduleByLongname = new Set<string>();\n  for (const p of apiPages) {\n    if (TYPEDOC_CONTAINER_KINDS.has(p.frontmatter.kind) && p.frontmatter.longname) {\n      moduleByLongname.add(p.frontmatter.longname);\n    }\n  }\n\n  const root = makeModuleTreeNode('');\n  const ensurePath = (segments: string[]): ModuleTreeNode => {\n    let node = root;\n    for (const seg of segments) {\n      let child = node.children.get(seg);\n      if (!child) {\n        child = makeModuleTreeNode(seg);\n        node.children.set(seg, child);\n        node.order.push(seg);\n      }\n      node = child;\n    }\n    return node;\n  };\n\n  // Root-scope symbols (no owning module) that still have their own page — they\n  // are surfaced as top-level nav leaves rather than dropped.\n  const rootSymbols: { label: string; slug: string; kind: PageKind }[] = [];\n  for (const p of apiPages) {\n    const kind = p.frontmatter.kind;\n    // The synthetic Globals page carries no longname/module path; TypeDoc has no\n    // such aggregate, so drop it from the module tree (its members already have\n    // their own pages under this flavor).\n    if (kind === 'global') continue;\n    const isContainer = TYPEDOC_CONTAINER_KINDS.has(kind);\n    if (isContainer) {\n      const path = typedocModulePath(p.frontmatter.longname);\n      if (!path) continue;\n      const node = ensurePath(splitModulePath(path));\n      node.slug = p.slug;\n      continue;\n    }\n    // A member: place it under its owning module node (the module path derived by\n    // stripping the trailing `<sep><name>` from its longname).\n    const ownerLongname = ownerModuleLongname(p.frontmatter.longname, moduleByLongname);\n    const ownerPath = typedocModulePath(ownerLongname);\n    if (ownerPath === undefined) {\n      // A genuine root-scope symbol (no enclosing module in its longname) whose\n      // page exists but has no owner to nest under. Surface it as a top-level nav\n      // leaf instead of silently dropping it from the sidebar.\n      if (p.frontmatter.longname) {\n        rootSymbols.push({ label: p.frontmatter.title, slug: p.slug, kind });\n      }\n      continue;\n    }\n    const node = ensurePath(splitModulePath(ownerPath));\n    node.members.push({ label: p.frontmatter.title, slug: p.slug, kind });\n  }\n\n  // Emit a folder/module subtree into NavNodes, applying compactFolders and the\n  // ordering rules. `group` propagates the top-level section label onto every\n  // descendant leaf/branch so the renderer keeps the section contiguous.\n  const emit = (node: ModuleTreeNode, group: string): NavNode => {\n    // Member leaves, kind-ordered then alphabetical by label.\n    const memberNodes: NavNode[] = [...node.members]\n      .sort((a, b) => {\n        const ap = TYPEDOC_MEMBER_KIND_ORDER[a.kind] ?? Number.POSITIVE_INFINITY;\n        const bp = TYPEDOC_MEMBER_KIND_ORDER[b.kind] ?? Number.POSITIVE_INFINITY;\n        if (ap !== bp) return ap - bp;\n        return a.label.localeCompare(b.label);\n      })\n      .map((m) => ({ label: m.label, slug: m.slug, group }));\n\n    // Nested container/folder children, alphabetical by (possibly compacted) label.\n    const childNodes: NavNode[] = node.order\n      .map((seg) => compact(node.children.get(seg)!, group))\n      .sort((a, b) => a.label.localeCompare(b.label));\n\n    const children = [...memberNodes, ...childNodes];\n    const out: NavNode = { label: node.segment, group };\n    if (node.slug !== undefined) out.slug = node.slug;\n    // A branch node (folder or module with members/children) opts into deep\n    // auto-expand: the sidebar opens it when ANY descendant is the current page,\n    // so a deep member reveals its enclosing folder+module. TypeDoc-only — the\n    // JSDoc nav never sets `deepExpand`, keeping its legacy direct-children check.\n    if (children.length > 0) {\n      out.children = children;\n      out.deepExpand = true;\n    }\n    return out;\n  };\n\n  // compactFolders: a folder node (no slug) with exactly one child folds into\n  // that child, prefixing the child's label (`base/Component`). Recursive. A\n  // node with a slug (a real module/namespace page) never compacts.\n  const compact = (node: ModuleTreeNode, group: string): NavNode => {\n    let emitted = emit(node, group);\n    while (\n      emitted.slug === undefined &&\n      emitted.children !== undefined &&\n      emitted.children.length === 1 &&\n      // Only fold into a child that is itself a branch/module (has children) or a\n      // navigable module — i.e. fold folder→module, not folder→member-leaf; a\n      // lone member under a folder keeps the folder (shouldn't happen for real\n      // TypeDoc output, but stays safe).\n      (emitted.children[0].children !== undefined || emitted.children[0].slug !== undefined)\n    ) {\n      const child = emitted.children[0];\n      emitted = { ...child, label: `${emitted.label}/${child.label}`, group };\n    }\n    return emitted;\n  };\n\n  // Top-level nodes, alphabetical. Each top-level module/folder renders as a\n  // SINGLE nav row (matching default TypeDoc, which shows no top-level section\n  // header for modules/folders), so it must carry NO `group` — otherwise the\n  // renderer's contiguous-run grouping would also emit a bold self-named header\n  // above the row (a double-render). Nested descendants keep a `group` (via\n  // retagGroup) but that is inert: NavEntry renders children recursively, not\n  // through groupNav. Doc-group/tutorial section headers are unaffected — they\n  // are built separately in assembleTypedocNav.\n  const topNodes = root.order.map((seg) => {\n    const node = compact(root.children.get(seg)!, seg);\n    // Re-tag the subtree first (compaction changes the top label — a folded\n    // `base/Component` node's label differs from the pre-compaction `seg`), then\n    // strip the top node's own group so it renders headerless.\n    const retagged = retagGroup(node, node.label);\n    delete retagged.group;\n    return retagged;\n  });\n  // Root-scope symbols with no owning module become plain top-level leaves,\n  // sitting alongside the module/folder nodes (they carry no `group`, so they too\n  // render headerless).\n  for (const s of rootSymbols) {\n    topNodes.push({ label: s.label, slug: s.slug });\n  }\n  return topNodes.sort((a, b) => a.label.localeCompare(b.label));\n}\n\n/**\n * Resolve a member page's owning module/namespace longname by walking UP its\n * longname — stripping the trailing `<sep><name>` segment (sep ∈ `.#~`) — until\n * the remainder is a registered container longname. This finds the nearest\n * enclosing module/namespace even when the symbol nests below it\n * (`module:m.Ns.Foo` → `module:m.Ns` when `Ns` is a namespace page, else\n * `module:m`). Note `/` is NOT a separator — it is part of a module's own path\n * name (`module:services/cache/Cache`), so it is never stripped. Returns\n * `undefined` for a top-level symbol with no separator (no module owner).\n */\nfunction ownerModuleLongname(\n  longname: string | undefined,\n  containers: ReadonlySet<string>\n): string | undefined {\n  if (!longname) return undefined;\n  let candidate = longname;\n  let firstOwner: string | undefined;\n  const sep = /^(.*)[.#~][^.#~]+$/;\n  while (true) {\n    const m = candidate.match(sep);\n    if (!m) break;\n    candidate = m[1];\n    if (firstOwner === undefined) firstOwner = candidate;\n    if (containers.has(candidate)) return candidate;\n  }\n  // No enclosing container matched — fall back to the direct owner (one strip),\n  // so a member always lands under some module node rather than vanishing.\n  return firstOwner;\n}\n\n/**\n * Re-tag a node subtree's `group` to `group` (the top-level section label). A\n * second pass is needed because compaction can change the top node's label\n * (`base` folder folds into `base/Component`), so the group emitted during the\n * first `emit` pass — keyed off the pre-compaction segment — no longer matches\n * the final top label; this rewrites the whole subtree to the compacted label.\n */\nfunction retagGroup(node: NavNode, group: string): NavNode {\n  const out: NavNode = { ...node, group };\n  if (node.children) out.children = node.children.map((c) => retagGroup(c, group));\n  return out;\n}\n\n/**\n * Assemble the final sidebar nav from its parts, honoring `sectionOrder`.\n *\n * Every entry carries a full `group` **path** — an `@category` tag (API pages)\n * or `frontmatter.group` (docs/tutorials), falling back to the kind section\n * label for untagged API symbols. The path's first segment is the top-level\n * group (a bold, non-collapsible title); deeper `/`-segments become nested,\n * collapsible branch nodes ({@link buildGroupTree}). So `@category Core/Parsing`\n * nests its page under `Core` ▸ `Parsing`.\n *\n * Top-level groups render in the effective order: `sectionOrder` labels first,\n * in that order (a *kind* label it omits is dropped — today's filter behavior);\n * then category/doc groups it doesn't list, appended alphabetically (doc groups\n * named in `docGroups` keep that explicit order). Within a deepest group, API\n * entries sort by `frontmatter.order` then title (a kind-only section stays\n * purely alphabetical, as before); tutorial/doc entries keep their tree order.\n * Home (if any) is always emitted first and Source Files (if any) always last;\n * neither is controlled by `sectionOrder`. Any page kind with no section mapping\n * is collected under \"Other\" and appended last (a safety net; in practice empty).\n *\n * Each node's `order` mirrors its emission position (section index), so the\n * monotonic-order invariant holds; the sidebar itself renders in array order.\n *\n * Backward compatible: a collection with no `@category`/group and a kind-only\n * `sectionOrder` produces byte-identical nav to the pre-nesting builder.\n */\nexport function assembleNav(options: AssembleNavOptions): NavNode[] {\n  // Under the typedoc flavor the sidebar mirrors default TypeDoc — a module/\n  // folder hierarchy instead of kind buckets — so it takes a wholly separate\n  // assembly path. The JSDoc path below is untouched (byte-identical); this\n  // branch is only reachable when the bridge passes `flavor: 'typedoc'`.\n  if (options.flavor === 'typedoc') return assembleTypedocNav(options);\n  return assembleJsdocNav(options);\n}\n\n/** JSDoc-flavor nav assembly — kind buckets + `@category`/doc-group nesting. */\nfunction assembleJsdocNav({\n  apiPages = [],\n  tutorials = [],\n  docs = [],\n  docGroups = [],\n  home,\n  source,\n  sectionOrder,\n  menu,\n  clubSidebarItems = false,\n  flavor = 'jsdoc',\n}: AssembleNavOptions): NavNode[] {\n  // Flatten every source into one list of grouped entries carrying their FULL\n  // group path (an `@category`/frontmatter group may be a `/`-path that nests\n  // the page). The first path segment is the top-level group (the bold title);\n  // deeper segments become nested branch nodes below.\n  const entries: GroupedEntry[] = [];\n  // Top-level groups that originate from an explicit `@category` (not a kind\n  // label), in first-seen order. Unlike kind labels — which `sectionOrder`\n  // filters — a category group not listed in `sectionOrder` is never dropped; it\n  // is appended after the listed sections (alphabetically, with doc groups). This\n  // keeps the no-category path byte-identical (this stays empty), so kind-only\n  // `sectionOrder` filtering is unchanged.\n  const categorySectionOrder: string[] = [];\n  for (const p of apiPages) {\n    const path = sectionForPage(p, flavor);\n    const explicit = p.frontmatter.group !== undefined;\n    if (explicit) {\n      const top = splitGroupPath(path)[0];\n      if (top && !categorySectionOrder.includes(top)) categorySectionOrder.push(top);\n    }\n    entries.push({\n      leaf: { label: p.frontmatter.title, slug: p.slug },\n      path,\n      // An explicit `frontmatter.group` (from `@category`) opts out of clubbing.\n      explicit,\n      order: p.frontmatter.order,\n      sort: 'alpha',\n    });\n  }\n  for (const t of tutorials) {\n    // Use the tutorial's own group, which carries the sub-tutorial hierarchy as\n    // a `Tutorials/<parent>/…` path (issue #253); buildGroupTree nests it. A\n    // declared hierarchy (group deeper than the bare section) opts out of\n    // clubbing so the nesting survives; a flat tutorial set keeps `path` ===\n    // TUTORIALS_SECTION and stays clubbable — byte-identical legacy behavior.\n    const path = t.group ?? TUTORIALS_SECTION;\n    entries.push({ leaf: { ...t }, path, explicit: path !== TUTORIALS_SECTION, sort: 'input' });\n  }\n  // Doc entries group by their OWN group path (fallback DOCS_SECTION). First-seen\n  // top-level group order is captured so groups absent from `docGroups`/\n  // `sectionOrder` still render deterministically.\n  const docSectionOrder: string[] = [];\n  for (const d of docs) {\n    const path = d.group ?? DOCS_SECTION;\n    const top = splitGroupPath(path)[0] ?? DOCS_SECTION;\n    if (!docSectionOrder.includes(top)) docSectionOrder.push(top);\n    // Docs carry an explicit `frontmatter.order` (unlike tutorials, which only\n    // have the builder's tree order), so sort them by it then title — `order: 2`\n    // sits after `order: 1` regardless of the directory-walk order they arrive in.\n    entries.push({\n      leaf: { ...d },\n      path,\n      explicit: d.group !== undefined,\n      order: d.order,\n      sort: 'alpha',\n    });\n  }\n\n  // Bucket entries by their TOP-LEVEL group (first path segment), preserving\n  // first-seen order, then build each bucket's nested `children` tree.\n  const byTopGroup = new Map<string, GroupedEntry[]>();\n  for (const e of entries) {\n    const top = splitGroupPath(e.path)[0] ?? OTHER_SECTION;\n    const bucket = byTopGroup.get(top);\n    if (bucket) bucket.push(e);\n    else byTopGroup.set(top, [e]);\n  }\n\n  const bySection = new Map<string, NavNode[]>();\n  for (const [top, groupEntries] of byTopGroup) {\n    let nodes = buildGroupTree(top, groupEntries);\n    // Club ONLY buckets whose entries carry no explicit category/group path\n    // (decision 6): a group built from category paths is already nested and is\n    // not additionally label-clubbed. Backward compatible — today every API\n    // bucket is kind-fallback (`explicit: false`), so clubbing still applies.\n    if (clubSidebarItems && groupEntries.every((e) => !e.explicit)) {\n      nodes = clubNavTree(nodes);\n    }\n    bySection.set(top, nodes);\n  }\n\n  const defaultOrder = flavor === 'typedoc' ? TYPEDOC_SECTION_ORDER : DEFAULT_SECTION_ORDER;\n  const baseOrder = sectionOrder && sectionOrder.length > 0 ? sectionOrder : defaultOrder;\n  // Fold doc-group section labels into the effective order, AFTER the base\n  // (API) sections: `sectionOrder` stays authoritative for any label it already\n  // lists; doc groups it omits are appended in `docGroups` order, then any\n  // remaining groups in first-seen order. This keeps the no-docs path's order\n  // byte-identical (docExtras is empty when there are no docs).\n  const inBase = new Set(baseOrder);\n  const seenExtra = new Set<string>();\n  // Doc groups named in `docGroups` keep that explicit order, appended first.\n  const docOrdered: string[] = [];\n  for (const label of docGroups) {\n    if (inBase.has(label) || seenExtra.has(label)) continue;\n    seenExtra.add(label);\n    docOrdered.push(label);\n  }\n  // Remaining explicit top-level groups (categories + doc groups not pinned by\n  // `docGroups`) that `sectionOrder` doesn't list: appended after the listed\n  // sections, ALPHABETICALLY (decision 3 — listed-first, then unlisted sorted).\n  const alphaExtras: string[] = [];\n  for (const label of [...categorySectionOrder, ...docSectionOrder]) {\n    if (inBase.has(label) || seenExtra.has(label)) continue;\n    seenExtra.add(label);\n    alphaExtras.push(label);\n  }\n  alphaExtras.sort((a, b) => a.localeCompare(b));\n  // Under the typedoc flavor, a kind section must never be dropped just because a\n  // user-supplied `sectionOrder` didn't list it (default TypeDoc always shows\n  // every kind). Append any present-but-unlisted TypeDoc kind label, in the\n  // canonical TypeDoc order. JSDoc keeps its legacy \"omitted kind = dropped\"\n  // filter (this loop never runs for it), so its nav stays byte-identical.\n  const kindExtras: string[] = [];\n  if (flavor === 'typedoc') {\n    for (const label of TYPEDOC_SECTION_ORDER) {\n      if (inBase.has(label) || seenExtra.has(label) || !bySection.has(label)) continue;\n      seenExtra.add(label);\n      kindExtras.push(label);\n    }\n  }\n  const extras = [...docOrdered, ...alphaExtras, ...kindExtras];\n  const order = extras.length > 0 ? [...baseOrder, ...extras] : baseOrder;\n  const out: NavNode[] = [];\n\n  if (menu && menu.length > 0) {\n    // Menu mode: the menu items form the top region (home/source/externals);\n    // they OWN the home/source links (auto Home/Source are suppressed). The API\n    // sections still follow `sectionOrder`, below a divider the sidebar draws.\n    menu.forEach((item, i) => {\n      const node = resolveMenuItem(item, home, source, i);\n      if (node) out.push(node);\n    });\n    appendSections(out, bySection, order);\n    return out;\n  }\n\n  // Section mode: Home first, ordered sections, Source Files last (no icons).\n  if (home) out.push({ ...home, order: -1 });\n  appendSections(out, bySection, order);\n  if (source) out.push({ ...source, order: order.length + 1 });\n  return out;\n}\n\n/**\n * Typedoc-flavor nav assembly — mirrors default TypeDoc's sidebar: documents\n * first, then a module/folder hierarchy ({@link buildTypedocApiNav}) replacing\n * the kind buckets, then tutorials, with Home first and Source Files last. Docs\n * keep their own doc-group nesting (via {@link buildGroupTree}) and render before\n * the module tree; tutorials keep theirs and render after. `sectionOrder` has no\n * effect under this flavor — the module hierarchy owns the API top level (default\n * TypeDoc shows every module), and doc groups are ordered by `docGroups` — so it\n * is intentionally not destructured here even though the shared\n * {@link AssembleNavOptions} carries it for the JSDoc path. This whole path is\n * gated on `flavor === 'typedoc'`, so the JSDoc nav is byte-identical.\n */\nfunction assembleTypedocNav({\n  apiPages = [],\n  tutorials = [],\n  docs = [],\n  docGroups = [],\n  home,\n  source,\n  menu,\n}: AssembleNavOptions): NavNode[] {\n  // The module/folder hierarchy for the API pages — the top-level nodes that\n  // replace the kind buckets. Top-level module/folder nodes carry NO `group` (so\n  // `groupNav` renders them as headerless single rows, not a self-named section),\n  // and the set is alphabetized.\n  const moduleNodes = buildTypedocApiNav(apiPages);\n\n  // Doc-group + tutorial sections, built with the SAME nesting machinery as the\n  // JSDoc path (so nested doc groups / sub-tutorials still work), then bucketed\n  // by their top-level label.\n  const auxEntries: GroupedEntry[] = [];\n  const docSectionOrder: string[] = [];\n  for (const d of docs) {\n    const path = d.group ?? DOCS_SECTION;\n    const top = splitGroupPath(path)[0] ?? DOCS_SECTION;\n    if (!docSectionOrder.includes(top)) docSectionOrder.push(top);\n    auxEntries.push({\n      leaf: { ...d },\n      path,\n      explicit: d.group !== undefined,\n      order: d.order,\n      sort: 'alpha',\n    });\n  }\n  for (const t of tutorials) {\n    const path = t.group ?? TUTORIALS_SECTION;\n    auxEntries.push({ leaf: { ...t }, path, explicit: path !== TUTORIALS_SECTION, sort: 'input' });\n  }\n  const byAuxTop = new Map<string, GroupedEntry[]>();\n  for (const e of auxEntries) {\n    const top = splitGroupPath(e.path)[0] ?? OTHER_SECTION;\n    const bucket = byAuxTop.get(top);\n    if (bucket) bucket.push(e);\n    else byAuxTop.set(top, [e]);\n  }\n  const docSections: NavNode[] = [];\n  const tutorialSections: NavNode[] = [];\n  // Doc groups render in `docGroups` order first, then first-seen; tutorials last.\n  const docOrder = [...docGroups.filter((g) => byAuxTop.has(g))];\n  for (const g of docSectionOrder) if (!docOrder.includes(g)) docOrder.push(g);\n  for (const top of docOrder) {\n    if (top === TUTORIALS_SECTION) continue;\n    const entries = byAuxTop.get(top);\n    if (entries && entries.length > 0) docSections.push(...buildGroupTree(top, entries));\n  }\n  const tutEntries = byAuxTop.get(TUTORIALS_SECTION);\n  if (tutEntries && tutEntries.length > 0) {\n    tutorialSections.push(...buildGroupTree(TUTORIALS_SECTION, tutEntries));\n  }\n  const out: NavNode[] = [];\n  if (menu && menu.length > 0) {\n    menu.forEach((item, i) => {\n      const node = resolveMenuItem(item, home, source, i);\n      if (node) out.push(node);\n    });\n    // Documents first, module hierarchy, then tutorials.\n    out.push(...docSections, ...moduleNodes, ...tutorialSections);\n    return out;\n  }\n\n  if (home) out.push({ ...home, order: -1 });\n  // Documents FIRST, then the module/folder hierarchy (alphabetical), then\n  // tutorials; Source Files last.\n  out.push(...docSections, ...moduleNodes, ...tutorialSections);\n  if (source) out.push({ ...source });\n  return out;\n}\n\n/**\n * Append the API/Tutorials section entries to `out`, in `order`. Sections absent\n * from `order` are dropped — EXCEPT the catch-all \"Other\" bucket (unmapped\n * kinds), appended last so content never vanishes silently. Mutates `out`.\n */\nfunction appendSections(\n  out: NavNode[],\n  bySection: Map<string, NavNode[]>,\n  order: readonly string[]\n): void {\n  const seen = new Set<string>();\n  order.forEach((label, i) => {\n    const items = bySection.get(label);\n    if (!items || items.length === 0) return;\n    for (const item of items) out.push({ ...item, order: i });\n    seen.add(label);\n  });\n\n  if (!seen.has(OTHER_SECTION)) {\n    const other = bySection.get(OTHER_SECTION);\n    if (other && other.length > 0) {\n      for (const item of other) out.push({ ...item, order: order.length });\n    }\n  }\n}\n\n/**\n * Resolve one {@link MenuItem} into a top-region nav node, or `null` to skip it.\n *\n * `id: 'home'` / `id: 'source'` (or `sourceFile`) resolve to the built-in home /\n * source link — skipped when that target doesn't exist. Everything else is an\n * external link to `link` (or `href`); an entry with neither a built-in id nor a\n * link is skipped. Icons: an explicit `icon` always wins; home/source fall back\n * to `house` / `code-xml`; an external link falls back to its `id` as a Simple\n * Icons slug, then to `external-link`. Each node is flagged `menu: true`.\n */\nfunction resolveMenuItem(\n  item: MenuItem,\n  home: NavNode | undefined,\n  source: NavNode | undefined,\n  order: number\n): NavNode | null {\n  const title = item.title?.trim();\n  const id = item.id?.trim();\n  const icon = item.icon?.trim();\n  const target = item.target?.trim();\n  const linkClass = item.class?.trim();\n  // Optional presentation fields, attached only when set so untouched entries\n  // stay byte-identical.\n  const extra = {\n    ...(target ? { target } : {}),\n    ...(linkClass ? { class: linkClass } : {}),\n  };\n\n  if (id === HOME_MENU_ID) {\n    if (!home) return null;\n    return {\n      ...home,\n      label: title || home.label,\n      icon: icon || HOME_ICON,\n      menu: true,\n      order,\n      ...extra,\n    };\n  }\n  if (id && (SOURCE_MENU_IDS as readonly string[]).includes(id)) {\n    if (!source) return null;\n    return {\n      ...source,\n      label: title || source.label,\n      icon: icon || SOURCE_ICON,\n      menu: true,\n      order,\n      ...extra,\n    };\n  }\n\n  // External link.\n  const link = (item.link ?? item.href)?.trim();\n  if (link) {\n    return {\n      label: title || link,\n      href: link,\n      external: true,\n      icon: icon || EXTERNAL_ICON,\n      menu: true,\n      order,\n      ...extra,\n    };\n  }\n\n  return null;\n}\n\n/**\n * Nav grouped by page kind in the default section order. Thin wrapper over\n * {@link assembleNav} kept for callers that only need the API section nav.\n */\nexport function buildNav(pages: readonly Page[]): NavNode[] {\n  return assembleNav({ apiPages: pages });\n}\n\n/**\n * `{timestamp}-{hash}` where the hash is a stable digest over slugs + bodies.\n * The timestamp prefix changes per build; the hash suffix is content-stable.\n */\nexport function computeBuildId(pages: readonly Page[]): string {\n  const hash = createHash('sha256');\n  for (const page of pages) {\n    hash.update(page.slug);\n    hash.update('\\0');\n    hash.update(page.body);\n    hash.update('\\0');\n  }\n  return `${Date.now().toString(36)}-${hash.digest('hex').slice(0, 8)}`;\n}\n","import { TDoclet, TJSDocSaltyCollection } from '@clean-jsdoc-theme/utils';\n\nexport interface FilterDocletsOptions {\n  /** Keep doclets marked `undocumented: true`. Default: false. */\n  includeUndocumented?: boolean;\n  /** Keep doclets with `access: 'private'`. Default: false. */\n  includePrivate?: boolean;\n}\n\n/**\n * Visibility/policy filter shared across consumers (class view, sidebar, …).\n * Does not mutate; returns a new array.\n */\nexport function filterDoclets<T extends TDoclet>(\n  doclets: readonly T[],\n  options: FilterDocletsOptions = {}\n): T[] {\n  const includeUndocumented = options.includeUndocumented ?? false;\n  const includePrivate = options.includePrivate ?? false;\n  return doclets.filter((d) => {\n    if (!includeUndocumented && d.undocumented) return false;\n    if (!includePrivate && d.access === 'private') return false;\n    return true;\n  });\n}\n\n/**\n * All doclets whose `memberof` is `longname` — the members of a container\n * (class, interface, mixin, module, namespace, …). Kind-agnostic: callers are\n * expected to check the canonical container doclet exists first.\n *\n * Excludes the container's own doclet: JSDoc can emit a container whose\n * `memberof` equals its own `longname` (an ES6 class with an explicit\n * `@constructor`/`@class` tag is the common trigger), which would otherwise\n * render as a duplicate member heading (the class name) under \"Other\". A real\n * member's longname is always `<container><sep><name>`, never the container\n * longname itself, so dropping `d.longname === longname` is always safe.\n */\nexport function getMembersOf(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  longname: string\n): TDoclet[] {\n  return collection({ memberof: longname })\n    .get()\n    .filter((d) => d.longname !== longname);\n}\n\n/** Alias for {@link getMembersOf} retained for existing class-path callers. */\nexport function getAllMembersOfClass(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  longname: string\n): TDoclet[] {\n  return getMembersOf(collection, longname);\n}\n\n/**\n * A container often appears as multiple doclets sharing one `longname` (e.g. a\n * class's `@class` comment, the constructor `MethodDefinition`, and a merged\n * record). JSDoc/salty marks the partial ones with `undocumented: true`; the\n * merged record is the one without that flag. Pick it. If all candidates are\n * flagged, fall back to the one with the most fields populated. When `kind` is\n * given, the query is narrowed to that kind.\n */\nexport function getCanonicalDoclet(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  longname: string,\n  kind?: string\n): TDoclet | null {\n  const matches = collection(kind ? { kind, longname } : { longname }).get();\n  if (matches.length === 0) return null;\n\n  const documented = matches.find((d) => !d.undocumented);\n  if (documented) return documented;\n\n  return matches.reduce((best, cur) =>\n    Object.keys(cur).length > Object.keys(best).length ? cur : best\n  );\n}\n\n/**\n * Alias for {@link getCanonicalDoclet} narrowed to `kind: 'class'`. Retained\n * for existing class-path callers (e.g. {@link walkAugmentsChain}).\n */\nexport function getCanonicalClassDoclet(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  longname: string\n): TDoclet | null {\n  return getCanonicalDoclet(collection, longname, 'class');\n}\n","import { PageKind, TDoclet, TDocletParam, TJSDocSaltyCollection } from '@clean-jsdoc-theme/utils';\nimport {\n  FilterDocletsOptions,\n  filterDoclets,\n  getAllMembersOfClass,\n  getCanonicalClassDoclet,\n  getCanonicalDoclet,\n} from './doclet';\n\nexport type GetClassViewOptions = FilterDocletsOptions;\n\nexport interface ClassMember extends TDoclet {\n  /** Longname of the ancestor this member was inherited from. Absent on own members. */\n  inheritedFrom?: string;\n}\n\nexport interface MemberBuckets {\n  instanceMethods: ClassMember[];\n  staticMethods: ClassMember[];\n  instanceFields: ClassMember[];\n  staticFields: ClassMember[];\n  /**\n   * Getter/setter accessors (`isAccessor` doclets) — TypeDoc surfaces these in a\n   * dedicated \"Accessors\" section. JSDoc never sets `isAccessor`, so this bucket\n   * is always empty on the JSDoc path (its members stay in the field buckets).\n   */\n  accessors: ClassMember[];\n  enums: ClassMember[];\n  events: ClassMember[];\n  /** Anything that did not match a bucket above (e.g. typedef nested under a class). */\n  other: ClassMember[];\n}\n\nexport interface ClassView extends MemberBuckets {\n  /** Canonical class doclet — see {@link getCanonicalClassDoclet}. */\n  doclet: TDoclet;\n  /** Parent class longnames in declaration order. Empty if this class extends nothing. */\n  augments: string[];\n  /** Constructor params, surfaced for convenience. Also present on `doclet.params`. */\n  constructorParams: TDocletParam[];\n}\n\n/**\n * Kind-parametric superset of {@link ClassView}: the same shape plus the page\n * `kind`. Covers any container (class/interface/mixin/module/namespace). A\n * {@link ClassView} is just a `ContainerView` with `kind: 'class'`.\n */\nexport interface ContainerView extends MemberBuckets {\n  /** Canonical container doclet — see {@link getCanonicalDoclet}. */\n  doclet: TDoclet;\n  /** The page kind this container renders as. */\n  kind: PageKind;\n  /** Parent longnames in declaration order. Empty if this container extends nothing. */\n  augments: string[];\n  /** Constructor params, surfaced for convenience. Empty for non-class kinds. */\n  constructorParams: TDocletParam[];\n  /**\n   * Ordered constructor parameter names, for rendering the call signature when\n   * the constructor is undocumented (no `@param` tags, so `constructorParams` is\n   * empty). Recovered from the `meta.code.paramnames` of any doclet sharing the\n   * longname, so `new Foo(a, b)` still shows. Empty for non-class kinds.\n   */\n  constructorParamNames: string[];\n}\n\n/**\n * Stable key used to detect when one member shadows another. Two members on\n * different scopes (instance vs static) with the same name are distinct\n * surfaces, so scope is part of the key.\n */\nexport function shadowKey(d: TDoclet): string {\n  return `${d.kind ?? ''}:${d.scope ?? ''}:${d.name ?? ''}`;\n}\n\n/**\n * Pure: bucket a flat list of members into roles (instance/static, methods/\n * fields, enums, events). Order within each bucket is preserved.\n */\nexport function bucketClassMembers(members: readonly ClassMember[]): MemberBuckets {\n  const buckets: MemberBuckets = {\n    instanceMethods: [],\n    staticMethods: [],\n    instanceFields: [],\n    staticFields: [],\n    accessors: [],\n    enums: [],\n    events: [],\n    other: [],\n  };\n\n  for (const m of members) {\n    if (m.kind === 'event') {\n      buckets.events.push(m);\n    } else if (m.isEnum) {\n      buckets.enums.push(m);\n    } else if (m.isAccessor) {\n      // Accessors are `kind: 'member'`; route them out before the field branch.\n      // Only the TypeDoc bridge sets this flag, so JSDoc bucketing is unchanged.\n      buckets.accessors.push(m);\n    } else if (m.kind === 'function') {\n      (m.scope === 'static' ? buckets.staticMethods : buckets.instanceMethods).push(m);\n    } else if (m.kind === 'member') {\n      (m.scope === 'static' ? buckets.staticFields : buckets.instanceFields).push(m);\n    } else {\n      buckets.other.push(m);\n    }\n  }\n\n  return buckets;\n}\n\n/**\n * Returns ancestor class longnames reachable from `longname` via `augments`,\n * in BFS order. Excludes `longname` itself. Safe against cycles and missing\n * ancestors (chain stops where the parent doclet is not found).\n */\nexport function walkAugmentsChain(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  longname: string\n): string[] {\n  const result: string[] = [];\n  const visited = new Set<string>([longname]);\n  const start = getCanonicalClassDoclet(collection, longname);\n  const queue: string[] = [...(start?.augments ?? [])];\n\n  while (queue.length > 0) {\n    const parent = queue.shift() as string;\n    if (visited.has(parent)) continue;\n    visited.add(parent);\n    result.push(parent);\n\n    const parentDoclet = getCanonicalClassDoclet(collection, parent);\n    if (parentDoclet?.augments) queue.push(...parentDoclet.augments);\n  }\n\n  return result;\n}\n\n/**\n * Members inherited from `longname`'s ancestors, with `inheritedFrom` set to\n * the ancestor's longname. Walks via {@link walkAugmentsChain} so closer\n * ancestors win shadow conflicts over distant ones. Does NOT shadow against\n * the class's own members — pass own-member shadow keys via `shadowedBy` for\n * that, or let {@link getClassView} compose it for you.\n */\nexport function getInheritedMembers(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  longname: string,\n  options: GetClassViewOptions = {},\n  shadowedBy: ReadonlySet<string> = new Set()\n): ClassMember[] {\n  const taken = new Set<string>(shadowedBy);\n  const inherited: ClassMember[] = [];\n\n  for (const ancestor of walkAugmentsChain(collection, longname)) {\n    const members = filterDoclets(getAllMembersOfClass(collection, ancestor), options);\n    for (const m of members) {\n      const key = shadowKey(m);\n      if (taken.has(key)) continue;\n      taken.add(key);\n      inherited.push({ ...m, inheritedFrom: ancestor });\n    }\n  }\n\n  return inherited;\n}\n\n/**\n * Returns the class's own members, filtered by `options`, with `inheritedFrom`\n * set on any doclets that JSDoc itself marked as inherited (via `inherited` +\n * `inherits` fields — distinct from the `augments` walk we do separately).\n */\nexport function getOwnClassMembers(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  longname: string,\n  options: GetClassViewOptions = {}\n): ClassMember[] {\n  return filterDoclets(getAllMembersOfClass(collection, longname), options).map((d) =>\n    d.inherited && d.inherits ? { ...d, inheritedFrom: d.inherits } : { ...d }\n  );\n}\n\n/**\n * Composes the building blocks into a container view ready for the renderer.\n * Returns `null` if no doclet of `kind` matches `longname`.\n *\n * - Own members are kind-agnostic (via {@link getOwnClassMembers}).\n * - The inheritance walk ({@link getInheritedMembers}) runs only for `class`\n *   and `interface` — the kinds that `@augments`/`@extends`. Other containers\n *   use own members only.\n * - `constructorParams` is populated only for `class` (`canonical.params`);\n *   empty for every other kind.\n */\nexport function getContainerView(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  longname: string,\n  kind: PageKind,\n  options: GetClassViewOptions = {}\n): ContainerView | null {\n  const canonical = getCanonicalDoclet(collection, longname, kind);\n  if (!canonical) return null;\n\n  const own = getOwnClassMembers(collection, longname, options);\n\n  const walksInheritance = kind === 'class' || kind === 'interface';\n  let inherited: ClassMember[] = [];\n  if (walksInheritance) {\n    const ownKeys = new Set(own.map(shadowKey));\n    inherited = getInheritedMembers(collection, longname, options, ownKeys);\n  }\n\n  const constructorParams = kind === 'class' ? (canonical.params ?? []) : [];\n\n  // Signature fallback for an undocumented constructor (no `@param` tags, so\n  // `constructorParams` is empty): the param NAMES still live on\n  // `meta.code.paramnames`, often on a sibling doclet of the same longname (the\n  // canonical/classdesc doclet may carry none). Recover them so the call\n  // signature can show `new Foo(a, b)` rather than a bare `new Foo()`. Empty when\n  // params are documented (the table-backed `constructorParams` is used instead).\n  let constructorParamNames: string[] = [];\n  if (kind === 'class' && constructorParams.length === 0) {\n    for (const d of collection({ longname }).get()) {\n      const names = d.meta?.code?.paramnames;\n      if (names && names.length > 0) {\n        constructorParamNames = [...names];\n        break;\n      }\n    }\n  }\n\n  return {\n    doclet: canonical,\n    kind,\n    augments: canonical.augments ?? [],\n    constructorParams,\n    constructorParamNames,\n    ...bucketClassMembers([...own, ...inherited]),\n  };\n}\n\n/** First non-empty array, base first; falls back to whichever is defined. */\nfunction pickArr<T>(a: readonly T[] | undefined, b: readonly T[] | undefined): T[] | undefined {\n  if (a && a.length) return a as T[];\n  if (b && b.length) return b as T[];\n  return (a ?? b) as T[] | undefined;\n}\n\n/** First defined scalar, base first. */\nfunction pickScalar<T>(a: T | undefined, b: T | undefined): T | undefined {\n  return a ?? b;\n}\n\n/**\n * Union the seven member buckets of two view, base-first, deduped by\n * {@link shadowKey} so a member present in both sides (e.g. an inherited member\n * that both doclets surface) appears once, keeping the base occurrence.\n */\nfunction mergeMemberBuckets(a: MemberBuckets, b: MemberBuckets): MemberBuckets {\n  const keys: (keyof MemberBuckets)[] = [\n    'instanceMethods',\n    'staticMethods',\n    'instanceFields',\n    'staticFields',\n    'accessors',\n    'enums',\n    'events',\n    'other',\n  ];\n  const out = {} as MemberBuckets;\n  for (const k of keys) {\n    const seen = new Set<string>();\n    const merged: ClassMember[] = [];\n    for (const m of [...a[k], ...b[k]]) {\n      const key = shadowKey(m);\n      if (seen.has(key)) continue;\n      seen.add(key);\n      merged.push(m);\n    }\n    out[k] = merged;\n  }\n  return out;\n}\n\n/**\n * Merge two container views that collapsed onto the same page slug.\n *\n * A single `@module` symbol is frequently emitted by JSDoc as two `kind:'class'`\n * doclets that slugify identically — e.g. `module:queue/Queue~Queue` (carries the\n * `classdesc`, `@augments`/`@implements`/`@mixes`, metadata, and instance\n * members) and `module:queue/Queue.Queue` (carries the constructor `@param`s and\n * possibly other members). The dedup pass would otherwise keep one and drop the\n * other, silently losing whichever fields lived only on the dropped doclet — the\n * surviving page would be missing its Constructor/Parameters section AND any\n * members under the dropped longname. Merging recovers both so neither doclet's\n * classdesc, params, relations, nor members are lost.\n *\n * Deterministic: `base` is the first-seen view, `extra` the colliding one. `base`\n * wins for any field it actually carries; `extra` only fills gaps (empty/absent\n * scalars, empty/absent arrays). Members are unioned and deduped by\n * {@link shadowKey}.\n */\nexport function mergeContainerViews(base: ContainerView, extra: ContainerView): ContainerView {\n  // Start from extra, let base override field-by-field, then patch the fields\n  // where base may hold an empty value that extra can fill.\n  const doclet: TDoclet = { ...extra.doclet, ...base.doclet };\n\n  // Scalars: first defined, base first.\n  doclet.classdesc = pickScalar(base.doclet.classdesc, extra.doclet.classdesc);\n  doclet.description = pickScalar(base.doclet.description, extra.doclet.description);\n  doclet.summary = pickScalar(base.doclet.summary, extra.doclet.summary);\n  doclet.deprecated = pickScalar(base.doclet.deprecated, extra.doclet.deprecated);\n  doclet.since = pickScalar(base.doclet.since, extra.doclet.since);\n  doclet.version = pickScalar(base.doclet.version, extra.doclet.version);\n  doclet.license = pickScalar(base.doclet.license, extra.doclet.license);\n  doclet.copyright = pickScalar(base.doclet.copyright, extra.doclet.copyright);\n  doclet.this = pickScalar(base.doclet.this, extra.doclet.this);\n  doclet.alias = pickScalar(base.doclet.alias, extra.doclet.alias);\n\n  // Arrays: first non-empty, base first. `params` is the critical one — the\n  // classdesc doclet usually has none, the constructor doclet has them.\n  doclet.params = pickArr(base.doclet.params, extra.doclet.params);\n  doclet.augments = pickArr(base.doclet.augments, extra.doclet.augments);\n  doclet.implements = pickArr(base.doclet.implements, extra.doclet.implements);\n  doclet.mixes = pickArr(base.doclet.mixes, extra.doclet.mixes);\n  doclet.examples = pickArr(base.doclet.examples, extra.doclet.examples);\n  doclet.properties = pickArr(base.doclet.properties, extra.doclet.properties);\n  doclet.fires = pickArr(base.doclet.fires, extra.doclet.fires);\n  doclet.listens = pickArr(base.doclet.listens, extra.doclet.listens);\n  doclet.see = pickArr(base.doclet.see, extra.doclet.see);\n  doclet.todo = pickArr(base.doclet.todo, extra.doclet.todo);\n  doclet.author = pickArr(base.doclet.author, extra.doclet.author);\n  doclet.requires = pickArr(base.doclet.requires, extra.doclet.requires);\n  doclet.tutorials = pickArr(base.doclet.tutorials, extra.doclet.tutorials);\n\n  return {\n    doclet,\n    kind: base.kind,\n    augments: pickArr(base.augments, extra.augments) ?? [],\n    constructorParams: base.constructorParams.length\n      ? base.constructorParams\n      : extra.constructorParams,\n    constructorParamNames: base.constructorParamNames.length\n      ? base.constructorParamNames\n      : extra.constructorParamNames,\n    ...mergeMemberBuckets(base, extra),\n  };\n}\n\n/**\n * Composes the building blocks into a class view ready for the renderer.\n * Returns `null` if no class doclet matches `longname`. Thin alias over\n * {@link getContainerView} with `kind: 'class'`.\n */\nexport function getClassView(\n  collection: TJSDocSaltyCollection<TDoclet>,\n  longname: string,\n  options: GetClassViewOptions = {}\n): ClassView | null {\n  return getContainerView(collection, longname, 'class', options);\n}\n","import type { PhrasingContent, Root, RootContent } from 'mdast';\nimport { ClassMember, ClassView, ContainerView, MemberBuckets } from '../class-view';\nimport { slugifyHeading, TDoclet, TDocletOverload, TDocletParam, TDocletTypeParam } from '@clean-jsdoc-theme/utils';\nimport { emphasis, h, hr, inlineCode, li, link, memberHeading, memberMeta, p, root, signature, strong, text, ul } from './builders';\nimport {\n  docletBlocks,\n  DocletBlocksOptions,\n  type DocletSection,\n  paramsList,\n  sourceLinkBlock,\n  typeExpressionString,\n} from './doclet';\nimport { htmlToMdastBlocks } from './from-html';\nimport { resolveSlotText } from '../slots';\n\nexport interface ClassViewToMdastOptions extends DocletBlocksOptions {\n  /** Heading level for the class title. Default: 1. */\n  pageHeadingLevel?: 1 | 2;\n  /** Drop empty member sections from output. Default: true. */\n  hideEmptySections?: boolean;\n  /**\n   * Document-model flavor. `'typedoc'` switches a class's member sections to\n   * TypeDoc labels (Constructors/Properties/Methods/Accessors), renders enum\n   * pages with an \"Enumeration Members\" section, and turns a module/namespace\n   * page into a kind-grouped index of links to its exports. `'jsdoc'` (default)\n   * keeps the original sections — byte-identical output.\n   */\n  flavor?: 'jsdoc' | 'typedoc';\n}\n\ninterface SectionSpec {\n  title: string;\n  members: ClassMember[];\n}\n\n/**\n * Default section order. A renderer that wants a different layout can build\n * its own SectionSpec[] and pass it to {@link memberSections}.\n */\nexport function defaultSections(buckets: MemberBuckets): SectionSpec[] {\n  return [\n    { title: 'Instance Methods', members: buckets.instanceMethods },\n    { title: 'Static Methods', members: buckets.staticMethods },\n    { title: 'Instance Fields', members: buckets.instanceFields },\n    { title: 'Static Fields', members: buckets.staticFields },\n    { title: 'Enums', members: buckets.enums },\n    { title: 'Events', members: buckets.events },\n    { title: 'Other', members: buckets.other },\n  ];\n}\n\n/**\n * TypeDoc-flavored member sections for a class/interface/mixin — TypeDoc's\n * labels (Properties / Accessors / Methods, plus static variants + Events). The\n * Constructor(s) section is emitted separately by {@link containerViewToMdast}.\n * Empty sections drop out via {@link memberSections}' `hideEmptySections`.\n */\nexport function typedocClassSections(buckets: MemberBuckets): SectionSpec[] {\n  return [\n    { title: 'Properties', members: buckets.instanceFields },\n    { title: 'Accessors', members: buckets.accessors },\n    { title: 'Methods', members: buckets.instanceMethods },\n    { title: 'Static Properties', members: buckets.staticFields },\n    { title: 'Static Methods', members: buckets.staticMethods },\n    { title: 'Events', members: buckets.events },\n    { title: 'Other', members: buckets.other },\n  ];\n}\n\n/** Enum page: every member collapsed under one \"Enumeration Members\" section. */\nexport function enumMemberSections(buckets: MemberBuckets): SectionSpec[] {\n  return [\n    {\n      title: 'Enumeration Members',\n      members: [\n        ...buckets.staticFields,\n        ...buckets.instanceFields,\n        ...buckets.enums,\n        ...buckets.other,\n      ],\n    },\n  ];\n}\n\n/**\n * Child-symbol → index section label, in TypeDoc display order. A member is\n * placed under the FIRST group it matches (so an `isEnum` symbol lands in\n * Enumerations, never Variables).\n */\nconst TYPEDOC_INDEX_GROUPS: { label: string; match: (m: ClassMember) => boolean }[] = [\n  { label: 'Enumerations', match: (m) => m.isEnum === true || m.kind === 'enum' },\n  { label: 'Classes', match: (m) => m.kind === 'class' },\n  { label: 'Interfaces', match: (m) => m.kind === 'interface' },\n  { label: 'Type Aliases', match: (m) => m.kind === 'typedef' },\n  { label: 'Functions', match: (m) => m.kind === 'function' },\n  { label: 'Variables', match: (m) => m.kind === 'variable' || m.kind === 'member' },\n  { label: 'Namespaces', match: (m) => m.kind === 'namespace' },\n  { label: 'Mixins', match: (m) => m.kind === 'mixin' },\n];\n\n/**\n * A module/namespace page under the typedoc flavor: a kind-grouped index of\n * LINKS to the exports that each own a standalone page, instead of inlining\n * their member bodies (matching default TypeDoc's module page). An export whose\n * longname doesn't resolve falls back to inert code.\n */\nexport function moduleIndexBlocks(\n  view: ContainerView,\n  options: ClassViewToMdastOptions\n): RootContent[] {\n  const members: ClassMember[] = [\n    ...view.instanceMethods,\n    ...view.staticMethods,\n    ...view.instanceFields,\n    ...view.staticFields,\n    ...view.accessors,\n    ...view.enums,\n    ...view.events,\n    ...view.other,\n  ];\n  if (members.length === 0) return [];\n\n  // Assign each member to the first matching group, preserving member order.\n  const grouped = new Map<string, ClassMember[]>();\n  for (const m of members) {\n    const group = TYPEDOC_INDEX_GROUPS.find((g) => g.match(m));\n    if (!group) continue;\n    const arr = grouped.get(group.label);\n    if (arr) arr.push(m);\n    else grouped.set(group.label, [m]);\n  }\n  if (grouped.size === 0) return [];\n\n  const resolve = options.resolveLink;\n  const blocks: RootContent[] = [hr()];\n  for (const { label } of TYPEDOC_INDEX_GROUPS) {\n    const items = grouped.get(label);\n    if (!items || items.length === 0) continue;\n    blocks.push(h(2, text(label)));\n    blocks.push(\n      ul(\n        items.map((m) => {\n          const name = m.name ?? m.longname ?? '(anonymous)';\n          const resolved = m.longname ? (resolve?.(m.longname) ?? null) : null;\n          const child: PhrasingContent =\n            resolved && !resolved.external ? link(resolved.href, inlineCode(name)) : inlineCode(name);\n          return li(p(child));\n        })\n      )\n    );\n  }\n  return blocks;\n}\n\n/**\n * Inline signature suffix shown after a method/function name in its heading,\n * e.g. `(data) -> Promise.<number>`. Top-level params only (nested\n * `options.timeout` entries live in the Parameters table), names only — no param\n * types — matching the requested heading style; the return type follows ` -> `.\n * Returns `undefined` for non-functions, so fields/constants keep a bare name.\n */\nexport function memberSignatureSuffix(member: ClassMember): string | undefined {\n  if (member.kind !== 'function') return undefined;\n  const params = (member.params ?? [])\n    .filter((param) => param.name && !param.name.includes('.'))\n    .map((param) => param.name)\n    .join(', ');\n  const ret = typeExpressionString(member.returns?.[0]?.type);\n  return `(${params})${ret ? ` -> ${ret}` : ''}`;\n}\n\n/**\n * Constructor call-signature for a class, e.g. `new Widget(id, [opts])`. Top-level\n * params only (nested `options.timeout` entries live in the Parameters table),\n * names only — no param types — mirroring {@link memberSignatureSuffix}. Optional\n * params are wrapped `[name]` and rest params prefixed `...name`, the look the\n * default JSDoc template gives a constructor. `name` is the class name.\n */\nexport function constructorSignature(name: string, params: readonly TDocletParam[]): string {\n  const list = params\n    .filter((param) => param.name && !param.name.includes('.'))\n    .map((param) => {\n      const pname = param.variable ? `...${param.name}` : (param.name as string);\n      return param.optional ? `[${pname}]` : pname;\n    })\n    .join(', ');\n  return `new ${name}(${list})`;\n}\n\n// ── TypeScript signature rendering (typedoc flavor) ──────────────────────────\n//\n// Build the full TS signature default TypeDoc shows — `new Component<P extends\n// ComponentProps = ComponentProps, S extends object = object>(props: P):\n// Component<P, S>`, `addChild(child: Component): void`, `get state():\n// ComponentState`, `_props: P`. JSDoc never reaches this path (gated on the\n// typedoc flavor), so its `memberSignatureSuffix`/`constructorSignature`\n// rendering is untouched.\n\n/** Wrap a single-line signature onto multiple lines past this width. */\nconst SIG_WRAP_WIDTH = 64;\n\n/** A type expression → its readable string (the `type.names`, `|`-joined). */\nfunction tsType(type: { names?: readonly string[] } | undefined): string {\n  return type?.names && type.names.length > 0 ? type.names.join(' | ') : '';\n}\n\n/** `<T extends C = D, …>` parts (one string per type parameter), or `[]`. */\nfunction tsTypeParamParts(typeParams: readonly TDocletTypeParam[] | undefined): string[] {\n  if (!typeParams || typeParams.length === 0) return [];\n  return typeParams.map((tp) => {\n    let s = tp.name;\n    if (tp.constraint) s += ` extends ${tp.constraint}`;\n    if (tp.default !== undefined && tp.default !== '') s += ` = ${tp.default}`;\n    return s;\n  });\n}\n\n/** `name: Type`, with `?` for optional and `...` for rest; top-level params only. */\nfunction tsParamParts(params: readonly TDocletParam[] | undefined): string[] {\n  if (!params) return [];\n  return params\n    .filter((pm) => pm.name && !pm.name.includes('.'))\n    .map((pm) => {\n      const base = pm.variable ? `...${pm.name}` : (pm.name as string);\n      const t = tsType(pm.type);\n      return `${base}${pm.optional ? '?' : ''}${t ? `: ${t}` : ''}`;\n    });\n}\n\n/**\n * Assemble a callable signature, wrapping onto multiple lines (one type param /\n * param per indented line) once the single-line form is long — matching how\n * default TypeDoc lays out wide constructor/method signatures.\n */\nfunction formatCallable(\n  prefix: string,\n  typeParamParts: readonly string[],\n  paramParts: readonly string[],\n  ret: string\n): string {\n  const tp = typeParamParts.length > 0 ? `<${typeParamParts.join(', ')}>` : '';\n  const single = `${prefix}${tp}(${paramParts.join(', ')})${ret}`;\n  if (single.length <= SIG_WRAP_WIDTH) return single;\n\n  // One type-param / param per line, each indented with a tab so the wrapped\n  // signature reads as an indented block (rang renders it `white-space: pre-wrap`,\n  // `tab-size: 2`). Matches how default TypeDoc lays out a wide signature.\n  const lines: string[] = [];\n  if (typeParamParts.length > 0) {\n    lines.push(`${prefix}<`);\n    for (const t of typeParamParts) lines.push(`\\t${t},`);\n    lines.push('>(');\n  } else {\n    lines.push(`${prefix}(`);\n  }\n  for (const pm of paramParts) lines.push(`\\t${pm},`);\n  lines.push(`)${ret}`);\n  return lines.join('\\n');\n}\n\n/** The class instance type for a constructor's return, e.g. `Component<P, S>`. */\nfunction instanceType(className: string, typeParams: readonly TDocletTypeParam[] | undefined): string {\n  if (!typeParams || typeParams.length === 0) return className;\n  return `${className}<${typeParams.map((tp) => tp.name).join(', ')}>`;\n}\n\n/** Full TS constructor signature, e.g. `new Widget<T>(opts: T): Widget<T>`. */\nfunction tsConstructorSignature(\n  className: string,\n  typeParams: readonly TDocletTypeParam[] | undefined,\n  params: readonly TDocletParam[]\n): string {\n  return formatCallable(\n    `new ${className}`,\n    tsTypeParamParts(typeParams),\n    tsParamParts(params),\n    `: ${instanceType(className, typeParams)}`\n  );\n}\n\n/** A callable signature `name<T>(p: T): Ret` from explicit signature parts. */\nfunction tsCallableSignature(\n  name: string,\n  typeParams: readonly TDocletTypeParam[] | undefined,\n  params: readonly TDocletParam[] | undefined,\n  returns: readonly TDocletParam[] | undefined\n): string {\n  const ret = tsType(returns?.[0]?.type);\n  return formatCallable(name, tsTypeParamParts(typeParams), tsParamParts(params), ret ? `: ${ret}` : '');\n}\n\n/**\n * Full TS signature for a member: a callable form for functions/methods\n * (`name<T>(p: T): Ret`), `get name(): Type` for accessors, and `name: Type`\n * for fields. Returns `null` when there's nothing meaningful to show.\n */\nfunction tsMemberSignature(member: ClassMember): string | null {\n  const name = member.name;\n  if (!name) return null;\n  if (member.kind === 'function') {\n    return tsCallableSignature(name, member.typeParams, member.params, member.returns);\n  }\n  const t = tsType(member.type);\n  if (member.isAccessor) return `get ${name}()${t ? `: ${t}` : ''}`;\n  return t ? `${name}: ${t}` : name;\n}\n\n/**\n * An object type literal `{ a: T; b?: U }` rebuilt from a doclet's `properties`,\n * wrapping onto indented lines (one member per line) once the single-line form is\n * long — matching how default TypeDoc lays out a wide object type. Nested\n * `options.timeout`-style entries are dropped (only the top-level shape shows;\n * the Properties section carries the full nesting). Used for the declaration\n * block of an object-literal variable (`HTTP_STATUS: { … }`) and object-literal\n * type alias.\n */\nfunction objectLiteralFromProperties(properties: readonly TDocletParam[]): string {\n  const members = properties\n    .filter((p) => p.name && !p.name.includes('.'))\n    .map((p) => {\n      const t = tsType(p.type);\n      return `${p.name}${p.optional ? '?' : ''}${t ? `: ${t}` : ''}`;\n    });\n  if (members.length === 0) return '{}';\n  const single = `{ ${members.join('; ')} }`;\n  if (single.length <= SIG_WRAP_WIDTH) return single;\n  return `{\\n${members.map((m) => `\\t${m};`).join('\\n')}\\n}`;\n}\n\n/**\n * Declaration block for a standalone variable page (typedoc flavor), e.g.\n * `HTTP_STATUS: { OK: 200; … }` or `VERSION: string`. An object-literal value\n * (its members recovered onto `properties` by the bridge) shows its shape; any\n * other value falls back to the member signature (`name: Type`).\n */\nfunction variableSignature(doclet: ContainerView['doclet']): string | null {\n  const name = doclet.name;\n  if (name && doclet.properties && doclet.properties.length > 0) {\n    return `${name}: ${objectLiteralFromProperties(doclet.properties as TDocletParam[])}`;\n  }\n  return tsMemberSignature(doclet as ClassMember);\n}\n\n/**\n * Declaration block for a standalone type-alias (typedef) page (typedoc flavor),\n * matching default TypeDoc's leading declaration. Three shapes:\n *   - function-type alias → arrow form `Name<T> = (p: P) => R`,\n *   - object-literal alias → `Name = { a: T; … }` (rebuilt from `properties`),\n *   - anything else (union / primitive / reference) → `Name = <type string>`.\n * Returns `null` when there's nothing meaningful to show.\n */\nfunction typedefSignature(doclet: ContainerView['doclet']): string | null {\n  const name = doclet.name;\n  if (!name) return null;\n  const tpParts = tsTypeParamParts(doclet.typeParams);\n  const head = tpParts.length > 0 ? `${name}<${tpParts.join(', ')}>` : name;\n\n  // Function-type alias: `type Fn = (x: number) => boolean` — the bridge sets\n  // `type.names === ['function']` and lifts the signature's params/returns.\n  if (doclet.type?.names?.length === 1 && doclet.type.names[0] === 'function') {\n    const params = tsParamParts(doclet.params).join(', ');\n    const ret = tsType(doclet.returns?.[0]?.type) || 'void';\n    return `${head} = (${params}) => ${ret}`;\n  }\n\n  // Object-literal alias: rebuild `{ … }` from the recovered properties.\n  if (doclet.properties && doclet.properties.length > 0) {\n    return `${head} = ${objectLiteralFromProperties(doclet.properties as TDocletParam[])}`;\n  }\n\n  // Plain alias: a single readable type string (union / primitive / reference).\n  const t = tsType(doclet.type);\n  if (!t || t === 'Object') return null;\n  return `${head} = ${t}`;\n}\n\n/** One interface member rendered as a TS declaration line (`name?(p: P): R`). */\nfunction interfaceMemberLine(member: ClassMember): string {\n  const name = member.name ?? '';\n  const opt = member.optional ? '?' : '';\n  if (member.kind === 'function') {\n    const tp = tsTypeParamParts(member.typeParams);\n    const tpStr = tp.length > 0 ? `<${tp.join(', ')}>` : '';\n    const params = tsParamParts(member.params).join(', ');\n    const ret = tsType(member.returns?.[0]?.type);\n    return `${name}${opt}${tpStr}(${params})${ret ? `: ${ret}` : ''}`;\n  }\n  const t = tsType(member.type);\n  if (member.isAccessor) return `get ${name}()${t ? `: ${t}` : ''}`;\n  return `${name}${opt}${t ? `: ${t}` : ''}`;\n}\n\n/**\n * Declaration block for a standalone interface page (typedoc flavor): the full\n * `interface Name<T> extends Base { member; … }` overview default TypeDoc shows\n * at the top, before the detailed member sections. Members come from the view's\n * buckets (properties, then accessors, then methods, static last) so the block\n * mirrors the page's own ordering. Always multiline so the shape reads clearly.\n */\nfunction interfaceSignature(view: ContainerView): string {\n  const name = view.doclet.name ?? view.doclet.longname ?? 'Interface';\n  const tp = tsTypeParamParts(view.doclet.typeParams);\n  const tpStr = tp.length > 0 ? `<${tp.join(', ')}>` : '';\n  const ext =\n    view.doclet.augments && view.doclet.augments.length > 0\n      ? ` extends ${view.doclet.augments.join(', ')}`\n      : '';\n  const members: ClassMember[] = [\n    ...view.instanceFields,\n    ...view.accessors,\n    ...view.instanceMethods,\n    ...view.staticFields,\n    ...view.staticMethods,\n  ];\n  const head = `interface ${name}${tpStr}${ext}`;\n  if (members.length === 0) return `${head} {}`;\n  const lines = members.map((m) => `\\t${interfaceMemberLine(m)};`);\n  return `${head} {\\n${lines.join('\\n')}\\n}`;\n}\n\n/** A callable doclet (function/method) that carries overload signatures. */\nfunction hasOverloads(doclet: { overloads?: readonly TDocletOverload[] }): boolean {\n  return (doclet.overloads?.length ?? 0) > 0;\n}\n\n/**\n * Sections rendered once on the shared member body when a callable is\n * overloaded — its `ts` signatures (with per-signature type params / parameters\n * / returns) move into {@link overloadSignatureBlocks}, so the shared body skips\n * exactly those.\n */\nconst SHARED_BODY_SKIP_FOR_OVERLOADS: readonly DocletSection[] = [\n  'typeParams',\n  'params',\n  'returns',\n  'type',\n];\n\n/**\n * Per-signature body sections: everything *except* the signature's own type\n * params / parameters / returns is rendered once on the shared body, so a\n * per-signature render skips it. (A signature's own `description` isn't a\n * skippable section — it flows through {@link docletBlocks} — which is exactly\n * how an overload's description renders under its own block.)\n */\nconst PER_SIGNATURE_SKIP: readonly DocletSection[] = [\n  'summary',\n  'modifiers',\n  'relations',\n  'this',\n  'alias',\n  'remarks',\n  'properties',\n  'yields',\n  'throws',\n  'type',\n  'default',\n  'fires',\n  'listens',\n  'examples',\n  'iframes',\n  'metadata',\n  'deprecation',\n  'inherited',\n];\n\n/**\n * One `<Signature>` per call signature of an overloaded function/method — the\n * first signature (from the doclet's own `typeParams`/`params`/`returns`) then\n * each `overloads[]` entry — each followed by that signature's Type Parameters /\n * Parameters / Returns (and an overload's own description). Matches default\n * TypeDoc, which stacks every overload signature with its own parameters. The\n * first signature's shared description/examples/etc. already render on the\n * member body, so they aren't repeated here. Only reached under the typedoc\n * flavor for a doclet that {@link hasOverloads}.\n */\nfunction overloadSignatureBlocks(\n  doclet: ClassMember | ContainerView['doclet'],\n  options: DocletBlocksOptions\n): RootContent[] {\n  const name = doclet.name;\n  if (!name) return [];\n  const signatures: TDocletOverload[] = [\n    { typeParams: doclet.typeParams, params: doclet.params, returns: doclet.returns },\n    ...(doclet.overloads ?? []),\n  ];\n  const out: RootContent[] = [];\n  for (const sig of signatures) {\n    out.push(signature(tsCallableSignature(name, sig.typeParams, sig.params, sig.returns)));\n    // A synthetic doclet carrying only this signature's data, so docletBlocks\n    // renders its Type Parameters / Parameters / Returns (and the overload's own\n    // description, which isn't a skippable section).\n    const synthetic: TDoclet = {\n      kind: doclet.kind,\n      name,\n      longname: doclet.longname,\n      scope: doclet.scope,\n      typeParams: sig.typeParams,\n      params: sig.params,\n      returns: sig.returns,\n    };\n    if (sig.description) synthetic.description = sig.description;\n    out.push(...docletBlocks(synthetic, { ...options, skip: PER_SIGNATURE_SKIP }));\n  }\n  return out;\n}\n\n/**\n * Modifier / kind badges for a member, in display order. Mirrors\n * {@link modifiersBlock} but adds the scope (`static`) and `deprecated` flags,\n * and drops the redundant `public` access (the default). Replaces the old\n * \"Modifiers:\" paragraph — `memberBlocks` skips that section.\n */\nexport function memberBadges(member: ClassMember): string[] {\n  const badges: string[] = [];\n  if (member.scope === 'static') badges.push('static');\n  if (member.async) badges.push('async');\n  if (member.generator) badges.push('generator');\n  if (member.virtual) badges.push('abstract');\n  if (member.readonly) badges.push('readonly');\n  if (member.kind === 'event') badges.push('event');\n  if (member.isEnum) badges.push('enum');\n  if (member.access && member.access !== 'public') badges.push(member.access);\n  if (member.deprecated) badges.push('deprecated');\n  return badges;\n}\n\n/**\n * Render one member as: a `<MemberHeading>` (an `h{depth}` whose content is one\n * `<code>` showing the full signature — `process(data) -> Promise.<number>` for\n * methods/functions, the bare name for fields — with an explicit id so the\n * anchor stays `slugifyHeading(name)`); a `<MemberMeta>` row (modifier/kind\n * chips on the left, the `filename:line` source link pinned right); then the\n * doclet's body via {@link docletBlocks}. TOC / search / `{@link}` resolve to\n * `#name` because the signature never feeds the slug (see {@link memberHeading}).\n * The `modifiers` section is skipped — the chips replace that paragraph.\n * Reusable for any kind with named, headed members.\n */\nexport function memberBlocks(\n  member: ClassMember,\n  options: DocletBlocksOptions = {},\n  headingLevel: 2 | 3 | 4 = 3\n): RootContent[] {\n  const name = member.name ?? '(anonymous)';\n  // The heading shows the full TypeScript signature (`addChild(child: Component):\n  // void`), shiki-highlighted inline by rang's MemberHeading — the same look in\n  // both flavors. The anchor stays `#name` (explicit id; the sig never feeds the\n  // slug). An overloaded member can't put N signatures in one heading, so it\n  // keeps a bare-name heading and stacks each signature as a `<Signature>` below.\n  const overloaded = options.flavor === 'typedoc' && hasOverloads(member);\n  const sig = overloaded ? name : (tsMemberSignature(member) ?? name);\n  const out: RootContent[] = [\n    memberHeading({ id: slugifyHeading(name), depth: headingLevel, name, sig }),\n  ];\n\n  const badges = memberBadges(member);\n  const resolved = options.sourceLink?.(member) ?? undefined;\n  if (badges.length > 0 || resolved) {\n    out.push(memberMeta({ badges, sourceHref: resolved?.href, sourceLabel: resolved?.label }));\n  }\n\n  // Inherited from / Overrides / Implementation of — typedoc flavor only (see\n  // memberRelationCaption's early return); emitted right after the heading/meta,\n  // before the member's body.\n  out.push(...memberRelationCaption(member, options));\n\n  // The type now lives in the heading signature, so the body's \"Type\" field is\n  // redundant in both flavors.\n  const skip: DocletSection[] = [...(options.skip ?? []), 'modifiers', 'type'];\n  // Under the typedoc flavor the caption above already renders \"Inherited from\"\n  // (from `inherits`, the `inherited` section) and \"Overrides\" (from `overrides`,\n  // part of the `relations` section) as short-name links — so suppress those\n  // body sections to avoid the raw-longname duplicate. TypeDoc members never\n  // carry member-level Extends/Implements/Mixes/Borrows (those are container-\n  // level, handled by relationshipBlocks), so dropping `relations` here loses\n  // nothing on the typedoc path. JSDoc keeps both sections → byte-identical.\n  if (options.flavor === 'typedoc') {\n    skip.push('inherited', 'relations');\n  }\n  if (overloaded) {\n    // The shared body (description/examples/…) renders once with its\n    // per-signature sections suppressed, then every signature stacks below with\n    // its own parameters/returns — matching default TypeDoc.\n    out.push(...docletBlocks(member, { ...options, skip: [...skip, ...SHARED_BODY_SKIP_FOR_OVERLOADS] }));\n    out.push(...overloadSignatureBlocks(member, options));\n    return out;\n  }\n\n  out.push(...docletBlocks(member, { ...options, skip }));\n  return out;\n}\n\n/**\n * Render N sections, each: H2 + per-member H3 blocks. Empty sections are\n * dropped unless `hideEmptySections` is false.\n */\nexport function memberSections(\n  sections: readonly SectionSpec[],\n  options: ClassViewToMdastOptions = {}\n): RootContent[] {\n  const hideEmpty = options.hideEmptySections ?? true;\n  const out: RootContent[] = [];\n  for (const section of sections) {\n    if (hideEmpty && section.members.length === 0) continue;\n    out.push(h(2, text(section.title)));\n    for (const member of section.members) {\n      out.push(...memberBlocks(member, options));\n    }\n  }\n  return out;\n}\n\n/**\n * \"Extends\" / \"Implements\" / \"Mixes\" lines for a class. Returns the blocks\n * that apply; empty if none. Each referenced symbol hyperlinks to its page when\n * `resolveLink` is supplied and the name resolves — otherwise it stays inert\n * code, byte-identical to before.\n */\nexport function classRelationsBlocks(\n  doclet: ClassView['doclet'],\n  resolveLink?: DocletBlocksOptions['resolveLink']\n): RootContent[] {\n  const lines: { label: string; refs: readonly string[] | undefined }[] = [\n    { label: 'Extends', refs: doclet.augments },\n    { label: 'Implements', refs: doclet.implements },\n    { label: 'Mixes', refs: doclet.mixes },\n  ];\n\n  return lines\n    .filter(({ refs }) => refs && refs.length > 0)\n    .map(({ label, refs }) => {\n      const children: PhrasingContent[] = [strong(text(`${label}: `))];\n      refs!.forEach((r, i) => {\n        if (i > 0) children.push(text(', '));\n        const resolved = resolveLink?.(r) ?? null;\n        children.push(resolved && !resolved.external ? link(resolved.href, inlineCode(r)) : inlineCode(r));\n      });\n      return p(...children);\n    });\n}\n\n/**\n * Short display name for a namepath: the last segment after `.`/`#`/`~`.\n */\nfunction shortRelationName(longname: string): string {\n  return longname.split(/[.#~]/).pop() ?? longname;\n}\n\n/**\n * A namepath rendered as a link when it resolves to a documented page,\n * otherwise inert code — same fallback rule as {@link classRelationsBlocks}.\n */\nfunction relationLinkName(\n  longname: string,\n  resolveLink: DocletBlocksOptions['resolveLink']\n): PhrasingContent {\n  const resolved = resolveLink?.(longname) ?? null;\n  const shortName = shortRelationName(longname);\n  return resolved && !resolved.external ? link(resolved.href, inlineCode(shortName)) : inlineCode(shortName);\n}\n\n/**\n * TypeDoc-only \"Hierarchy\" / \"Implements\" / \"Implemented By\" blocks for a\n * class/interface page — built from `view.augments` (direct parent chain) and\n * the doclet's `implements`/`implementations` (the inverse edge Task 1 attaches\n * to an interface doclet, pointing at each class that implements it). ONLY\n * called under `options.flavor === 'typedoc'` (see {@link typedocMemberBlocks}),\n * so the JSDoc path never reaches this — `augments`/`implements` are rendered\n * there via the pre-existing {@link classRelationsBlocks} \"Extends:\"/\n * \"Implements:\" paragraph instead.\n */\nfunction relationshipBlocks(view: ContainerView, options: ClassViewToMdastOptions): RootContent[] {\n  const resolveLink = options.resolveLink;\n  const out: RootContent[] = [];\n\n  const chain = [...view.augments].reverse();\n  if (chain.length > 0) {\n    const selfName = view.doclet.name ?? view.doclet.longname ?? '';\n    out.push(h(4, text('Hierarchy')));\n    out.push(\n      ul(\n        [...chain.map((ln) => li(p(relationLinkName(ln, resolveLink)))), li(p(inlineCode(selfName)))]\n      )\n    );\n  }\n\n  const impls = view.doclet.implements ?? [];\n  if (impls.length > 0) {\n    out.push(h(4, text('Implements')));\n    out.push(ul(impls.map((ln) => li(p(relationLinkName(ln, resolveLink))))));\n  }\n\n  const implementedBy = view.doclet.implementations ?? [];\n  if (implementedBy.length > 0) {\n    out.push(h(4, text('Implemented By')));\n    out.push(ul(implementedBy.map((ln) => li(p(relationLinkName(ln, resolveLink))))));\n  }\n\n  return out;\n}\n\n/**\n * TypeDoc-only per-member caption — \"Inherited from …\" / \"Overrides …\" /\n * \"Implementation of …\" — emitted right after a member's heading, before its\n * body. Strictly gated on `options.flavor === 'typedoc'`: `inheritedFrom` is\n * attached to inherited members by {@link getInheritedMembers} for BOTH\n * flavors, and `overrides`/`implementationOf` live on the raw doclet for both\n * flavors too, so without this early return the JSDoc path would regress.\n * JSDoc already shows its own \"Overrides:\" line via {@link relationsBlocks} in\n * `docletBlocks` — untouched by this helper.\n */\nfunction memberRelationCaption(\n  member: ClassMember,\n  options: DocletBlocksOptions\n): RootContent[] {\n  if (options.flavor !== 'typedoc') return [];\n  const resolveLink = options.resolveLink;\n  const caption = (label: string, longname: string): RootContent => {\n    return p(emphasis(text(`${label} `)), relationLinkName(longname, resolveLink));\n  };\n  const out: RootContent[] = [];\n  if (member.inheritedFrom) out.push(caption('Inherited from', member.inheritedFrom));\n  if (member.overrides) out.push(caption('Overrides', member.overrides));\n  if (member.implementationOf) out.push(caption('Implementation of', member.implementationOf));\n  return out;\n}\n\n/**\n * Top-level: turn a ContainerView into a complete mdast Root tree. Frontmatter\n * is NOT added here — that's the MDX serialization layer's job. Kind-parametric:\n * the Constructor section only appears for classes (other kinds carry no\n * `constructorParams`), and empty relations/member sections drop out via\n * `hideEmptySections`.\n */\nexport function containerViewToMdast(\n  view: ContainerView,\n  options: ClassViewToMdastOptions = {}\n): Root {\n  const pageLevel = options.pageHeadingLevel ?? 1;\n  const blocks: RootContent[] = [];\n\n  // Title — fall back to a capitalized kind word when a doclet carries neither\n  // a name nor a longname (rare), instead of the old hardcoded \"Class\".\n  const titleFallback = view.kind.charAt(0).toUpperCase() + view.kind.slice(1);\n  blocks.push(h(pageLevel, text(view.doclet.name ?? view.doclet.longname ?? titleFallback)));\n\n  // Extends/Implements/Mixes — JSDoc flavor only. The typedoc flavor renders\n  // these as the nicer \"Hierarchy\"/\"Implements\"/\"Implemented By\" lists via\n  // relationshipBlocks (see typedocMemberBlocks), so running classRelationsBlocks\n  // here too would duplicate them (raw-longname paragraphs alongside the short-\n  // name lists). The TypeDoc bridge never sets `doclet.mixes` (mixins aren't a\n  // TypeDoc reflection concept — confirmed: no `mixes` write in\n  // packages/typedoc/src), so gating this off drops nothing on the typedoc path.\n  // JSDoc is unchanged → byte-identical.\n  if (options.flavor !== 'typedoc') {\n    blocks.push(...classRelationsBlocks(view.doclet, options.resolveLink));\n  }\n\n  // Standalone pages (typedoc flavor) lead with the symbol's declaration as a\n  // shiki-highlighted inline `<Signature>`, right under the title — matching\n  // default TypeDoc, where a function page leads with `name<T>(p: T): Ret`, a\n  // variable with `name: { … }`, a type alias with `Name = …`, and an interface\n  // with `interface Name { … }`.\n  const fnVarPage =\n    options.flavor === 'typedoc' && (view.kind === 'function' || view.kind === 'variable');\n  // An overloaded standalone function stacks every signature below the body\n  // (handled after docletBlocks); a single-signature one leads with its block.\n  const fnOverloaded = fnVarPage && view.kind === 'function' && hasOverloads(view.doclet);\n  // Did we emit a typedef declaration block (`Name = …`)? If so its inline \"Type\"\n  // section below is redundant and gets skipped.\n  let typedefDeclEmitted = false;\n  if (fnVarPage && !fnOverloaded) {\n    const sig = view.kind === 'variable' ? variableSignature(view.doclet) : tsMemberSignature(view.doclet);\n    if (sig) blocks.push(signature(sig));\n  } else if (options.flavor === 'typedoc' && view.kind === 'typedef') {\n    const sig = typedefSignature(view.doclet);\n    if (sig) {\n      blocks.push(signature(sig));\n      typedefDeclEmitted = true;\n    }\n  } else if (options.flavor === 'typedoc' && view.kind === 'interface') {\n    blocks.push(signature(interfaceSignature(view)));\n  }\n\n  // Source link for the class declaration itself, when it resolves.\n  const classSource = sourceLinkBlock(view.doclet, options);\n  if (classSource) blocks.push(classSource);\n\n  // Class-level body: description, deprecation, examples, metadata. Relations\n  // (extends/implements/mixes) are already rendered above via\n  // classRelationsBlocks — skip them for every kind. Params/returns/yields/\n  // throws are skipped *only for classes*, where they're surfaced in the\n  // Constructor section below to avoid duplication. Other kinds (typedef,\n  // module, namespace, interface, mixin) have no Constructor section, so a\n  // function-signature typedef's params/returns (and any container doclet's\n  // own params/returns) must render here in the body.\n  const skip: DocletSection[] =\n    view.kind === 'class'\n      ? [...(options.skip ?? []), 'params', 'returns', 'yields', 'throws', 'relations']\n      : fnOverloaded\n        ? [...(options.skip ?? []), 'relations', ...SHARED_BODY_SKIP_FOR_OVERLOADS]\n        : [...(options.skip ?? []), 'relations'];\n  // The declaration block above already shows the type, so the inline \"Type\"\n  // section would just repeat it: drop it for an object-literal variable (whose\n  // members also list under \"Properties\") and for any typedef whose `Name = …`\n  // block was emitted.\n  const objectLiteralVariable =\n    options.flavor === 'typedoc' &&\n    view.kind === 'variable' &&\n    (view.doclet.properties?.length ?? 0) > 0;\n  if (objectLiteralVariable || typedefDeclEmitted) {\n    skip.push('type');\n  }\n  blocks.push(...docletBlocks(view.doclet, { ...options, skip }));\n\n  // Overloaded standalone function: stack each signature (with its own\n  // parameters/returns) after the shared body — matching default TypeDoc.\n  if (fnOverloaded) {\n    blocks.push(...overloadSignatureBlocks(view.doclet, options));\n  }\n\n  // Constructor: every class page gets a Constructor section so the call\n  // signature (e.g. `new Widget(id, [opts])`) always shows — conveying argument\n  // order at a glance, which the vertical Parameters list doesn't, and matching\n  // the default JSDoc/TypeDoc templates. A parameter-less class still shows a\n  // bare `new ClassName()`. `@hideconstructor` opts out entirely (the author's\n  // signal that the constructor isn't part of the public API).\n  //\n  // The constructor's own `description` (distinct from the class-level\n  // `classdesc` rendered in the body above) is shown here ONLY when both fields\n  // are present — the two-block case where a class and its `constructor` carry\n  // separate doc comments. When a class has a single comment it lives in\n  // `classdesc` (already shown), and a constructor-only comment is shown via the\n  // body's `classdesc ?? description` fallback — so this never duplicates.\n  if (view.kind === 'class' && !view.doclet.hideconstructor) {\n    // Constructor params belong to the class symbol; key them under\n    // `constructor.params.*` so their descriptions translate distinctly from any\n    // member-level params on the same longname.\n    const ctorParams = paramsList(\n      view.constructorParams,\n      { slots: options.slots, longname: view.doclet.longname, resolveLink: options.resolveLink },\n      'constructor.params'\n    );\n    // The separately-documented constructor description (only when a class has\n    // BOTH a classdesc and a constructor description). Translatable like any\n    // description, keyed `…#constructor.description`.\n    const ctorDescription =\n      view.doclet.classdesc && view.doclet.description\n        ? htmlToMdastBlocks(\n            resolveSlotText(\n              options.slots,\n              view.doclet.longname,\n              ['constructor', 'description'],\n              view.doclet.description\n            )\n          )\n        : [];\n    const ctorName = view.doclet.name ?? view.doclet.longname ?? 'constructor';\n    // Documented params carry optional/rest info (`new Cache([options])`); an\n    // undocumented constructor falls back to bare names from the code metadata\n    // (`new Base(options)`). The Parameters table below stays documented-only.\n    const ctorSigParams: TDocletParam[] = view.constructorParams.length\n      ? view.constructorParams\n      : view.constructorParamNames.map((name) => ({ name }));\n    if (options.flavor === 'typedoc') {\n      // TypeDoc layout: \"Constructors\" → a `constructor` member heading whose\n      // signature is the full TS call signature (shiki-highlighted inline, same\n      // as a method heading) → description → Parameters → Returns (the class\n      // instance type). The anchor stays `#constructor` (name attr); class type\n      // parameters are already shown in the class body above, so not repeated.\n      blocks.push(hr(), h(2, text('Constructors')));\n      blocks.push(\n        memberHeading({\n          id: 'constructor',\n          depth: 3,\n          name: 'constructor',\n          sig: tsConstructorSignature(ctorName, view.doclet.typeParams, ctorSigParams),\n        })\n      );\n      blocks.push(...ctorDescription);\n      if (ctorParams) blocks.push(p(strong(text('Parameters'))), ctorParams);\n      blocks.push(\n        p(strong(text('Returns'))),\n        p(inlineCode(instanceType(ctorName, view.doclet.typeParams)))\n      );\n    } else {\n      // JSDoc: \"Constructor\" section with the full TS call signature as a\n      // shiki-highlighted inline `<Signature>` (same look as the member\n      // headings), built from the documented `@param {T}` types.\n      blocks.push(hr(), h(2, text('Constructor')));\n      blocks.push(signature(tsConstructorSignature(ctorName, view.doclet.typeParams, ctorSigParams)));\n      blocks.push(...ctorDescription);\n      if (ctorParams) blocks.push(p(strong(text('Parameters'))), ctorParams);\n    }\n  }\n\n  // Members. Under the typedoc flavor the layout is kind-specific (a links index\n  // for modules/namespaces, \"Enumeration Members\" for enums, TypeDoc labels for\n  // classes); the jsdoc default keeps the original bucketed sections.\n  if (options.flavor === 'typedoc') {\n    blocks.push(...typedocMemberBlocks(view, options));\n  } else {\n    const sections = defaultSections(view);\n    if (sections.some((s) => s.members.length > 0)) blocks.push(hr());\n    blocks.push(...memberSections(sections, options));\n  }\n\n  return root(...blocks);\n}\n\n/**\n * TypeDoc-flavored member rendering for a container, dispatched by kind:\n * module/namespace → a kind-grouped links index ({@link moduleIndexBlocks});\n * enum → an \"Enumeration Members\" section; class/interface/mixin → TypeDoc\n * labels ({@link typedocClassSections}); function/variable/typedef carry their\n * content in the body (params/returns/type/properties) and have no member\n * sections.\n */\nfunction typedocMemberBlocks(view: ContainerView, options: ClassViewToMdastOptions): RootContent[] {\n  if (view.kind === 'module' || view.kind === 'namespace') {\n    return moduleIndexBlocks(view, options);\n  }\n  let sections: SectionSpec[] | null = null;\n  if (view.kind === 'enum') sections = enumMemberSections(view);\n  else if (\n    view.kind === 'class' ||\n    view.kind === 'interface' ||\n    view.kind === 'mixin' ||\n    view.kind === 'global'\n  ) {\n    sections = typedocClassSections(view);\n  }\n  if (!sections) return [];\n  const out: RootContent[] = [];\n  // Hierarchy / Implements / Implemented By — class & interface pages only.\n  if (view.kind === 'class' || view.kind === 'interface') {\n    out.push(...relationshipBlocks(view, options));\n  }\n  if (sections.some((s) => s.members.length > 0)) out.push(hr());\n  out.push(...memberSections(sections, options));\n  return out;\n}\n\n/**\n * Turn a ClassView into a complete mdast Root tree. Thin alias over\n * {@link containerViewToMdast} — a ClassView is a `ContainerView` with\n * `kind: 'class'`.\n */\nexport function classViewToMdast(view: ClassView, options: ClassViewToMdastOptions = {}): Root {\n  return containerViewToMdast(view as ContainerView, options);\n}\n","import type {\n  BlockContent,\n  Code,\n  DefinitionContent,\n  Emphasis,\n  Heading,\n  Html,\n  InlineCode,\n  Link,\n  List,\n  ListItem,\n  Paragraph,\n  PhrasingContent,\n  Root,\n  RootContent,\n  Strong,\n  Text,\n  ThematicBreak,\n} from 'mdast';\nimport type { MdxJsxAttribute, MdxJsxFlowElement } from 'mdast-util-mdx-jsx';\nimport type { EmbedSpec } from '../embed';\n\nexport const text = (value: string): Text => ({ type: 'text', value });\n\nexport const inlineCode = (value: string): InlineCode => ({ type: 'inlineCode', value });\n\nexport const strong = (...children: PhrasingContent[]): Strong => ({\n  type: 'strong',\n  children,\n});\n\nexport const emphasis = (...children: PhrasingContent[]): Emphasis => ({\n  type: 'emphasis',\n  children,\n});\n\nexport const link = (url: string, ...children: PhrasingContent[]): Link => ({\n  type: 'link',\n  url,\n  children: children.length ? children : [text(url)],\n});\n\nexport const p = (...children: PhrasingContent[]): Paragraph => ({\n  type: 'paragraph',\n  children,\n});\n\nexport const h = (depth: 1 | 2 | 3 | 4 | 5 | 6, ...children: PhrasingContent[]): Heading => ({\n  type: 'heading',\n  depth,\n  children,\n});\n\nexport const code = (lang: string | null, value: string): Code => ({\n  type: 'code',\n  lang,\n  value,\n});\n\nexport const hr = (): ThematicBreak => ({ type: 'thematicBreak' });\n\nexport const html = (value: string): Html => ({ type: 'html', value });\n\nexport const li = (...children: ListItem['children']): ListItem => ({\n  type: 'listItem',\n  spread: false,\n  children,\n});\n\nexport const ul = (items: ListItem[]): List => ({\n  type: 'list',\n  ordered: false,\n  spread: false,\n  children: items,\n});\n\nexport const ol = (items: ListItem[]): List => ({\n  type: 'list',\n  ordered: true,\n  spread: false,\n  children: items,\n});\n\nexport const root = (...children: RootContent[]): Root => ({ type: 'root', children });\n\n/**\n * A callout — rang's `MdxBlockquote` rendered with a `type` variant, emitted as\n * an MDX JSX element (`<Callout type=\"…\">`) rather than a markdown `>` quote.\n * The attribute is what a plain markdown blockquote can't express:\n * `mdast-util-to-markdown` drops the `data` field, so the variant would never\n * reach the renderer. As MDX JSX it round-trips through serialization (see the\n * `mdxJsxToMarkdown` wiring in `mdx.ts`) and arrives as a prop.\n *\n * The name is capitalized on purpose: MDX routes only capitalized JSX names\n * through the `components` map (lowercase literal JSX renders as a raw host\n * element, bypassing the map). rang registers `Callout` → `MdxBlockquote`, so\n * the rendered element is still a `<blockquote>`.\n */\nexport const callout = (\n  variant: 'info' | 'tip' | 'warning' | 'error',\n  children: (BlockContent | DefinitionContent)[]\n): MdxJsxFlowElement => ({\n  type: 'mdxJsxFlowElement',\n  name: 'Callout',\n  attributes: [{ type: 'mdxJsxAttribute', name: 'type', value: variant }],\n  children,\n});\n\n/**\n * A numbered stepper — rang's `Steps` emitted as an MDX JSX element\n * (`<Steps>` wrapping `<Step>` children). Like `callout`, the capitalized name\n * routes it through the `components` map (rang registers `Steps` → its SSR-only\n * stepper), and `mdxJsxToMarkdown` (wired in `mdx.ts`) serializes it so the prose\n * authoring tags survive into the compiled MDX.\n */\nexport const steps = (children: (BlockContent | DefinitionContent)[]): MdxJsxFlowElement => ({\n  type: 'mdxJsxFlowElement',\n  name: 'Steps',\n  attributes: [],\n  children,\n});\n\n/**\n * A single step — rang's `Step` emitted as an MDX JSX element\n * (`<Step label=\"…\">`). Capitalized so MDX routes it through the `components`\n * map (rang registers `Step` as the marker `Steps` reads). The optional `label`\n * becomes one `mdxJsxAttribute`, included only when it is a non-empty string so\n * the renderer can omit the heading when none was authored.\n */\nexport const step = (\n  label: string | undefined,\n  children: (BlockContent | DefinitionContent)[]\n): MdxJsxFlowElement => {\n  const attributes: MdxJsxAttribute[] = [];\n  if (label) attributes.push({ type: 'mdxJsxAttribute', name: 'label', value: label });\n  return { type: 'mdxJsxFlowElement', name: 'Step', attributes, children };\n};\n\n/**\n * A tabbed view — rang's `Tabs` emitted as an MDX JSX element (`<Tabs>` wrapping\n * `<Tab>` children). Like `callout`, the capitalized name routes it through the\n * `components` map (rang registers `Tabs` → its ARIA tablist), and\n * `mdxJsxToMarkdown` (wired in `mdx.ts`) serializes it so the prose authoring\n * tags survive into the compiled MDX.\n */\nexport const tabs = (\n  children: (BlockContent | DefinitionContent)[],\n  group?: string\n): MdxJsxFlowElement => {\n  const attributes: MdxJsxAttribute[] = [];\n  // `group` opts the block into cross-block sync (see rang's `Tabs`); included\n  // only when a non-empty string was authored so ungrouped blocks stay inert.\n  if (group) attributes.push({ type: 'mdxJsxAttribute', name: 'group', value: group });\n  return { type: 'mdxJsxFlowElement', name: 'Tabs', attributes, children };\n};\n\n/**\n * A single tab — rang's `Tab` emitted as an MDX JSX element (`<Tab label=\"…\">`).\n * Capitalized so MDX routes it through the `components` map (rang registers `Tab`\n * as the marker `Tabs` reads). The optional `label` becomes one `mdxJsxAttribute`,\n * included only when it is a non-empty string (the renderer falls back to\n * `Tab N` otherwise).\n */\nexport const tab = (\n  label: string | undefined,\n  children: (BlockContent | DefinitionContent)[],\n  value?: string\n): MdxJsxFlowElement => {\n  const attributes: MdxJsxAttribute[] = [];\n  if (label) attributes.push({ type: 'mdxJsxAttribute', name: 'label', value: label });\n  // `value` is the cross-block sync key (see rang's `Tabs`); when omitted the\n  // renderer falls back to the normalized label, so it's emitted only when set.\n  if (value) attributes.push({ type: 'mdxJsxAttribute', name: 'value', value });\n  return { type: 'mdxJsxFlowElement', name: 'Tab', attributes, children };\n};\n\n/**\n * An embed — rang's `Embed` island emitted as an MDX JSX element\n * (`<Embed src=\"…\" />`). Like `callout`, the capitalized name routes it through\n * the `components` map, and `mdxJsxToMarkdown` (wired in `mdx.ts`) serializes the\n * attributes verbatim. Self-closing (no children).\n *\n * Each defined `EmbedSpec` field becomes one string-valued `mdxJsxAttribute`;\n * numbers and booleans are stringified (`height=\"400\"`, `clickToLoad=\"true\"`),\n * and `undefined` fields are omitted so the renderer can apply its defaults.\n */\nexport const embed = (spec: EmbedSpec): MdxJsxFlowElement => {\n  const attributes: MdxJsxAttribute[] = [];\n  const attr = (name: string, value: string | number | boolean | undefined): void => {\n    if (value === undefined) return;\n    attributes.push({ type: 'mdxJsxAttribute', name, value: String(value) });\n  };\n\n  attr('src', spec.src);\n  attr('title', spec.title);\n  attr('height', spec.height);\n  attr('width', spec.width);\n  attr('aspectRatio', spec.aspectRatio);\n  attr('allow', spec.allow);\n  attr('sandbox', spec.sandbox);\n  attr('clickToLoad', spec.clickToLoad);\n  attr('themed', spec.themed);\n\n  return {\n    type: 'mdxJsxFlowElement',\n    name: 'Embed',\n    attributes,\n    children: [],\n  };\n};\n\n/**\n * A code playground — rang's `Playground` context wrapper emitted as an MDX JSX\n * element (`<Playground …>` wrapping a single fenced `code` child). Like\n * `callout`, the capitalized name routes it through the `components` map, and\n * `mdxJsxToMarkdown` (wired in `mdx.ts`) serializes the attributes + re-serializes\n * the code child as a real fence — so Shiki still highlights it and the LLM `.md`\n * keeps a clean fenced block under a small wrapper.\n *\n * Attributes (each omitted when empty): `providers` (space-joined provider ids\n * driving the \"Open Code in\" dropdown), `filename` (header label), and\n * `highlight` (comma-joined 1-based line numbers).\n */\nexport const playground = (\n  opts: { providers: readonly string[]; filename?: string; highlight?: readonly number[] },\n  child: Code\n): MdxJsxFlowElement => {\n  const attributes: MdxJsxAttribute[] = [];\n  if (opts.providers.length > 0) {\n    attributes.push({ type: 'mdxJsxAttribute', name: 'providers', value: opts.providers.join(' ') });\n  }\n  if (opts.filename) {\n    attributes.push({ type: 'mdxJsxAttribute', name: 'filename', value: opts.filename });\n  }\n  if (opts.highlight && opts.highlight.length > 0) {\n    attributes.push({ type: 'mdxJsxAttribute', name: 'highlight', value: opts.highlight.join(',') });\n  }\n  return { type: 'mdxJsxFlowElement', name: 'Playground', attributes, children: [child] };\n};\n\n/**\n * A source-location caption — rang's `SourceLink` emitted as a self-closing MDX\n * JSX element (`<SourceLink href=\"…\" label=\"…\" />`). Capitalized so MDX routes\n * it through the `components` map (same round-trip as `callout`/`embed`); the\n * component owns the markup — a small 12px caption with a `file:line` link —\n * rather than a full-size markdown paragraph.\n */\nexport const sourceLink = (href: string, label: string): MdxJsxFlowElement => ({\n  type: 'mdxJsxFlowElement',\n  name: 'SourceLink',\n  attributes: [\n    { type: 'mdxJsxAttribute', name: 'href', value: href },\n    { type: 'mdxJsxAttribute', name: 'label', value: label },\n  ],\n  children: [],\n});\n\n/**\n * A member meta row — rang's `MemberMeta` emitted as a self-closing MDX JSX\n * element (the same capitalized-JSX round-trip as {@link callout}/{@link embed}/\n * {@link sourceLink}). One container under a member's `###` heading: modifier/\n * kind chips on the left, the `filename:line` source link pinned right (empty\n * when the consumer opted out of source files). The heading stays a real ATX\n * heading so its anchor / TOC / search entry survive. Empty fields are omitted.\n */\nexport const memberMeta = (meta: {\n  badges?: readonly string[];\n  sourceHref?: string;\n  sourceLabel?: string;\n}): MdxJsxFlowElement => {\n  const attributes: MdxJsxAttribute[] = [];\n  const attr = (name: string, value: string | undefined): void => {\n    if (value) attributes.push({ type: 'mdxJsxAttribute', name, value });\n  };\n  attr('badges', meta.badges && meta.badges.length ? meta.badges.join(',') : undefined);\n  attr('sourceHref', meta.sourceHref);\n  attr('sourceLabel', meta.sourceLabel);\n  return { type: 'mdxJsxFlowElement', name: 'MemberMeta', attributes, children: [] };\n};\n\n/**\n * A member heading — rang's `MemberHeading` emitted as a self-closing MDX JSX\n * flow element instead of a markdown `###` heading. It renders an `h{depth}`\n * whose entire content is one `<code>` element showing the full signature\n * (`process(data) -> Promise.<number>`), with an **explicit `id`** so the anchor\n * stays clean (`#process`) regardless of the displayed signature.\n *\n * Why a component, not a markdown heading: a markdown heading derives its slug\n * from its visible text, so a signature heading would anchor as\n * `#process-data-promise-number`. Here the `id` is set explicitly and the\n * signature rides in the `sig` attribute (no text at rehype time), so dwar's\n * slug pass skips it. `setu`'s `extractHeadings` recognises this node and emits\n * a TOC/search entry from `name` + `id` (no dedup-registry touch, mirroring the\n * slug pass), so TOC / search / `{@link}` keep resolving to `#name`. Embedded\n * `\"` in `sig` is downgraded to `'` so the attribute can't terminate early.\n */\nexport const memberHeading = (opts: {\n  id: string;\n  depth: number;\n  name: string;\n  sig: string;\n}): MdxJsxFlowElement => ({\n  type: 'mdxJsxFlowElement',\n  name: 'MemberHeading',\n  attributes: [\n    { type: 'mdxJsxAttribute', name: 'id', value: opts.id },\n    { type: 'mdxJsxAttribute', name: 'depth', value: String(opts.depth) },\n    { type: 'mdxJsxAttribute', name: 'name', value: opts.name },\n    { type: 'mdxJsxAttribute', name: 'sig', value: opts.sig.replace(/\"/g, \"'\") },\n  ],\n  children: [],\n});\n\n/**\n * A standalone code signature — rang's `Signature`, emitted as a self-closing\n * MDX JSX flow element. Used where a signature isn't a heading: a top-level\n * function/variable page and each signature of an overloaded member. Like\n * {@link memberHeading} it renders one shiki-highlighted inline `<code>`, but in\n * its own block (no heading, no anchor). Embedded `\"` is downgraded to `'` so\n * the attribute can't terminate early.\n */\nexport const signature = (code: string): MdxJsxFlowElement => ({\n  type: 'mdxJsxFlowElement',\n  name: 'Signature',\n  attributes: [{ type: 'mdxJsxAttribute', name: 'code', value: code.replace(/\"/g, \"'\") }],\n  children: [],\n});\n","/**\n * Shared config parser for `@iframe` block tags (doclets) and ```` ```iframe ````\n * fenced blocks (prose). Both use the same grammar: the first whitespace-delimited\n * token is the URL, the rest are `key=value` pairs. Values may be quoted with\n * single or double quotes, and quoted values may contain spaces.\n *\n *     https://codepen.io/x/embed/abc height=400 title=\"Live demo\" clickToLoad=true\n *\n * See `packages/setu/docs/plan-iframe-embeds.md` (Design §1).\n */\n\nexport interface EmbedSpec {\n  /** Required; `https://` or protocol-relative `//` only (see security). */\n  src: string;\n  /** iframe title (a11y) + poster label. */\n  title?: string;\n  /** px. */\n  height?: number;\n  /** optional; default 100%. */\n  width?: string;\n  /** e.g. \"16/9\"; alternative to height. */\n  aspectRatio?: string;\n  /** iframe `allow=` (e.g. \"fullscreen; clipboard-write\"). */\n  allow?: string;\n  /** override default sandbox. */\n  sandbox?: string;\n  /** poster until clicked. */\n  clickToLoad?: boolean;\n  /**\n   * Sync the embed to the active theme. On by default (rang appends\n   * `?theme-id=<theme>` / swaps a `{theme}` token); set `themed=false` to opt\n   * out. Omitted here means \"use the default\"; only an explicit `false` is\n   * emitted as an attribute.\n   */\n  themed?: boolean;\n}\n\n/** Keys accepted in the `key=value` portion (everything in EmbedSpec but `src`). */\nconst STRING_KEYS = new Set<keyof EmbedSpec>(['title', 'width', 'aspectRatio', 'allow', 'sandbox']);\nconst NUMBER_KEYS = new Set<keyof EmbedSpec>(['height']);\nconst BOOLEAN_KEYS = new Set<keyof EmbedSpec>(['clickToLoad', 'themed']);\n\n/** All allowlisted config keys (used to detect unknown keys for the warning). */\nconst KNOWN_KEYS = new Set<string>([...STRING_KEYS, ...NUMBER_KEYS, ...BOOLEAN_KEYS] as string[]);\n\n/**\n * Tokenize a config string into whitespace-delimited tokens, keeping spaces\n * inside single- or double-quoted runs intact. Newlines and runs of whitespace\n * are treated as a single delimiter (the prose fence body can span lines).\n * Never throws.\n */\nfunction tokenize(text: string): string[] {\n  const tokens: string[] = [];\n  let current = '';\n  let quote: '\"' | \"'\" | null = null;\n  let started = false; // whether `current` holds a (possibly empty quoted) token\n\n  for (const ch of text) {\n    if (quote) {\n      if (ch === quote) {\n        quote = null;\n      } else {\n        current += ch;\n      }\n      continue;\n    }\n    if (ch === '\"' || ch === \"'\") {\n      quote = ch;\n      started = true;\n      continue;\n    }\n    if (ch === ' ' || ch === '\\t' || ch === '\\n' || ch === '\\r' || ch === '\\f' || ch === '\\v') {\n      if (started) {\n        tokens.push(current);\n        current = '';\n        started = false;\n      }\n      continue;\n    }\n    current += ch;\n    started = true;\n  }\n  if (started) tokens.push(current);\n  return tokens;\n}\n\n/**\n * Split a `key=value` token at the first `=`. Quotes around the value have\n * already been stripped by the tokenizer, so a quoted value with spaces arrives\n * here as one token. Returns null if there is no `=` (a bare flag).\n */\nfunction splitPair(token: string): { key: string; value: string } | null {\n  const eq = token.indexOf('=');\n  if (eq === -1) return null;\n  return { key: token.slice(0, eq), value: token.slice(eq + 1) };\n}\n\n/** Coerce a string to boolean: \"true\"/\"false\" (case-insensitive). null otherwise. */\nfunction toBoolean(value: string): boolean | null {\n  const v = value.trim().toLowerCase();\n  if (v === 'true') return true;\n  if (v === 'false') return false;\n  return null;\n}\n\n/**\n * Parse an embed config string into an EmbedSpec, or `null` if there is no URL\n * token, the input is empty, or the URL is not `https://` / protocol-relative\n * `//`. Never throws on malformed input — unknown keys are warned-and-ignored,\n * bad coercions are skipped.\n */\nexport function parseEmbedConfig(text: string): EmbedSpec | null {\n  if (typeof text !== 'string') return null;\n  const tokens = tokenize(text);\n  if (tokens.length === 0) return null;\n\n  const [src, ...rest] = tokens;\n  if (!src) return null;\n\n  // Security: only https or protocol-relative URLs.\n  if (!src.startsWith('https://') && !src.startsWith('//')) return null;\n\n  const spec: Record<string, unknown> = { src };\n\n  for (const token of rest) {\n    const pair = splitPair(token);\n\n    // A bare flag with no `=` (e.g. `clickToLoad`) → true for boolean keys.\n    if (!pair) {\n      if (BOOLEAN_KEYS.has(token as keyof EmbedSpec)) {\n        spec[token] = true;\n      } else if (token.length > 0) {\n        console.warn(`[setu:embed] ignoring unknown or malformed embed config token: \"${token}\"`);\n      }\n      continue;\n    }\n\n    const { key, value } = pair;\n\n    if (!KNOWN_KEYS.has(key)) {\n      console.warn(`[setu:embed] ignoring unknown embed config key: \"${key}\"`);\n      continue;\n    }\n\n    if (NUMBER_KEYS.has(key as keyof EmbedSpec)) {\n      const n = Number(value);\n      if (Number.isNaN(n)) continue; // drop NaN\n      spec[key] = n;\n      continue;\n    }\n\n    if (BOOLEAN_KEYS.has(key as keyof EmbedSpec)) {\n      const b = toBoolean(value);\n      if (b === null) continue; // drop unparseable boolean\n      spec[key] = b;\n      continue;\n    }\n\n    // String key.\n    spec[key] = value;\n  }\n\n  return spec as unknown as EmbedSpec;\n}\n","import type {\n  BlockContent,\n  Blockquote,\n  Code,\n  DefinitionContent,\n  PhrasingContent,\n  Root,\n  RootContent,\n} from 'mdast';\nimport { fromHtml } from 'hast-util-from-html';\nimport { toHtml } from 'hast-util-to-html';\nimport { toMdast } from 'hast-util-to-mdast';\nimport { fromMarkdown } from 'mdast-util-from-markdown';\nimport { gfmFromMarkdown } from 'mdast-util-gfm';\nimport { toHast } from 'mdast-util-to-hast';\nimport { gfm } from 'micromark-extension-gfm';\nimport { callout, code, playground, step, steps, tab, tabs } from './builders';\nimport {\n  KNOWN_PROVIDERS,\n  parsePlaygroundSpec,\n  resolvePlaygroundOpts,\n  type PlaygroundSpec,\n} from '../playground';\n\n/**\n * GitHub-style alert keyword → rang callout variant. A prose blockquote whose\n * first line is one of these markers (`> [!TIP]`, `> [!WARNING]`, …) becomes a\n * typed callout instead of a plain quote. The keywords fold onto rang's four\n * variants (`info` | `tip` | `warning` | `error`): `NOTE`/`IMPORTANT` read as\n * info, `TIP`/`SUCCESS` as the green tip, and `CAUTION` as warning.\n */\nconst CALLOUT_ALERTS: Record<string, 'info' | 'tip' | 'warning' | 'error'> = {\n  info: 'info',\n  note: 'info',\n  important: 'info',\n  tip: 'tip',\n  success: 'tip',\n  warning: 'warning',\n  caution: 'warning',\n  error: 'error',\n  danger: 'error',\n};\n\n/** Leading `[!type]` marker at the start of a blockquote's first text node. */\nconst ALERT_MARKER = /^\\s*\\[!(\\w+)\\]\\s*/;\n\n/**\n * Promote a blockquote that opens with a GitHub-style alert marker\n * (`> [!INFO]`, `> [!WARNING]`, …) to a rang callout, stripping the marker from\n * the body. An absent or unknown marker leaves the blockquote untouched (a plain\n * quote). The callout is the same capitalized `<Callout type=\"…\">` MDX JSX node\n * setu emits for `@deprecated`, so it round-trips through serialization to dwar.\n */\nfunction blockquoteToCallout(node: Blockquote): RootContent {\n  const para = node.children[0];\n  if (!para || para.type !== 'paragraph') return node;\n  const lead = para.children[0];\n  if (!lead || lead.type !== 'text') return node;\n  const match = ALERT_MARKER.exec(lead.value);\n  if (!match) return node;\n  const variant = CALLOUT_ALERTS[match[1].toLowerCase()];\n  if (!variant) return node;\n\n  // Strip the marker from the body. If that empties the lead text node, drop it\n  // (plus a soft break the conversion may have left right after the marker), and\n  // drop the now-empty first paragraph entirely.\n  lead.value = lead.value.slice(match[0].length);\n  if (lead.value.length === 0) {\n    para.children.shift();\n    if (para.children[0]?.type === 'break') para.children.shift();\n  }\n  if (para.children.length === 0) node.children.shift();\n\n  return callout(variant, node.children);\n}\n\n/** A node that may own a `children` array we can recurse into. */\ntype MaybeParent = RootContent & { children?: RootContent[] };\n\n/**\n * Promote GitHub-style alert blockquotes (`> [!NOTE]`, …) to typed callouts at\n * ANY depth — top level, inside list items, inside other blockquotes — mirroring\n * GitHub, which renders alerts nested in lists. Each node is promoted first\n * (outer blockquote → callout), then we descend into the result's children so a\n * nested alert inside it is promoted too. A blockquote with no recognized marker\n * is left as a blockquote but still descended into.\n */\nfunction promoteCallouts(nodes: RootContent[]): RootContent[] {\n  return nodes.map((node) => {\n    const promoted = node.type === 'blockquote' ? blockquoteToCallout(node) : node;\n    const parent = promoted as MaybeParent;\n    if (Array.isArray(parent.children)) parent.children = promoteCallouts(parent.children);\n    return promoted;\n  });\n}\n\n// ── `<steps>` / `<tabs>` authoring containers ───────────────────────────────\n\n/**\n * A `<steps>`/`<tabs>` container item: its optional `label` and the inner\n * markdown/HTML `raw` (full content, re-parsed recursively).\n */\ninterface ContainerItem {\n  label?: string;\n  /** `<tab value=\"…\">` sync key (see rang's `Tabs`); ignored for `<step>`. */\n  value?: string;\n  raw: string;\n}\n\n/**\n * One slice of a raw prose string: either a `plain` run (no container) handed\n * to the normal converter, or a `steps`/`tabs` container whose items expand into\n * the capitalized `<Steps>`/`<Tabs>` JSX nodes.\n */\ntype Segment =\n  | { kind: 'plain'; raw: string }\n  | { kind: 'steps' | 'tabs'; items: ContainerItem[]; group?: string }\n  | { kind: 'playground'; spec: PlaygroundSpec; raw: string };\n\n/** Matches a top-level `<steps …>` / `<tabs …>` / `<playground …>` opening tag. */\nconst CONTAINER_OPEN = /<(steps|tabs|playground)(\\s[^>]*)?>/i;\n\n/** Read a quoted attribute (`name=\"…\"` / `name='…'`) off an opening tag. */\nfunction readAttr(openTag: string, name: string): string | undefined {\n  const m = new RegExp(`${name}\\\\s*=\\\\s*(\"([^\"]*)\"|'([^']*)')`, 'i').exec(openTag);\n  return m ? (m[2] ?? m[3]) : undefined;\n}\n\n/**\n * Find the index just past the close tag matching an open tag of `name` that\n * begins at `openEnd` (the position right after the open tag). Depth-counts\n * same-name open/close tags so a `<steps>` nested inside a `<steps>` closes the\n * inner one first. Returns `-1` when no matching close exists.\n */\nfunction findMatchingClose(raw: string, name: string, openEnd: number): number {\n  const tag = new RegExp(`<(/?)${name}(\\\\s[^>]*)?>`, 'gi');\n  tag.lastIndex = openEnd;\n  let depth = 1;\n  let match: RegExpExecArray | null;\n  while ((match = tag.exec(raw)) !== null) {\n    if (match[1] === '/') {\n      depth -= 1;\n      if (depth === 0) return tag.lastIndex;\n    } else {\n      depth += 1;\n    }\n  }\n  return -1;\n}\n\n/**\n * Parse a container's INNER string into items by scanning for `<step …>…</step>`\n * (or `<tab …>…</tab>`) elements, depth-counted so a nested same-name container\n * inside an item doesn't terminate it early. Reads `label` from each item's open\n * tag; the item's `raw` is the trimmed inner content. Whitespace/text between\n * items is ignored.\n */\nfunction parseItems(inner: string, itemName: string): ContainerItem[] {\n  const items: ContainerItem[] = [];\n  const open = new RegExp(`<${itemName}(\\\\s[^>]*)?>`, 'gi');\n  let cursor = 0;\n  let match: RegExpExecArray | null;\n  while ((match = open.exec(inner)) !== null) {\n    if (match.index < cursor) continue; // inside a previously consumed item\n    const openTag = match[0];\n    const bodyStart = match.index + openTag.length;\n    const closeIndex = findMatchingClose(inner, itemName, bodyStart);\n    if (closeIndex === -1) break; // unterminated item — stop scanning\n    const close = new RegExp(`</${itemName}(\\\\s[^>]*)?>\\\\s*$`, 'i');\n    const body = inner.slice(bodyStart, closeIndex).replace(close, '');\n    const label = readAttr(openTag, 'label');\n    const value = readAttr(openTag, 'value');\n    items.push({ label: label || undefined, value: value || undefined, raw: body.trim() });\n    cursor = closeIndex;\n    open.lastIndex = closeIndex;\n  }\n  return items;\n}\n\n/**\n * Scan `raw` left to right for top-level `<steps>`/`<tabs>` containers, splitting\n * it into `plain` runs and container segments. A `raw` with no container returns\n * a single `plain` segment, so behavior is byte-identical to before when no\n * containers are present. A container that yields zero items falls back to a\n * `plain` segment carrying its whole match, so nothing is silently dropped.\n *\n * This must run on the RAW string BEFORE the HTML round-trip: `fromHtml`/\n * `toMdast` (and the markdown→html lowering) strip these custom lowercase tags,\n * so by the time conversion runs they would be gone.\n */\nfunction splitContainers(raw: string): Segment[] {\n  const segments: Segment[] = [];\n  let rest = raw;\n  for (;;) {\n    const open = CONTAINER_OPEN.exec(rest);\n    if (!open) {\n      if (rest.length > 0) segments.push({ kind: 'plain', raw: rest });\n      break;\n    }\n    const name = open[1].toLowerCase() as 'steps' | 'tabs' | 'playground';\n    const openEnd = open.index + open[0].length;\n    const closeEnd = findMatchingClose(rest, name, openEnd);\n    if (closeEnd === -1) {\n      // No matching close — treat the remainder as plain so nothing is dropped.\n      if (rest.length > 0) segments.push({ kind: 'plain', raw: rest });\n      break;\n    }\n\n    const before = rest.slice(0, open.index);\n    if (before.length > 0) segments.push({ kind: 'plain', raw: before });\n\n    const close = new RegExp(`</${name}(\\\\s[^>]*)?>\\\\s*$`, 'i');\n    const inner = rest.slice(openEnd, closeEnd).replace(close, '');\n    if (name === 'playground') {\n      // The opening tag's attributes ARE the playground config (same token\n      // grammar as the `@playground` tag / fence); the inner content holds the\n      // single fenced code block, lowered when the segment expands.\n      const spec = parsePlaygroundSpec((open[2] ?? '').trim());\n      segments.push({ kind: 'playground', spec, raw: inner });\n    } else {\n      const itemName = name === 'steps' ? 'step' : 'tab';\n      const items = parseItems(inner, itemName);\n      if (items.length > 0) {\n        // `group` (tabs only) opts the block into cross-block sync; read off the\n        // container's own opening tag (`open[0]`).\n        const group = name === 'tabs' ? readAttr(open[0], 'group') || undefined : undefined;\n        segments.push({ kind: name, items, group });\n      } else {\n        // Degenerate container (no items) — keep its source as plain text.\n        segments.push({ kind: 'plain', raw: rest.slice(open.index, closeEnd) });\n      }\n    }\n\n    rest = rest.slice(closeEnd);\n  }\n  return segments;\n}\n\n/**\n * Run {@link splitContainers} over `raw` and lower each segment: `plain` runs\n * through `plainFn` (the format's plain converter); `steps`/`tabs` containers\n * become the capitalized `<Steps>`/`<Tabs>` JSX nodes whose items re-parse their\n * inner content through `recurseFn` (the public converter, so nested callouts /\n * markdown / containers all resolve). `MdxJsxFlowElement` is assignable to\n * `RootContent` here (the mdast types are augmented), so no casts are needed.\n */\nfunction expandContainers(\n  raw: string,\n  plainFn: (s: string) => RootContent[],\n  recurseFn: (s: string) => RootContent[]\n): RootContent[] {\n  const out: RootContent[] = [];\n  // Prose conversion yields `RootContent[]`; the step/tab builders model their\n  // children as block content. The conversion only ever produces block-level\n  // nodes at the top level here (it lowers through `toMdast`), so narrowing to\n  // the builders' `(BlockContent | DefinitionContent)[]` is sound.\n  const asBlocks = (nodes: RootContent[]): (BlockContent | DefinitionContent)[] =>\n    nodes as (BlockContent | DefinitionContent)[];\n  for (const seg of splitContainers(raw)) {\n    if (seg.kind === 'plain') {\n      out.push(...plainFn(seg.raw));\n    } else if (seg.kind === 'playground') {\n      // Re-parse the inner content (so a fenced code block lowers to a `code`\n      // node) and wrap the FIRST code node in a `<Playground>`. Prose bare configs\n      // fall back to ALL providers (KNOWN_PROVIDERS). When the config warrants no\n      // wrapper or there's no code, the inner content passes through unchanged so\n      // nothing is dropped.\n      const inner = recurseFn(seg.raw);\n      const opts = resolvePlaygroundOpts(seg.spec, KNOWN_PROVIDERS);\n      const idx = inner.findIndex((n) => n.type === 'code');\n      if (opts && idx !== -1) {\n        // A <playground> is meant to hold ONE fenced code block; if an author\n        // nests more, only the first is wrapped (the rest pass through as plain\n        // code), warned-and-continue like the rest of the parser.\n        const codeCount = inner.reduce((n, node) => n + (node.type === 'code' ? 1 : 0), 0);\n        if (codeCount > 1) {\n          console.warn(\n            `[setu:playground] <playground> wraps only the first code block; ${codeCount - 1} additional fence(s) left unwrapped`\n          );\n        }\n        inner[idx] = playground(opts, inner[idx] as Code);\n      }\n      out.push(...inner);\n    } else if (seg.kind === 'steps') {\n      out.push(steps(seg.items.map((it) => step(it.label, asBlocks(recurseFn(it.raw))))));\n    } else {\n      out.push(\n        tabs(\n          seg.items.map((it) => tab(it.label, asBlocks(recurseFn(it.raw)), it.value)),\n          seg.group\n        )\n      );\n    }\n  }\n  return out;\n}\n\n/**\n * Convert an HTML fragment (as emitted by JSDoc into `description`, `classdesc`,\n * param descriptions, etc.) into block-level mdast nodes. Empty/blank input\n * returns `[]`.\n *\n * Path: HTML → hast (`hast-util-from-html`) → mdast (`hast-util-to-mdast`). This\n * is the canonical, structure-preserving conversion: it keeps GFM tables, lists,\n * code, links, emphasis, and arbitrary inline/block HTML, where the previous\n * HTML→Markdown→mdast round-trip silently dropped tables and other constructs.\n *\n * Why HTML in the first place: JSDoc's `plugins/markdown` renders Markdown in\n * doclet descriptions to HTML before the theme ever sees them, so a Markdown\n * table in a `@description` arrives here as a `<table>` — which this conversion\n * turns back into an mdast table node.\n *\n * `<steps>`/`<tabs>` container extraction (see {@link expandContainers}) happens\n * in the PUBLIC {@link htmlToMdastBlocks} wrapper; this is the plain conversion\n * for a segment with no containers.\n */\nfunction htmlBlocksPlain(html: string): RootContent[] {\n  const hast = fromHtml(html, { fragment: true });\n  const mdast = toMdast(hast) as Root;\n  // Promote GitHub-style alert blockquotes (`> [!INFO]`) to typed callouts,\n  // recursively so an alert nested in a list item is promoted too. Done here,\n  // after the HTML normalization, so it applies uniformly to every prose source\n  // (README, tutorials, docs) and to JSDoc doclet descriptions — including\n  // content nested inside steps/tabs, since the container recursion routes item\n  // content back through the public functions whose plain segments reach this\n  // transform.\n  return promoteCallouts(mdast.children);\n}\n\n/**\n * Convert an HTML fragment (as emitted by JSDoc into `description`, `classdesc`,\n * param descriptions, etc.) into block-level mdast nodes. Empty/blank input\n * returns `[]`.\n *\n * First splits out any lowercase `<steps>`/`<tabs>` authoring containers at the\n * RAW string level (see {@link splitContainers}), because the HTML round-trip\n * inside {@link htmlBlocksPlain} would strip those custom tags. Plain segments\n * go through {@link htmlBlocksPlain}; container segments become the capitalized\n * `<Steps>`/`<Tabs>` JSX nodes, their inner content re-parsed recursively (so\n * nested markdown, callouts, and even nested containers survive).\n */\nexport function htmlToMdastBlocks(html: string | null | undefined): RootContent[] {\n  if (!html) return [];\n  const trimmed = html.trim();\n  if (trimmed.length === 0) return [];\n  return expandContainers(trimmed, htmlBlocksPlain, htmlToMdastBlocks);\n}\n\n/**\n * Convert a raw Markdown document into block-level mdast nodes, routing through\n * the same HTML normalization {@link htmlToMdastBlocks} uses.\n *\n * Path: Markdown → mdast (GFM) → hast → HTML string → {@link htmlToMdastBlocks}.\n * The HTML round-trip is deliberate: Markdown tutorials are full of constructs\n * that are valid GitHub-Flavored Markdown but NOT valid MDX — angle-bracket\n * autolinks (`<https://…>`), void/unclosed raw HTML (`<img …>`), and inline HTML\n * MDX would otherwise parse as JSX and reject. Re-parsing the rendered HTML with\n * a lenient HTML parser (`fromHtml`) and lowering it through `hast-util-to-mdast`\n * yields only structured mdast nodes (links, images, tables, …) — no raw HTML —\n * which {@link import('../mdx').toMdx} can serialize into MDX-safe Markdown. This\n * mirrors the README path exactly, so tutorials and the README render identically.\n *\n * GFM (tables, strikethrough, task lists, autolink literals, footnotes) is parsed\n * via `micromark-extension-gfm`; without it those constructs would survive only\n * as plain text once round-tripped.\n *\n * `<steps>`/`<tabs>` container extraction (see {@link expandContainers}) happens\n * in the PUBLIC {@link markdownToMdastBlocks} wrapper; this is the plain\n * conversion for a segment with no containers. It calls {@link htmlBlocksPlain}\n * (not the public {@link htmlToMdastBlocks}) so a plain segment isn't re-scanned\n * for containers.\n */\nfunction convertMarkdownSegment(md: string): RootContent[] {\n  const mdast = fromMarkdown(md, {\n    extensions: [gfm()],\n    mdastExtensions: [gfmFromMarkdown()],\n  }) as Root;\n  // `allowDangerousHtml` keeps embedded raw HTML in the tree so the HTML parser\n  // downstream can normalize it (e.g. self-close `<img>`), rather than dropping it.\n  const hast = toHast(mdast, { allowDangerousHtml: true });\n  const html = toHtml(hast, { allowDangerousHtml: true });\n  return htmlBlocksPlain(html);\n}\n\n/** Matches a fenced-code OPEN line: optional ≤3-space indent + ``` / ~~~ run + info. */\nconst FENCE_OPEN = /^([ \\t]{0,3})(`{3,}|~{3,})[ \\t]*([^\\n]*)$/;\n\n/**\n * One slice of a raw Markdown segment: a `plain` run handed to the normal\n * converter, or a `fence` whose info string carried a `playground` meta token.\n */\ntype FenceSegment =\n  | { kind: 'plain'; raw: string }\n  | { kind: 'fence'; lang: string; spec: PlaygroundSpec; body: string };\n\n/**\n * Scan a raw Markdown string for fenced code blocks whose info string is\n * `<lang> playground …` and split it into `plain` runs + `fence` segments. This\n * runs on the RAW Markdown (docs + Markdown tutorials) BEFORE the HTML round-trip\n * in {@link convertMarkdownSegment}, because that round-trip drops a fence's\n * `meta` (only the language survives as a `language-*` class). A string with no\n * playground fence returns a single `plain` segment, so the common path stays\n * byte-identical. Unterminated fences are left in the plain run.\n */\nfunction splitPlaygroundFences(md: string): FenceSegment[] {\n  const lines = md.split('\\n');\n  const segments: FenceSegment[] = [];\n  let plain: string[] = [];\n  const flush = (): void => {\n    if (plain.length > 0) {\n      segments.push({ kind: 'plain', raw: plain.join('\\n') });\n      plain = [];\n    }\n  };\n\n  let i = 0;\n  while (i < lines.length) {\n    const open = FENCE_OPEN.exec(lines[i]);\n    if (!open) {\n      plain.push(lines[i]);\n      i++;\n      continue;\n    }\n\n    const tokens = open[3].trim().split(/\\s+/).filter(Boolean);\n    // `playground` may be the FIRST token (no language — ```` ```playground … ````)\n    // or the SECOND (language-prefixed — ```` ```js playground … ````). Anything\n    // else is a normal fence.\n    const pgIdx = tokens[0] === 'playground' ? 0 : tokens[1] === 'playground' ? 1 : -1;\n    const indent = open[1];\n    const fenceChar = open[2][0];\n    const fenceLen = open[2].length;\n    // A closing fence is the same char, at least as long (CommonMark), ≤3 indent.\n    const closeRe = new RegExp(`^[ \\\\t]{0,3}\\\\${fenceChar}{${fenceLen},}[ \\\\t]*$`);\n    let closeIdx = -1;\n    for (let j = i + 1; j < lines.length; j++) {\n      if (closeRe.test(lines[j])) {\n        closeIdx = j;\n        break;\n      }\n    }\n\n    // Unterminated fence: treat just the open line as plain and keep scanning\n    // (later lines may still be valid markdown / a real playground fence).\n    if (closeIdx === -1) {\n      plain.push(lines[i]);\n      i++;\n      continue;\n    }\n\n    if (pgIdx !== -1) {\n      // Markdown strips the opening fence's indent from each body line.\n      const bodyLines = lines\n        .slice(i + 1, closeIdx)\n        .map((l) => (indent && l.startsWith(indent) ? l.slice(indent.length) : l));\n      flush();\n      segments.push({\n        kind: 'fence',\n        // A first-token `playground` carries no language; otherwise the first\n        // token is the language and `playground` + spec follow it.\n        lang: pgIdx === 1 ? tokens[0] : '',\n        spec: parsePlaygroundSpec(tokens.slice(pgIdx + 1).join(' ')),\n        body: bodyLines.join('\\n'),\n      });\n    } else {\n      // A NORMAL fenced code block — keep the WHOLE block (open…close) as plain,\n      // verbatim. Crucially we do NOT scan inside it, so a `playground` fence that\n      // is merely being *displayed* inside an outer fence (e.g. a ```` ```` md\n      // example block on a docs page) is left as literal text, not lowered.\n      for (let k = i; k <= closeIdx; k++) plain.push(lines[k]);\n    }\n    i = closeIdx + 1;\n  }\n  flush();\n  return segments;\n}\n\n/**\n * Plain-Markdown converter with the playground-fence pre-scan layered on. A\n * ```` ```js playground … ```` fence becomes a `<Playground>`-wrapped `code`\n * node (bare prose configs default to ALL providers); every other run goes\n * through {@link convertMarkdownSegment}'s HTML round-trip. With no playground\n * fence the whole string takes the fast path, byte-identical to before.\n */\nfunction markdownBlocksPlain(md: string): RootContent[] {\n  const segments = splitPlaygroundFences(md);\n  if (segments.length === 1 && segments[0].kind === 'plain') return convertMarkdownSegment(md);\n\n  const out: RootContent[] = [];\n  for (const seg of segments) {\n    if (seg.kind === 'plain') {\n      if (seg.raw.trim().length > 0) out.push(...convertMarkdownSegment(seg.raw));\n    } else {\n      const opts = resolvePlaygroundOpts(seg.spec, KNOWN_PROVIDERS);\n      const codeNode = code(seg.lang || null, seg.body);\n      out.push(opts ? playground(opts, codeNode) : codeNode);\n    }\n  }\n  return out;\n}\n\n/**\n * Convert a raw Markdown document into block-level mdast nodes. Empty/blank\n * input returns `[]`.\n *\n * First splits out any lowercase `<steps>`/`<tabs>` authoring containers at the\n * RAW string level (see {@link splitContainers}), because the HTML round-trip\n * inside {@link markdownBlocksPlain} would strip those custom tags. Plain\n * segments go through {@link markdownBlocksPlain}; container segments become the\n * capitalized `<Steps>`/`<Tabs>` JSX nodes, their inner content re-parsed\n * recursively through this same function (so nested markdown, callouts, and even\n * nested containers survive). The recursion is finite: inner content without a\n * container hits the plain path.\n */\nexport function markdownToMdastBlocks(md: string | null | undefined): RootContent[] {\n  if (!md) return [];\n  const trimmed = md.trim();\n  if (trimmed.length === 0) return [];\n  return expandContainers(trimmed, markdownBlocksPlain, markdownToMdastBlocks);\n}\n\n/**\n * Like {@link htmlToMdastBlocks} but flattens to phrasing (inline) content by\n * pulling children out of the paragraph(s) the conversion produces. Use for\n * fields meant to appear inline, e.g. a param description inside a list item.\n *\n * Calls {@link htmlBlocksPlain} directly (no container splitting): an inline\n * context can't host a block-level `<Steps>`/`<Tabs>` element anyway.\n */\nexport function htmlToMdastInline(html: string | null | undefined): PhrasingContent[] {\n  if (!html) return [];\n  const trimmed = html.trim();\n  if (trimmed.length === 0) return [];\n  return blocksToInline(htmlBlocksPlain(trimmed));\n}\n\n/**\n * Parse a Markdown fragment into inline (phrasing) mdast content. Used for bits\n * of JSDoc text that are NOT pre-rendered to HTML by the markdown plugin — e.g.\n * an `@example` `<caption>`, which may carry Markdown (`*emphasis*`) and inline\n * HTML (`<b>`). Block structure is flattened to inline.\n */\nexport function markdownToMdastInline(md: string | null | undefined): PhrasingContent[] {\n  if (!md) return [];\n  const trimmed = md.trim();\n  if (trimmed.length === 0) return [];\n  return blocksToInline(fromMarkdown(trimmed).children);\n}\n\n/** mdast phrasing (inline) node types that can sit directly among `blocks`. */\nconst PHRASING_TYPES = new Set<string>([\n  'text',\n  'emphasis',\n  'strong',\n  'inlineCode',\n  'delete',\n  'link',\n  'linkReference',\n  'image',\n  'imageReference',\n  'break',\n  'html',\n  'footnoteReference',\n]);\n\n/**\n * Flatten block content to inline: unwrap paragraphs, and pass through any\n * phrasing node that the conversion left at the top level. A short HTML/text\n * fragment (e.g. a bare `@deprecated` reason like `use foo instead`) lowers to\n * a root-level `text` node rather than a paragraph — without this it would be\n * silently dropped. Genuine block nodes (tables, lists) are still skipped.\n */\nfunction blocksToInline(blocks: RootContent[]): PhrasingContent[] {\n  const out: PhrasingContent[] = [];\n  for (const block of blocks) {\n    if (block.type === 'paragraph') {\n      out.push(...block.children);\n    } else if (PHRASING_TYPES.has(block.type)) {\n      out.push(block as PhrasingContent);\n    }\n  }\n  return out;\n}\n","/**\n * Shared parser for the `@playground` block tag (doclets), the ```` ```js\n * playground … ```` prose fence, and the `<playground …>` prose container. All\n * three use ONE token grammar — the same whitespace-token / `key=value` style as\n * `embed.ts` — so a single {@link parsePlaygroundSpec} reads every authoring site:\n *\n *     codepen jsfiddle filename=resize.js highlight=1,4,8\n *\n * Tokens are: bare provider names (`codepen` | `jsfiddle` | `codesandbox`) that\n * enable those providers; `none`/`off` to opt a block out; `filename=<name>`; and\n * `highlight=1,4,8` (also `highlight=[1,4,8]`). Values may be single/double\n * quoted. Unknown tokens are warned-and-ignored; the parser never throws.\n */\n\nimport type { PlaygroundProvider } from '@clean-jsdoc-theme/utils';\n\n/** The providers a code block can be opened in. */\nexport const KNOWN_PROVIDERS = ['codepen', 'jsfiddle', 'codesandbox'] as const;\n\nconst PROVIDER_SET = new Set<string>(KNOWN_PROVIDERS);\nconst OFF_TOKENS = new Set<string>(['none', 'off']);\n\n/**\n * The parsed grammar of one `@playground` / fence / container config string.\n * `providers: null` means \"no explicit provider list was given\" (a bare\n * `@playground`) — distinct from an empty list — so callers can fall back to the\n * site-wide default set. `off` records a `none`/`off` opt-out token.\n */\nexport interface PlaygroundSpec {\n  /** `none`/`off` token present — opt this block out of the playground dropdown. */\n  off: boolean;\n  /** Explicit provider list (author order), or `null` when none were named. */\n  providers: PlaygroundProvider[] | null;\n  /** `filename=<name>` — header label for the code block. */\n  filename?: string;\n  /** `highlight=…` — sorted, de-duped 1-based line numbers (empty when unset). */\n  highlight: number[];\n}\n\n/** The resolved render opts a `<Playground>` wrapper carries (see {@link resolvePlaygroundOpts}). */\nexport interface PlaygroundOpts {\n  providers: PlaygroundProvider[];\n  filename?: string;\n  highlight: number[];\n}\n\n/**\n * Tokenize a config string into whitespace-delimited tokens, keeping spaces\n * inside single- or double-quoted runs intact (mirrors `embed.ts`'s tokenizer;\n * duplicated here to keep `embed.ts` untouched). Never throws.\n */\nfunction tokenize(text: string): string[] {\n  const tokens: string[] = [];\n  let current = '';\n  let quote: '\"' | \"'\" | null = null;\n  let started = false;\n\n  for (const ch of text) {\n    if (quote) {\n      if (ch === quote) quote = null;\n      else current += ch;\n      continue;\n    }\n    if (ch === '\"' || ch === \"'\") {\n      quote = ch;\n      started = true;\n      continue;\n    }\n    if (ch === ' ' || ch === '\\t' || ch === '\\n' || ch === '\\r' || ch === '\\f' || ch === '\\v') {\n      if (started) {\n        tokens.push(current);\n        current = '';\n        started = false;\n      }\n      continue;\n    }\n    current += ch;\n    started = true;\n  }\n  if (started) tokens.push(current);\n  return tokens;\n}\n\n/** Split a `key=value` token at the first `=`; `null` for a bare flag. */\nfunction splitPair(token: string): { key: string; value: string } | null {\n  const eq = token.indexOf('=');\n  if (eq === -1) return null;\n  return { key: token.slice(0, eq), value: token.slice(eq + 1) };\n}\n\n/**\n * Parse a `highlight=` value into sorted, de-duped 1-based line numbers. Accepts\n * `1,4,8` and `[1,4,8]` (brackets stripped). Non-numeric / `< 1` entries are\n * dropped; an all-junk value yields `[]`.\n */\nfunction parseHighlight(value: string): number[] {\n  const inner = value.trim().replace(/^\\[/, '').replace(/\\]$/, '');\n  const seen = new Set<number>();\n  for (const part of inner.split(',')) {\n    const n = Number(part.trim());\n    if (Number.isInteger(n) && n >= 1) seen.add(n);\n  }\n  return [...seen].sort((a, b) => a - b);\n}\n\n/**\n * Parse a config string into a {@link PlaygroundSpec}. Never throws — unknown\n * bare tokens / unknown keys are warned-and-ignored (mirroring `parseEmbedConfig`).\n */\nexport function parsePlaygroundSpec(text: string): PlaygroundSpec {\n  const spec: PlaygroundSpec = { off: false, providers: null, highlight: [] };\n  if (typeof text !== 'string') return spec;\n\n  const providers: PlaygroundProvider[] = [];\n  for (const token of tokenize(text)) {\n    const pair = splitPair(token);\n\n    if (!pair) {\n      const flag = token.toLowerCase();\n      if (OFF_TOKENS.has(flag)) {\n        spec.off = true;\n      } else if (PROVIDER_SET.has(flag)) {\n        if (!providers.includes(flag as PlaygroundProvider)) providers.push(flag as PlaygroundProvider);\n      } else if (token.length > 0) {\n        console.warn(`[setu:playground] ignoring unknown token: \"${token}\"`);\n      }\n      continue;\n    }\n\n    const { key, value } = pair;\n    if (key === 'filename') {\n      const name = value.trim();\n      if (name) spec.filename = name;\n    } else if (key === 'highlight') {\n      spec.highlight = parseHighlight(value);\n    } else {\n      console.warn(`[setu:playground] ignoring unknown config key: \"${key}\"`);\n    }\n  }\n\n  if (providers.length > 0) spec.providers = providers;\n  return spec;\n}\n\n/**\n * Resolve a {@link PlaygroundSpec} into the concrete {@link PlaygroundOpts} a\n * `<Playground>` wrapper carries, or `null` when nothing warrants a wrapper.\n *\n * `defaultProviders` fills in the provider list for a bare config (no explicit\n * providers and not opted out): API examples pass the site-wide default set,\n * prose fences/containers pass {@link KNOWN_PROVIDERS}. An `off` block keeps an\n * empty provider list but still wraps when it carries a `filename`/`highlight`\n * (so opting out of the dropdown doesn't lose the presentation options).\n */\nexport function resolvePlaygroundOpts(\n  spec: PlaygroundSpec,\n  defaultProviders: readonly PlaygroundProvider[]\n): PlaygroundOpts | null {\n  const providers = spec.off ? [] : (spec.providers ?? [...defaultProviders]);\n  const warrants = providers.length > 0 || !!spec.filename || spec.highlight.length > 0;\n  if (!warrants) return null;\n  return { providers, filename: spec.filename, highlight: spec.highlight };\n}\n","/**\n * Translatable API slots — the locale-independent template half of the two-phase\n * localization build (see `packages/aadesh-bhasha-plan.md`, Phase 2).\n *\n * Every translatable doclet prose field (a description, a `@summary`, an\n * `@example` caption) is funneled through {@link resolveSlotText} as its source\n * string is read, *before* it's converted to mdast. With no resolver the source\n * passes through untouched, so the default (no-locale) build is byte-identical.\n * When a resolver is threaded in, each slot is (a) recorded for extraction via\n * `collect` and (b) substituted with the active locale's translation via\n * `translate` — so the very same build pass, re-run with a translating resolver,\n * is the per-locale \"stamp\".\n *\n * Keys + hashes come from bhasha (`apiSlotKey` / `sourceHash`) so setu and aadesh\n * agree on identity and staleness. Only prose is a slot: names, type strings,\n * enum values, and `@example` code stay locale-invariant.\n */\n\nimport { apiSlotKey, sourceHash } from '@clean-jsdoc-theme/bhasha';\nimport type { SlotEntry } from '@clean-jsdoc-theme/utils';\n\n/**\n * Build-time resolver threaded through the doclet→mdast conversion. Both hooks\n * are optional: `collect` records a slot for the extractable template, `translate`\n * swaps in a locale's text. Omit both (or the whole resolver) for the\n * byte-identical default build.\n */\nexport interface SlotResolver {\n  /** Record a slot as its source string is read (template extraction). */\n  collect?: (entry: SlotEntry) => void;\n  /**\n   * Return the active-locale text for `key`, or `sourceText` when untranslated.\n   * Whatever it returns is fed to the same mdast converter as the source, so a\n   * translation must be authored in the source's format (HTML/Markdown prose).\n   */\n  translate?: (key: string, sourceText: string) => string;\n}\n\n/**\n * Resolve one translatable prose field to the string that should be rendered:\n * collect it (for extraction) and translate it (for stamping). Empty/absent\n * source, an absent longname, or no resolver all short-circuit to the source\n * unchanged — so nothing is keyed or substituted when there's nothing to\n * translate, and the default build is byte-identical.\n *\n * @param longname - The owning symbol's longname (the key's namespace).\n * @param field - Field path within the doclet (e.g. `'description'` or\n *   `['examples', '0', 'caption']`); must be `#`-free (bhasha key invariant).\n */\nexport function resolveSlotText(\n  resolver: SlotResolver | undefined,\n  longname: string | undefined,\n  field: string | readonly string[],\n  sourceText: string | null | undefined\n): string | null | undefined {\n  if (!sourceText || !longname || !resolver) return sourceText;\n  const key = apiSlotKey(longname, field);\n  resolver.collect?.({ key, sourceText, hash: sourceHash(sourceText) });\n  const translated = resolver.translate?.(key, sourceText);\n  // An empty translation counts as untranslated → fall back to the source.\n  return translated != null && translated !== '' ? translated : sourceText;\n}\n\n/**\n * Accumulate {@link SlotEntry}s into a deduped, insertion-ordered list — the\n * `manifest.slots` template. Dedup is by key (the same symbol+field is rendered\n * once per build, but the collector tolerates repeats); the first-seen source\n * wins, which is deterministic given setu's stable build order.\n */\nexport class SlotCollector {\n  private readonly byKey = new Map<string, SlotEntry>();\n\n  /** A `collect` hook bound to this collector, for a {@link SlotResolver}. */\n  readonly collect = (entry: SlotEntry): void => {\n    if (!this.byKey.has(entry.key)) this.byKey.set(entry.key, entry);\n  };\n\n  /** The collected slots, in first-seen order. */\n  list(): SlotEntry[] {\n    return [...this.byKey.values()];\n  }\n}\n\n/**\n * Make a `translate` hook from a flat locale message map (`key → translated\n * text`). A missing or empty entry falls back to the source string, so a\n * partially-translated catalog renders the default text for the gaps.\n */\nexport function makeSlotTranslator(\n  messages: Readonly<Record<string, string>>\n): NonNullable<SlotResolver['translate']> {\n  return (key, sourceText) => {\n    const value = messages[key];\n    return value != null && value !== '' ? value : sourceText;\n  };\n}\n","import type { List, ListItem, Paragraph, PhrasingContent, RootContent } from 'mdast';\nimport type { MdxJsxFlowElement } from 'mdast-util-mdx-jsx';\nimport { TDoclet, TDocletParam, TDocletTypeParam, TDocletTypeProperty } from '@clean-jsdoc-theme/utils';\nimport type { ResolvedLink } from '../link-registry';\nimport { parseEmbedConfig } from '../embed';\nimport {\n  callout,\n  code,\n  embed,\n  emphasis,\n  inlineCode,\n  li,\n  link,\n  p,\n  playground,\n  sourceLink,\n  strong,\n  text,\n  ul,\n} from './builders';\nimport type { PlaygroundOpts } from '../playground';\nimport { htmlToMdastBlocks, htmlToMdastInline, markdownToMdastInline } from './from-html';\nimport { resolveSlotText, type SlotResolver } from '../slots';\n\n// ── Small extractors ────────────────────────────────────────────────────────\n\n/**\n * Inline rendering of `type.names` as a single inline-code node, e.g.\n * `[\"Array.<string>\", \"null\"]` → `` `Array.<string> | null` ``.\n * No parsing of generics yet — kept literal so consumers can swap in a richer\n * type-expression renderer later.\n */\nexport function typeExpressionInline(type: TDocletTypeProperty | undefined): RootContent | null {\n  if (!type || !type.names || type.names.length === 0) return null;\n  return p(inlineCode(type.names.join(' | ')));\n}\n\n/**\n * `[\"Array.<string>\", \"null\"]` → `\"Array.<string> | null\"`. For embedding in\n * sentences without a wrapping paragraph.\n */\nexport function typeExpressionString(type: TDocletTypeProperty | undefined): string | null {\n  if (!type || !type.names || type.names.length === 0) return null;\n  return type.names.join(' | ');\n}\n\ntype LinkResolver = (target: string) => ResolvedLink | null;\n\n/**\n * Identifier-path token inside a type expression: a run of word chars plus the\n * JSDoc namepath separators (`.` `~` `#` `:` `/`) and `$`. Structural syntax —\n * `< > ( ) [ ] | , ? ! * = space` — falls in the gaps between matches, so\n * `Array.<MyClass> | null` yields the candidate tokens `Array.`, `MyClass`,\n * `null` (the `.` after `Array` rides along and simply fails to resolve).\n */\nconst TYPE_TOKEN_RE = /[\\w$./~#:]+/g;\n\n/**\n * Render a type expression string as phrasing content, hyperlinking each token\n * that resolves to a documented symbol — restoring the v4 behaviour where a\n * `@param {MyClass}` type linked to the `MyClass` page (members resolve to their\n * `slug#anchor` too). `style` picks the look of the non-link/link text: `'code'`\n * for the monospaced contexts (returns, the \"Type\" field) and `'text'` for the\n * plain-text parenthetical in the Parameters list.\n *\n * Stays byte-identical to the old single-node rendering whenever nothing links:\n * with no resolver, or when no token resolves, it returns one `inlineCode`/`text`\n * node holding the whole string — so the localization-extract path and any\n * resolver-less caller are unaffected.\n */\nfunction linkifyTypeExpression(\n  s: string,\n  resolveLink: LinkResolver | undefined,\n  style: 'code' | 'text'\n): PhrasingContent[] {\n  const base = style === 'code' ? inlineCode : text;\n  if (!resolveLink) return [base(s)];\n\n  const out: PhrasingContent[] = [];\n  let cursor = 0;\n  let pending = '';\n  let linked = false;\n  const flush = (): void => {\n    if (pending !== '') {\n      out.push(base(pending));\n      pending = '';\n    }\n  };\n\n  TYPE_TOKEN_RE.lastIndex = 0;\n  let match = TYPE_TOKEN_RE.exec(s);\n  while (match) {\n    const token = match[0];\n    const resolved = resolveLink(token);\n    if (resolved && !resolved.external) {\n      pending += s.slice(cursor, match.index);\n      flush();\n      out.push(link(resolved.href, base(token)));\n      linked = true;\n    } else {\n      pending += s.slice(cursor, match.index) + token;\n    }\n    cursor = match.index + token.length;\n    match = TYPE_TOKEN_RE.exec(s);\n  }\n  pending += s.slice(cursor);\n  flush();\n\n  return linked ? out : [base(s)];\n}\n\n/**\n * Type expression of a doclet as link-aware phrasing content, or `null` when the\n * doclet carries no type. See {@link linkifyTypeExpression} for the link rules.\n */\nfunction typeExpressionPhrasing(\n  type: TDocletTypeProperty | undefined,\n  resolveLink: LinkResolver | undefined,\n  style: 'code' | 'text'\n): PhrasingContent[] | null {\n  if (!type || !type.names || type.names.length === 0) return null;\n  return linkifyTypeExpression(type.names.join(' | '), resolveLink, style);\n}\n\n// ── Description ─────────────────────────────────────────────────────────────\n\n/**\n * Description blocks for a doclet. Prefers `classdesc` (class-level) over\n * `description` (constructor-level). Both come in as HTML from JSDoc. The chosen\n * source is routed through the `slots` resolver (keyed `…#description`) so it can\n * be collected for extraction and substituted per locale before conversion;\n * without a resolver the HTML passes through unchanged.\n */\nexport function descriptionBlocks(doclet: TDoclet, slots?: SlotResolver): RootContent[] {\n  const source = doclet.classdesc ?? doclet.description;\n  return htmlToMdastBlocks(resolveSlotText(slots, doclet.longname, 'description', source));\n}\n\n/**\n * `@summary` content if present, as block content. Distinct from\n * {@link descriptionBlocks} — both can coexist on a doclet. Routed through the\n * `slots` resolver (keyed `…#summary`).\n */\nexport function summaryBlocks(doclet: TDoclet, slots?: SlotResolver): RootContent[] {\n  return htmlToMdastBlocks(resolveSlotText(slots, doclet.longname, 'summary', doclet.summary));\n}\n\n// ── Examples ────────────────────────────────────────────────────────────────\n\n/** Leading `<caption>…</caption>` JSDoc puts before an example's code. */\nconst EXAMPLE_CAPTION_RE = /^\\s*<caption>([\\s\\S]*?)<\\/caption>\\s*/i;\n/** JSDoc's `{@lang xxx}` directive that overrides an example's code language. */\nconst EXAMPLE_LANG_RE = /\\{@lang\\s+([^}\\s]+)\\s*\\}\\s*/i;\n/**\n * An example body that is ITSELF a single fenced code block, start to end.\n * TypeDoc auto-wraps `@example` bodies in a ` ```ts ` fence (and a JSDoc author\n * may fence theirs too), so we unwrap it rather than wrapping again — otherwise\n * the body double-fences (` ````js ` around ` ```ts `), which the renderer's\n * brace-escaping then mis-parses. Captures the fence chars (for the matching\n * close), the info string (language), and the inner body.\n */\nconst EXAMPLE_FENCE_RE = /^(`{3,}|~{3,})([^\\n]*)\\n([\\s\\S]*?)\\n?\\1[ \\t]*$/;\n\n/**\n * Blocks for each `@example`. JSDoc emits examples as raw strings (the markdown\n * plugin does NOT touch them), optionally prefixed with a `<caption>` label and\n * a `{@lang xxx}` directive. The caption is rendered as a paragraph (supporting\n * Markdown + inline HTML); `{@lang}` sets the fence language; the remaining body\n * is a fenced code block. Falls back to `lang` when no `{@lang}` is given. An\n * example whose body is already a single fenced block is unwrapped (its fence\n * language wins unless `{@lang}` overrode it) so it isn't double-fenced.\n */\nexport function examplesBlocks(\n  doclet: TDoclet,\n  lang: string = 'js',\n  slots?: SlotResolver,\n  playgroundOpts?: PlaygroundOpts | null\n): RootContent[] {\n  const out: RootContent[] = [];\n  let exampleIndex = -1;\n  for (const raw of doclet.examples ?? []) {\n    exampleIndex++;\n    let src = String(raw);\n\n    let caption: string | null = null;\n    const capMatch = EXAMPLE_CAPTION_RE.exec(src);\n    if (capMatch) {\n      caption = capMatch[1].trim();\n      src = src.slice(capMatch[0].length);\n    }\n    // Only the caption prose is translatable; the example CODE stays\n    // locale-invariant (a locked decision). Keyed per example by index.\n    if (caption) {\n      caption =\n        resolveSlotText(\n          slots,\n          doclet.longname,\n          ['examples', String(exampleIndex), 'caption'],\n          caption\n        ) ?? caption;\n    }\n\n    let exampleLang = lang;\n    const langMatch = EXAMPLE_LANG_RE.exec(src);\n    if (langMatch) {\n      exampleLang = langMatch[1];\n      src = src.replace(EXAMPLE_LANG_RE, '');\n    }\n\n    src = src.replace(/^\\n+|\\s+$/g, '');\n\n    const fence = EXAMPLE_FENCE_RE.exec(src);\n    if (fence) {\n      const fenceLang = fence[2].trim().split(/\\s+/)[0];\n      if (!langMatch && fenceLang) exampleLang = fenceLang;\n      src = fence[3].replace(/\\s+$/, '');\n    }\n\n    if (caption) out.push(p(...markdownToMdastInline(caption)));\n    if (src.length > 0) {\n      // The caption (translatable prose) stays OUTSIDE the wrapper; only the code\n      // fence is wrapped, so Shiki still highlights it and the dropdown/filename/\n      // highlight ride on the `<Playground>` attributes.\n      const codeNode = code(exampleLang, src);\n      out.push(playgroundOpts ? playground(playgroundOpts, codeNode) : codeNode);\n    }\n  }\n  return out;\n}\n\n// ── Embeds (@iframe) ─────────────────────────────────────────────────────────\n\n/**\n * Blocks for each `@iframe` block tag. JSDoc lands a `@iframe <config>` tag as\n * `{ title: 'iframe', text: '<raw>', value: '<raw>' }`; we parse the raw config\n * with {@link parseEmbedConfig} and, for each valid {@link EmbedSpec}, emit an\n * `<Embed>` JSX element via the {@link embed} builder. Invalid configs (no URL,\n * non-`https`/protocol-relative, empty) parse to `null` and are dropped (the\n * parser already warns). Returns `[]` when the doclet has no `@iframe` tags.\n */\nexport function embedBlocks(doclet: TDoclet): RootContent[] {\n  const out: RootContent[] = [];\n  for (const tag of doclet.tags ?? []) {\n    if (tag.title !== 'iframe') continue;\n    const raw = typeof tag.value === 'string' ? tag.value : (tag.text ?? '');\n    const spec = parseEmbedConfig(raw);\n    if (spec) out.push(embed(spec));\n  }\n  return out;\n}\n\n// ── Inheritance note ────────────────────────────────────────────────────────\n\n/**\n * If the doclet was inherited from a parent (either via `augments` walk or\n * JSDoc's own `inherited` flag), returns a paragraph noting the source.\n * `inheritedFrom` is set by {@link getClassView} (and friends); for raw\n * doclets, `inherits` is checked as a fallback.\n */\nexport function inheritedFromParagraph(\n  doclet: TDoclet & { inheritedFrom?: string }\n): Paragraph | null {\n  const source = doclet.inheritedFrom ?? (doclet.inherited ? doclet.inherits : undefined);\n  if (!source) return null;\n  return p(emphasis(text('Inherited from '), inlineCode(source)));\n}\n\n// ── Deprecation ─────────────────────────────────────────────────────────────\n\n/** Human-readable noun for a doclet's kind, used in default messages. */\nfunction kindNoun(doclet: TDoclet): string {\n  switch (doclet.kind) {\n    case 'class':\n      return 'class';\n    case 'constant':\n      return 'constant';\n    case 'enum':\n      return 'enumeration';\n    case 'event':\n      return 'event';\n    case 'external':\n      return 'external';\n    case 'file':\n      return 'file';\n    case 'function':\n      return doclet.memberof ? 'method' : 'function';\n    case 'interface':\n      return 'interface';\n    case 'member':\n      return doclet.memberof ? 'property' : 'member';\n    case 'mixin':\n      return 'mixin';\n    case 'module':\n      return 'module';\n    case 'namespace':\n      return 'namespace';\n    case 'package':\n      return 'package';\n    case 'typedef':\n      return 'type definition';\n    default:\n      return 'symbol';\n  }\n}\n\n/**\n * Default deprecation message used when `@deprecated` carries no reason — the\n * wording adapts to the doclet's kind (e.g. \"This class is deprecated…\",\n * \"This method is deprecated…\").\n */\nexport function defaultDeprecationText(doclet: TDoclet): string {\n  return `This ${kindNoun(doclet)} is deprecated and should not be used.`;\n}\n\n/**\n * `@deprecated` rendered as a `warning` callout blockquote. JSDoc stores it as\n * either `true` (just deprecated) or a reason string. When it's `true` we fall\n * back to a kind-aware default sentence ({@link defaultDeprecationText}) so the\n * callout is never blank. Reason strings may contain HTML.\n */\nexport function deprecationBlock(doclet: TDoclet): MdxJsxFlowElement | null {\n  if (!doclet.deprecated) return null;\n  if (doclet.deprecated === true) {\n    return callout('error', [p(text(' '), text(defaultDeprecationText(doclet)))]);\n  }\n  const reason = htmlToMdastInline(doclet.deprecated);\n  return callout('error', [p(text(' '), ...reason)]);\n}\n\n// ── Modifiers (abstract / async / generator / readonly / override / access) ──\n\n/**\n * Boolean/scalar modifier flags collapsed into a single \"Modifiers:\" line:\n * `@abstract` (→ `virtual`), `@async`, `@generator`, `@readonly`, a bare\n * `@override` (no resolved parent — the resolved form is a relation line, see\n * {@link relationsBlocks}) and `@access` (private/protected/package/public).\n * Returns `null` when none apply.\n */\nexport function modifiersBlock(doclet: TDoclet): Paragraph | null {\n  const mods: string[] = [];\n  if (doclet.virtual) mods.push('abstract');\n  if (doclet.async) mods.push('async');\n  if (doclet.generator) mods.push('generator');\n  if (doclet.readonly) mods.push('readonly');\n  if (doclet.override && !doclet.overrides) mods.push('override');\n  if (doclet.access) mods.push(doclet.access);\n  if (mods.length === 0) return null;\n  return p(\n    strong(text('Modifiers:')),\n    text(' '),\n    ...interleave(\n      mods.map((m) => inlineCode(m)),\n      () => text(', ')\n    )\n  );\n}\n\n// ── Relations (extends / implements / mixes / overrides / borrows) ──────────\n\n/**\n * Inheritance & composition links for a doclet, each on its own line:\n * `@augments`/`@extends`, `@implements`, `@mixes`, the resolved `@override`\n * target (`overrides`), and `@borrows` (`borrowed`). Mirrors the class-level\n * `classRelationsBlocks` but works for any member doclet. Empty if none apply.\n */\nexport function relationsBlocks(doclet: TDoclet): RootContent[] {\n  const out: RootContent[] = [];\n\n  const refLine = (label: string, refs: readonly string[] | undefined) => {\n    if (!refs || refs.length === 0) return;\n    out.push(\n      p(\n        strong(text(`${label}: `)),\n        ...interleave(\n          refs.map((r) => inlineCode(r)),\n          () => text(', ')\n        )\n      )\n    );\n  };\n\n  refLine('Extends', doclet.augments);\n  refLine('Implements', doclet.implements);\n  refLine('Mixes', doclet.mixes);\n\n  if (doclet.overrides) {\n    out.push(p(strong(text('Overrides: ')), inlineCode(doclet.overrides)));\n  }\n\n  for (const b of doclet.borrowed ?? []) {\n    const children: Paragraph['children'] = [strong(text('Borrows: '))];\n    if (b.from) children.push(inlineCode(b.from));\n    if (b.as) children.push(text(' as '), inlineCode(b.as));\n    out.push(p(...children));\n  }\n\n  return out;\n}\n\n// ── Params (incl. nested object-destructured params) ────────────────────────\n\n/**\n * The owning symbol + slot resolver needed to translate a param/return/throws\n * **description**. Only the prose is a slot — names, type strings, optional/rest\n * markers, and default values stay locale-invariant. Omitted (or with no\n * resolver) → descriptions render from source, byte-identical to before.\n */\nexport interface ParamSlotCtx {\n  slots?: SlotResolver;\n  longname?: string;\n  /**\n   * Registry resolver for hyperlinking type names (param/return/property types)\n   * to the page/anchor of the symbol they reference. Omitted → types render as\n   * inert code/text, byte-identical to before.\n   */\n  resolveLink?: LinkResolver;\n}\n\n/**\n * Resolve one param/return description to its render string: collect it for the\n * extractable template and (when stamping) substitute the locale's translation.\n * Keyed `<fieldPrefix>.<discriminator>.description` under the owning longname,\n * so a parameter is `params.timeout.description` and a return is\n * `returns.0.description`.\n */\nfunction descriptionInline(\n  description: string | null | undefined,\n  ctx: ParamSlotCtx | undefined,\n  fieldPrefix: string,\n  discriminator: string\n) {\n  const source =\n    resolveSlotText(\n      ctx?.slots,\n      ctx?.longname,\n      [fieldPrefix, discriminator, 'description'],\n      description\n    ) ?? description;\n  return htmlToMdastInline(source);\n}\n\n/**\n * `params` array rendered as a nested list. Object-destructured params (e.g.\n * `name: \"options.timeout\"`) are nested under their parent.\n *\n * Each item: `` `name` `` (`type`, optional, default: `value`) — description.\n * Descriptions are translatable slots (keyed by `fieldPrefix` + param name)\n * when a {@link ParamSlotCtx} with a resolver is supplied.\n */\nexport function paramsList(\n  params: readonly TDocletParam[] | undefined,\n  ctx?: ParamSlotCtx,\n  fieldPrefix = 'params'\n): List | null {\n  if (!params || params.length === 0) return null;\n  return ul(nestParamItems(params, ctx, fieldPrefix));\n}\n\n/**\n * `@property` list. Same nested shape as {@link paramsList} — object-property\n * entries (`options.timeout`) nest under their parent. `properties` carries the\n * param-compatible fields (name/type/optional/defaultvalue/description), so it\n * reuses the same item builder (slots keyed under `properties.*`).\n */\nexport function propertiesList(\n  properties: readonly TDocletParam[] | undefined,\n  ctx?: ParamSlotCtx\n): List | null {\n  return paramsList(properties, ctx, 'properties');\n}\n\n/**\n * Same shape as {@link paramsList} but for `@returns`. The `name` field is\n * usually absent — just type + description (a translatable slot keyed by index).\n */\nexport function returnsList(\n  returns: readonly TDocletParam[] | undefined,\n  ctx?: ParamSlotCtx\n): List | null {\n  return labeledTypedList(returns, ctx, 'returns');\n}\n\n/** Same as {@link returnsList} for `@yields`. */\nexport function yieldsList(\n  yields: readonly TDocletParam[] | undefined,\n  ctx?: ParamSlotCtx\n): List | null {\n  return labeledTypedList(yields, ctx, 'yields');\n}\n\n/** Same as {@link returnsList} for `@throws` / `exceptions`. */\nexport function throwsList(\n  exceptions: readonly TDocletParam[] | undefined,\n  ctx?: ParamSlotCtx\n): List | null {\n  return labeledTypedList(exceptions, ctx, 'throws');\n}\n\nfunction labeledTypedList(\n  items: readonly TDocletParam[] | undefined,\n  ctx: ParamSlotCtx | undefined,\n  fieldPrefix: string\n): List | null {\n  if (!items || items.length === 0) return null;\n  return ul(items.map((it, i) => li(p(...typedDescriptionInline(it, ctx, fieldPrefix, i)))));\n}\n\nfunction typedDescriptionInline(\n  item: TDocletParam,\n  ctx: ParamSlotCtx | undefined,\n  fieldPrefix: string,\n  index: number\n) {\n  const out: PhrasingContent[] = [];\n  const typeNodes = typeExpressionPhrasing(item.type, ctx?.resolveLink, 'code');\n  if (typeNodes) out.push(...typeNodes);\n  // No name on a return/throws entry → key by position.\n  const desc = descriptionInline(item.description, ctx, fieldPrefix, String(index));\n  if (desc.length > 0) {\n    if (out.length > 0) out.push(text(' — '));\n    out.push(...desc);\n  }\n  return out;\n}\n\nfunction nestParamItems(\n  params: readonly TDocletParam[],\n  ctx: ParamSlotCtx | undefined,\n  fieldPrefix: string\n): ListItem[] {\n  // Group nested `options.timeout` under `options`. JSDoc lists them flat but\n  // in declaration order; we walk and build a name → ListItem map.\n  const items: ListItem[] = [];\n  const byName = new Map<string, ListItem>();\n\n  for (const param of params) {\n    const item = paramListItem(param, ctx, fieldPrefix);\n    const name = param.name ?? '';\n    byName.set(name, item);\n\n    const dotIdx = name.lastIndexOf('.');\n    if (dotIdx > 0) {\n      const parentName = name.slice(0, dotIdx);\n      const parent = byName.get(parentName);\n      if (parent) {\n        let nested = parent.children.find((c): c is List => c.type === 'list');\n        if (!nested) {\n          nested = ul([]);\n          parent.children.push(nested);\n        }\n        nested.children.push(item);\n        continue;\n      }\n    }\n    items.push(item);\n  }\n\n  return items;\n}\n\nfunction paramListItem(\n  param: TDocletParam,\n  ctx: ParamSlotCtx | undefined,\n  fieldPrefix: string\n): ListItem {\n  const line: Paragraph['children'] = [];\n\n  if (param.name) line.push(inlineCode(param.name));\n\n  // The parenthetical is `(type, optional, default: value)`. The type is the\n  // only linkable piece, so it renders as phrasing (a plain-text link when it\n  // resolves) while optional/default stay flat text — concatenating to the same\n  // string as before when nothing links.\n  const typeNodes = typeExpressionPhrasing(param.type, ctx?.resolveLink, 'text');\n  const trailingFlags: string[] = [];\n  if (param.optional) trailingFlags.push('optional');\n  if (param.defaultvalue !== undefined)\n    trailingFlags.push(`default: ${JSON.stringify(param.defaultvalue)}`);\n  if (typeNodes || trailingFlags.length > 0) {\n    if (line.length > 0) line.push(text(' '));\n    line.push(text('('));\n    if (typeNodes) {\n      line.push(...typeNodes);\n      if (trailingFlags.length > 0) line.push(text(`, ${trailingFlags.join(', ')}`));\n    } else {\n      line.push(text(trailingFlags.join(', ')));\n    }\n    line.push(text(')'));\n  }\n\n  // The param NAME is the slot discriminator (stable across reorders, unlike an\n  // index); nested `options.timeout` keeps its dotted name.\n  const desc = descriptionInline(param.description, ctx, fieldPrefix, param.name ?? '');\n  if (desc.length > 0) {\n    if (line.length > 0) line.push(text(' — '));\n    line.push(...desc);\n  }\n\n  return li(p(...line));\n}\n\n// ── Metadata (since / version / see / todo / author / tutorial / requires) ──\n\n/**\n * Combines `@since`, `@version`, `@see`, `@todo`, `@author`, `@tutorial`,\n * `@requires` into a single bullet list. Returns `null` if none are set.\n *\n * Order is fixed for deterministic output.\n */\nexport function metadataList(doclet: TDoclet, options?: DocletBlocksOptions): List | null {\n  const rows: ListItem[] = [];\n\n  if (doclet.since) rows.push(li(p(strong(text('Since:')), text(' '), text(doclet.since))));\n  if (doclet.version) rows.push(li(p(strong(text('Version:')), text(' '), text(doclet.version))));\n  if (doclet.license) rows.push(li(p(strong(text('License:')), text(' '), text(doclet.license))));\n  if (doclet.copyright) {\n    rows.push(li(p(strong(text('Copyright:')), text(' '), text(doclet.copyright))));\n  }\n  if (doclet.author && doclet.author.length > 0) {\n    rows.push(li(p(strong(text('Author:')), text(' '), text(doclet.author.join(', ')))));\n  }\n  if (doclet.requires && doclet.requires.length > 0) {\n    rows.push(\n      li(\n        p(\n          strong(text('Requires:')),\n          text(' '),\n          ...interleave(\n            doclet.requires.map((r) => inlineCode(r)),\n            () => text(', ')\n          )\n        )\n      )\n    );\n  }\n  if (doclet.tutorials && doclet.tutorials.length > 0) {\n    const resolveTutorial = options?.resolveTutorial;\n    rows.push(\n      li(\n        p(\n          strong(text('Tutorials:')),\n          text(' '),\n          ...interleave(\n            doclet.tutorials.map((t) => {\n              const resolved = resolveTutorial?.(t);\n              return resolved ? link(resolved.href, text(resolved.title)) : text(t);\n            }),\n            () => text(', ')\n          )\n        )\n      )\n    );\n  }\n  if (doclet.see && doclet.see.length > 0) {\n    rows.push(\n      li(\n        p(strong(text('See:'))),\n        ul(doclet.see.map((s) => li(p(...seeInline(s, options?.resolveLink)))))\n      )\n    );\n  }\n  if (doclet.todo && doclet.todo.length > 0) {\n    rows.push(li(p(strong(text('TODO:'))), ul(doclet.todo.map((t) => li(p(text(t)))))));\n  }\n\n  return rows.length === 0 ? null : ul(rows);\n}\n\n/**\n * Render one `@see` entry as phrasing content.\n *\n * Without a `resolve` function this preserves the original legacy behavior\n * byte-for-byte: a `{@link URL|label}` tag or a bare `https?://` string becomes\n * a `link`, anything else becomes plain `text`. Existing callers/tests that\n * pass no resolver are therefore unaffected.\n *\n * With a `resolve` function the entry becomes a real cross-reference:\n * - A single wrapping brace pair (`@see {namepath}`) is stripped first.\n * - A `{@link …}` / `{@linkcode …}` / `{@linkplain …}` tag is parsed into\n *   `(target, label)` (target first, optional label after `|` or whitespace,\n *   label defaulting to target). A bare value is treated as a namepath-or-URL\n *   with `target = label = value`.\n * - `resolve(target)` hit → a `link` (monospaced child for `@linkcode`, plain\n *   text otherwise). Miss → `text(see)` fallback, so nothing renders as a\n *   broken anchor.\n *\n * `{@link …} prose` case (a tag followed by trailing prose, e.g.\n * `@see {@link Queue} for the main engine.`): we resolve the leading tag and\n * append the remaining prose as a trailing `text` node (option (a)). If the tag\n * itself doesn't resolve we fall back to plain `text(see)`.\n */\nexport function seeInline(see: string, resolve?: (t: string) => ResolvedLink | null) {\n  if (resolve) {\n    const trimmed = see.trim();\n    // `@see {namepath}` — strip exactly one wrapping brace pair, but only when\n    // the inner value is NOT itself a `{@link …}` tag (those start with `{@`).\n    const value =\n      trimmed.startsWith('{') && trimmed.endsWith('}') && !trimmed.startsWith('{@')\n        ? trimmed.slice(1, -1).trim()\n        : trimmed;\n\n    // A `{@link|linkcode|linkplain target( |\\|)label?}` tag, possibly followed\n    // by trailing prose. We anchor at the start so a leading tag is detected\n    // even when prose follows.\n    const tagRe = /^\\{@(link|linkcode|linkplain)\\s+([^}|]+?)(?:[|\\s]([^}]*))?\\}/;\n    const m = value.match(tagRe);\n    if (m) {\n      const tag = m[1];\n      const target = (m[2] ?? '').trim();\n      const label = (m[3] ?? '').trim() || target;\n      const resolved = resolve(target);\n      if (resolved) {\n        const child = tag === 'linkcode' ? inlineCode(label) : text(label);\n        const out: PhrasingContent[] = [link(resolved.href, child)];\n        const rest = value.slice(m[0].length);\n        if (rest.length > 0) out.push(text(rest));\n        return out;\n      }\n      // Tag present but unresolved → preserve original text.\n      return [text(see)];\n    }\n\n    // Bare namepath-or-URL: the whole value is both target and label.\n    const resolved = resolve(value);\n    if (resolved) {\n      return [link(resolved.href, text(value))];\n    }\n    return [text(see)];\n  }\n\n  // ── Legacy behavior (no resolver) — must stay byte-identical ──────────────\n  // Common form: `{@link URL|label}` or a bare URL or just text. Keep simple:\n  // detect a leading URL pattern and emit a real link; otherwise raw text.\n  const linkMatch = see.match(/^\\{@link\\s+([^|}\\s]+)(?:\\|([^}]+))?\\}$/);\n  if (linkMatch) {\n    const url = linkMatch[1];\n    const label = linkMatch[2] ?? url;\n    return [link(url, text(label))];\n  }\n  if (/^https?:\\/\\//.test(see)) {\n    return [link(see, text(see))];\n  }\n  return [text(see)];\n}\n\nfunction interleave<T, S>(items: T[], sep: () => S): (T | S)[] {\n  const out: (T | S)[] = [];\n  items.forEach((it, i) => {\n    if (i > 0) out.push(sep());\n    out.push(it);\n  });\n  return out;\n}\n\n// ── Source link ─────────────────────────────────────────────────────────────\n\n/**\n * \"Source: file:line\" caption for a doclet, when `options.sourceLink` resolves\n * it. Emitted as a `<SourceLink href label />` MDX JSX node so rang owns the\n * markup (a small 12px caption) rather than a full-size paragraph. Returns\n * `null` when unresolved.\n */\nexport function sourceLinkBlock(\n  doclet: TDoclet,\n  options: DocletBlocksOptions = {}\n): MdxJsxFlowElement | null {\n  const resolved = options.sourceLink?.(doclet);\n  if (!resolved) return null;\n  return sourceLink(resolved.href, resolved.label);\n}\n\n// ── Composer: full per-doclet block ─────────────────────────────────────────\n\nexport type DocletSection =\n  | 'summary'\n  | 'modifiers'\n  | 'relations'\n  | 'this'\n  | 'alias'\n  | 'remarks'\n  | 'typeParams'\n  | 'params'\n  | 'properties'\n  | 'returns'\n  | 'yields'\n  | 'throws'\n  | 'type'\n  | 'default'\n  | 'fires'\n  | 'listens'\n  | 'examples'\n  | 'iframes'\n  | 'metadata'\n  | 'deprecation'\n  | 'inherited';\n\nexport interface DocletBlocksOptions {\n  /** Heading level for sub-section labels (\"Parameters\", \"Returns\", …). Default: 4. */\n  subHeadingLevel?: 4 | 5 | 6;\n  /** Language hint for example code blocks. Default: \"js\". */\n  exampleLang?: string;\n  /**\n   * Sections to suppress. Useful when the caller is surfacing them in a\n   * dedicated section elsewhere on the page (e.g. constructor params).\n   */\n  skip?: readonly DocletSection[];\n  /** When set, emits a \"Source: file:line\" link for a doclet that resolves. */\n  sourceLink?: (doclet: TDoclet) => { href: string; label: string } | null;\n  /** Resolves a {@link}/@see namepath or URL to an href. Mirrors sourceLink. */\n  resolveLink?: (target: string) => ResolvedLink | null;\n  /** Resolves a `@tutorial` name to its guide page href + display title. */\n  resolveTutorial?: (name: string) => { href: string; title: string } | null;\n  /**\n   * Resolves a doclet's `@playground` tag (+ the site-wide playground config)\n   * into the wrapper opts for its `@example` blocks, or `null` for none. Threaded\n   * like {@link DocletBlocksOptions.sourceLink}; omit for no playground (the\n   * byte-identical default).\n   */\n  playgroundFor?: (doclet: TDoclet) => PlaygroundOpts | null;\n  /**\n   * Translatable-prose resolver: collects each description/summary/example-\n   * caption slot and (when stamping a locale) substitutes its translation.\n   * Omitted for the byte-identical default build. See {@link SlotResolver}.\n   */\n  slots?: SlotResolver;\n  /**\n   * Document-model flavor. `'typedoc'` switches member rendering to full\n   * TypeScript signatures (a `ts` code block per member, with type parameters,\n   * parameter types, and return types). `'jsdoc'` (default/omitted) keeps the\n   * name-only heading signature — byte-identical.\n   */\n  flavor?: 'jsdoc' | 'typedoc';\n}\n\n/**\n * `typeParams` (generics) rendered as a list: `` `T` `` ` extends `Constraint``\n * ` = `Default`` — description`. Only the TypeDoc bridge ever populates\n * `typeParams`, so this never fires on the JSDoc path.\n */\nfunction typeParamsList(typeParams: readonly TDocletTypeParam[]): List {\n  return ul(\n    typeParams.map((tp) => {\n      const line: PhrasingContent[] = [inlineCode(tp.name)];\n      if (tp.constraint) line.push(text(' extends '), inlineCode(tp.constraint));\n      if (tp.default !== undefined && tp.default !== '') line.push(text(' = '), inlineCode(tp.default));\n      const desc = tp.description ? htmlToMdastInline(tp.description) : [];\n      if (desc.length > 0) {\n        line.push(text(' — '));\n        line.push(...desc);\n      }\n      return li(p(...line));\n    })\n  );\n}\n\n/**\n * Reusable: render a single doclet's content (everything *below* its heading)\n * as a sequence of mdast blocks. Used for class members, module members,\n * mixin members, globals — the per-item body is the same shape everywhere.\n *\n * Composes the small helpers above. Skip a section by omitting the field.\n */\nexport function docletBlocks(\n  doclet: TDoclet & { inheritedFrom?: string },\n  options: DocletBlocksOptions = {}\n): RootContent[] {\n  const skip = new Set<DocletSection>(options.skip ?? []);\n  const blocks: RootContent[] = [];\n\n  if (!skip.has('inherited')) {\n    const inherited = inheritedFromParagraph(doclet);\n    if (inherited) blocks.push(inherited);\n  }\n\n  if (!skip.has('modifiers')) {\n    const mods = modifiersBlock(doclet);\n    if (mods) blocks.push(mods);\n  }\n\n  if (!skip.has('relations')) {\n    blocks.push(...relationsBlocks(doclet));\n  }\n\n  if (!skip.has('summary')) {\n    blocks.push(...summaryBlocks(doclet, options.slots));\n  }\n\n  blocks.push(...descriptionBlocks(doclet, options.slots));\n\n  // `@remarks` — detailed prose shown as its own \"Remarks\" section after the\n  // description (matching TypeDoc). Only the TypeDoc bridge sets `remarks`, so\n  // JSDoc output is unchanged.\n  if (!skip.has('remarks') && doclet.remarks) {\n    blocks.push(p(strong(text('Remarks'))), ...htmlToMdastBlocks(doclet.remarks));\n  }\n\n  if (!skip.has('deprecation')) {\n    const dep = deprecationBlock(doclet);\n    if (dep) blocks.push(dep);\n  }\n\n  if (!skip.has('this') && doclet.this) {\n    blocks.push(p(strong(text('This:')), text(' '), inlineCode(doclet.this)));\n  }\n\n  if (!skip.has('alias') && doclet.alias) {\n    blocks.push(p(strong(text('Alias:')), text(' '), inlineCode(doclet.alias)));\n  }\n\n  // Generics (\"Type Parameters\") render before parameters — matching TypeDoc.\n  // Only the TypeDoc bridge sets `typeParams`, so JSDoc output is unchanged.\n  if (!skip.has('typeParams') && doclet.typeParams && doclet.typeParams.length > 0) {\n    blocks.push(p(strong(text('Type Parameters'))), typeParamsList(doclet.typeParams));\n  }\n\n  // Owning symbol + resolver for the translatable param/return descriptions,\n  // plus the link resolver so param/return/property type names hyperlink to the\n  // symbol they reference.\n  const slotCtx: ParamSlotCtx = {\n    slots: options.slots,\n    longname: doclet.longname,\n    resolveLink: options.resolveLink,\n  };\n\n  if (!skip.has('params')) {\n    const list = paramsList(doclet.params, slotCtx);\n    if (list) blocks.push(p(strong(text('Parameters'))), list);\n  }\n\n  if (!skip.has('properties')) {\n    const list = propertiesList(doclet.properties as readonly TDocletParam[] | undefined, slotCtx);\n    if (list) blocks.push(p(strong(text('Properties'))), list);\n  }\n\n  if (!skip.has('returns')) {\n    const list = returnsList(doclet.returns, slotCtx);\n    if (list) blocks.push(p(strong(text('Returns'))), list);\n  }\n\n  if (!skip.has('yields')) {\n    const list = yieldsList(doclet.yields, slotCtx);\n    if (list) blocks.push(p(strong(text('Yields'))), list);\n  }\n\n  if (!skip.has('throws')) {\n    const list = throwsList(doclet.exceptions, slotCtx);\n    if (list) blocks.push(p(strong(text('Throws'))), list);\n  }\n\n  // Type only when there's no params/returns (i.e. it's a field/event).\n  if (!skip.has('type') && !doclet.params && !doclet.returns && doclet.type) {\n    const typeNodes = typeExpressionPhrasing(doclet.type, options.resolveLink, 'code');\n    if (typeNodes) blocks.push(p(strong(text('Type'))), p(...typeNodes));\n  }\n\n  if (!skip.has('default') && doclet.defaultvalue !== undefined) {\n    const dv = doclet.defaultvalue;\n    const label = typeof dv === 'string' ? dv : JSON.stringify(dv);\n    blocks.push(p(strong(text('Default:')), text(' '), inlineCode(label)));\n  }\n\n  if (!skip.has('fires') && doclet.fires && doclet.fires.length > 0) {\n    blocks.push(p(strong(text('Fires'))), ul(doclet.fires.map((f) => li(p(inlineCode(f))))));\n  }\n\n  if (!skip.has('listens') && doclet.listens && doclet.listens.length > 0) {\n    blocks.push(p(strong(text('Listens'))), ul(doclet.listens.map((l) => li(p(inlineCode(l))))));\n  }\n\n  if (!skip.has('examples')) {\n    const pg = options.playgroundFor?.(doclet) ?? undefined;\n    const ex = examplesBlocks(doclet, options.exampleLang ?? 'js', options.slots, pg);\n    if (ex.length > 0) {\n      blocks.push(p(strong(text('Example'))));\n      blocks.push(...ex);\n    }\n  }\n\n  if (!skip.has('iframes')) {\n    blocks.push(...embedBlocks(doclet));\n  }\n\n  if (!skip.has('metadata')) {\n    const meta = metadataList(doclet, options);\n    if (meta) blocks.push(meta);\n  }\n\n  return blocks;\n}\n","/**\n * Inline `{@link}` / `{@linkcode}` / `{@linkplain}` rewriting over an mdast tree.\n *\n * JSDoc inline link tags survive into the mdast as plain `text` runs (dwar's\n * `preprocessJsdocInlineTags` only wraps them in code spans so MDX doesn't choke\n * on the `{`). This pass turns each tag into a real `link` node when its target\n * resolves, and into an inert `inlineCode` span when it doesn't — mirroring the\n * dwar safety net so an unresolved reference still reads as today's code span\n * rather than a broken anchor.\n *\n * Two rules keep the rewrite honest:\n * - We never descend into `code` / `inlineCode` subtrees, so a `{@link}` shown\n *   literally inside an example block stays literal.\n * - We only ever rewrite `text` children; existing `link` nodes are left alone.\n */\nimport type { Link, PhrasingContent, Root, RootContent, Text } from 'mdast';\nimport type { ResolvedLink } from '../link-registry';\nimport { inlineCode, link, text } from './builders';\n\n/** A node that owns a `children` array we can walk/rewrite. */\ninterface HasChildren {\n  children: RootContent[] | PhrasingContent[];\n}\n\nfunction hasChildren(node: unknown): node is HasChildren {\n  return (\n    typeof node === 'object' &&\n    node !== null &&\n    Array.isArray((node as { children?: unknown }).children)\n  );\n}\n\n/**\n * Combined matcher for both tag shapes, scanned left-to-right via `lastIndex`:\n *\n * 1. Leading-label: `[label]{@link|linkcode|linkplain target}` — the label is the\n *    `[...]` text; JSDoc ignores any in-brace label in this form.\n * 2. Bare tag: `{@link|linkcode|linkplain target( |\\|)label?}` — the target is the\n *    first token, the optional label follows a `|` or the first run of whitespace.\n *\n * Capture groups:\n *   1 label   2 tag   3 target   (leading-label branch)\n *   4 tag     5 target 6 label   (bare branch)\n */\nconst TAG_RE =\n  /\\[([^\\]]*)\\]\\{@(link|linkcode|linkplain)\\s+([^}]+)\\}|\\{@(link|linkcode|linkplain)\\s+([^}|]+?)(?:[|\\s]([^}]*))?\\}/g;\n\ntype Tag = 'link' | 'linkcode' | 'linkplain';\n\n/**\n * Split one text value into a sequence of `text` / `link` / `inlineCode` nodes.\n *\n * Gaps between tags (and surrounding prose/punctuation) are preserved as `text`\n * nodes. A value with no tags returns a single-element array holding the\n * original node, so the common case allocates nothing extra.\n */\nfunction splitText(\n  value: string,\n  resolve: (target: string) => ResolvedLink | null\n): PhrasingContent[] {\n  TAG_RE.lastIndex = 0;\n  let match = TAG_RE.exec(value);\n  if (!match) return [text(value)];\n\n  const out: PhrasingContent[] = [];\n  let cursor = 0;\n\n  while (match) {\n    if (match.index > cursor) {\n      out.push(text(value.slice(cursor, match.index)));\n    }\n\n    let tag: Tag;\n    let target: string;\n    let label: string;\n    if (match[2] !== undefined) {\n      // Leading-label branch: [label]{@tag target}\n      tag = match[2] as Tag;\n      target = match[3] ?? '';\n      label = match[1] ?? '';\n    } else {\n      // Bare branch: {@tag target( |\\|)label?}\n      tag = match[4] as Tag;\n      target = match[5] ?? '';\n      label = match[6] ?? '';\n    }\n\n    out.push(buildNode(tag, target.trim(), label.trim(), resolve));\n\n    cursor = TAG_RE.lastIndex;\n    match = TAG_RE.exec(value);\n  }\n\n  if (cursor < value.length) {\n    out.push(text(value.slice(cursor)));\n  }\n\n  return out;\n}\n\n/**\n * Build the node for a single matched tag. Resolved targets become a `link`\n * (monospaced child for `@linkcode`, plain text otherwise); unresolved targets\n * fall back to an `inlineCode` span carrying the label or target.\n */\nfunction buildNode(\n  tag: Tag,\n  target: string,\n  label: string,\n  resolve: (target: string) => ResolvedLink | null\n): Link | Text | ReturnType<typeof inlineCode> {\n  const displayLabel = label || target;\n  const resolved = resolve(target);\n  if (resolved) {\n    const child = tag === 'linkcode' ? inlineCode(displayLabel) : text(displayLabel);\n    return link(resolved.href, child);\n  }\n  return inlineCode(displayLabel);\n}\n\n/**\n * Rewrite every `{@link}` family tag in `tree` in place.\n *\n * Walks all parents recursively, rebuilding each one's children: `text` children\n * are run through {@link splitText} (which may fan out into several nodes),\n * `code` / `inlineCode` children pass through untouched (and we never recurse\n * into them), and any other parent is recursed into and kept.\n */\nexport function resolveLinkTags(\n  tree: Root,\n  resolve: (target: string) => ResolvedLink | null\n): void {\n  walk(tree, resolve);\n}\n\nfunction walk(parent: HasChildren, resolve: (target: string) => ResolvedLink | null): void {\n  const children = parent.children;\n  const next: (RootContent | PhrasingContent)[] = [];\n\n  for (const child of children) {\n    if (child.type === 'text') {\n      next.push(...splitText(child.value, resolve));\n    } else if (child.type === 'code' || child.type === 'inlineCode') {\n      // Never rewrite a tag shown literally inside a code span/block.\n      next.push(child);\n    } else {\n      if (hasChildren(child)) walk(child, resolve);\n      next.push(child);\n    }\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- mdast child unions are narrower than the rebuilt array; the contents are type-correct per branch above.\n  parent.children = next as any;\n}\n","import type { Link, Parents } from 'mdast';\nimport type { Root } from 'mdast';\nimport { toMarkdown } from 'mdast-util-to-markdown';\nimport type { Info, State } from 'mdast-util-to-markdown';\nimport { mdxJsxToMarkdown } from 'mdast-util-mdx-jsx';\nimport { gfmToMarkdown } from 'mdast-util-gfm';\nimport { ClassView } from './class-view';\nimport { classViewToMdast, ClassViewToMdastOptions } from './mdast/class-view';\n\n/**\n * Link serializer that always emits the resource form `[label](url)`, never the\n * autolink form `<url>`. mdast-util-to-markdown's default handler autolinks any\n * link whose text equals its URL (e.g. a bare `https://…` or an\n * `<https://…>`) — but MDX parses `<` as JSX, so an emitted `<url>` aborts the\n * whole page compile downstream in dwar. This is a copy of the default handler's\n * resource-form branch with the autolink branch removed, so every link we emit\n * is MDX-safe. (Adapted from `mdast-util-to-markdown/lib/handle/link.js`.)\n */\nfunction resourceLink(node: Link, _parent: Parents | undefined, state: State, info: Info): string {\n  const tracker = state.createTracker(info);\n  const exit = state.enter('link');\n  let subexit = state.enter('label');\n  let value = tracker.move('[');\n  value += tracker.move(\n    state.containerPhrasing(node, { before: value, after: '](', ...tracker.current() })\n  );\n  value += tracker.move('](');\n  subexit();\n\n  if ((!node.url && node.title) || /[\\0- ]/.test(node.url)) {\n    // URL has whitespace/control chars → angle-bracketed destination literal.\n    subexit = state.enter('destinationLiteral');\n    value += tracker.move('<');\n    value += tracker.move(\n      state.safe(node.url, { before: value, after: '>', ...tracker.current() })\n    );\n    value += tracker.move('>');\n  } else {\n    subexit = state.enter('destinationRaw');\n    value += tracker.move(\n      state.safe(node.url, {\n        before: value,\n        after: node.title ? ' ' : ')',\n        ...tracker.current(),\n      })\n    );\n  }\n  subexit();\n\n  if (node.title) {\n    subexit = state.enter('titleQuote');\n    value += tracker.move(' \"');\n    value += tracker.move(\n      state.safe(node.title, { before: value, after: '\"', ...tracker.current() })\n    );\n    value += tracker.move('\"');\n    subexit();\n  }\n\n  value += tracker.move(')');\n  exit();\n  return value;\n}\n// peek tells the phrasing serializer our first emitted char, so it can escape a\n// leading `[` if needed — always `[` since we never autolink.\nresourceLink.peek = (): string => '[';\n\nexport interface ToMdxOptions {\n  /** Optional YAML frontmatter object. Serialized at the top of the document. */\n  frontmatter?: Record<string, unknown>;\n}\n\n/** Serialize an mdast Root tree to an MDX-compatible markdown string. */\nexport function toMdx(tree: Root, options: ToMdxOptions = {}): string {\n  const body = toMarkdown(tree, {\n    bullet: '-',\n    fence: '`',\n    fences: true,\n    incrementListMarker: false,\n    rule: '-',\n    strong: '*',\n    emphasis: '_',\n    // Serialize MDX JSX nodes (e.g. callout blockquotes carrying a `type`\n    // attribute) verbatim so their props survive into the compiled MDX, and GFM\n    // nodes (tables, strikethrough, task lists) — produced when JSDoc HTML is\n    // converted to mdast — back into the `| … |` Markdown that dwar's remark-gfm\n    // re-parses and rang renders.\n    extensions: [mdxJsxToMarkdown(), gfmToMarkdown()],\n    // Force resource-form links so no `<url>` autolink reaches dwar's MDX compile.\n    handlers: { link: resourceLink },\n  });\n  return withFrontmatter(body, options.frontmatter);\n}\n\n/**\n * Prepend serialized YAML frontmatter to an already-formed MDX/Markdown body.\n * Use this for content that should NOT be re-serialized through mdast (e.g. raw\n * Markdown tutorials, where round-tripping would drop GFM tables and other\n * syntax the mdast serializer doesn't model).\n */\nexport function withFrontmatter(body: string, frontmatter?: Record<string, unknown>): string {\n  const fm = frontmatter ? renderFrontmatter(frontmatter) : '';\n  return fm + body;\n}\n\n/** Compose a class page MDX string from a ClassView. */\nexport function classViewToMdx(\n  view: ClassView,\n  options: ClassViewToMdastOptions & ToMdxOptions = {}\n): string {\n  const tree = classViewToMdast(view, options);\n  const frontmatter = options.frontmatter ?? defaultClassFrontmatter(view);\n  return toMdx(tree, { frontmatter });\n}\n\nfunction defaultClassFrontmatter(view: ClassView): Record<string, unknown> {\n  return {\n    title: view.doclet.name ?? view.doclet.longname,\n    kind: 'class',\n    longname: view.doclet.longname,\n  };\n}\n\n/**\n * Minimal YAML frontmatter serializer. Strings are quoted, scalars are\n * emitted bare. Arrays render as `[a, b]`. Nested objects are not supported\n * — we'd reach for `yaml` proper if we needed that.\n */\nfunction renderFrontmatter(data: Record<string, unknown>): string {\n  const lines = Object.entries(data)\n    .filter(([, v]) => v !== undefined && v !== null)\n    .map(([k, v]) => `${k}: ${formatYamlScalar(v)}`);\n  if (lines.length === 0) return '';\n  return ['---', ...lines, '---', '', ''].join('\\n');\n}\n\nfunction formatYamlScalar(v: unknown): string {\n  if (Array.isArray(v)) return `[${v.map((x) => formatYamlScalar(x)).join(', ')}]`;\n  if (typeof v === 'string') return needsYamlQuote(v) ? JSON.stringify(v) : v;\n  return String(v);\n}\n\nfunction needsYamlQuote(s: string): boolean {\n  if (s.length === 0) return true;\n  // Leading char that would be interpreted by YAML as a structure indicator.\n  if (/^[\\s\\-?:,[\\]{}#&*!|>'\"%@`]/.test(s)) return true;\n  // `: ` mid-string would split into key/value.\n  if (/:\\s/.test(s)) return true;\n  // Multiline scalars need quoting.\n  if (/[\\n\\r]/.test(s)) return true;\n  return false;\n}\n","/**\n * Link registry + resolver for `{@link}` / `@see` cross-references.\n *\n * The registry maps a JSDoc longname to the page slug (and optional heading\n * anchor) that setu actually generated for it. Keys are real generated\n * longnames — we never reverse-engineer JSDoc namepath semantics, we just look\n * up what we emitted. That keeps resolution honest: a target only resolves if a\n * page or member heading exists for it.\n *\n * Build order matters: pages link to each other, so the registry must be fully\n * populated before any page body renders (a two-pass build in `generateSite`).\n */\nimport { slugifyHeading } from '@clean-jsdoc-theme/utils';\nimport type { ContainerView } from './class-view';\n\n/** A resolved location: the page slug and an optional in-page heading anchor. */\nexport interface RegistryEntry {\n  slug: string;\n  anchor?: string;\n}\n\n/** longname → location. First registration wins (see {@link registerContainerView}). */\nexport type LinkRegistry = Map<string, RegistryEntry>;\n\n/** The result of resolving a link target. `external` flags off-site URLs. */\nexport interface ResolvedLink {\n  href: string;\n  external: boolean;\n}\n\n/**\n * Build the `href` for a registry entry. Absolute, leading-slash paths to match\n * how `Sidebar.tsx` renders links (`href={`/${node.slug}`}`).\n *\n * The empty slug is the home page, so it maps to `/` (not `/`-plus-nothing via\n * the template, which would still be `/` but we special-case for clarity). An\n * anchor on the home page is preserved in case one ever shows up.\n */\nexport function hrefFor(slug: string, anchor?: string): string {\n  if (slug === '') return '/' + (anchor ? `#${anchor}` : '');\n  return `/${slug}` + (anchor ? `#${anchor}` : '');\n}\n\n/**\n * Register everything reachable from a single container page into `registry`.\n *\n * - The page-level symbol (`view.doclet.longname`) maps to the bare slug.\n * - Every member across all buckets maps `member.longname → { slug, anchor }`\n *   where the anchor is `slugifyHeading(member.name)`.\n *\n * First registration wins (`registry.has` guard): if the same longname surfaces\n * on more than one page — e.g. an inherited member rendered on both the base and\n * the subclass — the earlier page keeps the link. Stable and good enough for v1.\n *\n * Known limitation: anchors are bare `slugifyHeading(member.name)` with no\n * per-page dedup counter, so a member whose heading slug collides with another\n * heading on the same page may get a slightly-off anchor. Documented; not fixed\n * here.\n */\nexport function registerContainerView(\n  registry: LinkRegistry,\n  view: ContainerView,\n  slug: string\n): void {\n  const pageKey = view.doclet.longname;\n  if (pageKey && !registry.has(pageKey)) {\n    registry.set(pageKey, { slug });\n  }\n\n  // Explicit list of bucket arrays so the walk is robust to bucket additions.\n  const buckets = [\n    view.instanceMethods,\n    view.staticMethods,\n    view.instanceFields,\n    view.staticFields,\n    view.accessors,\n    view.enums,\n    view.events,\n    view.other,\n  ];\n\n  for (const bucket of buckets) {\n    for (const member of bucket) {\n      const key = member.longname;\n      if (key && member.name && !registry.has(key)) {\n        registry.set(key, { slug, anchor: slugifyHeading(member.name) });\n      }\n    }\n  }\n}\n\n/** `module:` prefix, lifted so the slice length stays in sync with the literal. */\nconst MODULE_PREFIX = 'module:';\n\n/**\n * Leading namespace prefixes JSDoc puts on longnames. We strip these before\n * deriving a short name so `module:CoreSchema~BaseEntity` indexes under\n * `BaseEntity`, and we also index the prefix-stripped longname itself\n * (`CoreSchema~BaseEntity`) so a prefixless author target still hits.\n */\nconst NAMESPACE_PREFIXES = ['module:', 'event:', 'external:'];\n\n/** Strip a single leading JSDoc namespace prefix (`module:`, …) if present. */\nfunction stripNamespacePrefix(longname: string): string {\n  for (const prefix of NAMESPACE_PREFIXES) {\n    if (longname.startsWith(prefix)) return longname.slice(prefix.length);\n  }\n  return longname;\n}\n\n/**\n * The symbol's short name: the trailing segment after the last JSDoc namepath\n * separator (`~`, `#`, `.`). `/` is NOT a separator — it's part of a module\n * path — so `module:queue/types` → `queue/types` (after prefix strip), while\n * `module:CoreSchema~BaseEntity` → `BaseEntity` and `base/chains#open` → `open`.\n */\nfunction shortName(longname: string): string {\n  const stripped = stripNamespacePrefix(longname);\n  let last = -1;\n  for (let i = 0; i < stripped.length; i++) {\n    const c = stripped[i];\n    if (c === '~' || c === '#' || c === '.') last = i;\n  }\n  return last === -1 ? stripped : stripped.slice(last + 1);\n}\n\n/** Two entries collide only if they point at a different page/anchor. */\nfunction sameTarget(a: RegistryEntry, b: RegistryEntry): boolean {\n  return a.slug === b.slug && a.anchor === b.anchor;\n}\n\n/**\n * Build the secondary short-name index off the primary registry.\n *\n * For each `[longname, entry]` we record the entry under its short name and\n * under its prefix-stripped longname. A key that maps to two *different*\n * targets is marked ambiguous (`null`) so the resolver refuses to guess; the\n * same target seen twice is not a conflict. Empty keys are skipped.\n */\nfunction buildNameIndex(registry: LinkRegistry): Map<string, RegistryEntry | null> {\n  const index = new Map<string, RegistryEntry | null>();\n\n  const add = (key: string, entry: RegistryEntry): void => {\n    if (key === '') return;\n    if (!index.has(key)) {\n      index.set(key, entry);\n      return;\n    }\n    const existing = index.get(key);\n    if (existing === null) return; // already ambiguous\n    if (existing && !sameTarget(existing, entry)) index.set(key, null);\n  };\n\n  for (const [longname, entry] of registry) {\n    add(shortName(longname), entry);\n    add(stripNamespacePrefix(longname), entry);\n  }\n\n  return index;\n}\n\n/**\n * Build a `resolveLink(target)` closed over `registry`.\n *\n * Resolution steps:\n * 1. Trim; empty → `null`.\n * 2. Strip a single wrapping `{ … }` (the `@see {namepath}` form).\n * 3. URL detection (`//`, `http(s)://`, `mailto:`) → external, href verbatim.\n * 4. Registry lookup with a `module:`-prefix fallback both ways, because JSDoc\n *    is inconsistent about emitting the prefix in link targets vs. longnames.\n * 5. Unique short-name fallback: a bare authored name (`BaseEntity`) resolves to\n *    its symbol *only when that name is unambiguous* across the whole registry.\n *    Ambiguous names refuse to resolve rather than guess.\n * 6. Miss → `null` so the caller can fall back to inert inline code.\n *\n * The short-name index is derived once when the resolver is built; it never\n * changes any resolution the exact/`module:` lookups already made — it only adds\n * resolutions for keys that would otherwise have been `null`.\n */\nexport function makeLinkResolver(registry: LinkRegistry): (target: string) => ResolvedLink | null {\n  const nameIndex = buildNameIndex(registry);\n\n  return function resolveLink(target: string): ResolvedLink | null {\n    const t = target.trim();\n    if (t === '') return null;\n\n    // `@see {namepath}` — strip exactly one wrapping brace pair.\n    const key = t.startsWith('{') && t.endsWith('}') ? t.slice(1, -1).trim() : t;\n\n    // Off-site URLs (protocol-relative, http(s), mailto) pass straight through.\n    if (/^(https?:)?\\/\\//i.test(key) || /^mailto:/i.test(key)) {\n      return { href: key, external: true };\n    }\n\n    let entry = registry.get(key);\n    if (!entry) {\n      // JSDoc may or may not carry the `module:` prefix — try the other form.\n      if (!key.startsWith(MODULE_PREFIX)) {\n        entry = registry.get(MODULE_PREFIX + key);\n      } else {\n        entry = registry.get(key.slice(MODULE_PREFIX.length));\n      }\n    }\n\n    // Unique short-name fallback. Try the key as-authored, then prefix-stripped.\n    // `undefined` = not indexed; `null` = ambiguous (refuse). Only a concrete\n    // entry resolves.\n    if (!entry) {\n      const byName = nameIndex.get(key);\n      if (byName) {\n        entry = byName;\n      } else if (byName === undefined) {\n        const stripped = stripNamespacePrefix(key);\n        if (stripped !== key) {\n          const byStripped = nameIndex.get(stripped);\n          if (byStripped) entry = byStripped;\n        }\n      }\n    }\n\n    if (entry) {\n      return { href: hrefFor(entry.slug, entry.anchor), external: false };\n    }\n\n    return null;\n  };\n}\n","/**\n * README + tutorial + docs pages.\n *\n * JSDoc surfaces several kinds of free-form prose alongside the API: the project\n * README (`opts.readme`, already rendered to HTML by JSDoc's markdown plugin),\n * tutorials (the `--tutorials` directory, resolved into a tree of raw Markdown /\n * HTML documents), and — new in v5 — a docs directory the bridge walks. All\n * become ordinary {@link Page}s so they flow through the same MDX → dwar render\n * path as class pages — same chrome, TOC, heading anchors, and search indexing.\n *\n * The README becomes the site home page (slug `''` → `index.html`); tutorials\n * become guide pages under `tutorials/<name>`, grouped under \"Tutorials\" in the\n * nav with their resolved hierarchy flattened in document order.\n *\n * Tutorials and docs share one builder ({@link buildDocPages}) fed by the\n * exported {@link DocInput} shape: the docs front-end reads raw files (frontmatter\n * still embedded), while the tutorial front-end adapts the existing\n * {@link TutorialInput} tree via {@link tutorialsToDocInputs}. The adapter path\n * supplies metadata explicitly and disables frontmatter parsing, so legacy\n * tutorial output stays byte-identical.\n */\n\nimport type { PhrasingContent, Root, RootContent } from 'mdast';\nimport { slugifyPath, type Frontmatter, type NavNode, type Page } from '@clean-jsdoc-theme/utils';\nimport { htmlToMdastBlocks, markdownToMdastBlocks } from './mdast/from-html';\nimport { resolveLinkTags } from './mdast/link-tags';\nimport { embed } from './mdast/builders';\nimport { parseEmbedConfig } from './embed';\nimport { hrefFor, type ResolvedLink } from './link-registry';\nimport { toMdx } from './mdx';\nimport { extractHeadings } from './generate-site';\n\n/**\n * A tutorial, normalized away from JSDoc's `Tutorial` class so setu doesn't\n * depend on JSDoc internals. The bridge walks JSDoc's resolver tree and hands\n * setu this plain shape.\n */\nexport interface TutorialInput {\n  /** Identifier — the source filename without its extension. */\n  name: string;\n  /** Display title (from a `.json` config, else the file name). */\n  title: string;\n  /** Raw source content (Markdown or HTML, per `type`). */\n  content: string;\n  /** Source format. */\n  type: 'markdown' | 'html';\n  /** Child tutorials, in resolved order. */\n  children?: TutorialInput[];\n}\n\n/** Sidebar group label for tutorial pages. */\nexport const TUTORIALS_GROUP = 'Tutorials';\n/** URL prefix for tutorial pages (`tutorials/<name>`). */\nconst TUTORIAL_SLUG_PREFIX = 'tutorials';\n\n/**\n * A single doc-page input — the shared shape consumed by {@link buildDocPages}.\n * The docs front-end (the bridge's directory walk) emits these with frontmatter\n * still embedded in `content`; the tutorial front-end synthesizes them via\n * {@link tutorialsToDocInputs} with explicit `group`/`title`/`order` overrides.\n */\nexport interface DocInput {\n  /** Relative path, POSIX, no extension — drives slug + directory grouping. */\n  path: string;\n  /** Raw content (frontmatter may still be embedded). */\n  content: string;\n  type: 'markdown' | 'html';\n  /** Explicit override (used by the tutorial adapter). */\n  group?: string;\n  title?: string;\n  order?: number;\n}\n\n/** Options for {@link buildDocPages}. */\nexport interface BuildDocPagesOptions {\n  /** Group label assigned to a doc with no frontmatter/input/directory group. */\n  defaultDocGroup?: string;\n  /**\n   * Whether to parse + strip a leading YAML frontmatter block from each input's\n   * `content`. The docs front-end wants this (frontmatter drives metadata); the\n   * tutorial adapter sets it `false` so today's tutorial output stays\n   * byte-identical (tutorial content is never frontmatter-stripped). Default\n   * `true`.\n   */\n  parseFrontmatter?: boolean;\n}\n\n/**\n * Parse raw content into a structured mdast tree per its source format. Both\n * formats normalize through HTML so the resulting tree carries only structured\n * nodes (no raw HTML, no angle-bracket autolinks) — the prerequisite for\n * serializing MDX-safe output downstream. See {@link markdownToMdastBlocks}.\n */\nfunction contentToMdast(content: string, type: 'markdown' | 'html'): Root {\n  const children = type === 'html' ? htmlToMdastBlocks(content) : markdownToMdastBlocks(content);\n  return { type: 'root', children };\n}\n\n/** A node that owns a `children` array we can walk/rewrite. */\ninterface HasChildren {\n  children: (RootContent | PhrasingContent)[];\n}\n\nfunction hasChildren(node: unknown): node is HasChildren {\n  return (\n    typeof node === 'object' &&\n    node !== null &&\n    Array.isArray((node as { children?: unknown }).children)\n  );\n}\n\n/**\n * Rewrite ```` ```iframe ```` fenced code blocks in `tree` in place — the prose\n * counterpart to the doclet `@iframe` tag (Phase 2). The fence body uses the same\n * grammar as the block tag (see {@link parseEmbedConfig}) and may span multiple\n * lines.\n *\n * For each `code` node with `lang === 'iframe'`:\n * - a valid config → replaced with the `<Embed …/>` JSX node ({@link embed});\n * - an invalid config (e.g. non-https; `parseEmbedConfig` returns `null` and\n *   warns) → dropped entirely.\n *\n * All other fences (`js`, `ts`, `bash`, …) and every non-`code` node are left\n * untouched. Walks parents with a manual parent-aware recursion (matching\n * {@link resolveLinkTags}), rebuilding each parent's `children` so replacement /\n * removal never corrupts indices.\n */\nexport function resolveEmbedFences(tree: Root): void {\n  walkFences(tree);\n}\n\nfunction walkFences(parent: HasChildren): void {\n  const next: (RootContent | PhrasingContent)[] = [];\n\n  for (const child of parent.children) {\n    if (child.type === 'code' && child.lang === 'iframe') {\n      const spec = parseEmbedConfig(child.value);\n      // Valid → swap in the Embed JSX node; invalid → drop (parser already warned).\n      if (spec) next.push(embed(spec));\n      continue;\n    }\n    // Never descend into other code spans/blocks; recurse into real parents.\n    if (child.type !== 'code' && child.type !== 'inlineCode' && hasChildren(child)) {\n      walkFences(child);\n    }\n    next.push(child);\n  }\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- mdast child unions are narrower than the rebuilt array; the contents are type-correct per branch above.\n  parent.children = next as any;\n}\n\n/** Coerce a scalar frontmatter token into a string, number, or boolean. */\nfunction parseScalar(raw: string): string | number | boolean {\n  const value = raw.trim();\n  // Strip a single matching pair of surrounding quotes (preserve inner content).\n  if (\n    value.length >= 2 &&\n    ((value.startsWith('\"') && value.endsWith('\"')) ||\n      (value.startsWith(\"'\") && value.endsWith(\"'\")))\n  ) {\n    return value.slice(1, -1);\n  }\n  if (value === 'true') return true;\n  if (value === 'false') return false;\n  // A bare numeric token becomes a number; anything else stays a string.\n  if (value !== '' && /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)$/.test(value)) {\n    const n = Number(value);\n    if (!Number.isNaN(n)) return n;\n  }\n  return value;\n}\n\n/**\n * Parse a leading `---\\n…\\n---` YAML frontmatter block and return the parsed\n * `data` plus the remaining `body`. Dependency-light: a small hand-rolled parser\n * for the simple `key: value` (string / number / boolean) cases, which is all\n * the docs pipeline needs (`title`, `group`, `order`, `slug`, `hidden`, …).\n *\n * - No leading block → `{ data: {}, body: raw }`.\n * - Malformed / unterminated block (no closing `---`) → treated as no\n *   frontmatter: `{ data: {}, body: raw }`. Never throws.\n *\n * The block is stripped from the body BEFORE content is converted to mdast, so\n * it never renders as a thematic break.\n */\nexport function parseFrontmatter(raw: string): {\n  data: Record<string, unknown>;\n  body: string;\n} {\n  const text = typeof raw === 'string' ? raw : '';\n  // Frontmatter must be the very first line: `---` (allow a leading BOM and a\n  // trailing CR for CRLF files), followed by a newline.\n  const opener = /^\\uFEFF?---[ \\t]*\\r?\\n/;\n  const open = opener.exec(text);\n  if (!open) return { data: {}, body: raw };\n\n  const bodyStart = open[0].length;\n  // Find the closing fence: a line that is exactly `---` (optionally `...`).\n  const closer = /\\r?\\n(?:---|\\.\\.\\.)[ \\t]*(?:\\r?\\n|$)/g;\n  closer.lastIndex = bodyStart - 1; // start search at the newline ending the opener\n  const close = closer.exec(text);\n  if (!close) return { data: {}, body: raw }; // unterminated → no frontmatter\n\n  const block = text.slice(bodyStart, close.index);\n  const body = text.slice(close.index + close[0].length);\n\n  const data: Record<string, unknown> = {};\n  for (const line of block.split(/\\r?\\n/)) {\n    const trimmed = line.trim();\n    if (trimmed === '' || trimmed.startsWith('#')) continue;\n    const sep = line.indexOf(':');\n    if (sep === -1) continue; // not a `key: value` pair — skip leniently\n    const key = line.slice(0, sep).trim();\n    if (key === '') continue;\n    const value = line.slice(sep + 1).trim();\n    data[key] = value === '' ? '' : parseScalar(value);\n  }\n\n  return { data, body };\n}\n\n/** Humanize a slug-ish token into a display label: `getting-started` → `Getting Started`. */\nfunction humanize(token: string): string {\n  const words = token.replace(/[-_]+/g, ' ').replace(/\\s+/g, ' ').trim();\n  if (words === '') return token;\n  return words\n    .split(' ')\n    .map((w) => (w.length > 0 ? w[0].toUpperCase() + w.slice(1) : w))\n    .join(' ');\n}\n\n/** POSIX-normalize a path and split into non-empty segments. */\nfunction pathSegments(path: string): string[] {\n  return String(path ?? '')\n    .replace(/\\\\/g, '/')\n    .split('/')\n    .filter((s) => s.length > 0);\n}\n\n/** Coerce a frontmatter value to a non-empty trimmed string, else `undefined`. */\nfunction asString(value: unknown): string | undefined {\n  if (typeof value === 'string') {\n    const t = value.trim();\n    return t === '' ? undefined : t;\n  }\n  if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n  return undefined;\n}\n\n/** Coerce a frontmatter value to a finite number, else `undefined`. */\nfunction asNumber(value: unknown): number | undefined {\n  if (typeof value === 'number' && Number.isFinite(value)) return value;\n  if (typeof value === 'string') {\n    const n = Number(value.trim());\n    if (value.trim() !== '' && Number.isFinite(n)) return n;\n  }\n  return undefined;\n}\n\n/** Coerce a frontmatter value to a boolean (`true`/`'true'`), else `undefined`. */\nfunction asBoolean(value: unknown): boolean | undefined {\n  if (typeof value === 'boolean') return value;\n  if (typeof value === 'string') {\n    const t = value.trim().toLowerCase();\n    if (t === 'true') return true;\n    if (t === 'false') return false;\n  }\n  return undefined;\n}\n\n/**\n * Build the home page from the README HTML JSDoc provides in `opts.readme`.\n * Returns `null` when the README has no renderable content. The page lives at\n * the site root (slug `''`), so dwar writes it to `index.html`.\n */\nexport function buildReadmePage(\n  readmeHtml: string,\n  pkg?: { name?: string },\n  resolveLink?: (target: string) => ResolvedLink | null\n): Page | null {\n  const tree: Root = { type: 'root', children: htmlToMdastBlocks(readmeHtml) };\n  if (tree.children.length === 0) return null;\n  if (resolveLink) resolveLinkTags(tree, resolveLink);\n  // Prose `iframe` fences → <Embed/> (after normalization, before toMdx).\n  resolveEmbedFences(tree);\n\n  const title = pkg?.name ?? 'Home';\n  const frontmatter: Frontmatter = { title, kind: 'index' };\n  // README arrives as HTML, so serialize the converted tree (no raw Markdown to\n  // preserve). dwar compiles the resulting MDX exactly like any other page.\n  const body = toMdx(tree, { frontmatter });\n  const headings = extractHeadings(tree);\n\n  return { slug: '', frontmatter, body, mdast: tree, headings };\n}\n\n/** A resolved `@tutorial`/`{@link}` cross-reference: page href + display title. */\nexport interface ResolvedTutorial {\n  href: string;\n  title: string;\n}\n\n/** A resolver: a cross-reference name → its target, or `null` when unknown. */\nexport type CrossRefResolver = (name: string) => ResolvedTutorial | null;\n\n/** A keyed cross-reference target, before it's folded into a resolver map. */\ninterface NamedEntry {\n  /** The identifier a `@tutorial <name>` / `{@link <name>}` references. */\n  name: string;\n  href: string;\n  title: string;\n}\n\n/**\n * Fold a list of {@link NamedEntry} into a `name → { href, title }` resolver,\n * the shared core behind {@link makeTutorialResolver} and {@link makeDocResolver}.\n * The lookup key is trimmed; an empty name and any duplicate are dropped\n * (**first registration wins**); an unknown name resolves to `null` so the\n * caller falls back to plain text rather than a broken anchor.\n */\nfunction makeNamedResolver(entries: Iterable<NamedEntry>): CrossRefResolver {\n  const byName = new Map<string, ResolvedTutorial>();\n  for (const { name, href, title } of entries) {\n    const key = name.trim();\n    if (key !== '' && !byName.has(key)) byName.set(key, { href, title });\n  }\n  return (name: string) => byName.get(name.trim()) ?? null;\n}\n\n/**\n * Build a `@tutorial <name>` resolver over the tutorial tree, so a tag links to\n * the guide page setu generates for it. Walks the same hierarchy\n * {@link buildTutorialPages} flattens, keying each tutorial by its `name` (the\n * identifier the tag references). The href and slug share `slugifyPath`, so they\n * always agree with the emitted page.\n */\nexport function makeTutorialResolver(tutorials: readonly TutorialInput[]): CrossRefResolver {\n  const entries: NamedEntry[] = [];\n  const walk = (t: TutorialInput): void => {\n    if (t.name) {\n      const slug = `${TUTORIAL_SLUG_PREFIX}/${slugifyPath([t.name])}`;\n      entries.push({ name: t.name, href: hrefFor(slug), title: t.title?.trim() || t.name });\n    }\n    for (const child of t.children ?? []) walk(child);\n  };\n  for (const t of tutorials) walk(t);\n  return makeNamedResolver(entries);\n}\n\n/**\n * Build a `@tutorial`/`{@link}` resolver over the docs directory, the docs\n * counterpart of {@link makeTutorialResolver}. Each doc is keyed by its **slug**\n * — its canonical address (a frontmatter `slug:` override, else the path) — so\n * `@tutorial guides/advanced` links to that page. Derives the slug/title through\n * the same {@link deriveDocMeta} the page builder uses, so the resolved href can\n * never drift from the emitted page. The home page (slug `''`) is not linkable.\n */\nexport function makeDocResolver(docs: readonly DocInput[]): CrossRefResolver {\n  const entries: NamedEntry[] = [];\n  for (const input of docs) {\n    const { slug, title, isHome } = deriveDocMeta(input, { parseFrontmatter: true });\n    if (isHome) continue;\n    entries.push({ name: slug, href: hrefFor(slug), title });\n  }\n  return makeNamedResolver(entries);\n}\n\n/**\n * Chain cross-reference resolvers, trying each in order and returning the first\n * hit (so an earlier resolver wins a name collision). Skips absent resolvers and\n * returns `undefined` when none are active, matching the optional `resolveTutorial`\n * the render path threads through.\n */\nexport function composeResolvers(\n  ...resolvers: Array<CrossRefResolver | undefined>\n): CrossRefResolver | undefined {\n  const active = resolvers.filter((r): r is CrossRefResolver => typeof r === 'function');\n  if (active.length === 0) return undefined;\n  if (active.length === 1) return active[0];\n  return (name: string) => {\n    for (const resolve of active) {\n      const hit = resolve(name);\n      if (hit) return hit;\n    }\n    return null;\n  };\n}\n\n/**\n * Build guide/doc pages + flat nav entries from a list of {@link DocInput}.\n * Shared by the tutorial adapter ({@link tutorialsToDocInputs}) and the docs\n * front-end. Per input:\n *\n * - Parse + strip leading YAML frontmatter from `content` (unless\n *   `opts.parseFrontmatter === false`), so the block never renders as a\n *   thematic break.\n * - `slug` = `data.slug` ?? slugify the `path` (split on `/`, `slugifyPath` per\n *   segment, join — no prefix).\n * - `group` = `data.group` ?? `input.group` ?? the directory path derived from\n *   `path` (humanized per segment) ?? `opts.defaultDocGroup`.\n * - `title` = `data.title` ?? `input.title` ?? humanized basename of `path`.\n * - `order` = `data.order` ?? `input.order`.\n * - `kind: 'guide'`; `hidden` honored. A root `index` path → slug `''`,\n *   `kind: 'index'` (the home page).\n *\n * A `NavNode` is emitted per page carrying `label`/`slug`/`group`/`order`; nav\n * is skipped for `hidden` pages and for the home page (whose nav entry is added\n * elsewhere, matching `buildReadmePage`).\n */\nexport function buildDocPages(\n  docs: readonly DocInput[],\n  opts: BuildDocPagesOptions = {},\n  resolveLink?: (target: string) => ResolvedLink | null\n): { pages: Page[]; nav: NavNode[] } {\n  const { defaultDocGroup, parseFrontmatter: doParse = true } = opts;\n  const pages: Page[] = [];\n  const nav: NavNode[] = [];\n\n  for (const input of docs) {\n    const { slug, title, group, order, hidden, isHome, kind, body } = deriveDocMeta(input, {\n      defaultDocGroup,\n      parseFrontmatter: doParse,\n    });\n\n    const tree = contentToMdast(body, input.type);\n    if (tree.children.length === 0) continue;\n    if (resolveLink) resolveLinkTags(tree, resolveLink);\n    // Prose `iframe` fences → <Embed/> (after normalization, before toMdx).\n    resolveEmbedFences(tree);\n\n    const frontmatter: Frontmatter = { title, kind };\n    // Tutorials carry group/order on the NAV node only (today's behavior), never\n    // in page frontmatter — so the legacy tutorial output stays byte-identical.\n    // The docs front-end (which parses frontmatter) does surface them on the\n    // page, where the sidebar plan reads `frontmatter.group`/`order`.\n    if (doParse) {\n      if (group !== undefined) frontmatter.group = group;\n      if (order !== undefined) frontmatter.order = order;\n      if (hidden) frontmatter.hidden = true;\n    }\n\n    // Both formats are normalized to structured mdast (see contentToMdast), then\n    // serialized to MDX-safe Markdown. Markdown is no longer passed through\n    // verbatim: GFM-but-not-MDX constructs (angle-bracket autolinks, raw/unclosed\n    // HTML) would otherwise abort the page compile in dwar. The GFM round-trip\n    // preserves tables, task lists, strikethrough, and footnotes.\n    const pageBody = toMdx(tree, { frontmatter });\n    const headings = extractHeadings(tree);\n\n    pages.push({ slug, frontmatter, body: pageBody, mdast: tree, headings });\n\n    // No nav for hidden pages, nor for the home page (added elsewhere).\n    if (hidden || isHome) continue;\n    nav.push({\n      label: title,\n      slug,\n      ...(group !== undefined ? { group } : {}),\n      ...(order !== undefined ? { order } : {}),\n    });\n  }\n\n  return { pages, nav };\n}\n\n/** A {@link DocInput}'s derived page metadata — the shared truth for the page\n * builder and the cross-reference resolver. */\ninterface DocMeta {\n  slug: string;\n  title: string;\n  group: string | undefined;\n  order: number | undefined;\n  hidden: boolean;\n  isHome: boolean;\n  kind: 'index' | 'guide';\n  /** Frontmatter-stripped raw content, ready for {@link contentToMdast}. */\n  body: string;\n}\n\n/**\n * Derive a doc page's metadata (slug, title, group, order, …) from one\n * {@link DocInput} — the single place that resolution rule lives, so the page\n * builder ({@link buildDocPages}) and the `@tutorial`/`{@link}` resolver\n * ({@link makeDocResolver}) can never disagree about a page's slug.\n *\n * - `slug` = frontmatter `slug` ?? slugified `path` (no prefix); `index` → `''`.\n * - `title` = frontmatter → input → humanized basename.\n * - `group` = frontmatter → input → humanized directory path → default.\n * - `order`/`hidden` from frontmatter (or `input.order`).\n */\nfunction deriveDocMeta(\n  input: DocInput,\n  opts: { defaultDocGroup?: string; parseFrontmatter: boolean }\n): DocMeta {\n  const rawContent = typeof input.content === 'string' ? input.content : '';\n  const { data, body } = opts.parseFrontmatter\n    ? parseFrontmatter(rawContent)\n    : { data: {} as Record<string, unknown>, body: rawContent };\n\n  const segments = pathSegments(input.path);\n  const basename = segments.length > 0 ? segments[segments.length - 1] : input.path;\n  const isHome = input.path === 'index';\n\n  // slug: frontmatter override, else slugify the path (no prefix).\n  const slugFromData = asString(data.slug);\n  const slug = isHome ? '' : (slugFromData ?? slugifyPath(segments));\n\n  // title: frontmatter → input → humanized basename.\n  const title = asString(data.title) ?? (input.title?.trim() || undefined) ?? humanize(basename);\n\n  // group: frontmatter → input → directory path (humanized) → default.\n  const dirSegments = segments.slice(0, -1);\n  const dirGroup = dirSegments.length > 0 ? dirSegments.map(humanize).join('/') : undefined;\n  const group =\n    asString(data.group) ?? (input.group?.trim() || undefined) ?? dirGroup ?? opts.defaultDocGroup;\n\n  const order = asNumber(data.order) ?? input.order;\n  const hidden = asBoolean(data.hidden) ?? false;\n  const kind = isHome ? 'index' : 'guide';\n\n  return { slug, title, group, order, hidden, isHome, kind, body };\n}\n\n/**\n * Adapt the tutorial tree into {@link DocInput}s for {@link buildDocPages},\n * depth-first (parent before its children — JSDoc's resolved order). Each\n * tutorial gets the path `tutorials/<name>` (so slugify yields exactly today's\n * `tutorials/<name>`), its title, source type/content, and an incrementing\n * `order`.\n *\n * The sidebar **group** mirrors the tutorial hierarchy (issue #253): a tutorial\n * that has sub-tutorials opens a nested group named after itself\n * (`Tutorials/<title>`), with its own page as the first entry; a leaf sits\n * directly in its parent's group. {@link buildGroupTree} turns these `/`-paths\n * into nested, collapsible nav branches. A flat tutorial set still yields one\n * flat \"Tutorials\" group, and page slugs/frontmatter/bodies are unchanged either\n * way — only the nav grouping reflects the hierarchy.\n */\nexport function tutorialsToDocInputs(tutorials: readonly TutorialInput[]): DocInput[] {\n  const out: DocInput[] = [];\n  let order = 0;\n  const walk = (t: TutorialInput, parentGroup: string): void => {\n    const title = t.title?.trim() || t.name;\n    const hasChildren = (t.children?.length ?? 0) > 0;\n    // A parent (has sub-tutorials) opens a collapsible group named after itself;\n    // its page + children live inside it. A leaf stays in its parent's group.\n    const group = hasChildren ? `${parentGroup}/${title}` : parentGroup;\n    out.push({\n      path: `${TUTORIAL_SLUG_PREFIX}/${t.name}`,\n      content: typeof t.content === 'string' ? t.content : '',\n      type: t.type,\n      group,\n      title,\n      order: order++,\n    });\n    for (const child of t.children ?? []) walk(child, group);\n  };\n  for (const t of tutorials) walk(t, TUTORIALS_GROUP);\n  return out;\n}\n\n/**\n * Build guide pages + nav entries from the tutorial tree. The hierarchy drives\n * the sidebar grouping (issue #253): a parent tutorial becomes a nested,\n * collapsible group (see {@link tutorialsToDocInputs}); a flat tutorial set\n * stays a single \"Tutorials\" group.\n *\n * Expressed via the shared {@link buildDocPages} builder. Frontmatter parsing is\n * disabled so a tutorial whose content begins with `---` keeps its exact output;\n * page slugs / frontmatter / bodies are unchanged — only the nav grouping now\n * reflects the hierarchy.\n */\nexport function buildTutorialPages(\n  tutorials: readonly TutorialInput[],\n  resolveLink?: (target: string) => ResolvedLink | null\n): { pages: Page[]; nav: NavNode[] } {\n  return buildDocPages(tutorialsToDocInputs(tutorials), { parseFrontmatter: false }, resolveLink);\n}\n","/**\n * Source-file viewer pages + the \"Source: file:line\" link resolver.\n *\n * JSDoc records, per doclet, the file + line it was declared in (`meta.path`,\n * `meta.filename`, `meta.lineno`). When the bridge hands setu the project's\n * source files, this module turns each into a read-only `kind: 'source'`\n * {@link Page} (rendered by dwar in an editor island, not compiled as MDX), an\n * index page listing them all, a nav node, and a `resolve(meta)` function that\n * maps a doclet's `meta` back to its source page anchor.\n *\n * The module is pure: it only transforms the inputs it is given — no fs, no\n * cwd. Path normalization is defensive (backslashes → `/`) because the inputs\n * arrive pre-normalized from the bridge in Phase 5.\n */\n\nimport {\n  slugifySourcePath,\n  type Frontmatter,\n  type NavNode,\n  type Page,\n  type TDoclet,\n} from '@clean-jsdoc-theme/utils';\nimport { h, link, li, p, text, ul } from './mdast/builders';\nimport { toMdx } from './mdx';\nimport { extractHeadings } from './generate-site';\nimport type { Root } from 'mdast';\n\n/** One source file the bridge wants rendered as a viewer page. */\nexport interface SourceFileInput {\n  /** Absolute path on disk (used to match doclet `meta.path` + `meta.filename`). */\n  absPath: string;\n  /** Project-relative path (drives the slug, title, and link labels). */\n  relPath: string;\n  /** Raw file content, rendered verbatim in the editor island. */\n  content: string;\n}\n\n/** Map a file extension to a Monaco language id. */\nconst EXTENSION_LANGUAGE: Record<string, string> = {\n  js: 'javascript',\n  mjs: 'javascript',\n  cjs: 'javascript',\n  jsx: 'javascript',\n  ts: 'typescript',\n  mts: 'typescript',\n  cts: 'typescript',\n  tsx: 'typescript',\n  json: 'json',\n  css: 'css',\n  scss: 'scss',\n  less: 'less',\n  html: 'html',\n  htm: 'html',\n  md: 'markdown',\n  markdown: 'markdown',\n  yml: 'yaml',\n  yaml: 'yaml',\n  vue: 'vue',\n  svelte: 'html',\n};\n\n/**\n * Detect a Monaco language id from a file path's extension. Returns\n * `'plaintext'` for unknown or extension-less paths. Uses Monaco ids\n * (`javascript`/`typescript`), not the bare extension.\n */\nexport function detectLanguage(relPath: string): string {\n  const normalized = String(relPath ?? '').replace(/\\\\/g, '/');\n  const base = normalized.slice(normalized.lastIndexOf('/') + 1);\n  const dotIdx = base.lastIndexOf('.');\n  if (dotIdx <= 0) return 'plaintext';\n  const ext = base.slice(dotIdx + 1).toLowerCase();\n  return EXTENSION_LANGUAGE[ext] ?? 'plaintext';\n}\n\n/** A resolved \"Source: file:line\" link target. */\nexport interface SourceLink {\n  href: string;\n  label: string;\n}\n\n/** Tuning for {@link buildSourceModel}. */\nexport interface SourceModelOptions {\n  /**\n   * When `true`, a `Source: file:line` link points at the doclet's raw\n   * `meta.lineno` — which, for a container documented with a leading JSDoc\n   * block (class/interface/mixin/module/namespace/typedef), is the FIRST line of\n   * the doc comment. The default (`false`) instead lands on the first line of the\n   * actual declaration, skipping past the comment block, so readers see code\n   * rather than a long comment when they follow the link.\n   */\n  linkToComment?: boolean;\n}\n\n/**\n * Given a file's content and a doclet's 1-based `lineno`, return the line of the\n * actual declaration. JSDoc reports `meta.lineno` as the code line for most\n * symbols (their doclet carries a real AST `range`), but for a container\n * documented with a leading `/** … *\\/` block the documented doclet points at\n * the comment's opening line (and has no `range`). When `lineno` lands on a line\n * that opens a block comment, advance past the closing `*\\/` to the first\n * non-blank line — the declaration. Any other line is already code, so it's\n * returned unchanged. Out-of-range or unterminated input falls back to `lineno`.\n */\nexport function firstCodeLine(content: string, lineno: number): number {\n  if (!Number.isFinite(lineno) || lineno < 1) return lineno;\n  const lines = content.split('\\n');\n  let i = lineno - 1;\n  if (i >= lines.length) return lineno;\n  // Only adjust when this line OPENS a block comment; code lines pass through.\n  if (!/^\\s*\\/\\*/.test(lines[i])) return lineno;\n  while (i < lines.length && !lines[i].includes('*/')) i++;\n  if (i >= lines.length) return lineno; // unterminated — don't guess.\n  i++; // step past the line carrying the closing `*/`.\n  while (i < lines.length && lines[i].trim() === '') i++;\n  return i < lines.length ? i + 1 : lineno;\n}\n\n/** Result of building source pages: pages, index, nav node, and a resolver. */\nexport interface SourceModel {\n  /** One `kind: 'source'` page per input file. */\n  pages: Page[];\n  /** The \"Source Files\" index page listing every source file. */\n  indexPage: Page;\n  /** Nav entry pointing at the index page. */\n  navNode: NavNode;\n  /**\n   * Resolve a doclet's `meta` to its source page anchor. Returns `null` when\n   * there is no `meta`, no matching source file, or insufficient info.\n   */\n  resolve(meta: TDoclet['meta']): SourceLink | null;\n}\n\n/** Forward-slash join that normalizes backslashes and collapses repeats. */\nfunction joinPath(dir: string, file: string): string {\n  const a = String(dir ?? '')\n    .replace(/\\\\/g, '/')\n    .replace(/\\/+$/, '');\n  const b = String(file ?? '')\n    .replace(/\\\\/g, '/')\n    .replace(/^\\/+/, '');\n  if (!a) return b;\n  if (!b) return a;\n  return `${a}/${b}`;\n}\n\nconst SOURCE_SLUG_PREFIX = 'source';\n/** Sidebar label + nav title for the source section. */\nconst SOURCE_FILES_LABEL = 'Source Files';\n\n/** Slug for a single source file viewer page. */\nfunction fileSlug(relPath: string): string {\n  return `${SOURCE_SLUG_PREFIX}/${slugifySourcePath(relPath)}`;\n}\n\n/** Build a single read-only `kind: 'source'` viewer page. */\nfunction buildSourcePage(input: SourceFileInput): Page {\n  const frontmatter: Frontmatter = {\n    title: input.relPath,\n    kind: 'source',\n    hidden: true,\n  };\n  return {\n    slug: fileSlug(input.relPath),\n    frontmatter,\n    body: '',\n    headings: [],\n    source: {\n      code: input.content,\n      language: detectLanguage(input.relPath),\n      filename: input.relPath,\n    },\n  };\n}\n\n/** Build the \"Source Files\" index page: a heading + a sorted list of links. */\nfunction buildIndexPage(sources: readonly SourceFileInput[]): Page {\n  const sorted = [...sources].sort((a, b) => a.relPath.localeCompare(b.relPath));\n  // Each entry is a list item wrapping a paragraph with a link to the file page.\n  const listItems = sorted.map((s) => li(p(link(`/${fileSlug(s.relPath)}/`, text(s.relPath)))));\n\n  const tree: Root = {\n    type: 'root',\n    children: [h(1, text(SOURCE_FILES_LABEL)), ul(listItems)],\n  };\n\n  const frontmatter: Frontmatter = { title: SOURCE_FILES_LABEL, kind: 'guide' };\n  return {\n    slug: SOURCE_SLUG_PREFIX,\n    frontmatter,\n    body: toMdx(tree, { frontmatter }),\n    mdast: tree,\n    headings: extractHeadings(tree),\n  };\n}\n\n/**\n * Turn a set of source files into viewer pages, an index page, a nav node, and\n * a `resolve(meta)` that maps a doclet's declaration site back to its page.\n */\nexport function buildSourceModel(\n  sources: readonly SourceFileInput[],\n  options: SourceModelOptions = {}\n): SourceModel {\n  const { linkToComment = false } = options;\n  const pages = sources.map(buildSourcePage);\n  const indexPage = buildIndexPage(sources);\n  const navNode: NavNode = { label: SOURCE_FILES_LABEL, slug: SOURCE_SLUG_PREFIX };\n\n  // Primary match: doclet `meta.path` + `meta.filename` → normalized abs path.\n  // Fallback: bare `meta.filename` (when `meta.path` is absent). Both map to the\n  // file's relPath so we can derive its slug and label.\n  const byAbs = new Map<string, SourceFileInput>();\n  const byFilename = new Map<string, SourceFileInput>();\n  for (const s of sources) {\n    byAbs.set(s.absPath.replace(/\\\\/g, '/'), s);\n    const filename = s.relPath.replace(/\\\\/g, '/').split('/').pop() ?? s.relPath;\n    // First writer wins so an unambiguous match is preferred over a later dup.\n    if (!byFilename.has(filename)) byFilename.set(filename, s);\n  }\n\n  const resolve = (meta: TDoclet['meta']): SourceLink | null => {\n    if (!meta) return null;\n    const filename = meta.filename;\n    let hit: SourceFileInput | undefined;\n\n    if (meta.path && filename) {\n      hit = byAbs.get(joinPath(meta.path, filename));\n    }\n    if (!hit && filename) {\n      hit = byFilename.get(filename.replace(/\\\\/g, '/').split('/').pop() ?? filename);\n    }\n    if (!hit) return null;\n\n    const rawLine = meta.lineno ?? 1;\n    // Default: jump to the declaration, not the doc comment above it.\n    const lineno = linkToComment ? rawLine : firstCodeLine(hit.content, rawLine);\n    return {\n      href: `/${fileSlug(hit.relPath)}/#L${lineno}`,\n      label: `${filename ?? hit.relPath}:${lineno}`,\n    };\n  };\n\n  return { pages, indexPage, navNode, resolve };\n}\n"],"mappings":"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","names":["import_utils","import_utils","code","text","tokenize","text","splitPair","resolved","p","shortName","import_mdast_util_gfm","p","text","sourceLink","root","node","link","import_utils","import_utils","import_utils","hasChildren","text","walk","import_utils","sourceLink","p"]}