highlightjs-copy icon indicating copy to clipboard operation
highlightjs-copy copied to clipboard

TypeScript Support

Open jdgamble555 opened this issue 2 years ago • 6 comments

Please add TypeScript types!

This seems awesome, but unusable for me without types.

Thanks for writing this!

J

jdgamble555 avatar Nov 27 '22 17:11 jdgamble555

This would be the declaration module (theoretically), but you need to have a default export:

declare module 'highlightjs-copy' {
    class CopyButtonPlugin {
        constructor(options?: { hook?: Function, callback?: Function });
    };
    export = CopyButtonPlugin;
}

J

jdgamble555 avatar Nov 27 '22 17:11 jdgamble555

Ok, here is full TypeScript version, please add to repo :)

/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/ban-types */
/**
 *  @file highlight-copy.js
 *  @author Arron Hunt <[email protected]>
 *  @copyright Copyright 2021. All rights reserved.
 */

/**
 * Adds a copy button to highlightjs code blocks
 */
export class CopyButtonPlugin {

    hook!: Function | undefined;
    callback!: Function | undefined;

    /**
     * Create a new CopyButtonPlugin class instance
     * @param {Object} [options] - Functions that will be called when a copy event fires
     * @param {CopyCallback} [options.callback]
     * @param {Hook} [options.hook]
     */
    constructor({ hook, callback }: { hook?: Function | undefined, callback?: Function | undefined } = {}) {
        this.hook = hook;
        this.callback = callback;
    }
    "after:highlightElement"({ el, text }: { el: Element, text: string }) {
        // Create the copy button and append it to the codeblock.
        const button = Object.assign(document.createElement("button"), {
            innerHTML: "Copy",
            className: "hljs-copy-button",
        });
        button.dataset.copied = 'false';
        el.parentElement!.classList.add("hljs-copy-wrapper");
        el.parentElement!.appendChild(button);

        // Add a custom proprety to the code block so that the copy button can reference and match its background-color value.
        el.parentElement!.style.setProperty(
            "--hljs-theme-background",
            window.getComputedStyle(el).backgroundColor
        );

        const hook = this.hook;
        const callback = this.callback;

        button.onclick = function () {
            if (!navigator.clipboard) return;

            let newText = text;
            if (hook && typeof hook === "function") {
                newText = hook(text, el) || text;
            }

            navigator.clipboard
                .writeText(newText)
                .then(function () {
                    
                    button.innerHTML = "Copied!";
                    button.dataset.copied = 'true';
                    

                    let alert: HTMLDivElement | null = Object.assign(document.createElement("div"), {
                        role: "status",
                        className: "hljs-copy-alert",
                        innerHTML: "Copied to clipboard",
                    });
                    el.parentElement!.appendChild(alert);

                    setTimeout(() => {
                        if (alert) {
                            button.innerHTML = "Copy";
                            button.dataset.copied = "false";
                            el.parentElement!.removeChild(alert);
                            alert = null;
                        }
                    }, 2000);
                })
                .then(function () {
                    if (typeof callback === "function") return callback(newText, el);
                });
        };
    }
}

/**
 * @typedef {function} CopyCallback
 * @param {string} text - The raw text copied to the clipboard.
 * @param {HTMLElement} el - The code block element that was copied from.
 * @returns {undefined}
 */
/**
 * @typedef {function} Hook
 * @param {string} text - The raw text copied to the clipboard.
 * @param {HTMLElement} el - The code block element that was copied from.
 * @returns {string|undefined}
 */

J

jdgamble555 avatar Nov 27 '22 18:11 jdgamble555

Hey @jdgamble555, please open a PR with your code changes :)

arronhunt avatar Dec 06 '22 18:12 arronhunt

You would need to add TS Support in the package.

J

jdgamble555 avatar Dec 06 '22 20:12 jdgamble555

@jdgamble555 for now I guess you can add to https://github.com/DefinitelyTyped/DefinitelyTyped

thdoan avatar Oct 30 '23 02:10 thdoan

I created PR for TS support #25

I publish this in npm.

github: https://github.com/marucjmar/highlightjs-copy npm package: highlightjs-copy-ts

marucjmar avatar Dec 29 '23 16:12 marucjmar