Mutating Unist AST

Great example https://css-tricks.com/how-to-modify-nodes-in-an-abstract-syntax-tree/

The code below will change a list of images into a grid of images.

import { selectAll } from "unist-util-select";
import { visit } from "unist-util-visit";

export default () => {
  return (ast) => {
    visit(
      ast,
      (x) => x.tagName === "ul",
      (node) => {
        const images = selectAll("element", node).filter(
          (y) => y.tagName === "img"
        );
        if (images.length) {
          node.tagName = "div";
          node.properties["class"] =
            "grid grid-col-1 md:grid-col-3 lg:grid-cols-4";
          node.children = images;
        }
      }
    );
  };
};

Wrapping an element

For the code examples on this site I needed to wrap the pre > code tags in a div with the class not-prose so that they could be highlighted correctly using highlightjs via remark-highlight. This is because I am using the typography plugin from tailwindcss.

import { visit } from "unist-util-visit";
import { h } from "hastscript";

export default () => {
  return (ast, file) => {
    visit(
      ast,
      (x) =>
        x.tagName === "pre" && x.children.some((n) => n.tagName === "code"),

      (node, idx, parent) => {
        file.data.meta = file.data.meta || {};
        file.data.meta.hasCode = true;

        parent.children[idx] = h("div", { class: "not-prose" }, [node]);
      }
    );
  };
};

The code above turns:

<pre>
  <code>Some code</code>
</pre>

into:

<div class="not-prose">
  <pre>
    <code>Some code</code>
  </pre>
</div>