Skip to content

Releases

Markanto 0.2.3 — code in lists keeps its indentation

Choose a tag to compare

@mkorun mkorun released this 10 Nov 18:54

Markanto 0.2.3 fixes list items that changed the code inside them, and reads nested lists the way most editors and AI agents write them. The language is still 0.2.0. Update if you write code blocks in lists, or Markdown from Prettier or an AI.

Fixed

  • Code and math blocks in a list item keep the indentation of their content, with or without a blank line before them. Before, a python block right under - A lost the indentation of its lines.
  • A nested list on its parent's content column is read as the parent's child, as §9.4 requires: three spaces under 1. , four under 10. . Before, it was a syntax error. Two spaces per level remain the canonical form, which the formatter writes and strict mode requires, and documents that were valid keep their meaning.
  • Indentation of four or more spaces that Markanto drops now gets its advisory in quotes, containers, Grid cells and list items too, not only at the top level. Continuation lines and the content of code or math blocks get none.

Apart from the code blocks above and the new advisories, documents that were valid parse as they did under 0.2.2, and as fast.

Markanto 0.2.2 — recovery that finishes and keeps every line

Choose a tag to compare

@mkorun mkorun released this 09 Nov 09:53

Markanto 0.2.2 fixes a parser that could not finish when asked to recover from errors, and recovery that lost text. Update if you parse documents you do not trust, or show invalid documents to their authors.

Fixed

  • With errorRecovery, a container whose name has a character a name may not have (::: A|B) made parse run forever: the recovery read the same line again and again. It goes on after the line now, as after any error. From a security review.
  • With errorRecovery, a block that failed lost part of what it had read: a container whose body failed, a quote that failed at one level, a table whose header failed, and a second definition of a footnote. The error block now holds all of it, and the diagnostic stays where the error is. An unclosed container no longer claims the lines after it, which then appeared twice.
  • :::tldr, a fence with its name but without the space before it, now says "a fenced container's name follows its fence after a space" instead of "list marker requires exactly one space".

Valid documents parse as they did under 0.2.1, and as fast.

Markanto 0.2.1 — a parser that finishes

Choose a tag to compare

@mkorun mkorun released this 31 Oct 18:31

Markanto 0.2.1 fixes a parser that could not finish. Update if you parse documents you do not trust.

Fixed

  • A document of open brackets did not end: each [ or ![ doubled the time the search for a label's end took, so a line of forty stopped parse for good. The search is now one forward pass, with the same results: 200,000 random documents parse as they did under 0.2.0.

Markanto 0.2.0 — two changes towards GFM

Choose a tag to compare

@mkorun mkorun released this 29 Oct 13:58

Markanto 0.2.0 (spec/markanto-spec-v0.2.0.md): two changes towards GFM. The
specification of 0.1.0 stays as it was.

Language

  • A number with a dot is text. Digits followed by . or ) and then a
    decimal digit open no list item: 3.14 is close to pi, 2.0 and later and
    1.2.3 Overview are ordinary text at the start of a line, where 0.1.0
    reported "list marker requires exactly one space". 1.Item and 2)Second
    stay errors. The escape 0.1.0 needed (3\.14) is now a tolerated,
    noncanonical surface.
  • \| in a table cell is a pipe, inside code too. Within a table cell,
    \| stands for | also inside a code span, inline math, an autolink, a
    superscript and a subscript, as in GFM; \\| stands for \| in a code
    span, inline math and an autolink. Canonical cells write every literal | as
    \|, in all of these and in link destinations and titles as well, so a
    canonical table is the same table on GitHub. An MIB attribute value keeps |
    as written, and GitHub splits a cell there. A superscript or subscript is not
    atomic for the row tokenizer, so in a cell its value cannot hold a \
    directly before a |; format reports such a tree as invalid.

Conformance

  • Nine table cases now expect the escaped canonical form; thirty-nine new cases
    cover both changes, among them pipes in wrapped images, downloads, metadata
    spans, superscripts and subscripts, and numbers in list items, quotes,
    footnotes and headings. The corpus has 622 cases.

Markanto 0.1.1 — Diagnostic.range

Choose a tag to compare

@mkorun mkorun released this 16 Sep 06:44

Diagnostics now carry source locations.

Parser

  • Diagnostic.range — part of the type since 0.1.0, but never populated by
    any emission site — is now set on every syntax, semantic, and advisory
    diagnostic parse() reports: duplicate/unreferenced footnote definitions,
    an unresolved footnote reference, invalid or duplicate block ids, unclosed
    wrappers and other recognition failures, malformed {#id} suffixes,
    dropped leading indentation, and invalid transport (lone CR / lone
    surrogate). A consumer (e.g. an editor) can now locate an error precisely
    instead of matching on message text, which stays implementation-defined.
  • No parsing behaviour changed and no new public API was added — range was
    already part of the Diagnostic type (docs/IMPLEMENTATION.md §12). As
    before, validate(), format(), and strict-mode canonicality diagnostics
    operate on a source-less semantic AST and never carry range.

Markanto 0.1.0 — frozen reference implementation

Choose a tag to compare

@mkorun mkorun released this 04 Sep 09:01

First release of @markantolang/parser as the reference implementation of the
redesigned Markanto 0.1.0 language. It supersedes the earlier builds based
on the 0.5.3-era specification (previously versioned 0.3.0 package-local). The
lower version number is deliberate: it marks the new, stable language baseline.
See docs/MIGRATION.md for the consumer cutover and
docs/EVOLUTION_V053_TO_010.md for every
language delta.

Public API

  • Every operation returns a tagged status union — consumers branch on
    status before reading a payload. parse() yields
    status: "ok" | "invalid" | "resource"; format(), validate(), and
    checkCanonical() use corresponding envelopes. This replaces the previous
    thrown-error and inline-ErrorBlock model for ordinary failures.
  • Source positions are no longer fields of AST nodes. Each ok (and each
    recovery) result carries an annotations sidecar that maps nodes to source
    ranges on demand.
  • parse(source, { strict: true }) accepts only the canonical surface;
    { errorRecovery: true } adds a RecoveryDocument on invalid input without
    affecting valid input.
  • CommonMark / GFM import moved to the explicit @markantolang/parser/commonmark
    subpath. Its micromark / mdast dependencies are optional peer
    dependencies
    ; the core parser and root entry point ship dependency-free.

Language

  • Canonical surface: exactly one serialisation per meaning, enforced by the
    formatter and the spec-dogfood gate (the specification itself is stored in
    canonical Markanto).
  • Wrapper tags reduced from 7 to 3; reference links resolved at import time;
    hard breaks in headings written as \n; uniform list model (spec §9.9).
  • Full v0.5.3 → 0.1.0 migrator (tools/migrate/) with a frozen-corpus
    evolution gate: every case maps to a valid 0.1.0 AST or a construct-named
    diagnostic — no silent loss.

Quality

  • Language design and specification independently audited (2026-08-30);
    independent whole-repo review of the implementation completed with a
    SHIP / FREEZE verdict — 0 blockers, 0 retained major findings.
  • Resource safety: a Grid occupancy matrix is bounded by a caller-tunable
    default (DEFAULT_MAX_MATRIX_SLOTS, 100 000) and an absolute, non-overridable
    ceiling (HARD_MAX_MATRIX_SLOTS, 1 000 000); an over-budget or
    non-representable matrix returns resource, never a native RangeError.
  • Gates at release: verify (type + boundary + 583-case conformance corpus +
    the full 1898-test suite), verify:node, compat:report (672 vendored
    CommonMark 0.31.2 / GFM cases, 0 fail), soak (100 000 seeded documents
    per stream through the §7.2 laws plus a parser-linearity probe).