Skip to content

calternal_collab::markdown

Markdown dialect bridge for editor content. Frontmatter belongs to the host.

This module is a port of the editor’s converter (packages/editor/src/markdown.ts): the same reader and the same writer, step for step. Both sides must produce the same bytes for the same document, or opening and saving a Note in one place rewrites bytes the user did not touch. contracts/vectors/markdown/ and the seeded cross-language test in tests/cross_language.rs pin that contract; the decisions are in docs/DESIGN.md §9. Reader or writer changes need the same change in the TypeScript module, and the other way round. The server-only conflict-anchor helper below edits a canonical tree; it does not change the shared Markdown dialect (#634, DESIGN §33).

JavaScript semantics that matter for byte parity are kept on purpose: trim and \s use the JavaScript whitespace set, . in a regular expression stops at U+2028 and U+2029, and indentation widths count UTF-16 code units.

The reader never drops source bytes: a form it cannot build as a schema node stays literal paragraph text, which the writer escapes so that it reads back as the same text. Markdown wiki embeds (![[file.png]]) have no node in the editor schema, so they are plain text, and a wikilink span is copied byte for byte in both directions.

A Note is untrusted input, so work and recursion are bounded by the input size, not by its shape. The TypeScript reader has no such bounds. Two bounds can therefore give a different (but lossless) document for hostile input only: block nesting deeper than MAX_BLOCK_DEPTH, and an inline run whose delimiter search exceeds its work budget. Both keep the text as literal paragraph text (see markdown_to_prosemirror_tolerant).

Source: crates/calternal-collab/src/markdown.rs

pub fn literal_document(source: &str) -> Value

A document that holds the whole source as one literal paragraph. This is the last fallback when even the tolerant reader’s output cannot be stored.

Source: crates/calternal-collab/src/markdown.rs:1519

pub fn markdown_to_prosemirror(source: &str) -> Result<Value, BridgeError>

Parse the supported editor Markdown dialect into normalized schema JSON. It never fails; the Result is kept for callers.

Source: crates/calternal-collab/src/markdown.rs:2162

pub fn markdown_to_prosemirror_tolerant(source: &str) -> (Value, usize)

Parse Markdown and count the blocks kept as literal text because they passed a work or depth bound. A Note always opens and no byte is dropped; the caller logs the count with the Note id (never the content).

Source: crates/calternal-collab/src/markdown.rs:2169

pub fn prosemirror_to_markdown(pm: &Value) -> Result<String, BridgeError>

Serialize a document to a Markdown body (docToMarkdown).

Source: crates/calternal-collab/src/markdown.rs:2890