import { Token } from 'marked'; import { MarkdownEditorLabels } from './types'; /** * Markdown to DOM for the rich surface and the preview, one top-level block at * a time. * * Both views keep one element per block, so an edit re-renders only the blocks * whose source changed, and every element can say which slice of the source it * came from. Spans the surface cannot edit as text — a formula, an image, an * emoji shortcode, a callout's marker, raw HTML — render as atoms that carry * their exact source in `data-md-src`, which the serializer writes back * verbatim. * * KaTeX is applied after sanitizing: DOMPurify strips the MathML `semantics` * and `annotation` elements KaTeX emits, so formulas leave the parser as * placeholders and are typeset into the sanitized DOM. * * Source and TeX stay URI-encoded in the DOM (`data-md-src`, `data-tx-tex`): * DOMPurify drops any attribute whose value contains `]>` or `` back into the page's markup. */ export interface MarkdownRenderOptions { math: boolean; emoji: boolean; highlight: boolean; callouts: boolean; sanitize: boolean; } export interface MarkdownSegment { type: string; /** The block's source, without the newlines that end it. */ raw: string; from: number; to: number; token: Token; } export interface MarkdownSegmentation { segments: MarkdownSegment[]; /** `gaps[i]` is the source before `segments[i]`; the last entry trails the document. */ gaps: string[]; } export interface MarkdownHydrateOptions { editable: boolean; /** Task checkboxes toggle their `[ ]` marker. */ checkable: boolean; /** The preview opens links in a new tab; on the editing surface they stay inert. */ externalLinks: boolean; decorateUpload?: (card: HTMLElement, id: string) => void; } export declare const MARKDOWN_UPLOAD_PREFIX = "#upload-"; export declare function escapeHtml(value: string): string; export declare class MarkdownRenderer { private readonly marked; private readonly html; private readonly typeset; private linksKey; private katex; private katexRequested; private katexOutput; private emojiMap; private calloutTitles; /** * Bumped whenever the same block source can render differently: reference * definitions changed, the emoji set arrived, the labels changed. Views * re-render on a change. */ version: number; /** Called when a lazily loaded asset (KaTeX) arrives and placeholders can be upgraded. */ onAssetsReady: (() => void) | null; readonly options: MarkdownRenderOptions; constructor(options: MarkdownRenderOptions); private emojiExtension; /** Shortcodes render once the map is in; until then they stay literal text. */ setEmoji(map: ReadonlyMap | null): void; get hasEmoji(): boolean; /** The words the renderer writes into documents: callout titles. True when they changed. */ setLabels(labels: MarkdownEditorLabels): boolean; segment(doc: string): MarkdownSegmentation; /** Sanitized HTML of one block, before hydration. */ blockHtml(segment: MarkdownSegment): string; /** The block sources of a short snippet lexed on its own, for checks that need block boundaries. */ blockRaws(source: string): string[]; /** Inline tokens of one line of source, with this renderer's extensions. */ inlineTokens(source: string): Token[]; private ensureKatex; /** KaTeX markup for `tex`, or null while KaTeX is still loading. */ typesetTex(tex: string, display: boolean): string | null; /** Upgrade placeholders and set the DOM-only attributes the sanitizer would have stripped. */ hydrate(root: ParentNode, options: MarkdownHydrateOptions): void; }