webpack.js.org icon indicating copy to clipboard operation
webpack.js.org copied to clipboard

Add copy button for code blocks

Open TusharThakur04 opened this issue 1 year ago • 7 comments

  • This feature will add a copy button on every code block in the documentation.
  • It will help readers to easily copy and test the code.

TusharThakur04 avatar Dec 31 '24 16:12 TusharThakur04

@snitin315 Could you please assign this issue to me.

TusharThakur04 avatar Dec 31 '24 16:12 TusharThakur04

@alexander-akait could you help me getting through this issue. So far i have created an copybutton component , integrated it with pre tag and replaced pre element with the integrated one using mdxProvider. But its not working

import { useState } from 'react';
import PropTypes from 'prop-types';

function CopyButton({ text }) {
  const [copied, setCopied] = useState(false);

  const handleCopy = () => {
    navigator.clipboard.writeText(text).then(() => {
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    });
  };

  const buttonStyle = {
    position: 'absolute',
    top: '0.5rem',
    right: '0.5rem',
    backgroundColor: '#e5e7eb',
    fontSize: '0.875rem',
    padding: '0.25rem 0.5rem',
    borderRadius: '0.25rem',
    cursor: 'pointer',
    transition: 'background-color 0.3s ease',
  };

  const handleMouseOver = (e) => {
    e.target.style.backgroundColor = '#d1d5db';
  };

  const handleMouseOut = (e) => {
    e.target.style.backgroundColor = '#e5e7eb';
  };

  return (
    <button
      className="copy-button"
      style={buttonStyle}
      onClick={handleCopy}
      onMouseOver={handleMouseOver}
      onMouseOut={handleMouseOut}
    >
      {copied ? 'Copied!' : 'Copy'}
    </button>
  );
}
CopyButton.propTypes = {
  text: PropTypes.string.isRequired,
};

//integrating the CopyButton component into the CodeBlock component

export default function CodeBlock({ children }) {
  const codeText = children?.props?.children?.toString() || '';

  return (
    <div style={{ position: 'relative',}}>
      <CopyButton text={codeText} />
      <pre>{children}</pre>
    </div>
  );
}

CodeBlock.propTypes = {
  children: PropTypes.node.isRequired,
};

Code added into page.jsx:

// Import External Dependencies
import { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { useLocation } from 'react-router-dom';
import { MDXProvider } from '@mdx-js/react';

// Import Components
import PageLinks from '../PageLinks/PageLinks';
import Markdown from '../Markdown/Markdown';
import Contributors from '../Contributors/Contributors';
import { PlaceholderString } from '../Placeholder/Placeholder';
import AdjacentPages from './AdjacentPages';
import CodeBlock from '../CodeBlock/CodeBlock';

// Load Styling
import './Page.scss';
import Link from '../Link/Link';


//  **change**
const components = { pre: CodeBlock };


export default function Page(props) {
  const {
    title,
    contributors = [],
    related = [],........  rest of code 
.......

 <Markdown>
        <h1>{title}</h1>

        {rest.thirdParty ? (
          <div className="italic my-[20px]">
            <strong className="font-bold">Disclaimer:</strong> {title} is a
            third-party package maintained by community members, it potentially
            does not have the same support, security policy or license as
            webpack, and it is not maintained by webpack.
          </div>
        ) : null}

// **change** 

        <MDXProvider components={components}>
          <div id="md-content">{contentRender}</div>
        </MDXProvider>

        {loadRelated && (
          <div className="print:hidden">......... code continues



TusharThakur04 avatar Jan 17 '25 19:01 TusharThakur04

@TusharThakur04 Yeash, it will be useful, do you want to send a PR? I am glad to review them

alexander-akait avatar Feb 04 '25 16:02 alexander-akait

It is hard to say what it wrong, if you send a PR and can loop deeply on this

alexander-akait avatar Feb 04 '25 16:02 alexander-akait

@evenstensberg i am done with creating a custom component which renders a copy button inside button , the only problem i am facing is passing of components inside the imported mdx document , i.e. <Content components = {components}/>. But in this code base there is no direct import of mdx which is making me stuck on where to pass the custom component.

Page.jsx Image

this is how its rendering the mdx document.

TusharThakur04 avatar Feb 21 '25 16:02 TusharThakur04

I am willing to send a PR

swastikCommits avatar Mar 01 '25 07:03 swastikCommits

Send a PR if you want 👍🏾

evenstensberg avatar Oct 11 '25 16:10 evenstensberg