/** * The pivot format: a ProseMirror document. * * Every CMS in this package models rich text differently — Contentful nests a * recursive `document` tree, Sanity keeps a flat array of Portable Text blocks, * Strapi a flat Slate-shaped array — and Avocado's own `richtext` fields hold a * markdown string. Converting each pair directly would need six converters and * would still lose whatever the two ends did not have in common. Instead every * format converts to and from one shape, and that shape is the ProseMirror * document the property panel already edits natively (`RichTextJsonField`). * * The types are deliberately open — `type` is a `string`, not a union of the * names we know. A Portable Text block with a custom `_type`, a Contentful * `embedded-entry-block`, a mark some space enabled last week: none of them are * in our vocabulary, and a closed union would force each converter to throw the * value away. They ride through the pivot as data instead, which is what makes * a round trip through Avocado non-destructive for content Avocado cannot edit. * * Node and mark names are Tiptap's, because the editor is Tiptap: `paragraph`, * `heading`, `bulletList`, `orderedList`, `listItem`, `blockquote`, `codeBlock`, * `horizontalRule`, `hardBreak`, `text`; marks `bold`, `italic`, `strike`, * `code`, `underline`, `link`. */ export type RichTextMark = { type: string; attrs?: Record | null; }; export type RichTextNode = { type: string; attrs?: Record | null; content?: RichTextNode[]; marks?: RichTextMark[]; text?: string; }; export type RichTextDoc = { type: "doc"; content: RichTextNode[]; }; /** Node names this package produces and understands. */ export declare const NODE: { readonly doc: "doc"; readonly paragraph: "paragraph"; readonly heading: "heading"; readonly bulletList: "bulletList"; readonly orderedList: "orderedList"; readonly listItem: "listItem"; readonly blockquote: "blockquote"; readonly codeBlock: "codeBlock"; readonly horizontalRule: "horizontalRule"; readonly hardBreak: "hardBreak"; readonly text: "text"; /** * A block the pivot could not model — a Portable Text `_type` we do not know, * a Contentful embedded entry, a Strapi image. It carries the source object * untouched under `attrs.data` so the converter back out can re-emit it * unchanged. The editor registers a matching read-only node, so it also * survives a trip through the property panel in its original position. */ readonly unknown: "avocadoUnknownBlock"; /** * The same thing in inline position: a ``, an * `` or any other void element sitting inside a run of text. * * It is a separate name from `avocadoUnknownBlock` because ProseMirror makes * a node inline or block and never both, and a paragraph's content is * `inline*`. Emitting the block name here put a block node inside a * paragraph, which is not a document the editor's schema can hold: it was * dropped on load, taking the element with it. */ readonly unknownInline: "avocadoUnknownInline"; }; /** Mark names this package produces and understands. */ export declare const MARK: { readonly bold: "bold"; readonly italic: "italic"; readonly strike: "strike"; readonly code: "code"; readonly underline: "underline"; readonly link: "link"; /** * An inline element the pivot has no mark for, carried rather than dropped. * * The inline twin of `avocadoUnknownBlock`, and it exists for HTML: a * template stores `` * as content, and neither half of that can be thrown away. The text inside * is ordinary editable text; the wrapper rides along in `attrs` as its tag * and its attributes in source order, and is re-emitted around whatever the * text became. * * Unknown marks already survive a round trip untouched — the Storyblok * converter relies on it for `styled` and `highlight`. This one is named so * the HTML converter can recognise its own and rebuild the element. */ readonly unknownHtml: "avocadoUnknownHtml"; }; /** * A richtext value stored as a document rather than a markdown string. * * The same signature `block-manifest.ts` keys its `isProseMirrorDocSchema` off: * an object whose `type` is the literal `"doc"`. Anything else — a markdown * string included — is not a document and must not be handed to the converters. */ export declare function isRichTextDoc(value: unknown): value is RichTextDoc; export declare function emptyDoc(): RichTextDoc; /** Parse an Avocado markdown richtext value into the pivot document. */ export declare function fromMarkdown(markdown: string): RichTextDoc; export declare function escapeMarkdownText(text: string): string; /** Serialise the pivot document to an Avocado markdown richtext value. */ export declare function toMarkdown(input: RichTextDoc | RichTextNode[]): string;