import type{LyraAnchorTargetEventMap}from'../../../internal/anchor-target.js';import{type LyraMarkedParser}from'./markdown-loader.js';import{type ShikiLanguageInput}from'../code-block/code-loader.js';import{type PendingHighlight,type MarkdownHeadingItem as SharedMarkdownHeadingItem,type MarkdownHtmlMode}from'./markdown-shared.js';import{MarkdownRuntimeBase,type MarkdownHighlightAttempt,type MarkdownVariantContext}from'./markdown-base.class.js'; /** Re-exported so `markdown.ts`'s `export *` keeps exposing this from the same public path as * before this type moved into the pair's shared module -- see `markdown-shared.ts`'s class doc. */ export type MarkdownHeadingItem=SharedMarkdownHeadingItem; /** Peer-neutral public alias matching the upstream static `getMarked()` signature without * importing the optional `marked` peer into the runtime graph. */ export type Marked=LyraMarkedParser; /** `true`-defaulting boolean attribute converter -- Lit's default presence-based `type: Boolean` * can never be set back to `false` from a plain-HTML attribute once the property's own default is * `true` (removing an attribute that was never present fires no `attributeChangedCallback`), so * `fromAttribute` checks the literal string instead. Shared by `gfm` and `highlightCode`. */ export interface LyraMarkdownEventMap extends LyraAnchorTargetEventMap{'lr-render-error':CustomEvent<{error:unknown;}>;'lr-link-click':CustomEvent<{href:string;}>;'lr-content-settled':CustomEvent;} /** * `` — sanitized Markdown-to-HTML rendering (GFM tables, * fenced code blocks, links, blockquotes) built on the optional peer * dependencies `marked` (parsing) and `dompurify` (sanitizing), both * lazy-loaded via `markdown-loader.ts` on first connect. * * Rendering never ships unsanitized or broken markup silently: * - If `marked` fails to load, or throws while parsing malformed input, the * component falls back to plain text (`white-space: pre-wrap`, no HTML * parsing at all) and fires `lr-render-error`. * - If `htmlMode` is `sanitize` (the default) and `dompurify` fails to load, the * component *also* falls back to plain text + `lr-render-error` — it * never renders marked's raw HTML output when sanitization was requested * (or defaulted to) but is unavailable, even though `marked` itself loaded * fine. * - If `htmlMode` is explicitly `trusted`, marked's raw output renders as-is * regardless of whether `dompurify` is installed — the consumer opted out * of sanitization, so `dompurify`'s absence is irrelevant to that path. * * That same plain-text fallback rendering (`data-fallback` on the `content` * part) is also, unconditionally and by default, a brief *transient* state on * every connect, not just a failure path: `connectedCallback()`'s dynamic * `import()` of `marked`/`dompurify` (see `markdown-loader.ts`) is * asynchronous, so the very first paint of any `` on a page * shows plain text for at least one microtask — even when both peers are * already installed and load without error — until that import resolves and * a second render replaces it with the real Markdown output. Call `preloadMarkdown()` before * mounting the first instance to avoid that window; later instances always adopt its settled * shared dependency cache synchronously. * Disconnecting and reconnecting while the shared load is pending invalidates the earlier * connection's settlement callback, so the current connection parses only once. * * `heading`/`code`/`blockquote`/`table`/`link`/`image` tokens are rendered * through a `marked` renderer override that injects `part="..."` attributes * directly into the produced HTML — a single pass, not a second DOM walk * after insertion. * * Fenced code blocks are syntax-highlighted via the same optional `shiki` peer `` * uses (`highlightCode`, default `true` — a pure upgrade gated by whether `shiki` is installed at * all, not a separate opt-in). `languages` supplies explicit grammars while the full loader * remains the fallback. The very first render of any content is always plain * (identical to today's output); highlighting arrives as an asynchronous upgrade one render later, * once shiki resolves. No highlighting is attempted while `streaming` is `true` — it applies once a * stream settles, so there is no added per-chunk cost while content is still arriving. * * Highlighted blocks follow the page's resolved theme. Shiki emits both palettes at once, so * `[part="content"]` carries `data-dark-theme="true"` whenever the component's own resolved * `--lr-color-text` is lighter than its `--lr-color-surface`, and the stylesheet then paints each * token from `--shiki-dark`/`--shiki-dark-bg` instead of the light inline color. It keys off the * resolved tokens rather than `prefers-color-scheme`, so a consumer theming with * `--lr-theme-color-*` independently of the OS setting gets the dark palette too -- the same * mechanism `` uses for its own `[part="body"]`. * * When `heading-anchors` is set, every rendered heading's slug (computed via the shared * GitHub-slugger-style `Slugger`) is stamped as its `id`; `getHeadingTree()` computes that same * outline on every parse regardless of `heading-anchors`, so a host can build a table of contents * even while ids aren't in the DOM yet. `scrollToAnchor()` (from the adopted `DocumentAnchorTarget` * mixin) resolves `fragment` anchors against that outline and `text-quote` anchors via * `internal/text-quote.ts`'s shared scope/resolve helpers; `highlights` re-resolve by quote after * every render (never by node identity), so a highlight painted before a `streaming` update * finishes still finds its quote once the matching text arrives. Highlight painting uses * `internal/text-highlights.ts`'s `acquireHighlightHandle()` -- the CSS Custom Highlight API where * the browser supports it (no DOM mutation at all), a ``-wrap fallback otherwise. Quote * resolution indexes at most 1,000,000 code units/20,000 text nodes per content generation, bounds * each quote/context field to 4,096 code units and each pass to 4,000,000 scanned code units, and * paints at most 100 host highlights from a 1,000-entry candidate window while preserving the * active entry from the bounded host snapshot. * * `math` renders `$...$`/`$$...$$` TeX as MathML via the optional `katex` peer's * `renderToString(tex, { output: 'mathml' })` -- MathML Core renders natively and accessibly in * evergreen browsers with no extra stylesheet or webfont needing to cross the shadow boundary. A * missing `katex` peer renders the literal, unparsed TeX source (delimiters included) and fires one * `lr-render-error`. * * Migrating a `` usage: on * connect, a direct `