# code-block-pro/1.13.0/src/front/front.js

Code Block Pro – Beautiful Syntax Highlighting, version 1.13.0. 169 lines.

- Page: https://pluginprobe.com/plugins/code-block-pro/1.13.0/code/src/front/front.js
- Raw: https://pluginprobe.com/plugins/code-block-pro/1.13.0/raw/src/front/front.js
- Modified: 2023-02-06T00:28:04+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/code-block-pro/1.13.0/code/src/front/front.js#L10-L20`.

```javascript
import copy from 'copy-to-clipboard';

const containerClass = '.wp-block-kevinbatdorf-code-block-pro';

const handleCopyButton = () => {
    const buttons = Array.from(
        document.querySelectorAll(
            '.code-block-pro-copy-button:not(.cbp-cb-loaded)',
        ),
    );
    buttons.forEach((button) => {
        button.classList.add('cbp-cb-loaded');
        // Setting it to block here lets users deactivate the plugin safely
        button.style.display = 'block';
        button.addEventListener('click', (event) => {
            const b = event.target?.closest('span');
            copy(b?.dataset?.code ?? '', {
                format: 'text/plain',
            });
            b.classList.add('copying');
            setTimeout(() => {
                b.classList.remove('copying');
            }, 2000);
        });
    });
};

const handleHighlighter = () => {
    const codeBlocks = Array.from(
        document.querySelectorAll(`${containerClass} pre:not(.cbp-hl-loaded)`),
    );

    codeBlocks.forEach((codeBlock) => {
        codeBlock.classList.add('cbp-hl-loaded');
        // Search for highlights
        const highlighters = codeBlock.querySelectorAll('.cbp-line-highlight');
        if (!highlighters.length) return;

        // We need to track the block width so we can adjust the
        // highlighter width in case of overflow
        const resizeObserver = new ResizeObserver((entries) => {
            entries.forEach((entry) => {
                // get width of inner code block
                codeBlock.style.setProperty('--cbp-block-width', '0');
                const codeWidth =
                    entry.target.querySelector('code').offsetWidth;
                const computed =
                    codeWidth + 16 === entry.target.scrollWidth
                        ? codeWidth + 16
                        : entry.target.scrollWidth + 16;
                codeBlock.style.setProperty(
                    '--cbp-block-width',
                    `${computed}px`,
                );
            });
        });
        resizeObserver.observe(codeBlock);

        // add the highlighter
        highlighters.forEach((highlighter) => {
            highlighter.insertAdjacentHTML(
                'beforeend',
                '<span aria-hidden="true" class="cbp-line-highlighter"></span>',
            );
        });
    });
};

const handleFontLoading = () => {
    if (!window.codeBlockPro?.pluginUrl) return;
    const elements = Array.from(
        document.querySelectorAll(
            '[data-code-block-pro-font-family]:not(.cbp-ff-loaded)',
        ) || [],
    );
    elements.forEach((e) => e.classList.add('cbp-ff-loaded'));
    const fontsToLoad = new Set(
        elements.map((f) => f.dataset.codeBlockProFontFamily).filter(Boolean),
    );
    [...fontsToLoad].forEach(async (fontName) => {
        const font = new FontFace(
            fontName,
            `url(${window.codeBlockPro.pluginUrl}/build/fonts/${fontName}.woff2)`,
        );
        await font.load();
        document.fonts.add(font);
    });
};

const handleSeeMore = () => {
    const seeMoreLines = Array.from(
        document.querySelectorAll(
            `${containerClass}:not(.cbp-see-more-loaded) .cbp-see-more-line`,
        ),
    );
    seeMoreLines.forEach((line) => {
        const currentContainer = line.closest(containerClass);
        currentContainer.classList.add('cbp-see-more-loaded');
        const pre = line.closest('pre');
        const initialHeight = pre.offsetHeight;
        let animationSpeed = 0;

        if (line.classList.contains('cbp-see-more-transition')) {
            const lineCount = pre.querySelectorAll('code > *').length;
            const linesBeforeCurrent = Array.from(
                line.closest('code').children,
            ).filter((l) => l.offsetTop < line.offsetTop)?.length;
            animationSpeed = 0.5 + (lineCount - linesBeforeCurrent) * 0.01;
            pre.style.transition = `max-height ${animationSpeed}s ease-out`;
        }

        // if the first child it a span then get the height of that span
        const headerHeight =
            currentContainer.children[0].tagName === 'SPAN'
                ? currentContainer.children[0].offsetHeight
                : 0;
        const lineHeight = parseFloat(window.getComputedStyle(line).lineHeight);
        pre.style.maxHeight = `${line.offsetTop + lineHeight - headerHeight}px`;

        const buttonContainer = line
            .closest(containerClass)
            .querySelector('.cbp-see-more-container');
        if (!buttonContainer) return;
        buttonContainer.style.display = 'flex';
        const button = buttonContainer.querySelector(
            '.cbp-see-more-simple-btn',
        );
        if (!button) return;
        if (currentContainer.classList.contains('padding-disabled')) {
            button.classList.remove('cbp-see-more-simple-btn-hover');
        }
        button.style.transition = `all ${
            Math.max(animationSpeed, 1) / 1.5
        }s linear`;

        const handle = (event) => {
            event.preventDefault();
            button.classList.remove('cbp-see-more-simple-btn-hover');
            pre.style.maxHeight = initialHeight + 'px';
            setTimeout(() => {
                button.style.opacity = 0;
                button.style.transform = 'translateY(-100%)';
                setTimeout(
                    () => button.remove(),
                    Math.max(animationSpeed, 1) * 1000,
                );
            }, animationSpeed * 1000);
        };
        button.addEventListener('click', handle);
        button.addEventListener('keypress', (event) => {
            if (event.key === 'Enter') handle(event);
        });
    });
};

const init = () => {
    handleSeeMore();
    handleCopyButton();
    handleHighlighter();
    handleFontLoading();
};

// Functions are idempotent, so we can run them on load and DOMContentLoaded
init();
// Useful for when the DOM is modified or loaded in late
window.codeBlockProInit = init;
window.addEventListener('DOMContentLoaded', init);
window.addEventListener('load', init);

```
