The Wayback Machine - https://web.archive.org/web/20220323002121/https://github.com/unifiedjs/unified/discussions/178
Skip to content

Visiting a custom AST without `position` field doesn't seem to work (sometimes)? #178

Answered by ChristianMurphy
horacioh asked this question in Q&A
Visiting a custom AST without `position` field doesn't seem to work (sometimes)? #178
Nov 23, 2021 · 1 answers · 1 reply

Somethign strange happened to me just now:

I'm buyilding a custom transformer from hast to mttast which is a custom Unist-Compatible AST. after I run all the transform I'm then removing all the position data with usint-util-remove-position. Then when I want to visit all the text nodes on the resulting AST, and my visitor function signature defines the parent seems to break the visit?

export function toMttast(tree: Node, options: Options = {}) {
  let mttast
  const h = Object.assign<any, any>(transformer, {
    handlers: options.handlers ? {...handlers, ...options.handlers} : handlers,
    wrapText: true,
    textProps: {},
  } as Context)

  let result = one(h, tree, undefined)

  if (!result) {
    mttast = u('root', [])
  } else if (Array.isArray(result)) {
    mttast = u('root', result)
  } else {
    mttast = result
  }

  removePosition(mttast, true)

  // visit(mttast, 'text', ontext)
  visit<any, 'text'>(mttast, 'text', (node, index, parent) => {
    console.log('visit: ', {node, index, parent}) // ⬅️ because `parent` is defined in the visitor function it just hangs 🤷🏼‍♂️
  })

  return mttast
}

(This function follows the hast-util-to-mdast structure, so you can "guess" what the implementation of transformer & one looks like)

I tried to replicate the error outside with a raw object but it does visit. and in my code if I remove the parent from the signature it does work too 🤯
it DOES work also if I move the removePosition function call after the visit.

maybe this is not a bug on any unified tool, but I was curious to know if this happened before to someone else?

here's the simple demo example I ran that worked:

import { toMdast } from "hast-util-to-mdast"
import rehypeParse from "rehype-parse"
import { unified } from "unified"
import { removePosition } from "unist-util-remove-position"
import { visit } from "unist-util-visit"

let hast = unified()
  .use(rehypeParse, { fragment: true })
  .parse(`<span>hello </span><span>world</span>`)

let mdast = toMdast(hast, { fragment: true })

let noPosASt = removePosition(mdast, true)

// visit(noPosASt, "text", (node, index, parent) => {
//   console.log("visit: ", node, index, parent)
// })

visit(
  {
    type: "root",
    children: [
      {
        type: "text",
        value: "hello ",
        strong: true,
      },
      {
        type: "text",
        value: "world",
        underline: true,
      },
    ],
  },
  "text",
  (node, index, parent) => {
    console.log("visit: ", node, index, parent)
  }
)

console.log(JSON.stringify(mdast, null, 2))

thanks in advance!

and my visitor function signature defines the parent seems to break the visit?
because parent is defined in the visitor function it just hangs

Are you using TypeScript 4.5 by any chance? This could be the same as #175
In which case downgrade to TypeScript 4.4 for now, while we wait for microsoft/TypeScript#46900 to be addressed.

Replies

1 suggested answer
·
1 reply

and my visitor function signature defines the parent seems to break the visit?
because parent is defined in the visitor function it just hangs

Are you using TypeScript 4.5 by any chance? This could be the same as #175
In which case downgrade to TypeScript 4.4 for now, while we wait for microsoft/TypeScript#46900 to be addressed.

1 reply
@horacioh

seems to be that!! yes I was using TS 4.5.x :)

thanks!!

Answer selected by horacioh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
2 participants