unified

Learn/Recipe/Find a node

How to find a node

Contents

What is a node

A node is a single language specific unit inside a syntax tree. For example: a heading in markdown, or anchor element in HTML. In unified, nodes follow the unist specification.

Finding a node

The concept of finding a node involves tree traversal of a syntax tree.

unified compatible utilities should be used for finding a node. Utilities are functions that work with nodes. All specifications that extend unist can use the unist utilities, but they can also have their own utilities for more specific nodes.

To start finding nodes for your input you’ll need:

For this example we use remark and unist-util-find. We want to find the first occurrence of emphasis in our markdown.

/**
 * @import {Root} from 'mdast'
 */

import {remark} from 'remark'
import {find} from 'unist-util-find'

await remark()
  .use(function () {
    /**
     * @param {Root} tree
     * @returns {undefined}
     */
    return function (tree) {
      const node = find(tree, {type: 'emphasis'})
      console.log(node)
    }
  })
  .process('Some _emphasis_, **strongness**, _more emphasis_, and `code`.')
(alias) const remark: Processor<Root, undefined, undefined, Root, string>
import remark

Create a new unified processor that already uses remark-parse and remark-stringify.

(alias) function find<V extends Node>(tree: Node, condition: TestFn | TestObj | TestStr): V | undefined
import find

Find a node in tree matching condition.

  • @template {Node} V Node to search for.
  • @param tree Tree to search in.
  • @param condition Condition used to test each node, which matches V.
  • @returns The first node that matches condition, or undefined if no node matches.
(alias) remark(): Processor<Root, undefined, undefined, Root, string>
import remark

Create a new unified processor that already uses remark-parse and remark-stringify.

(method) Processor<Root, undefined, undefined, Root, string>.use<[], Root, undefined>(plugin: Plugin<[], Root, undefined>, ...parameters: [] | [boolean]): Processor<Root, Root, undefined, Root, string> (+2 overloads)

Configure the processor to use a plugin, a list of usable values, or a preset.

If the processor is already using a plugin, the previous plugin configuration is changed based on the options that are passed in. In other words, the plugin is not added a second time.

Note: use cannot be called on frozen processors. Call the processor first to create a new unfrozen processor.

  • @example There are many ways to pass plugins to .use(). This example gives an overview:
    import {unified} from 'unified'
    
    unified()
      // Plugin with options:
      .use(pluginA, {x: true, y: true})
      // Passing the same plugin again merges configuration (to `{x: true, y: false, z: true}`):
      .use(pluginA, {y: false, z: true})
      // Plugins:
      .use([pluginB, pluginC])
      // Two plugins, the second with options:
      .use([pluginD, [pluginE, {}]])
      // Preset with plugins and settings:
      .use({plugins: [pluginF, [pluginG, {}]], settings: {position: false}})
      // Settings only:
      .use({settings: {position: false}})
    
  • @template {Array} [Parameters=[]]
  • @template {Node | string | undefined} [Input=undefined]
  • @template [Output=Input]
  • @overload
  • @overload
  • @overload
  • @param value Usable value.
  • @param parameters Parameters, when a plugin is given as a usable value.
  • @returns Current processor.
(parameter) tree: Root
  • @param tree
const node: Node | undefined
(alias) find<Node>(tree: Node, condition: TestFn | TestObj | TestStr): Node | undefined
import find

Find a node in tree matching condition.

  • @template {Node} V Node to search for.
  • @param tree Tree to search in.
  • @param condition Condition used to test each node, which matches V.
  • @returns The first node that matches condition, or undefined if no node matches.
(parameter) tree: Root
  • @param tree
(property) type: string
namespace console
var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
//   Error: Whoops, something bad happened
//     at [eval]:5:15
//     at Script.runInThisContext (node:vm:132:18)
//     at Object.runInThisContext (node:vm:309:38)
//     at node:internal/process/execution:77:19
//     at [eval]-wrapper:6:22
//     at evalScript (node:internal/process/execution:76:60)
//     at node:internal/main/eval_string:23:3

const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);

myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err

const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

  • @since v0.1.100
const node: Node | undefined
(method) Processor<Root, Root, undefined, Root, string>.process(file?: Compatible | undefined): Promise<VFile> (+1 overload)

Process the given file as configured on the processor.

Note: process freezes the processor if not already frozen.

Note: process performs the parse, run, and stringify phases.

  • @overload
  • @overload
  • @param file File (optional); typically string or VFile]; any value accepted as x in new VFile(x).
  • @param done Callback (optional).
  • @returns Nothing if done is given. Otherwise a promise, rejected with a fatal error or resolved with the processed file. The parsed, transformed, and compiled value is available at file.value (see note).

    Note: unified typically compiles by serializing: most compilers return string (or Uint8Array). Some compilers, such as the one configured with rehype-react, return other values (in this case, a React tree). If you’re using a compiler that doesn’t serialize, expect different result values.

    To register custom results in TypeScript, add them to {@linkcode CompileResultMap}.

…yields:

{
  type: 'emphasis',
  children: [ { type: 'text', value: 'emphasis', position: [Object] } ],
  position: {
    start: { line: 1, column: 6, offset: 5 },
    end: { line: 1, column: 16, offset: 15 }
  }
}

Read more about unist-util-find in its readme.

The package unist-util-find is rather basic and slow. You likely want to traverse a tree with unist-util-visit