@markup-carve/carve
v0.1.6
Published
Reference TypeScript implementation of the Carve markup language
Maintainers
Readme
carve-js
Reference TypeScript implementation of the Carve markup language.
Implements Carve spec 0.1 (see Versioning & Changelog).
Status: the parser, renderers, and migration tooling are implemented and pass the spec corpus.
What this is
- A linear-time parser for
.crvsource → typed AST - Renderers to HTML (canonical), Markdown, plain text, and ANSI
- A test runner that validates output against the shared corpus
The spec, EBNF grammar, and example pairs live in the upstream markup-carve/carve repo, pulled in here as a git submodule under spec/. The corpus at spec/tests/corpus/ is the contract this implementation honors.
Install
npm install @markup-carve/carveWorking on carve-js itself instead? See docs/development.md.
Usage
import { carveToHtml } from '@markup-carve/carve'
carveToHtml('# Hello\n\nThis is /italic/ and *bold*.')
// <section id="Hello">
// <h1>Hello</h1>
// <p>This is <em>italic</em> and <strong>bold</strong>.</p>
// </section>The package exposes one-call converters per output format, plus the lower-level
parse / resolve / render* functions for inspecting or transforming the AST:
import {
carveToHtml,
carveToHtmlWithReport,
carveToMarkdown,
carveToPlainText,
carveToAnsi,
parse,
resolve,
renderHtml,
} from '@markup-carve/carve'
const doc = resolve(parse(source)) // typed Document AST
const html = renderHtml(doc) // same as carveToHtml(source)Raw nodes are routed to their named target. If omitted content must be observable, use the checked sibling of either API:
const result = carveToHtmlWithReport('`x`{=latex}')
// result.value is the unchanged HTML output
// result.losses[0].code === 'raw-format-dropped'
carveToHtmlWithReport('`x`{=latex}', { strictLosses: true })
// throws RenderLossError before a value is returnedReports are bounded to 100 entries by default while totalLosses retains the
complete count. Set maxRenderLosses to change the bound. The compatible
string-returning APIs remain available.
Tools that need to retain unrelated source bytes can use carveToCarvePatch
and applySourcePatch; see
source-preserving patches.
HTML rendering accepts a symbols map for symbol shortcodes (e.g. emoji):
mapped values are trusted raw HTML output, and unmapped :name: shortcodes
render literally.
It runs in a browser too, from a script tag or a module - docs/browser.md.
How the renderers derive heading ids, wrap sections and bound nesting depth is in docs/rendering.md.
Import HTML
htmlToCarve and htmlToAst convert HTML into Carve, with ordered loss
diagnostics and safe / semantic / trusted-roundtrip policies:
import { htmlToCarve } from '@markup-carve/carve'
const { carve, losses } = htmlToCarve('<h1>Title</h1>', { mode: 'safe' })Markdown and Djot convert in as well (markdownToCarve, djotToCarve).
What the HTML importer models and what it deliberately does not is in
docs/html-import.md.
CLI
npx carve README.crv > README.html # render (HTML by default)
npx carve --markdown README.crv # or --plain, --ansi, --json
npx carve lint README.crv # report problems, change nothing
npx carve fmt -w README.crv # format canonicallyEvery subcommand and flag is in docs/cli.md. For running it over a repository - a GitHub Action, a pre-commit hook, or Prettier - see docs/integrations.md.
Untrusted input
Rendering attacker-controlled Carve needs the safe path: --safe on the CLI,
or the checked render options in the library, which escape raw HTML instead
of emitting it. Nesting depth and other renderer limits are bounded by
default. The threat model and every knob is in docs/security.md.
Documentation
Extensions - opt-in extensions (
smartQuotes,tabNormalize,details,tabs,codeGroup,mermaid,wikilinks,externalLinks,headingPermalinks,tableOfContents,autolink) and how to add your own syntax with parse-stage matchers.Migration and linting -
markdownToCarve,djotToCarve, Djot collision warnings +carve fix, andlintCarve/carve lint.HTML import - what the importer models, and what it does not.
Command line - every subcommand and flag.
Integrations - GitHub Action, pre-commit, Prettier.
Untrusted input - the threat model and the safe path.
Rendering behavior - heading ids, section wrappers, depth limits.
Browser use - script tag and module.
Accessibility lint - the accessibility rules.
Streaming render - rendering without buffering.
Reversible patches - editing an AST in place.
Source-preserving patches - stale-safe UTF-8 edits.
Development - the checkout, the layout, the roadmap.
Try Carve live in the playground, which runs this implementation in the browser.
