/** * A shared documentation renderer for the {@link featureOptions!FeatureOptions | FeatureOptions} catalog. * * Every plugin in the family used to ship a near-duplicate `*-gendocs.ts` script that walked its feature-options catalog and printed a markdown category index plus * per-category option tables, then pasted the result into its `docs/FeatureOptions.md` by hand. ~95% of each script was identical, and each hand-rolled the dotted-key * construction and the value-vs-toggle distinction that this library already owns as single-source-of-truth helpers. This module collapses all of that into one * elegant renderer so the documentation becomes a pure projection of the live catalog. * * The module exports two pure string functions: * * - {@link renderFeatureOptionsReference} - the projection itself. It derives every key via {@link expandOption}, decides value-ness via {@link isValueOption}, and * builds the catalog index once via {@link buildCatalogIndex}; it never re-derives any of those. Plugin-private scope prose is supplied through two optional render * hooks that mirror the webUI's field-blind `validOption` / `validOptionCategory` predicate seam, lifted from *filter* (boolean) to *describe* (string). No * plugin-specific field name appears anywhere in this file. * * - {@link spliceMarkedRegion} - the in-place splice that replaces the region between {@link FEATURE_OPTIONS_DOC_BEGIN} / {@link FEATURE_OPTIONS_DOC_END} in an * existing doc with freshly rendered content, leaving each plugin's hand-written header and intro untouched. * * Both functions are pure and isomorphic: no `node:` imports, no `fs`, no `process`. The only I/O - reading the doc and writing it back - is two lines of * `node:fs/promises` in each plugin's build-script shim, which is inherently a tooling concern. This module is therefore browser-safe and trivially testable, but it * is a tooling concern and is deliberately NOT mirrored into `dist/ui/` by the build pipeline. * * @module */ import type { FeatureCategoryEntry, FeatureOptionEntry } from "./featureOptions.ts"; /** * The opening marker of the auto-generated region in a plugin's `docs/FeatureOptions.md`. {@link spliceMarkedRegion} replaces everything strictly between this marker * and {@link FEATURE_OPTIONS_DOC_END}, preserving both markers and the hand-written prose around them. The text doubles as an in-document warning to maintainers not to * edit the region by hand. * * @category Feature Options */ export declare const FEATURE_OPTIONS_DOC_BEGIN = ""; /** * The closing marker of the auto-generated region. See {@link FEATURE_OPTIONS_DOC_BEGIN}. * * @category Feature Options */ export declare const FEATURE_OPTIONS_DOC_END = ""; /** * Render a feature-options catalog into the markdown reference fragment a plugin embeds in its `docs/FeatureOptions.md`. The output is a category index (one bullet per * category, deep-linking to its detail section), an optional one-line legend explaining the `.` notation, and then one detail section per category, each carrying * an optional device-scope line and a flat table of option rows. The legend is emitted only when the catalog has at least one value option, since a toggle-only catalog * never renders the `.` placeholder the legend describes. * * The renderer owns all base-shaped scaffolding - the index, headings, per-row deep-link anchors, the key cell with its value/toggle placeholder, the default cell, the * description cell, and the column math - purely from the base {@link FeatureOptionEntry} / {@link FeatureCategoryEntry} fields. The two optional hooks own *only* the * plugin-private scope prose: `describeCategoryScope` contributes the device-scope sentence under a category heading, and `describeOptionScope` contributes a suffix * appended to an option's description cell. A hook returning `undefined` omits its contribution cleanly - never an "undefined" literal, never a stray blank line. * * The catalog index is built once via {@link buildCatalogIndex}; value-ness is decided via {@link isValueOption}; the canonical dotted key is derived via * {@link expandOption}. None of those is re-derived here - the renderer is a projection of the same single source of truth the rest of the module owns. * * @typeParam TOptionMeta - The concrete type of an option entry's opaque `meta` annotation, reconstituted at this boundary so `describeOptionScope` sees it typed. * @typeParam TCategoryMeta - The concrete type of a category entry's opaque `meta` annotation, reconstituted so `describeCategoryScope` sees it typed. * @param input * @param input.categories - The catalog's category list, in the order the index and detail sections should follow. * @param input.describeCategoryScope - Optional. Returns the device-scope sentence emitted under a category's heading, or `undefined` to omit it. The hook owns the full * sentence including any leading or trailing text. * @param input.describeOptionScope - Optional. Returns a suffix appended to an option's description cell, or `undefined` to omit it. The hook owns its full text * including any leading separator. * @param input.options - The catalog's options map keyed by category name. * * @returns The rendered markdown fragment. */ export declare function renderFeatureOptionsReference(input: { categories: readonly FeatureCategoryEntry[]; describeCategoryScope?: (category: FeatureCategoryEntry) => string | undefined; describeOptionScope?: (option: FeatureOptionEntry, category: FeatureCategoryEntry) => string | undefined; options: Readonly[]>>; }): string; /** * Replace the region strictly between {@link FEATURE_OPTIONS_DOC_BEGIN} and {@link FEATURE_OPTIONS_DOC_END} in `source` with `content`, leaving both markers and all * surrounding prose untouched. This is the pure half of the in-place splice each plugin's build-script shim performs; the shim supplies the trivial `readFile` / * `writeFile` around it. * * The replacement inserts a newline before and after `content`, so a marker pair on its own lines stays on its own lines and the rendered fragment is cleanly framed. * The operation is repeatable: splicing the same `content` into an already-spliced document reproduces it byte-for-byte. Each marker may be overridden through the * options object for documents that use a different convention, though the defaults match what every plugin in the family embeds. * * @param source - The full document text. * @param content - The fragment to insert between the markers, typically the output of {@link renderFeatureOptionsReference}. * @param markers * @param markers.beginMarker - The opening marker to search for. Defaults to {@link FEATURE_OPTIONS_DOC_BEGIN}. * @param markers.endMarker - The closing marker to search for. Defaults to {@link FEATURE_OPTIONS_DOC_END}. * * @returns `source` with the marked region's contents replaced by `content`. * * @throws `Error` naming the offending marker when either marker is absent, when the closing marker precedes the opening marker, or when the document is ambiguous - a * second begin marker after the first, or a second end marker - since the marked region would not be uniquely identified. */ export declare function spliceMarkedRegion(source: string, content: string, { beginMarker, endMarker }?: { beginMarker?: string; endMarker?: string; }): string; //# sourceMappingURL=featureOptions-docs.d.ts.map