jc_adf/lib.rs
1//! Markdown ↔ Atlassian Document Format (ADF) converter.
2//!
3//! Pure functions, no I/O. Load-bearing for every read and write path in
4//! `jc`.
5//!
6//! ## Coverage
7//!
8//! - **Full round-trip:** paragraphs, headings (H1–H6), text marks (strong,
9//! em, code, strike), links, bullet and ordered lists (including
10//! tight-list inline handling), fenced code blocks with language hints,
11//! blockquotes, horizontal rules, hard breaks, GFM tables (header + body,
12//! inline marks preserved; column alignment is dropped because ADF has
13//! no per-column alignment).
14//! - **Read-only:** `@user` mentions (rendered as `@name`), `mediaSingle`
15//! images (rendered as `` sidecar references),
16//! `inlineCard`, `emoji`.
17//! - **Lossless escape hatch:** any ADF node type the converter doesn't
18//! explicitly handle is rendered as a ` ```adf:<type>` fenced code block
19//! whose body is the raw node JSON. When that markdown is re-parsed by
20//! [`to_adf`], the fenced block re-inflates verbatim. Fence length is
21//! chosen dynamically so nested backticks in the serialized JSON can't
22//! break out of the block.
23//!
24//! ## Deferred
25//!
26//! Write-path implementations for: generated table of contents, typed
27//! user mentions (requires an async accountId lookup hook), and the
28//! inline-image upload pipeline. All of these round-trip losslessly
29//! via the escape hatch; they just lack friendly markdown syntax.
30
31pub mod from_adf;
32pub mod to_adf;
33
34/// ADF is kept as `serde_json::Value` internally. That keeps the converter
35/// small and trivially extensible — new node types are one match arm away.
36pub type AdfDocument = serde_json::Value;
37
38pub use from_adf::to_markdown;
39pub use to_adf::to_adf;