Repository navigation
Releases
Lima 0.8.1 — outline() reads as the parser reads
Lima 0.8.1 reworks outline() inside the JavaScript package: the positions of keys and comments now come from the parser's own readers, as they read.
Changed
- JavaScript:
outline()reads positions as the parser reads. The readers for the top level, blocks, flow values and comments report each key and comment through a hook that onlyoutline()sets, instead ofoutline()matching the parsed tree to the lines afterwards. It now grows linearly with its input: 2,048 malformed lines take 15 ms instead of 527. For a few malformed inputs the result is now right, where the old matching took a key from another line.
parse, parseCore and parseReferences keep their path and their speed; benchmarks on the host show no regression. Rust and Go are unchanged; their version follows the repository's.
Lima 0.8.0 — outline() for editors
Lima 0.8.0 adds outline() to the JavaScript package: where each key, comment and error of a document stands in the source, for editors.
Added
- JavaScript:
outline(input). Returns every key with its decoded name, its path, the span of the key as written and of its separator, every comment, and what a strictparsewould report. Spans have a line, a column and an offset in UTF-16 code units, the shapes the Markanto parser uses. It reads with the parser's own readers, soAutor:in: xhas the keyAutor:inand the lines of a|scalar are no keys; it never throws for content, and a half-typed line leaves the keys below it in place. The first user is the block editor of hadley, which shows front matter as a striped table.
Rust and Go are unchanged; their version follows the repository's.
parse, parseCore and parseReferences are unchanged; benchmarks show no regression.
Lima 0.7.1 — security review of 0.7
Lima 0.7.1 fixes what a security review of 0.7 found in all three implementations, with one erratum to Core 1.2.
Security
- References could fill the memory. A few KB of references copied millions of nodes before the limit on the result stopped them, and interpolation kept growing a value past its limit. Resolution now counts what it copies and stops during expansion (References §4.1), with the same error. Upgrade if you parse documents you do not trust.
- Rust panicked on short input: a last line of whitespace after a mapping in a sequence item, and whitespace before a flow value in one.
Erratum to Core 1.2
Inline value processing trims whitespace as §1 defines it, not only spaces, as every value in a block already did. draft: false followed by a no-break space is the boolean. Whitespace inside quotes, inside a block scalar and inside a value stays.
Fixed
- JavaScript and Rust: a value or sequence item followed by whitespace other than spaces kept it.
- JavaScript and Rust:
.0and-.0are zero, not an underflow. - JavaScript: an empty key in a block is an unrecognised line; spaces before a flow value in a sequence item threw an error without a code; messages no longer quote control or direction characters, and shorten a long line.
- Go: dates are only the forms of Core §15.9.
Added
- JavaScript:
LimaErroris exported.
Benchmarks show no regression on real front matter, and at most 3 % on documents made of references.
Lima 0.7.0 — Core 1.2: keys in any script
All three implementations ship 0.7.0 from this tag:
| npm | @limaformat/[email protected] |
| crates.io | lima = "0.7.0" |
| Go | go get github.com/limaformat/lima/[email protected] |
Package versions are independent of the Lima specification version; this release implements Lima Core 1.2 and
Lima References 2.1 (docs/lima-core-1.0-spec.md and docs/lima-references-2.0-spec.md, under their old names
so that published links keep working). Documents that 0.6.0 skipped or rejected for their keys' characters now read,
hence the minor version.
Core 1.2: keys in any script
An unquoted key starts with a letter or number of Unicode 18.0 or _, and after its first character also holds
marks, * and ·. Keys can be written in any language, and gendered, without quotes:
größe: 42
título: Hola
題名: こんにちは
autor:in: Noa
autor*in: Noa
autor·in: Noa
- Unicode 18.0, fixed. The categories are those of the Unicode Character Database 18.0.0, not of whatever Unicode
the host language knows, so TypeScript, Rust and Go read every key alike. Each carries a generated table; there is
still no runtime dependency, and ASCII keys are read as fast as before. - Keys compare as written. Lima normalises no Unicode: an
ötyped as one character and one typed asoplus a
combining mark are two keys. A consumer that wants them equal normalises them itself. - Invisible characters stay out. Whitespace, control and format characters, the bidirectional controls among
them, are in no unquoted key. - A document is Unicode scalar values. TypeScript rejects a lone surrogate and Go invalid UTF-8 with
INVALID_DOCUMENTand the line, as Rust strings cannot hold them. - Hints: whitespace other than spaces before a key, a FULLWIDTH COLON (U+FF1A) in place of
:, and the
key-grammar hint for a key such asx y: 2at every level.
References 2.1
Reference names take the characters of a Core 1.2 key: ${größe}, ${autor*in}, $(personen/zoë.name).
Core 1.2: what each kind of line does, in one table
§7.1 states in one normative table what each kind of line — blank, comment, entry, item, other — does where it
stands, in non-strict and in strict mode, in place of the prose where the Core 1.1 reviews found their issues. No
outcome changes; 124 new corpus cases pin every row, and all three implementations pass them.
Requirements
@limaformat/limaneeds Node.js 22 or later (String.prototype.isWellFormed).
Numbers
Measured by the new scripts/facts.ts and checked in CI: 620 conformance cases in the current target (479 Core, 141
References), 200,000 differential parses per implementation and run, and an npm tarball of 72.3 KB — js-yaml 5.2.3's
is 4.7 times its size.
The full list is in each package's CHANGELOG.md.
Lima 0.6.0 — Core 1.1: every line belongs to the structure
All three implementations ship 0.6.0 from this tag:
| npm | @limaformat/[email protected] |
| crates.io | lima = "0.6.0" |
| Go | go get github.com/limaformat/lima/[email protected] |
Package versions are independent of the Lima specification version; this release implements Lima Core 1.1
(docs/lima-core-1.0-spec.md, under its old name so that published links keep working). Strict mode now rejects
documents 0.5.1 accepted, and some non-strict results change, hence the minor version.
Core 1.1: every line belongs to the structure
In strict mode a content line belongs to a key, a block or a scalar, or it is an error at its line. Core 1.0 dropped
such a line silently, in strict mode too:
title: A
author: B # INVALID_INDENTATION, line 2 (a tab is two spaces, after an inline value)
description: >
A folded text # INVALID_INDENTATION, line 4: ">" is YAML's folded scalar; Lima writes "|"
author Odile # UNRECOGNIZED_LINE (new code), line 5: a key needs ": " after it
--- # UNRECOGNIZED_LINE: a YAML document marker; Lima has one document
Non-strict mode skips such lines, as before.
Core 1.1: what Core 1.0 left open
- Compact sequences. A bare key's sequence may start at the key's own column, as YAML writes it, at any level:
tags:/- a/- b. - Indentation is spaces only. Other whitespace before content, such as a pasted U+00A0, starts the content, so
the line is unrecognised. Whitespace is defined once (§1). - An object item's keys stand at its first key's column; another column is inconsistently indented.
- A block holds entries or items, as its first entry or item decides; a line non-strict mode skips decides
nothing, but its indentation counts. - Nested sequences: an item whose value is a flow sequence (
- [a, b]) is a nested sequence —nullin
non-strict mode,INVALID_FLOW_SYNTAXin strict mode. |alone is the marker:a: |with no content is'';a: | # cis the string"|"at every level.- The end of the input ends the last line, so a last
key:isnull(TypeScript dropped it).
Fixed
Found by a new three-way differential test; most were already in 0.5.1.
- Go: a negative number as a sequence item (
- -7) was read as a nested sequence (null); a line of spaces could
panic on untrusted input; an object item's keys after a blank, comment or skipped line were lost; more than 128
top-level keys with a duplicate reported the duplicate before the limit. - TypeScript and Rust: an unclosed
{as an item passed strict mode; a mixed block lost all its entries in
non-strict mode. - All three: a
|scalar as an object item's first key measured its body from the dash plus two, so after wider
whitespace (- a: |) it took the next key as text.
Conformance
- Corpus: 126 Core 1.1 cases in
corpus/core-1.1/(their own frozen manifest), superseding 8 Core 1.0 cases, which
stay byte-identical in the 1.0 baseline: 336 Core and 136 References 2.0 cases, passed by TypeScript, Rust and Go. - Differential test in CI: TypeScript, Rust and Go parse the same 100,000 random documents in both modes on every
run and must agree on every value, warning, and error code and line (corpus/runner/src/differential.ts).
Performance
Strict mode costs a little more for its new guarantee: against 0.5.1 on real front matter, TypeScript +5 %, Rust
+10–12 %, Go unchanged; non-strict mode is within a few percent. The cross-language benchmarks gain strict scenarios.
The npm package is 60.8 KB (0.5.1: 55.7 KB).
Editors
The tree-sitter grammar reads | x and | # c correctly; the Zed extension and the Neovim/Helix examples pin it at
this release. Compact sequences are not yet shown as sequences in the tree (no error node).
The full record of the decision and its six reviews: docs/decisions/top-level-indentation-after-inline-value.md.
Lima 0.5.1 — aligned top-level values are trimmed
All three implementations ship 0.5.1 from this tag:
| npm | @limaformat/[email protected] |
| crates.io | lima = "0.5.1" |
| Go | go get github.com/limaformat/lima/[email protected] |
Package versions are independent of the Lima specification version; Lima Core 1.0 gains errata 1.0.10, which adds
conformance cases only — no rule changed.
Fixed
-
Aligned top-level values are trimmed (TypeScript, Rust). A top-level inline value kept every space after
:
but the first, so an aligned document read wrong values:title: Hello # was ' Hello', now 'Hello' count: 42 # was the string ' 42', now the integer 42 quoted: "x" # was the text ' "x"', now 'x'This was against Core §4 step 3 and its own examples (§4
title: Hello World # comment→'Hello World',
§5.1title: Hello→'Hello'). Nested keys were not affected, and Go already trimmed. The top-level scalar fast
path handed the untrimmed value on; it now skips the whitespace after the separator, as the block mapping does.
Reported References 2.0 columns were already physical and are unchanged; the flat-frontmatter benchmark stays within
noise of 0.5.0.
Corpus
7 new Core cases (since: "1.0.10"), 211 → 218: the §4 example verbatim, a strict pair, every scalar type, quoted,
flow and empty values at the top level. TypeScript, Rust and Go pass all 218 Core and 136 References 2.0 cases.
Lima 0.5.0 — References 1.0 resolver dropped from published packages
All three implementations ship 0.5.0 from this tag:
| npm | @limaformat/[email protected] |
| crates.io | lima = "0.5.0" |
| Go | go get github.com/limaformat/lima/[email protected] |
Package versions are independent of the Lima specification version; the
Lima Core 1.0 and References 2.0 specs are unchanged from 0.4.0.
What's in it
Scope cleanup, not a language change. References 1.0 was published briefly
in mid-2026 and superseded almost immediately by References 2.0, which is
not syntax-compatible with it. Its frozen resolver was still being shipped
to consumers of all three packages for no reason.
- The frozen References 1.0 resolver is no longer bundled in any
published package. It was never a public entry point (parseReferences
andparseare References 2.0) — it only existed to run the frozen 1.0
conformance corpus, which now does so against the repository source
instead. The 1.0 spec and its 101-case corpus stay in the repo as a
frozen regression target. - No changes to Core 1.0 or References 2.0 syntax, semantics, or public
API in any of the three implementations. - Packed npm tarball: 59.3 KB → 53.4 KB (verified with
npm pack --dry-run). Ratio vs js-yaml 5.2.3 is now ~6.3× (was ~5.7×). js/distis no longer tracked in git — it's pure build output,
reproduced byprepack/pretest/pretypecheckbefore every build,
test, or publish.
Full changelogs
The rust/v0.5.0 and go/v0.5.0 tags point at the same commit and exist
for the crates.io and Go module tooling; this is the single release for
all three.
Lima 0.4.0 — the 2026-09 review campaign
All three implementations ship 0.4.0 from this tag:
| npm | @limaformat/[email protected] |
| crates.io | lima = "0.4.0" |
| Go | go get github.com/limaformat/lima/[email protected] |
Package versions are independent of the Lima specification version; the
Lima Core 1.0 and References 2.0 specs stay Final, gaining only
non-normative clarifications (§5, §5.2, §6.1.3, error-api).
What's in it
0.4.0 is the result of the first independent whole-repo review of Lima, a
second review of the consolidated result, a delta review of the final fix
batch, and four intermediate re-review rounds.
- Nine rounds of Core 1.0 errata (
1.0.1–1.0.9) — block scalars,
escape-aware key and quoted-string lexing, comment-line lookahead, the
§5.1 unquoted-key grammar enforced in every context, sibling-key column
alignment, int/float corpus assertions, raw line terminators and
U+2028/U+2029 in quoted keys,\#handling in and out of quotes, and the
comment-boundary whitespace set — all fixing behaviour the specs already
required. - Cross-implementation References 2.0 error positions — every token
now reports its physical(line, column)in the original source,
counted in Unicode code points, byte-identical across TypeScript,
Rust, and Go (including inside flow[...]/{...}and across
\#collapses). Ordering follows the earliest participating token. - Corpus — 149 → 211 Core and 119 → 136 References 2.0 cases.
The frozen 1.0.0 baseline (149 Core cases) is byte-identical and
cryptographically anchored. CI now runs all three implementations.
Accepted cost: parseCore in Rust and Go carries a ~10–20 % regression
from the §5.1 per-key validation and the physical-position token scan.
Realistic frontmatter still parses several times faster than the
corresponding YAML library.
Full changelogs
js/CHANGELOG.mdrust/CHANGELOG.mdgo/CHANGELOG.mddocs/review-2026-09-followups.md— the full review record
The rust/v0.4.0 and go/v0.4.0 tags point at the same commit and exist
for the crates.io and Go module tooling; this is the single release for
all three.
Rust v0.3.0 — References 2.0
Rust 0.3.0 brings the Rust crate to Lima References 2.0 parity with TypeScript.
Highlights:
- dotted document and partial paths
- bounded three-edge transitive resolution and cycle handling
- structural copies, canonical interpolation, and ordered diagnostics
- final resource validation and duplicate-key warning callbacks
- all 369 shared conformance cases pass
- Core performance remains within the release regression gates
The primary entry point is parse with ParseOptions; parse_references remains as a deprecated References 2.0 alias.
See rust/CHANGELOG.md for the complete release notes.
Go v0.3.0 — References 2.0
Go 0.3.0 brings the Go module to Lima References 2.0 parity with TypeScript and Rust.
Highlights:
- dotted document and partial paths
- bounded three-edge transitive resolution and cycle handling
- structural copies, canonical interpolation, and ordered diagnostics
- final resource validation and duplicate-key warning callbacks
- structured LimaError diagnostics through errors.As
- all 369 shared conformance cases pass
- Core performance remains within the release regression gates
The primary entry point is Parse with ParseOptions; ParseReferences remains as a deprecated References 2.0 alias.
See go/CHANGELOG.md for the complete release notes.