Custom syntax and nodes
Add parsing and reading support for application syntax, using task status markers.
To display [[done]] as “Done”, first recognize the syntax and read its status, then render that status. A parsing extension handles recognition; a reading contribution handles presentation.
1. Reuse a parsing extension
Install existing MSFE Node / Mark definitions through options.extensions.
withMarkdownReading(extension, { render, load?, cacheKey? }) adds reading to the same source codec.
Fields keep their addAttributes defaults and validation; invalid values and incomplete
syntax retain source. Configure or extend the extension before wrapping its reading contribution.
2. Display the status
The example's status/reading.ts passes Status to withMarkdownReading() and returns “To do” or “Done” from attrs.value. Readers see a label while the saved source remains [[todo]] or [[done]].
This example defines [[todo]] / [[done]] grammar, replaces links and enables
HTML. Stream characters to observe incomplete nodes, HTML and late reference updates together.
Read the complete example by file: status/status.ts defines syntax and fields, status/types.ts defines the status value type, status/reading.ts defines reading output, and reading/custom.vue supplies the reader configuration. A separate reading/link.vue replaces links, as explained in Custom components.
3. Handle children and asynchronous resources
render receives read-only document, node, attrs, locale and range-checked
renderInline() / renderBlocks() helpers. Custom blocks can recursively render their
parsed children. load(context, signal) returns { value, release? } or a Promise for it.
Replacing the snapshot/message or unmounting cancels old work; late results are released too.
Unchanged blocks retain resources when they satisfy the cache dependency contract.
Reading, rendering and loading failures emit error and preserve that node's source.
More complex syntax
For more complex grammar, install native Lezer MarkdownExtension values, including block
and inline parsers, through options.syntax, then interpret fields with a source codec.
For direct read-only projection, renderNode(context, node) can handle named syntax nodes;
return undefined to use built-in dispatch. Grammar and fields belong to source extensions;
presentation belongs to reading contributions, without regex replacements on rendered HTML.