Technical previewShare feedback

Search

Search documentation

Getting started

Updated Nov 1, 2026

Install

npm install textlane

The package brings a prebuilt addon for your platform as an optional dependency, so never install with --omit=optional. Addons cover Linux on glibc and musl (Alpine), macOS and Windows, each on x64 and arm64. Node.js 20 or later loads it as an ES module.

A first pipeline

A pipeline parses text into a tree, runs plugins over it and serializes the result. Each plugin is a function from its domain's subpath: textlane/md, textlane/html, textlane/mdx and textlane/nl.

import { textlane } from "textlane"
import * as html from "textlane/html"
import * as md from "textlane/md"

const file = await textlane()
  .use(md.parse())
  .use(md.toHtml())
  .use(html.stringify())
  .process("# Hello *world*")
file.value
// <h1>Hello <em>world</em></h1>

md.parse reads Markdown into mdast, md.toHtml turns it into hast and html.stringify writes HTML. process returns a promise of the file; processSync returns the file itself.

Adding syntax

Syntax extensions sit beside the parser. Add md.gfm for tables, task lists, strikethrough and autolinks, md.cjkFriendly for emphasis next to Chinese, Japanese and Korean text, and md.frontmatter to read a YAML block at the top:

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.frontmatter())
  .use(md.toHtml())
  .use(html.stringify())
  .processSync("---\ntitle: Notes\n---\n\n~~draft~~ done")
file.value
// <p><del>draft</del> done</p>

Reading the result

The file holds the output as value, the messages plugins reported and the data they set. Checks such as nl.repeatedWords leave the text alone and report a message:

import { textlane } from "textlane"
import * as md from "textlane/md"
import * as nl from "textlane/nl"

const file = textlane()
  .use(md.parse())
  .use(md.toNaturalLanguage())
  .use(nl.repeatedWords())
  .use(nl.stringify())
  .processSync("It is the the best.")
file.messages[0].reason
// Unexpected repeated `the`, remove one occurrence

Next, the processor covers every method, and the plugin pages list each plugin with its options.

Created with ❤ and Livemark