Skip to content

Playground

Type Carve on the left. The rendered result and generated HTML appear on the right. Processing happens in your browser; the document is not sent to a server. The playground uses the JavaScript parser tested by this project's shared input/output tests.

Sharing a document as a link

The share button in the toolbar puts the whole document in the URL fragment, so a playground state is bookmarkable and sendable. The fragment never reaches a server: it is compressed and base64-encoded in the browser, and decoded there again. Very large documents are refused rather than turned into a link that arrives truncated.

Opening someone else's link. A document that arrives in a link renders with raw HTML disabled — raw blocks show as escaped text instead of running. A link is written by whoever sent it, and enabling raw HTML would make one a way to run script on this site. For the same reason the Rust (WASM) engine is not offered for a shared document: its binding has no switch for raw HTML. Reload the playground without the fragment for a normal session.

Engine PHP ↗

Carve Feature Demo

A single document touching every core construct, plus a few renderer-dependent extensions at the end.

Level 1

Level 2

Level 3

Level 4

Level 5
Level 6

A heading carries an explicit id and classes from a block-attribute line on the line directly above it:

{#install .lead}
## Setup

Inline formatting

italic, bold, bold italic, underline, strikethrough, highlight, superscript and subscript. Inline code span, and raw inline passthrough quoted emitted verbatim.

Semantic spans reach elements that have no delimiter of their own: press Ctrl+C to copy, and expand HTML.

Editorial markup: added text, deleted text, old phrasenew phrase, and an editorial note.

Escapes keep specials literal: *not bold*, /not italic/, #not-a-tag.

Lists

Unordered:

  • apples
  • oranges
    • clementines
    • blood oranges
  • pears

Ordered:

  1. clone the repo
  2. install dependencies
    • run the build
    • run the tests
  3. ship it

Tasks:

  • write the grammar
  • write the corpus
  • write more demos

Definition list:

Carve
A post-Markdown lightweight markup language.
Djot
The markup language Carve evolves from.

Blockquotes

The best way to predict the future is to invent it.

Alan Kay

Tables

Table 1: column alignment - left, right, center.
FruitPriceStock
Apple1.20In
Banana0.50In
Dragon fruit4.00Out

Code and raw blocks

A fenced code block with a language:

def greet(name: str) -> str:
    return f"Hello, {name}!"

A quoted “header” after the language sets the block’s title (rendered as the title attribute on the <pre> - a filename bar or hover tooltip):

def greet(name: str) -> str:
    return f"Hello, {name}!"

A tilde fence works too:

key: value
list:
  - one
  - two

A raw block passes content through to a named format unchanged:

Native HTMLRendered as-is.

Math

Inline math uses a dollar before a code span: \(e = mc^2\).

Display math uses a double dollar:

\[e^{i\pi} + 1 = 0\]

A fenced math block is the GFM-style block form (mathBlock extension):

\[\sum_{k=1}^{n} k = \frac{n(n+1)}{2}\]

Admonitions and divs

A bare ::: fence with no admonition type is a generic styled container, not a colored callout. Its id and classes go on a block-attribute line directly above the fence:

This block has only an id and classes, so it renders as a plain <div id="callout" class="highlight"> wrapper you can target with your own CSS.

Mentions, tags, and inline extensions

Mention a person with @alice and reference a tag like #release-1.0. An inline extension names a role for a handler to render: dQw4w9WgXcQ becomes an embed where the handler is registered, and degrades to its content where it is not.

Footnotes

Carve supports footnotes1 with definitions collected anywhere.2

Smart typography

Dashes and ellipsis: an em dash — an en range 10–20 … and so on. Arrows and comparisons: → ← ↔ ⇒ ⇐ ⇔ , ≠ ≤ ≥ , © ® ™.


List tables (Tier-2 extension)

Quarterly results
RegionNotes
EMEA

Strong quarter.

Drivers:

  • new logos
  • renewals
APAC

Code groups (Tier-3 extension)

npm install @markup-carve/carve
pnpm add @markup-carve/carve
yarn add @markup-carve/carve

Mermaid (Tier-3 extension)

Charts (Tier-3 extension)

Spoilers (Tier-2 extension)

The killer is the lighthouse keeper - click the blur to reveal.

Plot ending

Everyone makes it home. The dog lives too.


  1. The reference and its definition are linked by label.

  2. Definitions can appear in any order.

JavaScript
<section id="top">
  <h1>Carve Feature Demo <a href="#top" class="permalink" aria-label="Permalink">¶</a></h1>
  <p>A single document touching every core construct, plus a few renderer-dependent
extensions at the end.</p>
  <section id="headings">
    <h2 class="featured">Headings and attributes <a href="#headings" class="permalink" aria-label="Permalink">¶</a></h2>
  </section>
</section>
<section id="Level-1">
  <h1>Level 1 <a href="#Level-1" class="permalink" aria-label="Permalink">¶</a></h1>
  <section id="Level-2">
    <h2>Level 2 <a href="#Level-2" class="permalink" aria-label="Permalink">¶</a></h2>
    <section id="Level-3">
      <h3>Level 3 <a href="#Level-3" class="permalink" aria-label="Permalink">¶</a></h3>
      <section id="Level-4">
        <h4>Level 4 <a href="#Level-4" class="permalink" aria-label="Permalink">¶</a></h4>
        <section id="Level-5">
          <h5>Level 5 <a href="#Level-5" class="permalink" aria-label="Permalink">¶</a></h5>
          <section id="Level-6">
            <h6>Level 6 <a href="#Level-6" class="permalink" aria-label="Permalink">¶</a></h6>
            <p>A heading carries an explicit id and classes from a block-attribute line on
the line directly above it:</p>
            <pre><code class="language-carve">{#install .lead}
## Setup
</code></pre>
          </section>
        </section>
      </section>
    </section>
  </section>
  <section id="Inline-formatting">
    <h2>Inline formatting <a href="#Inline-formatting" class="permalink" aria-label="Permalink">¶</a></h2>
    <p><em>italic</em>, <strong>bold</strong>, <strong><em>bold italic</em></strong>, <u>underline</u>, <s>strikethrough</s>, <mark>highlight</mark>,
super<sup>script</sup> and sub<sub>script</sub>. Inline <code>code span</code>, and raw inline passthrough
<q>quoted</q> emitted verbatim.</p>
    <p>Semantic spans reach elements that have no delimiter of their own: press
<kbd>Ctrl+C</kbd> to copy, and expand <abbr title="HyperText Markup Language">HTML</abbr>.</p>
    <p>Editorial markup: <ins>added text</ins>, <del>deleted text</del>,
<del>old phrase</del><ins>new phrase</ins>, and an <span class="critic-comment">editorial note</span>.</p>
    <p>Escapes keep specials literal: *not bold*, /not italic/, #not-a-tag.</p>
  </section>
  <section id="Links-and-images">
    <h2>Links and images <a href="#Links-and-images" class="permalink" aria-label="Permalink">¶</a></h2>
    <p>Inline <a href="https://example.com" target="_blank" rel="noopener noreferrer">link</a>, titled
<a href="https://example.com" title="Hover title" target="_blank" rel="noopener noreferrer">link</a>, autolink <a href="https://example.com" target="_blank" rel="noopener noreferrer">https://example.com</a>,
email autolink <a href="mailto:hello@example.com">hello@example.com</a>, and a reference <a href="https://example.com" title="Reference definition" target="_blank" rel="noopener noreferrer">link</a>.</p>
    <p>A collapsed reference <a href="https://example.com" title="Reference definition" target="_blank" rel="noopener noreferrer">site</a> reuses the label as the reference.</p>
    <p>Cross-reference to a heading by id: jump to <a href="#top">Carve Feature Demo</a>.</p>
    <figure>
      <img src="/carve/images/diagram.png" alt="A descriptive alt text">
      <figcaption>Figure 1: images may carry a caption line.</figcaption>
    </figure>
  </section>
  <section id="Lists">
    <h2>Lists <a href="#Lists" class="permalink" aria-label="Permalink">¶</a></h2>
    <p>Unordered:</p>
    <ul>
      <li>apples</li>
      <li>oranges
        <ul>
          <li>clementines</li>
          <li>blood oranges</li>
        </ul>
      </li>
      <li>pears</li>
    </ul>
    <p>Ordered:</p>
    <ol>
      <li>clone the repo</li>
      <li>install dependencies
        <ul>
          <li>run the build</li>
          <li>run the tests</li>
        </ul>
      </li>
      <li>ship it</li>
    </ol>
    <p>Tasks:</p>
    <ul>
      <li><input type="checkbox" checked disabled aria-label="write the grammar"> write the grammar</li>
      <li><input type="checkbox" checked disabled aria-label="write the corpus"> write the corpus</li>
      <li><input type="checkbox" disabled aria-label="write more demos"> write more demos</li>
    </ul>
    <p>Definition list:</p>
    <dl>
      <dt>Carve</dt>
      <dd>A post-Markdown lightweight markup language.</dd>
      <dt>Djot</dt>
      <dd>The markup language Carve evolves from.</dd>
    </dl>
  </section>
  <section id="Blockquotes">
    <h2>Blockquotes <a href="#Blockquotes" class="permalink" aria-label="Permalink">¶</a></h2>
    <figure>
      <blockquote><p>The best way to predict the future is to invent it.</p></blockquote>
      <figcaption>Alan Kay</figcaption>
    </figure>
  </section>
  <section id="Tables">
    <h2>Tables <a href="#Tables" class="permalink" aria-label="Permalink">¶</a></h2>
    <table>
      <caption>Table 1: column alignment - left, right, center.</caption>
      <thead>
        <tr><th scope="col">Fruit</th><th scope="col" style="text-align: right;">Price</th><th scope="col" style="text-align: center;">Stock</th></tr>
      </thead>
      <tbody>
        <tr><td>Apple</td><td style="text-align: right;">1.20</td><td style="text-align: center;">In</td></tr>
        <tr><td>Banana</td><td style="text-align: right;">0.50</td><td style="text-align: center;">In</td></tr>
        <tr><td>Dragon fruit</td><td style="text-align: right;">4.00</td><td style="text-align: center;">Out</td></tr>
      </tbody>
    </table>
  </section>
  <section id="Code-and-raw-blocks">
    <h2>Code and raw blocks <a href="#Code-and-raw-blocks" class="permalink" aria-label="Permalink">¶</a></h2>
    <p>A fenced code block with a language:</p>
    <pre><code class="language-python">def greet(name: str) -&gt; str:
    return f"Hello, {name}!"
</code></pre>
    <p>A quoted “header” after the language sets the block’s title (rendered as the
<code>title</code> attribute on the <code>&lt;pre&gt;</code> - a filename bar or hover tooltip):</p>
    <pre title="greet.py"><code class="language-python">def greet(name: str) -&gt; str:
    return f"Hello, {name}!"
</code></pre>
    <p>A tilde fence works too:</p>
    <pre><code class="language-yaml">key: value
list:
  - one
  - two
</code></pre>
    <p>A raw block passes content through to a named format unchanged:</p>
    <details><summary>Native HTML</summary>Rendered as-is.</details>
  </section>
  <section id="Math">
    <h2>Math <a href="#Math" class="permalink" aria-label="Permalink">¶</a></h2>
    <p>Inline math uses a dollar before a code span: <span class="math inline" role="math">\(e = mc^2\)</span>.</p>
    <p>Display math uses a double dollar:</p>
    <p><span class="math display" role="math">\[e^{i\pi} + 1 = 0\]</span></p>
    <p>A fenced <code>math</code> block is the GFM-style block form (mathBlock extension):</p>
    <div class="math display">\[\sum_{k=1}^{n} k = \frac{n(n+1)}{2}\]</div>
  </section>
  <section id="Admonitions-and-divs">
    <h2>Admonitions and divs <a href="#Admonitions-and-divs" class="permalink" aria-label="Permalink">¶</a></h2>
    <aside class="admonition note" aria-label="Note">
      <p>A plain note callout.</p>
    </aside>
    <aside class="admonition tip" aria-labelledby="adm-1">
      <p class="admonition-title" id="adm-1">With a title</p>
      <p>Admonitions accept an optional quoted title.</p>
    </aside>
    <aside class="admonition warning" aria-label="Warning">
      <p>Heed this warning.</p>
    </aside>
    <aside class="admonition danger" aria-label="Danger">
      <p>Critical information.</p>
    </aside>
    <p>A bare <code>:::</code> fence with no admonition type is a generic styled container, not a
colored callout. Its id and classes go on a block-attribute line directly above
the fence:</p>
    <div id="callout" class="highlight">
      <p>This block has only an id and classes, so it renders as a plain
<code>&lt;div id="callout" class="highlight"&gt;</code> wrapper you can target with your own CSS.</p>
    </div>
  </section>
  <section id="Mentions-tags-and-inline-extensions">
    <h2>Mentions, tags, and inline extensions <a href="#Mentions-tags-and-inline-extensions" class="permalink" aria-label="Permalink">¶</a></h2>
    <p>Mention a person with <span class="mention"><strong>@alice</strong></span> and reference a tag like <span class="tag"><strong>#release-1.0</strong></span>.
An inline extension names a role for a handler to render: <span class="ext-youtube">dQw4w9WgXcQ</span>
becomes an embed where the handler is registered, and degrades to its content
where it is not.</p>
  </section>
  <section id="Footnotes">
    <h2>Footnotes <a href="#Footnotes" class="permalink" aria-label="Permalink">¶</a></h2>
    <p>Carve supports footnotes<a id="fnref1" href="#fn1" role="doc-noteref"><sup>1</sup></a> with definitions collected anywhere.<a id="fnref2" href="#fn2" role="doc-noteref"><sup>2</sup></a></p>
  </section>
  <section id="Smart-typography">
    <h2>Smart typography <a href="#Smart-typography" class="permalink" aria-label="Permalink">¶</a></h2>
    <p>Dashes and ellipsis: an em dash — an en range 10–20 … and so on.
Arrows and comparisons: → ← ↔ ⇒ ⇐ ⇔ , ≠ ≤ ≥ , © ® ™.</p>
    <hr>
  </section>
  <section id="List-tables-Tier-2-extension">
    <h2>List tables (Tier-2 extension) <a href="#List-tables-Tier-2-extension" class="permalink" aria-label="Permalink">¶</a></h2>
    <table>
      <caption>Quarterly results</caption>
      <thead>
        <tr><th scope="col">Region</th><th scope="col">Notes</th></tr>
      </thead>
      <tbody>
        <tr><td>EMEA</td><td><p>Strong quarter.</p>
<p>Drivers:</p>
<ul>
  <li>new logos</li>
  <li>renewals</li>
</ul></td></tr>
        <tr><td colspan="2">APAC</td></tr>
      </tbody>
    </table>
  </section>
  <section id="Code-groups-Tier-3-extension">
    <h2>Code groups (Tier-3 extension) <a href="#Code-groups-Tier-3-extension" class="permalink" aria-label="Permalink">¶</a></h2>
    <div class="code-group" role="group" aria-label="Code examples">
<input type="radio" name="codegroup-1" id="codegroup-1-tab-1" class="code-group-radio" checked>
<label for="codegroup-1-tab-1" class="code-group-label">npm</label>
<input type="radio" name="codegroup-1" id="codegroup-1-tab-2" class="code-group-radio">
<label for="codegroup-1-tab-2" class="code-group-label">pnpm</label>
<input type="radio" name="codegroup-1" id="codegroup-1-tab-3" class="code-group-radio">
<label for="codegroup-1-tab-3" class="code-group-label">yarn</label>
<div class="code-group-panel" role="group" aria-label="npm"><pre><code class="language-bash">npm install @markup-carve/carve
</code></pre>
</div>
<div class="code-group-panel" role="group" aria-label="pnpm"><pre><code class="language-bash">pnpm add @markup-carve/carve
</code></pre>
</div>
<div class="code-group-panel" role="group" aria-label="yarn"><pre><code class="language-bash">yarn add @markup-carve/carve
</code></pre>
</div>
    </div>
  </section>
  <section id="Mermaid-Tier-3-extension">
    <h2>Mermaid (Tier-3 extension) <a href="#Mermaid-Tier-3-extension" class="permalink" aria-label="Permalink">¶</a></h2>
    <pre class="mermaid" role="img" aria-label="mermaid">flowchart TD
    A[Write Carve] --> B{LSP diagnostics}
    B -->|clean| C[Preview]
    B -->|warnings| D[Quick fix]
    D --> A
    C --> E[Publish]</pre>
    <pre class="mermaid" role="img" aria-label="mermaid">sequenceDiagram
    Author->>Editor: type Carve
    Editor->>LSP: textDocument/didChange
    LSP-->>Editor: diagnostics + semantic tokens
    Editor-->>Author: live preview</pre>
  </section>
  <section id="Charts-Tier-3-extension">
    <h2>Charts (Tier-3 extension) <a href="#Charts-Tier-3-extension" class="permalink" aria-label="Permalink">¶</a></h2>
    <div class="chart" role="img" aria-label="chart"><script type="application/json">{"type":"bar","data":{"labels":["Q1","Q2","Q3","Q4"],"datasets":[{"label":"Revenue","data":[12,19,14,23]}]}}</script></div>
  </section>
  <section id="Spoilers-Tier-2-extension">
    <h2>Spoilers (Tier-2 extension) <a href="#Spoilers-Tier-2-extension" class="permalink" aria-label="Permalink">¶</a></h2>
    <p>The killer is <span class="spoiler">the lighthouse keeper</span> - click the blur to reveal.</p>
    <details class="spoiler">
      <summary>Plot ending</summary>
      <p>Everyone makes it home. The dog lives too.</p>
    </details>
  </section>
</section>
<section role="doc-endnotes" aria-label="Footnotes">
  <hr>
  <ol>
    <li id="fn1">
      <p>The reference and its definition are linked by label.<a href="#fnref1" role="doc-backlink" aria-label="Back to reference">↩</a></p>
    </li>
    <li id="fn2">
      <p>Definitions can appear in any order.<a href="#fnref2" role="doc-backlink" aria-label="Back to reference">↩</a></p>
    </li>
  </ol>
</section>

Visual editor

Prefer direct visual editing to this source-to-preview flow? The Carve visual editor offers rich WYSIWYG authoring while keeping the underlying Carve source available for inspection.

Build-time example

This example is read from a .crv file and converted to HTML during the VitePress build by @markup-carve/vite-plugin-carve.

Imported Carve

# Plugin Dogfood

This snippet is rendered from a `.crv` import by *vite-plugin-carve*.

Inline math like $`E = mc^2` and a display equation render with KaTeX:

$$`\int_0^\infty e^{-x^2}\,dx = \frac{\sqrt{\pi}}{2}`

Rendered HTML

Plugin Dogfood

This snippet is rendered from a .crv import by vite-plugin-carve.

Inline math like \(E = mc^2\) and a display equation render with KaTeX:

\[\int_0^\infty e^{-x^2}\,dx = \frac{\sqrt{\pi}}{2}\]

Version used by this playground

The playground and documentation examples use @markup-carve/carve. The exact source revision is recorded in package.json, so the examples do not change when a new package version is published.

Released under the MIT License.