1

I am building a note taking app and for text I use the Slate.js editor. Twitter mention also works with stocks like this enter image description here

It basically turns into a mention if /\$[a-zA-Z]{1,6}/ is true. What I have tried is to use the normalizeNode callback to change if the regex matches, by deleting the text and inserting a new node at that location but so far I've been unsuccessful.

Slate.js also has a nice set of examples but unfortunately haven't found any of them to demonstrate what I'm trying to do. What would be a good way to go about implementing this feature? Am I wrong to assume it's through using normalizeNode?

Filuren
  • 661
  • 2
  • 7
  • 19

1 Answers1

1

I solved this question when working on typed in emojis. For example, when a person typed :smile: we wanted the emoji to appear (a la Slack). The only differences with stock symbols and emojis would be the stock lookup and the usage of Transforms.insertNodes instead of Transforms.insertText.

The code below should be enough to help someone solve their use case. The key is startIndex and endIndex which targets the replacement.

Here's my solution:

editor.normalizeNode = entry => {
  const [node, path] = entry;

  if (!Text.isText(node)) {
   return normalizeNode([node, path]);
  }

  const emojiMatch = node.text.match(EMOJI_REGEX);

  if (!emojiMatch) {
    return normalizeNode([node, path]);
  }

  const [searchMatch, colonMatch] = emojiMatch;
  const { index: startIndex } = emojiMatch;
  const endIndex = startIndex + searchMatch.length;

  const [matchedEmoji] = emojiIndex.search(colonMatch).map(emoji => emoji) as BaseEmoji[];

  if (!matchedEmoji) {
    return normalizeNode([node, path]);
  }

  Transforms.insertText(editor, matchedEmoji.native, {
    at: {
      anchor: { path, offset: startIndex },
      focus: { path, offset: endIndex },
    }
  })

  normalizeNode([node, path]);
}
Brandon
  • 1,399
  • 4
  • 20
  • 37