rehype-pretty / rehype-pretty-code

Beautiful code blocks for Markdown or MDX.
https://rehype-pretty.pages.dev
MIT License
1.01k stars 63 forks source link

Error: Expected onClick listener to be a function, instead got a value of string type. #235

Open Vallerian opened 1 month ago

Vallerian commented 1 month ago

I am encountering an error while using the rehype-pretty-code package in a Next.js project, specifically when utilizing the transformerCopyButton feature. The error message I receive is:

Error: Expected `onClick` listener to be a function, instead got a value of `string` type.

This error seems to occur when the transformerCopyButton attempts to render the copy button for code blocks. It appears that the onClick event listener is being assigned a string value instead of a function.

Next.js version: 14.2.5 rehype-pretty version: 0.13.2

next.config.mjs

import createMDX from '@next/mdx'
import remarkSlug from 'remark-slug'
import rehypePrettyCode from "rehype-pretty-code";
import remarkGfm from 'remark-gfm'
import remarkFrontmatter from 'remark-frontmatter'
import {transformerCopyButton} from "@rehype-pretty/transformers";

/** @type {import('next').NextConfig} */
const nextConfig = {
    pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
    reactStrictMode: false,
    compiler: {styledComponents: true}
}

const withMDX = createMDX({
    extension: /\.mdx?$/,
    options: {
        remarkPlugins: [
            [remarkFrontmatter],
            [remarkGfm],
            [remarkSlug],
        ],
        rehypePlugins: [
            [rehypePrettyCode, {
                theme: "github-dark-default",
                transformers: [
                    transformerCopyButton({
                        visibility: 'hover',
                        feedbackDuration: 2_000,
                    }),
                ]
            }],
        ],
    },
});

export default withMDX(nextConfig)
haris989 commented 1 month ago

Hi Vallerian, Getting the same error. Any luck?

Vallerian commented 1 month ago

Unfortunately, no, but if you find a way to extract the content of code blocks within React components using Rehype or Remark plugins, like remark-code-blocks, I'd be happy if you let me know.

o-az commented 3 weeks ago

unfortunately the copy button transformer currently doesn't work with Next.js unless you use a Server Component

Example implementation: https://github.com/rehype-pretty/rehype-pretty-code/blob/master/examples/next/src/app/code.tsx

demo: https://rehype-pretty-example-next.pages.dev/rsc

2wndrhs commented 1 day ago

You can easily add a custom pre component with a copy button.

import { Check, Clipboard } from 'lucide-react'; import { DetailedHTMLProps, HTMLAttributes, useRef, useState } from 'react';

export default function Pre({ children, ...props }: DetailedHTMLProps<HTMLAttributes, HTMLPreElement>) { const [isCopied, setIsCopied] = useState(false); const preRef = useRef(null);

const handleClickCopy = async () => { const code = preRef.current?.textContent;

if (code) {
  await navigator.clipboard.writeText(code);
  setIsCopied(true);

  setTimeout(() => {
    setIsCopied(false);
  }, 3000);
}

};

return ( <pre ref={preRef} {...props} className='relative'> <button disabled={isCopied} onClick={handleClickCopy} className='absolute right-4 size-6'

{isCopied ? : } {children} ); }


- `mdx-component.tsx` (if you are using @next/mdx)
```tsx
import type { MDXComponents } from 'mdx/types';
import Pre from './components/mdx/Pre';

export function useMDXComponents(components: MDXComponents): MDXComponents { return { pre: (props) => <Pre {...props} />, ...components, };



- Result
<img width="785" alt="image" src="https://github.com/user-attachments/assets/223d7549-516f-4b04-a71b-1ad11ad12e37">