/** * {@link RichDoc} → markdown — the serializer (inverse of `mdToDoc`). * * Segments the flat text by `blocks[]` (raw chunks verbatim; heading / list / * blockquote / codeBlock lines get their markers re-synthesized — markers are * never in the doc text; remaining lines as paragraphs), then serializes * inline spans per segment via elementary runs + a close/reopen delimiter * stack (valid nesting from arbitrarily overlapping spans). * * Consecutive same-kind block lines join into one group (`\n`-separated: * a tight list, one quote, one fence); groups separate with blank lines. * Ordered numbering derives from the run position, restarting at each run's * first-line `level` (a non-1 start) — so two adjacent ordered runs merge * into one list (the flat model has no list-boundary marker; documented * normalization, idempotent). * * Round-trip contract: `mdToDoc(docToMd(doc))` is structurally equal to a * *normalized* `doc` — emphasis markers, hard breaks (→ paragraph breaks), and * blank lines normalize; `raw` blocks round-trip byte-for-byte. */ import type { InlineSpan, RichDoc } from '@sigx/lynx-richtext'; /** Serialize one plugin-owned span back to markdown (a plugin's `inline.serialize`). */ export type SpanSerializer = (span: InlineSpan, text: string) => string; export interface DocToMdOptions { /** * Plugin serializers keyed by the span type they own * (`docMapping.spanType`). A plugin-owned span is emitted **atomically**: * the serializer's output replaces the covered text entirely. */ serializers?: ReadonlyMap; } export declare function docToMd(doc: RichDoc, options?: DocToMdOptions): string;