maxeth / react-type-animation

A React typewriter animation based on typical with extended functionality and customization.
https://react-type-animation.netlify.app/
MIT License
352 stars 26 forks source link

Support code syntax highlighter #52

Open aakrem opened 4 months ago

aakrem commented 4 months ago

Great library! As you support similar feature like chatgpt I was wondering if we can also support a code syntax highlighter when the text is code.

Tried to make it working with the syntax-highlighter but unfortunately it's not something doable.

Any hints how to do this?

maxeth commented 4 months ago

I'm not familiar with that package, but from what it seems it expects a raw string, and not a HTML element.

import SyntaxHighlighter from 'react-syntax-highlighter';
import { docco } from 'react-syntax-highlighter/dist/esm/styles/hljs';
const Component = () => {
  const codeString = '(num) => num + 1';
  return (
    <SyntaxHighlighter language="javascript" style={docco}>
      {codeString}
    </SyntaxHighlighter>
  );
};

The <TypeAnimation /> component, however, renders a HTML node and continuously updates its text content, so I assume it's not possible to get this working because you'd break the animation if you were to alter the rendered element in any way.

Unless you only type out stuff once and then fully remount the animation. In that case you could get it working by constantly monitoring the typed out content for a code snippet via the MutationObserver API for example, and then splitting the typed out animation text by that code snipped and injecting that <SyntaxHighlighter/> component with that given code snippet between the two rendered animation text snippets, like this.

Document before

<span>
A B C [someCodeSnippet] D E F
</span>

Document after:

<span>
<span> A B C </span>
<SyntaxHighlighter>
[someCodeSnippet]
</SyntaxHighlighter>
<span> D E F </span>
</span>

But keep in mind that only the <span> D E F </span> part would be the actual <TypeAnimation/> component, so after the animation finishes, you'd have to manually unmount the <span> A B C </span> in this case.

I know it's super hacky 😐


As an alternative, maybe you could use something like a React markdown renderer/formatter, and make your type animation type the code in markdown format, like this:

" ``` [code here] ``` "

You could then pass a React ref to the <TypeAnimation/> component, make it hidden and manually render its inner text in formatted Markdown, accessed via ref.current?.innerText.

const innerText = someRef.current?.innerText;

<>
<div style={{display:"none"}}>
<TypeAnimation ref={someRef}/>
</div>

<Markdown>
{innerText}
</Markdown/>
</>

Now innerText won't be responsive, so, again, you'd need something like the MutationObserver API.

I know this is far from optimal. Really need to add an animation hook that exports a responsive string of the rendered text...

AbianS commented 3 days ago

What is the current status of this issue?