Unist Utility for Ancestral Node Traversal

6.0.2 · active · verified Sun Apr 19

unist-util-visit-parents is a robust utility within the unist (Universal Syntax Tree) ecosystem designed for deeply traversing ASTs (Abstract Syntax Trees) while providing a full lineage of parent nodes for each visited node. This functionality is crucial for transformations or analyses that require contextual information about a node's position within the tree. The current stable version is 6.0.2, with active development evidenced by frequent minor and major releases, particularly focusing on TypeScript type improvements and ESM compatibility. It differentiates itself from `unist-util-visit` by offering an array of parent nodes, making it indispensable for scenarios where ancestral context is necessary, such as scope analysis or complex rewrite operations. The library is ESM-only and requires Node.js 16 or higher, adhering to modern JavaScript module standards.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates how to use `visitParents` to traverse a Markdown AST, log node types with ancestral paths, modify nodes, and control traversal flow using `SKIP`.

import { visitParents, SKIP } from 'unist-util-visit-parents';
import { fromMarkdown } from 'mdast-util-from-markdown';
import type { Root, Paragraph, Strong, PhrasingContent } from 'mdast';

const markdownInput = 'This is a *test* with **strong** emphasis and `code` blocks.';
const tree: Root = fromMarkdown(markdownInput);

console.log('Original Tree:');
console.log(JSON.stringify(tree, null, 2));

// Example 1: Log all nodes and their direct parent types
visitParents(tree, (node, ancestors) => {
  const parentTypes = ancestors.length > 0 ? ancestors.map(p => p.type).join(' > ') : 'Root';
  console.log(`- Node Type: ${node.type}, Parents: ${parentTypes}`);
});

// Example 2: Skip children of 'strong' nodes and modify content
visitParents<Strong>(tree, 'strong', (node, ancestors) => {
  console.log(`\nVisiting strong node: ${node.value || ''}`);
  if (node.children && node.children.length > 0 && node.children[0].type === 'text') {
    node.children[0].value = (node.children[0].value || '') + ' (MODIFIED)';
    console.log(`  Modified strong text. Skipping its children for further traversal.`);
  }
  return SKIP; // Do not traverse children of this 'strong' node
});

console.log('\nModified Tree (strong nodes updated and their children skipped):');
console.log(JSON.stringify(tree, null, 2));

// Example 3: Find a specific node type and its ancestors, then exit
let foundCode = false;
visitParents<PhrasingContent>(tree, 'inlineCode', (node, ancestors) => {
  console.log(`\nFound inlineCode: ${node.value}`);
  console.log('  Ancestors:', ancestors.map(a => a.type));
  foundCode = true;
  return true; // Use true (CONTINUE) or EXIT to stop, depending on requirement
});

if (!foundCode) {
  console.log('\nNo inlineCode nodes found.');
}

view raw JSON →