Add copy button to published article code paragraph of anflext press

In anflext press used tiptap to edit article. After published html content, the code paragraph (pre tag of html) will normal display.

The code sometimes is needed to copy for use. Before you only select the code text and select copy by Ctrl+C or mouse right menu. Normal site will provide one copy button on code. And I want to implement the function.

After google, I find one article discus the issue: Inject Copy Button into Code Block Using MutationObserver in a React Application. After learned the code and idea. I use mantine UI CopyButton to perform the action. The code like bellow:

import { ActionIcon, CopyButton, MantineProvider, Tooltip, Typography } from "@mantine/core";
import { IconCheck, IconCopy } from '@tabler/icons-react';
import theme from './theme.js';

// Use the below article code and replace with CopyButton
// https://www.alexandru-barbulescu.com/posts/inject-copy-button-into-code-block-using-mutationobserver-in-a-react-application
const CopyButtonsInjector = () => {

  useEffect(() => {
    const pres = document.querySelectorAll('pre');

    pres.forEach(pre => {
      if (pre.querySelector('.copy-btn-wrapper')) return;
      if (!pre.textContent?.trim()) return;

      const wrapper = document.createElement('div');
      wrapper.className = 'copy-btn-wrapper';
      wrapper.style.position = 'absolute';
      wrapper.style.top = '0.1rem';
      wrapper.style.right = '0.5rem';
      wrapper.style.zIndex = '10';

      pre.style.position = 'relative';
      pre.appendChild(wrapper);

      const root = createRoot(wrapper);
      root.render(
        <MantineProvider theme={theme}>
        <CopyButton value={pre.textContent}>
          {({ copied, copy }) => (
            <Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position="right">
              <ActionIcon color={copied ? 'teal' : 'gray'} variant="subtle" onClick={copy}>
                {copied ? <IconCheck size={16} /> : <IconCopy size={16} />}
              </ActionIcon>
            </Tooltip>
          )}
        </CopyButton></MantineProvider>
      );
    });
  });

  return null;
};


export default function Article() {
// some other code
    return (
      <>
        <CopyButtonsInjector />
        <Typography dangerouslySetInnerHTML={{ __html: '<p>test only</p>' }} />
      </>
    );
}

Notice: the theme must be define. If not provide and you use the MantineProvider on parent component. The runtime error will stop render the copy button.

But in dark mode the code with different back group color to parent pre tag. So look like ugly:

So I check the default @mantine/core/styles.css and hack the two colors to same one:

// @mantine/core/styles.css:7678
// pills variant
  :where([data-mantine-color-scheme='dark']) .m_d08caa0 :where(pre) {
      background-color: var(--mantine-color-dark-8);
}

// Changed to

  :where([data-mantine-color-scheme='dark']) .m_d08caa0 :where(pre) {
      background-color: var(--mantine-color-dark-5);
}

The final result look like better:

35

Top articles