CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-unified

Parse, inspect, transform, and serialize content through syntax trees

Pending
Overview
Eval results
Files

processing-pipeline.mddocs/

Processing Pipeline

Core content processing functionality providing a three-phase pipeline for parsing text to syntax trees, running transformations, and compiling back to text format. Supports both synchronous and asynchronous operation modes.

Capabilities

Parse

Parses text input into a syntax tree using the configured parser.

/**
 * Parse text to a syntax tree
 * @param file - File to parse (string, VFile, or compatible)
 * @returns Syntax tree representing the input
 * @throws Error if no parser is configured
 */
parse<ParseTree extends Node = Node>(file?: Compatible): ParseTree;

Usage Examples:

import { unified } from "unified";

const processor = unified().use(someParser);

// Parse string content
const tree = processor.parse("# Hello World");

// Parse with VFile
import { VFile } from "vfile";
const file = new VFile({value: "# Hello", path: "readme.md"});
const tree = processor.parse(file);

Errors:

  • Throws "Cannot \parse` without `parser`"` if no parser is configured

Stringify

Compiles a syntax tree back to text using the configured compiler.

/**
 * Compile a syntax tree to text
 * @param tree - Syntax tree to compile
 * @param file - File context (optional)
 * @returns Compiled text or custom result
 * @throws Error if no compiler is configured
 */
stringify<CompileTree extends Node = Node, CompileResult = CompileResults>(
  tree: CompileTree,
  file?: Compatible
): CompileResult;

Usage Examples:

import { unified } from "unified";

const processor = unified()
  .use(someParser)
  .use(someCompiler);

const tree = processor.parse("# Hello World");
const output = processor.stringify(tree);
console.log(String(output)); // Compiled text

Result Types:

  • string or Uint8Array: Standard text output
  • Custom types: When using specialized compilers (e.g., React components)

Run (Async)

Runs all configured transformers on a syntax tree asynchronously.

/**
 * Run transformers on a syntax tree (async)
 * @param tree - Tree to transform
 * @param file - File context (optional)
 * @param done - Completion callback (optional)
 * @returns Promise resolving to transformed tree if no callback
 */
run(
  tree: HeadTree extends undefined ? Node : HeadTree,
  file?: Compatible,
  done?: RunCallback<TailTree extends undefined ? Node : TailTree>
): Promise<TailTree extends undefined ? Node : TailTree> | undefined;

// Overloaded signatures
run(
  tree: HeadTree extends undefined ? Node : HeadTree,
  done: RunCallback<TailTree extends undefined ? Node : TailTree>
): undefined;

Usage Examples:

import { unified } from "unified";

const processor = unified()
  .use(someParser)
  .use(someTransformer)
  .use(anotherTransformer);

// Promise-based usage
const tree = processor.parse("content");
const transformedTree = await processor.run(tree);

// Callback-based usage
processor.run(tree, (error, resultTree, file) => {
  if (error) throw error;
  console.log("Transformed:", resultTree);
});

// With file context
import { VFile } from "vfile";
const file = new VFile("content");
const tree = processor.parse(file);
const result = await processor.run(tree, file);

Run Sync

Runs all configured transformers on a syntax tree synchronously.

/**
 * Run transformers on a syntax tree (sync)
 * @param tree - Tree to transform
 * @param file - File context (optional)
 * @returns Transformed tree
 * @throws Error if async transformers are configured
 */
runSync<HeadTree extends Node = Node, TailTree extends Node = Node>(
  tree: HeadTree,
  file?: Compatible
): TailTree;

Usage Examples:

const processor = unified()
  .use(someParser)
  .use(someSyncTransformer);

const tree = processor.parse("content");
const transformedTree = processor.runSync(tree);

Errors:

  • Throws "\runSync` finished async. Use `run` instead"` if async transformers are used

Process (Async)

Complete processing pipeline: parse → run → stringify, executed asynchronously.

/**
 * Process content through complete pipeline (async)
 * @param file - Input content to process
 * @param done - Completion callback (optional)
 * @returns Promise resolving to processed VFile if no callback
 */
process(
  file?: Compatible,
  done?: ProcessCallback<VFileWithOutput<CompileResult>>
): Promise<VFileWithOutput<CompileResult>> | undefined;

Usage Examples:

import { unified } from "unified";

const processor = unified()
  .use(someParser)
  .use(someTransformer)
  .use(someCompiler);

// Promise-based usage
const result = await processor.process("# Hello World");
console.log(String(result)); // Final output
console.log(result.path);    // File metadata

// Callback-based usage
processor.process("content", (error, file) => {
  if (error) throw error;
  console.log("Result:", String(file));
});

// With VFile input
import { VFile } from "vfile";
const input = new VFile({value: "content", path: "input.md"});
const result = await processor.process(input);

Result Structure:

  • file.value: Contains the final compiled output (string/Uint8Array)
  • file.result: Contains custom compiler results (non-serialized output)
  • file.messages: Processing messages and warnings
  • File metadata preserved throughout pipeline

Process Sync

Complete processing pipeline executed synchronously.

/**
 * Process content through complete pipeline (sync)
 * @param file - Input content to process
 * @returns Processed VFile with result
 * @throws Error if async operations are detected
 */
processSync<CompileResult = CompileResults>(
  file?: Compatible
): VFileWithOutput<CompileResult>;

Usage Examples:

const processor = unified()
  .use(someParser)
  .use(someSyncTransformer)
  .use(someCompiler);

const result = processor.processSync("# Hello World");
console.log(String(result));

Errors:

  • Throws "Cannot \process` without `parser`"` if no parser configured
  • Throws "Cannot \process` without `compiler`"` if no compiler configured
  • Throws "\processSync` finished async. Use `process` instead"` for async operations

Processing Phases

Phase 1: Parse

  • Converts input text/file to syntax tree (AST)
  • Uses configured parser function
  • Input: string, VFile, or compatible object
  • Output: Node (syntax tree)

Phase 2: Run

  • Applies all configured transformers to the syntax tree
  • Transformers can modify, replace, or validate the tree
  • Supports sync/async/Promise-based transformers
  • Input: Node (from parse phase)
  • Output: Node (transformed tree)

Phase 3: Stringify

  • Converts syntax tree back to text/binary output
  • Uses configured compiler function
  • Input: Node (from run phase)
  • Output: string, Uint8Array, or custom result type

Error Handling

Configuration Errors

  • Missing parser/compiler throw descriptive errors
  • Operations on frozen processors are prevented

Runtime Errors

  • Transformer errors propagate through callbacks/promises
  • Sync methods throw immediately on async operations
  • File processing errors include context information

Async vs Sync Behavior

  • Async methods support callbacks and promises
  • Sync methods throw if async operations are detected
  • Error messages clearly indicate required alternative method

Install with Tessl CLI

npx tessl i tessl/npm-unified

docs

configuration-management.md

index.md

plugin-system.md

processing-pipeline.md

tile.json