Stringify SDK

Document Serialization

Serialize AST nodes and full Documents back to Markdown.

The Stringify SDK provides two ways to turn AST data back into Markdown: stringify() for full documents, and toMarkdown() for individual nodes.

stringify(doc)

Serializes a complete Document back to a Markdown string.

import { parse, stringify } from "datamark";

const doc = parse(`
---
title: Hello
---

# Hello World

This is the first paragraph.

## Section

More content here.
`);

const output = stringify(doc);
// ---
// title: Hello
// ---
//
// # Hello World
//
// This is the first paragraph.
//
// ## Section
//
// More content here.

stringify() flattens the section tree before serializing. The result is a clean Markdown string with frontmatter when present.

toMarkdown(node)

Serializes a single AST node to Markdown. Useful when you need to output a subset of the tree.

import { toMarkdown } from "datamark/stringify";

const headingNode = { type: "heading", depth: 2, children: [{ type: "text", value: "Title" }] };
toMarkdown(headingNode); // "## Title"

toMarkdown accepts a single Node or an array of BlockNode[] and returns the corresponding Markdown string.

Round-trip

Parse and stringify are reversible for most Markdown:

import { parse, stringify } from "datamark";

const input = "# Title\n\nBody text";
const doc = parse(input);
const output = stringify(doc);

console.log(output); // "# Title\n\nBody text\n"

Positions may shift slightly on roundtrip because toMarkdown re-serializes from the AST rather than preserving the original raw text. Whitespace and exact indentation are normalized.

stringifyYaml(data)

For cases where you need YAML output without a full frontmatter fence, stringifyYaml produces clean YAML from a JavaScript object:

import { stringifyYaml } from "datamark/stringify";

stringifyYaml({ title: "Hello", tags: ["a", "b"] })
// "title: Hello\ntags:\n  - a\n  - b\n"

This is the same function used internally by frontmatter().

Building documents from scratch

When you need full control over output, combine builder primitives with stringify():

import { parse } from "datamark";
import { heading, paragraph, list } from "datamark/stringify";

function buildReport(data: { title: string; items: string[] }) {
  const markdown = [
    heading(data.title, 2),
    paragraph(`Generated on ${new Date().toISOString()}`),
    list(data.items),
  ].join("\n\n");

  // If you need a Document object, parse it back
  return parse(markdown);
}

For format definitions, this is usually handled inside the stringify function passed to datamark().

On this page