Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next-generation API #117

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open

Next-generation API #117

wants to merge 7 commits into from

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.

1 participant