ranui
Version:
A framework-agnostic Web Components UI library built on native custom elements, with TypeScript types, light/dark theming, SSR and PWA support.
87 lines (86 loc) • 3.18 kB
TypeScript
import { RanElement } from '../../utils';
import '@/components/icon';
type RenderModule = typeof import('./render');
interface BlockState {
/** The block's diff key (source + the document's link definitions). */
key: string;
incomplete: boolean;
el: HTMLElement;
/** Embedded renderers in this block whose theme follows the host. */
themed: HTMLElement[];
}
/**
* `<r-markdown>` — streaming-friendly Markdown renderer.
*
* Designed for AI-chat style output (à la Vercel Streamdown), but works for static
* content too. In `mode="streaming"` (default) the text is first run through
* `remend`, which closes half-streamed `**bold`, `` `code ``, links, `$$` math and so on,
* then split into blocks; only the block whose text changed is re-rendered, so a
* long answer never re-parses from the top on every token.
*
* Fenced ```mermaid blocks become `<r-mermaid>`, `$$…$$` / `\[…\]` / `\(…\)` become
* `<r-math>`; both are lazily registered only when the content needs them.
*/
export declare class Markdown extends RanElement {
_shadowDom: ShadowRoot;
_wrap: HTMLElement;
_body: HTMLElement;
_blocks: BlockState[];
/** Content set through the property (not reflected — streaming text can be huge). */
_content: string | null;
/** In-flight render, so tests (and consumers) can `await el._pending`. */
_pending: Promise<void>;
_renderToken: number;
_renderModule: RenderModule | null;
_themeObserver?: MutationObserver;
_lightDomObserver?: MutationObserver;
_copyResetTimer?: number;
_error?: HTMLElement;
static get observedAttributes(): string[];
constructor();
/**
* Markdown source. Resolution order: the `content` property (set via JS, not
* reflected), the `content` attribute, then the element's text content.
*/
get content(): string;
set content(value: string);
get mode(): string;
set mode(value: string);
get theme(): string;
set theme(value: string);
get caret(): string;
set caret(value: string | null);
get copyable(): boolean;
set copyable(v: boolean);
get downloadable(): boolean;
set downloadable(v: boolean);
get lineNumbers(): boolean;
set lineNumbers(v: boolean);
/** `""` → github-light/github-dark; `"a"` → both; `"a b"` → light / dark theme. */
get highlight(): string | null;
set highlight(value: string | null);
get inlineMath(): boolean;
set inlineMath(v: boolean);
get linkTarget(): string;
set linkTarget(value: string);
get sheet(): string;
set sheet(value: string);
private label;
private emit;
handlerExternalCss: () => void;
private resolveTheme;
private syncTheme;
private observeTheme;
render(): void;
private renderWith;
private createBlockElement;
private showError;
/** Force a full re-render (e.g. after toggling controls). */
private rerender;
private copyCode;
private downloadCode;
connectedCallback(): void;
disconnectedCallback(): void;
attributeChangedCallback(k: string, o: string | null, n: string | null): void;
}
export default Markdown;