ctrlplusb / react-tree-walker

Walk a React (or Preact) element tree, executing a "visitor" function against each element.
MIT License
345 stars 34 forks source link

Add cursor to visitor #34

Open ashtonsix opened 6 years ago

ashtonsix commented 6 years ago

This lets us do stuff that depends on knowing where the node we're visiting is.

For example, I noticed <v:roundrect /> is invalid but React.createElement('v:roundrect') is fine, so wrote some code like <v$roundrect /> & a function that can find/replace $ with : after an intermediate build step.

const React = require('react')
const ReactWalker = require('./reactTreeWalker').default

const ReactMapper = async (element, f) => {
  let root
  let next = new Map()
  await ReactWalker(
    element,
    (e, _0, _1, _2, cursor) => {
      if (typeof e.type === 'function') return
      if (e.type && e.type.toString().includes('react.fragment')) return

      const parent = cursor.filter(e => typeof e.type === 'string').slice(-1)[0]

      let ni
      if (typeof e.type === 'string') {
        ni = f(e)
        ni.children = []
        next.set(e, ni)
      }
      if (parent) next.get(parent).children.push(ni || e)
      if (!root) root = ni
    },
    {}
  )

  const recursive = el => {
    if (typeof el === 'string' || typeof el === 'number') return el
    const {type, props, children} = el
    return React.createElement(type, props, ...children.map(recursive))
  }

  return recursive(root)
}

const repairNamespaces = async element => {
  element = await ReactMapper(element, e => {
    const type = e.type.replace('$', ':')
    const props = e.props
    return {type, props}
  })

  return element
}
codecov[bot] commented 6 years ago

Codecov Report

Merging #34 into master will not change coverage. The diff coverage is 83.33%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master      #34   +/-   ##
=======================================
  Coverage   95.29%   95.29%           
=======================================
  Files           1        1           
  Lines          85       85           
  Branches       24       24           
=======================================
  Hits           81       81           
  Misses          4        4
Impacted Files Coverage Δ
src/index.js 95.29% <83.33%> (ø) :arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update b6c594f...d467f70. Read the comment docs.

ctrlplusb commented 6 years ago

This seems like a super interesting idea and could open up some powerful ideas. I'll need to give it a thorough bashing before we merge, but i feel like it holds a lot of promise. Thanks so much for this proposal!

ashtonsix commented 6 years ago

@ctrlplusb how's the bashing going?