Search
Search documentation
Processor
Updated Nov 1, 2026
textlane() returns a new processor, which follows unified's: plugins added with use,
shared data, freeze, and parse, run, stringify and process for the stages.
use
use takes a plugin, a plugin and its options as two arguments, a list, or a preset. In a
list, a plugin with options is a [plugin, options] pair; a top-level array is always a
list, as in unified. The functions in textlane/md and the other subpaths build a
descriptor, { name, options }; a plugin's name works as well. A JavaScript function is a
unified attacher run between the native stages, as the
Overview describes.
import { textlane } from "textlane"
import * as html from "textlane/html"
import * as md from "textlane/md"
const file = textlane()
.use(md.parse())
.use("md.gfm")
.use([
[md.toHtml(), { allowDangerousHtml: true }],
[html.stringify(), { allowDangerousHtml: true }],
])
.processSync("Hi <kbd>Ctrl</kbd>")
file.value
// <p>Hi <kbd>Ctrl</kbd></p>A plugin used again is reconfigured: its new options merge into the earlier ones. A preset
bundles plugins, { plugins: [...] }, for reuse:
import { textlane } from "textlane"
import * as html from "textlane/html"
import * as md from "textlane/md"
const markdownToHtml = { plugins: [md.parse(), md.gfm(), md.toHtml(), html.stringify()] }
const file = textlane().use(markdownToHtml).processSync("**bold**")
file.value
// <p><strong>bold</strong></p>Each stage must take the tree the one before returns: Markdown into mdast, then mdast to
hast, then hast to HTML. A pipeline out of order fails with invalid-stage when it runs.
data
data gets and sets values shared across the pipeline, as unified's does: data() returns
all of it, data(key) one value, data(key, value) and data(object) set it.
import { textlane } from "textlane"
const processor = textlane().data("site", "textlane.dev")
processor.data("site")
// textlane.devfreeze
freeze attaches every plugin once. Later use and data setters fail with
frozen-processor, so a frozen processor can be shared and reused for many documents.
process freezes the processor itself when it first runs.
Stages
process runs all three stages; each also runs on its own:
parse(text)returns the tree the parser reads, as plain JSONrun(tree, file?)runs the transforms over a tree and resolves to the new tree;runSyncreturns it. Pass the text the tree came from asfileto keep positionsstringify(tree)serializes a tree with no transformprocess(text)resolves to the file;processSync(text)returns it. Unless the pipeline holds a JavaScript plugin,processruns on a libuv worker thread, soPromise.allover many documents uses several cores and the event loop stays free
import { textlane } from "textlane"
import * as md from "textlane/md"
const processor = textlane()
.use(md.parse())
.use(md.stringify({ bullet: "-" }))
const tree = processor.parse("* one\n* two")
tree.children[0].type
// list
processor.stringify(tree)
// - one
// - twoThe sync forms fail with async-in-sync when a stage has asynchronous work to finish; use
process and run then.
The file
process gives back a file shaped as a vfile:
value— the output textmessages— what plugins reported, as vfile-messages: each has areason, aruleId, thesourceplugin, aplacewith thestartandendpoints, itsline,columnandname(1:1-1:4),fataland thefilepath; a JavaScript plugin's own message comes back as the object it made,urlandnoteincludeddata— what plugins stored on the file
Package exports
version()— the version of the native cratepluginNames()— every plugin's name, as a pipeline names itretainedMemory()andsetRetainedMemory(bytes)— see Memory
Created with ❤ and Livemark