Skip to content

Conversation

@milesj
Copy link
Owner

@milesj milesj commented Mar 25, 2020

Interweave has served it's purpose rather well over the years, but has grown to accrue lots of cruft and questionable implementations (we're on v12 already). I believe it's time to rewrite this library from the ground-up, to improve the API, remove weirdness, greatly reduce filesize, improve performance, and much more.

Primary goals:

  • Avoid classes as much as possible as they're the biggest contributor to the large filesize.
  • Remove "magic" props from the Interweave + Parser coupling.
  • Use explicit React element render factories instead of the weird component type implementation.
  • Allow factories to easily be swapped out by consumers.
  • Root-level props are available throughout the entire API, so that factories can utilize them.

Matchers are now createMatcher

This new functional API accepts a regex pattern, some customizable options, and a render factory. It then returns a "matcher" to be used by the parser.

const matcher = createMatcher(
  /\[b\](\w+)\[\/b\]/iug,
  ({ word }, props, children) => <strong>{word}</strong>,
  {
    tagName: 'strong',
    onMatch(result) {
      return {
        word: result.matches[1],
      };
    },
  },
);

Filters and transformers are now createTransformer

Filters and transformers did similar things, they operated on DOM/HTML elements. This new API will unify them both into a more streamlined API, where you can easily mutate attributes/elements, replace with new elements, or inject React components.

Like matchers, they use a new functional API, which accepts a tag name they want to operate on (or * for all), and a factory to transform the element. Some examples.

// Remove invalid inline styles on all elements
const transformer = createTransformer('*', (element) => {
  Object.keys(element.style).forEach((key) => {
    if (String(element.style[key]).match(INVALID_STYLES)) {
      delete element.style[key];
    }
  });
});

// Replace all anchors with a custom React element
const transformer = createTransformer('a', (anchor, props, children) => {
  return (
    <Link openInNewWindow={props.newWindow} href={anchor.getAttribute('href')}>
      {children || anchor.textContent || ''}
    </Link>
  );
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants