- e20efd7 Fixed the tree functions and plugins failing in the browser with a
Buffererror. — Thanks @Princesseuh!
- ae6c881 Fixed the package failing to load because its native bindings were not installed with it. — Thanks @Princesseuh!
- 3df0ea8 Fixed 0.11.1 and 0.11.3 failing to load because their native bindings were not installed with them. — Thanks @Princesseuh!
- c472f43 Fixed a code block losing its
metawhen a plugin setsdata.hChildrenon it. — Thanks @Princesseuh! - c472f43 Fixed plugins that hand nodes back becoming very slow on documents with long lines. — Thanks @Princesseuh!
- a102233 Fixed 0.11.1 failing to load because its native bindings were not installed with it. — Thanks @Princesseuh!
- c472f43 Fixed a brace inside a quoted attribute value, such as
{title="a{b"}, stopping the attributes from applying to a fenced code block, paragraph or table cell. — Thanks @Princesseuh! - c472f43 Fixed braces written as character references, such as
{.a}, being read as a fenced code block's attributes. — Thanks @Princesseuh!
- 1be47fb Added the
attributesfeature, which reads{...}attributes on fenced code blocks (```js {.class #id}) as well as on headings. — Thanks @Saeris! - 99e7ab5 Added inline elements to the
attributesfeature: a{...}right after emphasis, strong, a code span, a link, an image or strikethrough (*em*{.class}) applies to it. — Thanks @Saeris! - 7db3e86 Added blocks to the
attributesfeature: a{...}ending a paragraph, list item, table cell or definition list entry applies to it, and one on a line of its own applies to the block it follows. — Thanks @Saeris! - 4ef9200 Fixed
data.hName,data.hPropertiesanddata.hChildrenon a code block applying to its<pre>instead of its<code>. — Thanks @Saeris! - c6cbc06 Fixed
data.hName,data.hPropertiesanddata.hChildrenbeing ignored on table rows and cells. — Thanks @Saeris! - d95c76c Changed definition list terms to fit on one line, so a
:marker after a paragraph of several lines no longer makes each line a term. — Thanks @Saeris! - beae7c9 Fixed nodes a plugin passes back losing their
position: a spread copy of a node, or a custom node given a position, now keeps it for the plugins after it. — Thanks @Saeris! - 1be47fb Deprecated the
headingAttributesfeature in favor ofattributes, which reads heading attributes as well as attributes on other elements.headingAttributeskeeps working. — Thanks @Saeris! - fc432e5 Added
featuresto the plugin factory context, so a plugin can compile a fragment with the same syntax as the document:markdownToMdast(fragment, { features: ctx.features }). — Thanks @Saeris!
- 04dffbe Fixed the 0.11.0 release, which never reached npm. — Thanks @Princesseuh!
-
81be9ae Added
ctx.setFieldfor a node's own fields andctx.setAttributeforattributesentries, so plugins can now rename elements, MDX JSX elements and directives, and set directive attributes.ctx.setPropertykeeps setting HAST element properties; using it for fields or MDX JSX attributes is deprecated, and it is deprecated outright on MDAST. — Thanks @Princesseuh! -
6a66463 A node read from the tree and handed back to
insertBefore,insertAfter,prependChild,appendChild,insertChildAtorreplaceNode, or returned from a visitor, is now that node rather than a snapshot of how it looked when you read it, so it arrives carrying every change the pass made to it. This is how reused children already behaved when nested inside new content, and it means an inserted node no longer silently misses a transform another visitor queued on it in the same pass. PassstructuredClone(node)during its visitor pass when you want a detached copy instead; a node from another tree or pass cannot be inserted as a reference.Two shapes have no answer under that rule and now report an error when queued edits are applied, instead of quietly inserting a stale copy: inserting a node inside itself, as
insertAfter(node, ctx.parent(node))does, and swapping or sorting siblings with a pair of inserts that each name the other's node. Reorder by handing the parent the order you want, withsetProperty(parent, "children", [...]). — Thanks @Princesseuh!
-
e72e72f Fixed
data.hPropertiesanddata.hChildrenbeing ignored on the last paragraph of a footnote. — Thanks @Princesseuh! -
897072d Fixed raw MDAST content adding paragraph wrappers in phrasing-content mutations. — Thanks @Princesseuh!
-
5a49ee3 Improved MDAST and HAST plugin performance for visitors, full-tree traversal, and small documents. — Thanks @Princesseuh!
-
f74fa8f Fixed setProperty for MDX JSX attributes — Thanks @Princesseuh!
-
af7e7ed Made
position: falsefaster and fixes cases were it could lower performance by accident compared to enabling positions. — Thanks @Princesseuh! -
371b584 Added Android ARM64 native binding support. — Thanks @dcavalcante for your first contribution 🎉!
-
d4be776 Fixed SVG script and style text being corrupted and elements with HTML void-element names losing children or absorbing siblings during HTML serialization and rawHtml reparsing. HTML content inside SVG integration points keeps its normal serialization rules, including with optimizeStatic. — Thanks @gtritchie!
-
af7e7ed Made parsing, HTML rendering, and tree building faster, by 3% to 35% depending on the document and output, with the largest gains on small documents. — Thanks @Princesseuh!
-
a12138b Fixed markdownToMdast and mdxToMdast return types to Root — Thanks @Princesseuh!
-
af7e7ed Made
markdownToMdast,markdownToHast, and the MDX tree functions faster and less memory-hungry, with the largest gains on text-heavy and non-ASCII documents. — Thanks @Princesseuh! -
73ba4b0 Added the
MdastVisitorFnandHastVisitorFntype exports, so a visitor shared by several node types can be typed once, for exampleMdastVisitorFn<Paragraph | Blockquote>. — Thanks @dgesteves for your first contribution 🎉! -
4171b78 Fixed list-valued properties on HAST elements: numeric items (like
coords) no longer disappear, lists are separated by comma or space according to the schema of the element they sit in, and a comma-separated attribute parsed from HTML round-trips unchanged. — Thanks @Princesseuh! -
5a49ee3 Improved Markdown parsing, HAST conversion, and HTML rendering performance for prose, tables, links, autolinks, code spans, and strong emphasis. Reduced unnecessary allocations when compiling MDX with configured ignored elements, and fixed panics and incorrect strong-emphasis output when an autolink immediately follows an inline link.
Changed Rust tree APIs to use
Documentfor both borrowed and owned source text, withNodePositionarguments for construction and position setters. JavaScript APIs and wire layouts are unchanged. — Thanks @Princesseuh! -
f74fa8f Fixed
ctx.setFieldfor structured fields, including MDX JSX and directive attributes, table alignment, and HAST element properties. For example,ctx.setField(node, "attributes", [])now clears an MDX JSX element's attributes while preserving its children. — Thanks @Princesseuh! -
036507d Fixed raw HTML MathML default namespace attributes being serialized as
:xmlnsinstead ofxmlns. — Thanks @odysseus0 for your first contribution 🎉! -
565f6d4 Fix tables consuming directive closing fences — Thanks @Princesseuh!
-
6a66463 Fixed
structuredClonethrowing on a node read from the tree, and stopped internal fields riding along on a clone or a spread copy of one. — Thanks @Princesseuh! -
9b7688f Added a native binding for FreeBSD x64. — Thanks @Princesseuh!
-
5a49ee3 Improved MDAST and HAST visitor performance, especially for text-heavy plugins. Retaining HAST visitor nodes after compilation can use more memory. — Thanks @Princesseuh!
-
bbe6744 Require MDAST and HAST plugin definitions to declare at least one visitor or lifecycle hook. — Thanks @Princesseuh!
-
d4be776 Fixed
rawHtmllosing the SVG attribute schema for raw HTML inside a JSX<svg>element, sofill-rulenow maps tofillRuleinstead of passing through as an unknown property. — Thanks @gtritchie! -
af7e7ed Fixed list and list-item nodes sometimes having corrupted values — Thanks @Princesseuh!
-
4171b78 Fixed text inside an element nested in
<script>or<style>rendering unescaped; only text directly inside those elements is left as-is. — Thanks @Princesseuh! -
a612576 Fixes numbered instructions after indented code examples rendering as plain text when numbering starts above 1. — Thanks @Princesseuh!
-
4171b78 Added
hastToHtml, which serializes a HAST tree, a single node, or a list of nodes back to an HTML string, the reverse ofhtmlToHast. — Thanks @Princesseuh! -
b2e7533 Added plugin support to the tree functions:
markdownToMdastandmdxToMdastacceptmdastPlugins, andmarkdownToHastandmdxToHastaccept bothmdastPluginsandhastPlugins, alongsidefileURLanddataas the compile functions already do.const tree = markdownToHast(source, { mdastPlugins: [myMdastPlugin], hastPlugins: [myHastPlugin], });
As with
markdownToHtml, an async plugin makes the call return a promise. — Thanks @Princesseuh! -
597ed59 Fixed the default
elementAttributeNameCase: "react"compiling the SVGdatatypeattribute todata-type. It now emitsdatatype, while customdata-*attributes on SVG and HTML elements are still kebab-cased. — Thanks @gtritchie! -
0c2c869 Fixed raw MathML children inside MDX elements being parsed as HTML. — Thanks @Princesseuh!
-
c522b99 Fixes missing exports for custom MDAST, HAST, and MDX node types. — Thanks @Princesseuh!
-
2a9ad06 Fixes empty titles appearing in rendered output when a directive has an empty label. — Thanks @Princesseuh!
- 393aed7 Fixed
satterifailing to load on Apple Silicon macOS and musl Linux x64, where the native bindings were missing from the 0.10.4 release. — Thanks @Princesseuh!
- 72d4710 Fixed plugin-inserted elements being emitted as literal JSX tags, instead of going through
_components, when another plugin-inserted node was marked as explicit JSX. — Thanks @Princesseuh!
- 1a052cf Improved performance. — Thanks @Princesseuh!
- 2cf9aef Added
clobberPrefixoption to footnotes, mirroringremark-rehype— Thanks @Princesseuh!
- c363b97 Fixed text being dropped when one paragraph held two footnote references whose identifier contains a backtick, or a
$with the math feature enabled. The words between the two references, and the second reference itself, are no longer swallowed. — Thanks @Princesseuh! - c363b97 Fixed the footnote back-reference link landing inside an earlier paragraph when the definition ends in a list, code block, blockquote, table, or heading. It is now appended after that last block, as remark and GitHub do. — Thanks @Princesseuh!
- 003158b Added
visitMdastHook,visitHastHookandnormalizePluginsto the exports, so a hand-driven plugin pipeline can runbefore/afterhooks and resolve plugin factories the waymarkdownToHtmldoes. The diagnostic and hook types (MdastDiagnostic,HastDiagnostic,MdastHookFn,HastHookFn) are exported alongside them. — Thanks @Princesseuh! - c363b97 Fixed footnote links and IDs for identifiers containing non-ASCII characters or URL punctuation, which are now percent-encoded.
[^café]links to#user-content-fn-caf%C3%A9, and an identifier holding a bare%no longer produces an invalid URL. — Thanks @Princesseuh!
-
1b09752 Added
{ fragment: true }tohtmlToHast, which parses the string as a fragment so the returnedrootholds its own top-level nodes instead of an implied<html>/<head>/<body>.Pass
space: "svg"alongside it to read the fragment as foreign content, so<circle />self-closes and camel-cased tags likeclipPathkeep their casing instead of parsing as unknown HTML elements.import { htmlToHast } from "satteri"; const tree = htmlToHast("<p>hi</p>", { fragment: true }); // { type: "root", children: [{ type: "element", tagName: "p", ... }] } const icon = htmlToHast(`<circle cx="1" />`, { fragment: true, space: "svg" });
— Thanks @Princesseuh!
-
137ff48 Nodes handed to plugins are shared and now frozen: writing to a node's fields,
position,properties/attributes, orchildrenthrows aTypeErrorinstead of silently corrupting what later plugins see; go through the context methods to make changes.Keeping a node around after your visitor ran now works: it reads as the tree looked at that moment, instead of always throwing. The error only remains if you never read the node's content before the tree changed. Trees returned by
markdownToMdast/mdxToMdast/markdownToHast/mdxToHastare your own data and stay fully mutable. — Thanks @Princesseuh! -
e53e725 Added a way to run a plugin only on some documents: a plugin factory now receives the file's
fileURL,sourceFormat,sourceanddata, and can returnnull,undefinedorfalseto be left out for that document. Those skip values are also accepted anywhere a plugin entry can appear.const onlyChangelogs = (ctx) => ctx.fileURL?.pathname.endsWith("/CHANGELOG.md") ? rewriteVersions : null; markdownToHtml(source, { mdastPlugins: [onlyChangelogs, myPlugin] });
Anything else in a plugin list now fails with an error naming the option and what it expected. — Thanks @Princesseuh!
-
2b85f56 Adds
{ raw }support towrapNode()in HAST plugins: the HTML is parsed and the node is wrapped in the resulting element. — Thanks @Princesseuh! -
d8b7172 Adds a
definitionListfeature (off by default) that renders definition lists to<dl>/<dt>/<dd>.New
descriptionList/descriptionTerm/descriptionDetailsnodes are available to plugins when this option is enabled.Apple : Pomaceous fruit. : A tech company.— Thanks @lolifamily for your first contribution 🎉!
-
d8639d6 Added a
rawHtmlfeature that reparses raw HTML embedded in Markdown into real HAST nodes. Enable it withfeatures: { rawHtml: true }on any entry point; it is applied during the MDAST→HAST conversion, somarkdownToHast,markdownToHtml, and the plugin pipelines all reparse identically, and hast plugins always see the reparsed elements.The whole tree is reparsed through the HTML parser, so a tag opened in one raw block and closed in another is resolved against the surrounding Markdown. Attributes are normalized into typed hast properties (
class→className: [...],disabled→true,tabindex→ number,data-foo-bar→dataFooBar).htmlToHastnormalizes properties the same way.MDX nodes are passed through the reparse rather than dropped: each JSX element/expression is preserved in place while the surrounding raw HTML is still resolved around it. So
mdxToHast(source, { features: { rawHtml: true } })keeps its MDX content.import { markdownToHast } from "satteri"; const tree = markdownToHast(`<div class="note">\n\n**hi**\n\n</div>`, { features: { rawHtml: true }, }); // <div> is a real element wrapping <p><strong>hi</strong></p>
— Thanks @IEvangelist for your first contribution 🎉!
-
166419c Added
markdownToJs, the plain-Markdown counterpart tomdxToJs: MDX syntax like{...}stays literal text.import { markdownToJs } from "satteri"; const { code } = markdownToJs("Hello {world}");
HTML in the source is dropped. Pass
features: { rawHtml: true }to parse it into real elements instead. — Thanks @Princesseuh! -
eeb7f07 Source positions are now opt-in per plugin via
options: { position: true }, andnode.positionisundefinedin visitors otherwise. — Thanks @Princesseuh! -
c9ea0c9 Adds user-defined MDAST node types. A plugin can create a node with any
typestring, render it as an element throughdata.hName(or as text from avalue), and reach every one of them from the newcustomvisitor key. Content nested inside a custom node stays visible to other plugins and to the HTML output. — Thanks @Princesseuh! -
8df3f76 Added support for nested arrays in
mdastPluginsandhastPlugins, so a package can export a bundle of plugins that you pass without spreading it. A bundle's plugins run in their own order, at the bundle's position. A factory can return a bundle as well as a single plugin, giving its plugins state they share with each other and reset per document.import { typography } from "some-package"; // an array of plugins markdownToHtml(source, { mdastPlugins: [typography, myPlugin] });
— Thanks @Princesseuh!
-
53fa9a9
ctx.replaceNode(node, newNode)now accepts an array of nodes as well as a single node, matchinginsertBefore,insertAfter,prependChild,appendChildandinsertChildAt. The nodes take the target's place in order, soctx.replaceNode(node, [a, b])leavesaandbwherenodewas. This works on both the MDAST and HAST visitor contexts. — Thanks @Princesseuh! -
2ac113e Added
position: falsetomarkdownToMdast,mdxToMdast,markdownToHast, andmdxToHast, which skips recordingnode.position. On a 1 MB document that halves both the time to build a tree and the memory it occupies, so it is worth passing whenever nothing downstream reads positions.const tree = markdownToMdast(source, { position: false });
— Thanks @Princesseuh!
-
63fbb77 Plugins now splice strings with a single shape,
{ raw: string, mdxExpressions?: boolean }, accepted by visitor return values and every structural mutator (replace,insertBefore,insertAfter,prependChild,appendChild,wrapNode). The string is re-parsed in place of the node.mdxExpressions(defaulttrue) controls what{…}means when the document is MDX: live expressions by default, or literal text withmdxExpressions: false— the right choice when injecting generated HTML whose braces are not expressions, like a Mermaid decision nodeC{JWT valid?}or math renderer output. Plain Markdown has no expressions, so the option is a no-op there.{ rawHtml: string }is deprecated; it keeps working and behaves exactly like{ raw, mdxExpressions: false }.defineMdastPlugin({ code(node) { if (node.lang !== "mermaid") return; return { raw: renderMermaid(node.value), mdxExpressions: false }; }, });
— Thanks @Princesseuh!
-
d8639d6 Added
htmlToHast, which parses an HTML string into a HAST tree (elements, text, comments, doctype) with the same spec-compliant parsing a browser does. The result is arootwrapping the implied<html>subtree.import { htmlToHast } from "satteri"; const tree = htmlToHast("<p>hi</p>"); // { type: "root", children: [{ type: "element", tagName: "html", ... }] }
— Thanks @IEvangelist for your first contribution 🎉!
-
6050fc4 Adds
before/afterlifecycle hooks to plugins that run exactly once per document. — Thanks @Princesseuh!
-
ac99c4f Improved HTML rendering performance with faster character escaping. — Thanks @Princesseuh!
-
5a581ad Fixed a line holding only a vertical tab or form feed counting as a blank line, which split paragraphs and let a definition run past its destination. — Thanks @Princesseuh!
-
ac99c4f Improved Markdown to HTML performance when no HAST plugins run and nothing sets
hName,hProperties, orhChildren(which heading attributes do). — Thanks @Princesseuh! -
88fbb7e Fixes a crash in the browser and bundler builds where loading Sätteri could fail with
WebAssembly.Compile is disallowed on the main thread, if the buffer size is larger than 4KB. The WebAssembly module now initializes asynchronously instead of compiling synchronously on the main thread. — Thanks @Princesseuh! -
ac2b172 Fixed GFM autolinks sometimes missing position information, such as a bare URL after an unclosed
[. — Thanks @Princesseuh! -
c9985d9 Fixed
development: trueline and column numbers, missing-component references, and MDX parse error locations being wrong in documents with multibyte or emoji characters. — Thanks @Princesseuh! -
f868e26 Fixed React-cased SVG property names like
strokeLinecapandstrokeLinejoinleaking into HTML output as-is instead of serializing asstroke-linecap/stroke-linejoin. — Thanks @gtritchie! -
7441ecd Fixed a defined footnote reference like
[^x](y)parsing as a link instead of a footnote reference followed by text. — Thanks @Princesseuh! -
7e9ac4c Fixed very deeply nested documents crashing the process instead of compiling. — Thanks @Princesseuh!
-
a27c06d Fixed MDX expressions failing to parse when a string inside them is continued over a CRLF line ending with a backslash. — Thanks @Princesseuh!
-
ac99c4f Improved parsing performance for documents with few or no autolink candidates. — Thanks @Princesseuh!
-
ac2b172 Fixed a bare URL or email not linking when a character reference supplies its first character, as in
http://example.com. — Thanks @Princesseuh! -
a27c06d Fixed MDX line comments and
import/exportblocks swallowing the lines after them in files that use lone carriage returns as line endings. — Thanks @Princesseuh! -
137ff48 Editing a node that belongs to a different document (a node kept from a previous compile, or an mdast node used in a hast plugin) now fails the compile with
invalid node id. A few pathological edits now throwunsupported patch shape, most notably replacing a node with new content that reuses that same node while another plugin edits something inside it in the same pass, and inserting a sibling next to the root.Edits to nodes that another plugin removed in the same pass are still just dropped with a warning, and replacing, removing, or wrapping the root keeps working. — Thanks @Princesseuh!
-
d6dbbad Fixed an email overlapping a
www.link swallowing the link, likeuser@www.example.orgafter an unclosed bracket. — Thanks @Princesseuh! -
be2c1a1 Fixed emphasis being parsed around a
~when GFM is disabled, soa*~*now stays plain text. — Thanks @Princesseuh! -
a27c06d Fixed GFM autolinks losing their positions when smart punctuation is enabled. — Thanks @Princesseuh!
-
18d123b Fixed a
{inside an MDX link destination or title raising a parse error when the link tail spans more than one line, as in[a](/u\n"ti{tle"). — Thanks @Princesseuh! -
5a581ad Fixed a vertical tab or form feed at the end of a line being dropped from the text. — Thanks @Princesseuh!
-
39bc97f Fixed a Promise in a plugin list being silently ignored instead of failing with a clear error, and gave malformed hast element visitors a real error message. — Thanks @Princesseuh!
-
5c4cd17 Fixed
elementAttributeNameCase: "html"leaving a nested<svg>element's own React-cased attributes (likestrokeWidth) unconverted on the MDX compile path; the SVG schema now covers the<svg>element itself, not just its descendants. — Thanks @gtritchie! -
ac2b172 Fixed inline code ending at the wrong backtick when its content looks like a URL. — Thanks @Princesseuh!
-
a27c06d Fixed emphasis and character references being lost after a GFM autolink whose URL ends in a backslash. — Thanks @Princesseuh!
-
9094edd Improved
markdownToMdastandmarkdownToHastperformance by reading each node from the wire buffer once while building the tree. — Thanks @Princesseuh! -
eeb7f07 Faster parsing, MDX compilation, and plugin execution. — Thanks @Princesseuh!
-
f0c24d7 Improved HAST property types in plugins:
node.properties.href,className,startand every other known property are now typed individually, so reading one no longer needs atypeofguard to narrow it.element: { filter: ["a"], visit(node, ctx) { if (node.properties.href?.startsWith("http")) { // ... } }, }
— Thanks @Princesseuh!
-
2ac113e Walking a tree from
markdownToMdast,mdxToMdast,markdownToHast,mdxToHast, orhtmlToHastis roughly 4x faster. — Thanks @Princesseuh! -
1126ad0 Fixed a tight definition list gluing a definition's continuation paragraph onto the first block with no separator. — Thanks @Princesseuh!
-
5a581ad Fixed a vertical tab or form feed standing in for a space in an ATX heading opener, a task list marker, an HTML tag, or a link or footnote label. — Thanks @Princesseuh!
-
6a1eaec Fixed
wrapNode()not accepting the{ raw }shape that every other structural mutator takes. — Thanks @Princesseuh! -
204fb3a Fixed documents with many unclosed parenthesized link titles taking quadratic time to parse. — Thanks @Princesseuh!
-
a27c06d Fixed a zero-width no-break space being dropped when it starts a text value. — Thanks @Princesseuh!
-
166419c Fixed
jsx: trueoutput not saying which JSX runtime to use, so a bundler compiling the JSX ignoredjsxImportSourceand the pragma options. — Thanks @Princesseuh! -
c16f684 Fixes an issue with MDAST plugin visitors receiving
undefinedinstead of an empty array for thechildrenproperty of empty parent nodes. — Thanks @HiDeoo! -
35913b9 Fixed compiles that produced very large plugin output permanently retaining tens of megabytes of buffer memory. — Thanks @Princesseuh!
-
2e3ed23 Faster Markdown-to-HTML rendering, most noticeably on prose-heavy documents where GFM autolink scanning dominated: a 200KB CommonMark document renders about 7% faster end to end. — Thanks @Princesseuh!
-
3068358 Fixed compile results being typed as synchronous when options come through a variable typed as the general options interface. — Thanks @Princesseuh!
-
64f3d5f Fixes inline code being mangled when it contains directive-like syntax. With directives enabled, writing something like
`:foo[`followed by more inline code no longer merges the two code spans or drops a backtick: a:inside a code span is now treated as literal text, so you can safely show directive syntax in code. — Thanks @Princesseuh! -
ac2b172 Fixed a
www.URL linking when the character right before it is U+0085, which does not separate words. — Thanks @Princesseuh! -
ac2b172 Fixed GFM autolinks getting the wrong URL, or being dropped entirely, when a
[earlier in the paragraph belongs to a code span, inline HTML, a pointed autolink, or a link that never resolves. — Thanks @Princesseuh! -
a27c06d Fixed text being dropped when an MDX expression contains the
]that ends a reference label. — Thanks @Princesseuh! -
7e28d6c Fixed a
:directiveafter an invalid bare URL being destroyed instead of parsed, as inhttp://my_app.localhost:3000/admin. — Thanks @Princesseuh! -
166419c Fixed
development: trueleaving out the line and column of elements that came from Markdown rather than from JSX written by hand. — Thanks @Princesseuh! -
9094edd Improved parsing performance for documents with many link reference definitions inside lists or blockquotes. — Thanks @Princesseuh!
-
47768aa Fixed whitespace between adjacent components disappearing in MDX compiled with static optimization enabled. — Thanks @Princesseuh!
-
abe1ee9 Fixed a hard line break inside an image label adding a stray newline to the image's alt text. — Thanks @Princesseuh!
-
8df3f76 Fixed
markdownToHtml,mdxToJsandmarkdownToJsbeing typed as synchronous when a plugin list mixed sync and async plugins. The result is now correctly typed as aPromise. — Thanks @Princesseuh! -
9a164f1 Fixes footnotes being ignored inside directives. A footnote reference nested in a rendered directive (e.g.
:::note … [^id] … :::) now works like anywhere else (it renders as a footnote link and its definition appears in the footnotes section) instead of being left as literal[^id]text. — Thanks @Princesseuh! -
2b85f56 Fixed
wrapNode()silently misplacing or dropping the node when given a parent that cannot hold children: anhtmlnode, a leaf-shaped custom node, or a void element like<img>. These now throw an error explaining what to use instead, andparentNodeonly accepts parent-capable nodes in TypeScript, so most of them are caught before running.Wrapping in a container is unchanged:
blockquoteand friends, a HAST element, an MDX JSX element, a custom node declaring achildrenarray, and the root itself all keep working. — Thanks @Princesseuh! -
46e2572 Fixed a
{inside an MDX link destination or title raising a parse error when the tail holds an escaped or quoted), as in[a](\){), and stopped a link tail forming from a[that is backslash-escaped, inside a code span, already wrapped by another link, or in an earlier block. — Thanks @Princesseuh! -
58add58 Fixed nodes created from raw string splices reporting garbage positions; they now report no position, like other plugin-created nodes. — Thanks @Princesseuh!
-
9bb585d Fixed edits to a node another plugin removed being dropped silently instead of with the documented warning. — Thanks @Princesseuh!
-
9094edd Improved parsing performance for documents with paragraphs inside lists, blockquotes, and other containers. — Thanks @Princesseuh!
-
2c14a38 Fixed links and reference definitions whose parenthesized title holds an unescaped
(, as in[a](* (()), not being parsed as links, and in MDX a{inside such a title no longer raises a parse error. — Thanks @Princesseuh! -
ac2b172 Fixed two bare URLs separated by a
]being merged into one over-long link, as in[www.a.com]www.b.com. — Thanks @Princesseuh! -
ac2b172 Fixed a bare URL swallowing the text after it when the two are separated by a non-breaking space or other Unicode whitespace. — Thanks @Princesseuh!
-
9094edd Improved MDX to JavaScript compilation performance. — Thanks @Princesseuh!
-
acee492 Fixed a link title being accepted with no whitespace after a
<...>destination, so[a](<u>"t")is now plain text like in remark. — Thanks @Princesseuh! -
6696c1c Fixed
positionoffsets being wrong in documents with multibyte characters. — Thanks @Princesseuh! -
291369a Fixed edits to a node kept from a previous compile silently changing an unrelated node instead of failing with
invalid node id. — Thanks @Princesseuh! -
abe1ee9 Fixed documents that use standalone carriage returns (
\r) as line endings parsing differently from documents that use\n. Values such as inline code and definition titles now keep the document's own line endings instead of always reporting\n. — Thanks @Princesseuh! -
fdaa021 Fixed a node losing its position when an async HAST visitor returns a new text value. — Thanks @Princesseuh!
-
5a581ad Fixed the start offset of text in a table cell when it begins with an escaped pipe. — Thanks @Princesseuh!
-
a27c06d Fixed an email address starting with
www.linking as a URL instead of an email. — Thanks @Princesseuh! -
9094edd Improved
markdownToMdastandmarkdownToHastperformance on documents containing non-ASCII characters, which previously fell off a fast path and cost more than twice as much to decode. — Thanks @Princesseuh! -
ac2b172 Fixed the text after a GFM autolink being mangled when the URL ends on a character reference or a backslash, which could decode the wrong character, report an overlapping position, or swallow the inline HTML or emphasis that followed. — Thanks @Princesseuh!
-
137ff48 Faster across the board: parsing is ~10% cheaper, editing the tree from plugins now costs proportionally to how much you change rather than how big the document is (3 edits on a 115KB document: ~160µs → under 50µs), reading nodes inside plugins is 40-75% faster, and memory stays flat under sustained workloads. — Thanks @Princesseuh!
-
c9f0757 Fixed MDX error messages reporting two different locations for documents that use lone carriage returns as line endings. — Thanks @Princesseuh!
-
50824f3 Fixed every position being shifted by one in documents that start with a byte-order mark. — Thanks @Princesseuh!
-
ac2b172 Fixed fenced code block
langandmetasplitting on whitespace that a character reference produced. — Thanks @Princesseuh! -
419e711 With smart punctuation enabled, an unmatched close-flanking double quote (like the inch mark in
24" monitor) now renders as a closing curly quote instead of an opening one. A double quote after a digit no longer opens a quotation, so dimension notation like24"x36"closes throughout. — Thanks @Princesseuh! -
ac2b172 Fixed a bare URL or email not linking when the character just before it is an emoji or other astral punctuation. — Thanks @Princesseuh!
- ef3974e Exposes a
ctx.sourceFormatproperty on both mdast and hast plugin contexts. It is"markdown"when the plugin runs during a Markdown compile (markdownToHtml) and"mdx"during an MDX compile (mdxToJs), letting a plugin shared between both pipelines branch on which format it is handling. — Thanks @Princesseuh! - 92c006a Fixed
satterifailing to bundle due to wasm dependencies — Thanks @The-LukeZ for your first contribution 🎉! - a579002 Set the license field in the package.json — Thanks @ghostdevv!
- c6a9088 Fixes plugin
ctx.sourcebeing polluted with duplicated, concatenated content appended after the original document. — Thanks @Princesseuh! - 65e0758 Exposes the
MdastVisitorContexttype from thesatteripackage. — Thanks @HiDeoo! - 07ee532 Fixes JSX nested in an MDX attribute expression (e.g.
prop={<p>hi</p>}ortitle={<>x</>}) being emitted as raw, un-lowered JSX, which produced invalid JavaScript. Also fixes quotes and apostrophes in such JSX text (e.g.prop={<p>Acme Corp.'s "best" tool</p>}) being mis-scanned as JS string literals and causing a parse error — the expression scanner now consumes a JSX element's children as text. — Thanks @vaneenige for your first contribution 🎉! - 2be5f6b Updated
binding.browser.tsto export functions frombrowser.js— Thanks @noClaps for your first contribution 🎉!
- fab4a2d Fixes a blank line inside a template literal or block comment in an MDX
import/exportcausing anUnterminated stringerror. The blank line no longer ends the statement early. — Thanks @Princesseuh! - fab4a2d Fixes inline math like
$\frac{-b}{2a}$failing to compile in MDX. Braces inside$...$are now treated as math text, not a JSX expression. — Thanks @Princesseuh! - 66e4f07 Fixes Markdown plugins returning
rawHtmlwith literal{or}rendering those braces as MDX escape fragments inmarkdownToHtml. — Thanks @snvtac for your first contribution 🎉! - fab4a2d Fixes quotes inside a regex in an MDX JSX attribute (e.g.
ins={[/icon="[^"]+"/g]}) causing a parse error. — Thanks @Princesseuh! - 27c9023 Fixes
headingAttributessilently dropping parsed attributes. — Thanks @Princesseuh!
- 6128184 Add prebuilt native bindings for more platforms:
linux-arm64-gnu,linux-x64-musl,linux-arm64-musl, andwin32-arm64-msvc. — Thanks @Princesseuh!
- 64877f0 Adds a
dataoption tomarkdownToHtml,mdxToJs, andCompileOptionsthat seeds the document data bag before plugins run. The same object is surfaced to plugins asctx.dataand returned asresult.data, so values can be passed both into and out of a compile. — Thanks @Princesseuh! - 855379c Fix MDX
import/exportblocks being broken by a following whitespace-only line. A line containing only spaces or tabs now ends the ESM block exactly like an empty line, instead of being consumed as a statement continuation (which produced aCould not parse esm with oxcerror). — Thanks @Princesseuh! - 855379c MDX parse errors now carry a source line and column. Previously, errors in
import/exportblocks dropped the position entirely, and errors in{…}expressions and JSX attributes were reported as a bare byte offset, so downstream tooling reported an unknown location. JSX attribute and spread expression errors now point at the offending attribute rather than the element's opening<. — Thanks @Princesseuh! - 7c78426 Fixes a performance regression when not using any plugins. — Thanks @Princesseuh!
- b2ae465 Improves performance when using plugins by using a new method of communication between Rust and JS. — Thanks @Princesseuh!
-
6bcdf06
features.superscriptandfeatures.subscriptnow render^text^as<sup>text</sup>and~text~as<sub>text</sub>as documented, instead of<em>. The MDAST now exposes dedicatedsuperscriptandsubscriptnode types, which plugins can visit and construct. Plugins that previously matched these spans asemphasisnodes should switch to the new node types. — Thanks @morinokami for your first contribution 🎉! -
d6e28f4 Fixes a parse error when an MDX expression uses top-level
await, such as<Card data={await getData()} />. — Thanks @Princesseuh! -
9867bbc Add
ctx.parent(node)andctx.indexOf(node)to the MDAST and HAST plugin visitor contexts.parent()returns a node's parent (orundefinedat the root) and is climbable to reach any ancestor;indexOf()returns a node's position within its parent's children. Together they make it possible to do operations depending on ancestry and siblings. — Thanks @Princesseuh! -
0d36b24 Aligns directive attribute type with
mdast-util-directiveby allowing nullish attribute values. — Thanks @HiDeoo! -
efba0de Add the missing
positionanddataproperties to therawhast node type. — Thanks @Princesseuh! -
77b8b1d Add
ctx.data, a document-scoped data bag shared across every plugin in the compile.Writes from one plugin are visible to later plugins, and the bag persists across the mdast→hast boundary, so hast plugins can read what mdast plugins wrote. After compilation the final state is returned on
result.data. The bag lives entirely on the JS side, so any value is allowed (functions, class instances,Map/Set) and references are preserved, much likevfile.data. Specific keys can be typed by augmenting theDataMapinterface viadeclare module "satteri". — Thanks @Princesseuh!
- 42835bc Fixes a smart punctuation issue where double quotes could be rendered with the wrong direction when quoted text appeared next to text without whitespace. — Thanks @HiDeoo for your first contribution 🎉!
-
e58b500 Fixes a parsing error when a MDX attribute contained the closing tag of itself, e.g.
<Component attr="</Component>">. The parser would incorrectly treat the</Component>as the closing tag of the component, instead of part of the attribute value. — Thanks @Princesseuh! -
f41d32f Fixes
ctx.setProperty(node, "children", [...]), which used to throw an error. You can now set a node's children directly, and any other properties you set on the same node still take effect. — Thanks @Princesseuh! -
67ac7b0 Fixes
ctx.textContent()not including inline math. A heading like# Energy $E=mc^2$would only returnEnergyinstead ofEnergy E=mc^2. — Thanks @Princesseuh! -
67ac7b0 Fixes several kinds of nodes getting mangled when a plugin would move or duplicate them. — Thanks @Princesseuh!
-
7979f1e Fixes a crash when a plugin replaces a node with a tree containing an empty text node in a document that has non-ASCII characters (e.g.
é). — Thanks @HiDeoo for your first contribution 🎉! -
f41d32f Adds
ctx.insertChildAt(node, index, child)andctx.removeChildAt(node, index)for editing a node's children by position.insertBefore,insertAfter,prependChild,appendChild, andinsertChildAtnow also accept an array of nodes, so you can insert several at once. — Thanks @Princesseuh!
- 5b45ec8 Disabled math parsing by default; pass
math: trueto re-enable inline$...$and display$$...$$math. — Thanks @Princesseuh!
- c91de73 Made HAST plugins match MDAST when a transform targets a node removed or replaced earlier in the same pass: the stranded transform is now dropped with a warning instead of throwing a fatal error. — Thanks @Princesseuh!
- c91de73 Fixed
ctx.wrapNode()dropping content: the wrapper's own children are now kept after the wrapped node, andprependChild/appendChildcalls on a node in the same pass it is wrapped are applied instead of being silently dropped. — Thanks @Princesseuh! - c91de73 Fixed a crash when a plugin returned a replacement node whose children included the node being visited (for example, wrapping a heading in a
<div>that contains it). — Thanks @Princesseuh!
-
8d84807 Adds granular
features.gfmcontrol. Footnotes can now be customized without requiring a plugin.backContentandbackLabeleach accept either a string template or a JS callback(referenceNumber, rerunIndex) => stringfor cases that need to branch on the index.// Disable footnotes, keep the rest of GFM. markdownToHtml(source, { features: { gfm: { footnotes: false } } }); // String templates. markdownToHtml(source, { features: { gfm: { footnotes: { label: "Notes de bas de page", backContent: "↑", backLabel: "Retour à la référence {reference}", }, }, }, }); // Callbacks for per-backref control. markdownToHtml(source, { features: { gfm: { footnotes: { backLabel: (n, k) => (k > 1 ? `Retour ${n}-${k}` : `Retour ${n}`), backContent: (_n, k) => (k === 1 ? "↑" : `↑${k}`), }, }, }, });
In a string template,
{reference}expands to the footnote number on the first backref and tonumber-Kon repeated backrefs to the same definition. Template mode also appends<sup>K</sup>after the back content on reruns; callback mode skips the auto-sup and lets the callback return the final content. — Thanks @Princesseuh! -
b8d8fa8 The
filenameoption (and thectx.filenameit surfaced to plugins) is nowfileURLand only accepts aURLinstead of a string. Create one withnew URL('path/to/file', import.meta.url), convert a file path withpathToFileURL('path/to/file'), or pass an existing file URL directly.This change was made to avoid normalization issues across operating systems, enable the support of virtual paths and just generally promote a more consistent format over raw strings. — Thanks @Princesseuh!
-
8d84807 Adds granular
features.mathcontrol.singleDollarTextMath: falsekeeps single-$constructs as literal text (so prose can carry currency like "$50 to $100") while$$ ... $$still parses as display math.markdownToHtml(source, { features: { math: { singleDollarTextMath: false } }, });
— Thanks @Princesseuh!
-
b8d8fa8 Nested directives now transform correctly. When a plugin turns a directive into something else (for example a
containerDirectivevisitor that renders both an outer:::noteand a nested:::tipas asides), the inner one is transformed too — in a single pass.A node returned from a visitor that passes existing children through (e.g.
{ ...node, children: [...node.children] }) now keeps those children's identity, so a transform queued on a nested one in the same pass still applies. Previously this crashed withpatch targets node N inside a removed subtree.Note: a visitor's own freshly-built nodes are not re-walked by that same visitor. Produce their final shape directly, or hand off to a later plugin (which sees the materialized tree). — Thanks @Princesseuh!
-
c69e907 Fixes Markdown plugins that return raw Markdown or HTML (
{ raw }/{ rawHtml }) sometimes inserting unnecessary nestedrootnodes into the MDAST tree. — Thanks @Princesseuh! -
d6badad Fixes
positionproperty always returningundefinedon hast nodes. — Thanks @Princesseuh! -
b8d8fa8 Directive labels now render full Markdown.
:::note[Custom **strong** Label]shows bold text instead of literal**markers. Emphasis, links, inline code, and (in MDX) components and expressions all work inside a label now, on container, leaf, and text directives. Previously a label only understood inline code.Directives that end with an HTML block also close cleanly now. A
:::notewhose last line before the closing fence is</details>no longer leaks a stray:::into the output. — Thanks @Princesseuh! -
18f269f Fixed inline
stylecustom properties (--*) being lowercased in MDX, which brokevar()references to case-sensitive names like--tmLabel— Thanks @Princesseuh!
- 1c7b915 Type
parseExpression()as an actual ESTreePrograminstead ofRecord<string, any>. — Thanks @Princesseuh!
- 82928b3 Export the MDX node types (
MdxJsxFlowElement,MdxJsxFlowElementHast, and the rest) — Thanks @Princesseuh!
- befcaf0 Fix a crash when an MDX file defines a component with
export const,export function, orexport classand then uses it as a JSX tag. Previously the component would be treated as if it had to come fromprops.components, and rendering threw "Expected component X to be defined" unless you also passed it in. It now resolves to the locally-defined component as expected. — Thanks @Princesseuh!
- f12e64e Added
elementAttributeNameCaseandstylePropertyNameCaseoptions. SetelementAttributeNameCase: "html"to emitclass/forinstead ofclassName/htmlFor, andstylePropertyNameCase: "css"to keep kebab-case keys instyleobjects. Defaults stay React-compatible. — Thanks @Princesseuh!
- f12e64e Fixed MDX files that declare a layout via
export { default } from ...orexport defaultnot rendering at runtime. — Thanks @Princesseuh!
- 4a189f7 Fixed possible memory leak when a plugin threw during compilation. — Thanks @Princesseuh!
- 4a189f7 Fixed plugin-inserted MDX JSX elements compiling as literal HTML tags instead of routing through
_components, which prevented user overrides via thecomponentsprop. — Thanks @Princesseuh!
-
adeb321
markdownToHtmlandmdxToJsnow return an object instead of a bare string. The first field carries the rendered output (html, orcodefor MDX), and a newfrontmatterfield exposes the first YAML or TOML frontmatter block in the document, ornullif none.// Before const html = markdownToHtml(source); // After const { html, frontmatter } = markdownToHtml(source);
This makes it easier to then pass the frontmatter to a YAML / TOML library of your choice, without needing to extract it using a plugin. — Thanks @Princesseuh!
- 26f2c22 Add a fallback for WebContainer that downloads
@bruits/satteri-wasm32-wasion demand when none of the native or WASI bindings are reachable in the install. — Thanks @Princesseuh!
- 6f380d3 Added factory-shape support to
hastPluginsandmdastPlugins: each entry can now be a function returning a plugin definition, called once per compile. This is useful for stateful plugins. — Thanks @Princesseuh!
- 22c4f06 Fixes a rare case where plugins could produce corrupted output in very specific situations. — Thanks @Princesseuh!
- 80d21c8 Fix a crash when an MDAST plugin returns a tree containing a directive
(
containerDirective/leafDirective/textDirective) and the surrounding document contains multi-byte text (e.g. Devanagari, CJK). — Thanks @Princesseuh! - 80d21c8 Reduced memory usage when using MDAST plugins. — Thanks @Princesseuh!
- 8e7642c Fixed compilation crashing with
invalid type: map, expected a sequencewhen an MDAST plugin returned a tree containing a directive node (containerDirective,leafDirective,textDirective). Directive children now round-trip through plugins correctly. — Thanks @Princesseuh!
- bf7c5a0 Fixed SVG attributes names (e.g.
viewBox,fillOpacity) being converted to lowercase when set on elements from JS plugins — Thanks @Princesseuh! - bf7c5a0 Fixed numeric property values (e.g.
width: 16,start: 5) being silently dropped when set on elements from JS plugins. — Thanks @Princesseuh!
- 467bdf9 Fixed plugin-set
databeing lost or corrupted on MDAST and HAST nodes in certain cases. — Thanks @Princesseuh!
-
baae3b8 MDAST plugins can now set
data.hName,data.hProperties, anddata.hChildrenon a node and have Sätteri render the corresponding HAST element, matching the rehype idiom.This is especially useful for rendering directives, given a
containerDirective, anhNameof"aside"andhPropertiesof{ className: ["note"] }, satteri will emit<aside class="note">…</aside>. — Thanks @Princesseuh!
-
baae3b8 Fixed a crash when an MDAST plugin called
ctx.setProperty(node, "data", …)on certain specific node types (e.g.paragraph,blockquote,delete). The call now succeeds and the data round-trips through the conversion pipeline as expected. — Thanks @Princesseuh! -
baae3b8 Fixed plugins silently dropping all but the last structural change against a given node. Multiple
insertBefore/insertAftercalls on the same node, or sibling inserts paired with aremoveNodeon that same node, now all apply in the order they were issued.Combinations that don't have a sensible meaning, like modifying something inside a removed subtree, now report an error instead of silently dropping the change. — Thanks @Princesseuh!
-
1f92697 Added visitor support for
containerDirective,leafDirective, andtextDirectivenodes. Plugin authors can now subscribe to directive nodes directly (with typedname/attributesand children).Removed the
rootvisitor key. Plugins should subscribe to specific node types instead; a dedicated API for prepending or appending content at the document level will land separately. — Thanks @Princesseuh!
-
f632abf Various MDX parsing fixes:
- Fixed non-ASCII content in MDX expressions/JSX inside containers (blockquotes, lists) being corrupted due to byte-by-byte char casting.
- Fixed MDX-only paragraphs inside blockquotes not being unraveled (producing spurious
<p>wrappers). - Fixed multiple JSX elements on one line only rendering the first element.
- Multiple other cases of small inconsistencies with
@mdxjs/mdx, notably in whitespace handling and node positions. — Thanks @Princesseuh!
-
f632abf Added granular smart punctuation options (
ENABLE_SMART_QUOTES,ENABLE_SMART_DASHES,ENABLE_SMART_ELLIPSES) that can be enabled independently instead of the entire group. — Thanks @Princesseuh! -
5736ca4 Fixes many output inconsistencies with remark across Markdown, GFM, and MDX parsing, mostly found by extensive property-based fuzz testing. Notable areas: GFM bare-URL detection, MDX JSX flow vs inline classification, footnote numbering and section ordering, directive label inline parsing, list spread/tight handling, and reference link spans. — Thanks @Princesseuh!
- 11ffcfc Fixed unclosed
{in a paragraph silently consuming later blocks as an MDX expression, and fixed literal{inside code spans being falsely reported as an unclosed MDX expression — Thanks @Princesseuh!
- 6f9f66f Fixed JSX inside MDX expression bodies, JSX inside
.map()callbacks or other expressions is now compiled to_jsx()calls instead of being dropped or emitted as raw JSX — Thanks @Princesseuh!
- ef20299 Fixed hyphenated JSX element names (e.g.
<my-widget>) written explicitly in MDX being incorrectly routed through the components provider and producing invalid JavaScript — Thanks @Princesseuh! - ef20299 Fixed script and style element contents being entity-escaped, which produced invalid output (e.g.
<inside<script>) — Thanks @Princesseuh! - ef20299 Fixed HAST property names not being mapped to their HTML attribute names during rendering (e.g.
classNamenow renders asclass,htmlForasfor) — Thanks @Princesseuh! - ef20299 Fixed source positions being dropped for most node types during mdast-to-hast conversion, so hast plugins now see accurate positions across the tree — Thanks @Princesseuh!
- ef20299 Fixed code blocks missing trailing newlines when using hast plugins — Thanks @Princesseuh!
- ef20299 Fixed footnote references and definitions not being rendered when using hast plugins — Thanks @Princesseuh!
- ef20299 Fixed table column alignment being dropped when using hast plugins — Thanks @Princesseuh!
- ef20299 Fixed
code.valuein the MDAST tree including a trailing newline for well-formed fenced code blocks, which diverged fromremark-parse. MDAST plugins inspectingnode.valuenow see the same bytes as remark. — Thanks @Princesseuh! - ef20299 Fixed task list classes and checkbox inputs being missing when using hast plugins — Thanks @Princesseuh!
- ae83450 Fixed optimizeStatic silently collapsing elements that have runtime component overrides via
export const components— Thanks @Princesseuh!
- 6f08f69 Fixes missing
optionalDependenciesfield. — Thanks @Princesseuh!
- b0cdb9b Added
parseExpression()tomdxjsEsmnodes, allowing ESM import/export statements to be parsed into ESTree ASTs. — Thanks @Princesseuh!
- 893ef59 Fix MDX import/export and expression handling to match the behavior of the original JavaScript implementation:
- Fix
mdxjsEsmnodes not being delivered to HAST plugin visitors - Fix multiline
exportblocks (e.g. objects, arrays) being truncated - Fix expression boundaries for edge cases involving comments, template literals, regex, and JSX
- Report errors for unclosed MDX expressions — Thanks @Princesseuh!
- Fix