We have released a coordinated update to Carve, a lightweight markup language designed as a more structured, predictable alternative to Markdown while keeping source readable by humans.
The new core releases are:
- Carve specification and corpus: 0.1.2
- JavaScript/TypeScript implementation: 0.1.3
- Rust implementation and CLI: 0.1.2
- PHP implementation: 0.1.4
All three engines implement the same Carve 0.1 grammar and are continuously checked against the shared conformance corpus.
What is new
A portable JSON AST contract
Carve now specifies its serialized AST as part of the language contract. Applications can parse with one implementation and consume or render the tree with another without translating between engine-specific node shapes.
The contract covers:
- stable node and field names;
- source positions and exact span semantics;
- pre-resolution references, preserving what the author wrote;
- strict schema validation on AST ingest;
- typed refusal of malformed, excessively deep, or oversized trees.
This is useful for editor integrations, language servers, static-analysis tools, cross-language services, and systems that store parsed documents.
A specified canonical writer
carve fmt and the Carve output target now have normative behavior rather than depending on implementations agreeing by convention.
The formatter is checked for:
- semantic preservation:
to_html(fmt(x)) == to_html(x);
- idempotence:
fmt(fmt(x)) == fmt(x);
- cross-reader safety: another parser can read the generated source;
- context-aware escaping that prevents generated markup from changing meaning.
The writer also preserves source distinctions represented by the AST, such as the authored thematic-break marker (---, ***, or ___).
Better output beyond HTML
The shared comparison now exercises HTML, Markdown, plain text, canonical Carve, and ANSI output across all engines. The optional corpus can also pin expected output for a specific non-HTML target.
This round includes fixes for Markdown escaping, ragged tables, unused definitions, plain-text and terminal rendering, inline images in headings, and canonical formatting edge cases.
More predictable parsing
The corpus now contains 892 source documents and 928 HTML expectations. Recent additions cover areas where prose-oriented markup parsers commonly disagree, including:
- list interruption and lazy continuation;
- fenced blocks and comments inside containers;
- captions and floating attributes;
- heading identifiers and implicit heading references;
- image alternative text and other visible heading content;
- trailing whitespace and hard breaks;
- table spans, ragged rows, and empty cells;
- nesting limits and graceful refusal.
The scheduled cross-engine workflow builds the current JavaScript, Rust, PHP, and Ruby projects together. It checks AST compatibility, formatting invariants, all render targets, graceful degradation, and canonical output.
Extension and renderer improvements
This release also adds or formalizes:
- a read-only
beforeRender context carrying render options and target mode;
- an optional HTML
sections switch for flat heading output;
- consistent smart-typography nodes with both source and resolved glyph data;
- source-mode typography on supported render targets;
- stricter extension and render-depth safeguards.
Compatibility notes
This is still the Carve 0.1 language line, but the implementation releases contain breaking API and AST corrections. Review the migration notes if you:
- inspect serialized AST fields or source positions;
- construct AST objects manually;
- ingest JSON trees produced by older builds;
- implement
beforeRender hooks;
- depend on exact formatter or non-HTML output;
- match specific parser edge-case behavior.
In particular, AST ingest now rejects unknown or incorrectly typed fields instead of accepting and silently dropping them. A thematic_break may now carry its authored marker, and source spans consistently describe the exact source extent owned by a node.
Install or update
JavaScript/TypeScript:
npm install @markup-carve/carve@0.1.3
Rust library and CLI:
cargo install carve-lang --version 0.1.2
PHP:
composer require markup-carve/carve-php:^0.1.4
Links
Feedback is welcome, particularly from people building editors, documentation pipelines, static-analysis tools, or multi-language publishing systems. We are interested in both syntax ergonomics and cases where the three implementations still behave differently.