79085997

Date: 2024-10-14 11:39:43
Score: 1.5
Natty:
Report link

For anyone having the same problem: Following is a function that will set highlight format on any matching node with the words array that you have. call this inside a useEffect hook. you can provide the words as array of strings. you can change the style for highlighted text with your CSS outside of the javascript.

 const highlightWords = () => {
      editor.update(() => {
        const root = $getRoot()
        const textNodes: TextNode[] = []

        // Traverse all nodes to find text nodes
        root.getChildren().forEach((node) => {
          if ($isTextNode(node)) {
            textNodes.push(node)
          } else if ($isElementNode(node)) {
            node.getChildren().forEach((child) => {
              if ($isTextNode(child)) {
                textNodes.push(child)
              }
            })
          }
        })

        // Process each text node
        textNodes.forEach((textNode) => {
          let text = textNode.getTextContent()
          let newNodes: TextNode[] = []
          let lastIndex = 0

          words.forEach((word) => {
            const regex = new RegExp(`\\b${word}\\b`, 'gi')
            let match

            while ((match = regex.exec(text)) !== null) {
              const start = match.index
              const end = start + word.length

              // Add text before the match
              if (start > lastIndex) {
                newNodes.push($createTextNode(text.slice(lastIndex, start)))
              }

              // Add highlighted text
              const highlightedNode = $createTextNode(text.slice(start, end))
              highlightedNode.setFormat('highlight')
              newNodes.push(highlightedNode)

              lastIndex = end
            }
          })

          // Add remaining text
          if (lastIndex < text.length) {
            newNodes.push($createTextNode(text.slice(lastIndex)))
          }

          // Replace the original node with new nodes
          if (newNodes.length > 0) {
            textNode.replace(newNodes[0])
            for (let i = 1; i < newNodes.length; i++) {
              newNodes[i - 1].insertAfter(newNodes[i])
            }
          }
        })
      })
    }

What is does is that checks for all matching nodes and goes inside a loop one by one of the nodes and checks the text of the node with the word you are looking for.

Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • Me too answer (2.5): having the same problem
  • Low reputation (0.5):
Posted by: Reza