About Us

[custom_chat_bubble]

<?php
/**
 * Enhance Gutenberg Code blocks:
 * - Copy icon with checkmark feedback
 * - Line numbers
 * - Mobile-friendly horizontal scroll
 * - Improved accessibility and selection
 */

function ewdt_enhance_code_blocks_with_copy() {
    if ( is_admin() ) {
        return;
    }

    // CSS
    $css = "
    /* General code block improvements */
    pre.wp-block-code {
        overflow-x: auto;
        white-space: pre;
        -webkit-overflow-scrolling: touch;
        position: relative;
        padding-right: 3em; /* room for copy icon */
    }

    pre.wp-block-code code {
        user-select: text;
        word-break: normal;
        white-space: pre;
        display: block;
    }

    /* Line number support */
    .wp-block-code.has-line-numbers {
        counter-reset: line;
        padding-left: 3em;
    }

    .wp-block-code.has-line-numbers code span {
        display: block;
        padding-left: 0.5em;
        position: relative;
    }

    .wp-block-code.has-line-numbers code span::before {
        counter-increment: line;
        content: counter(line);
        position: absolute;
        left: -2.5em;
        color: #999;
        font-size: 0.85em;
        text-align: right;
        width: 2em;
    }

    /* Copy button styles */
    .code-copy-btn {
        position: absolute;
        top: 8px;
        right: 8px;
        background: transparent;
        border: none;
        cursor: pointer;
        padding: 4px;
        opacity: 0.6;
        transition: opacity 0.3s ease;
        z-index: 20;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .code-copy-btn:hover {
        opacity: 1;
    }

    .code-copy-btn svg {
        width: 18px;
        height: 18px;
        fill: #0073aa;
        transition: fill 0.3s ease;
    }

    .code-copy-tooltip {
        position: absolute;
        top: -28px;
        right: 0;
        background: #0073aa;
        color: #fff;
        padding: 4px 8px;
        border-radius: 3px;
        font-size: 11px;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.3s ease;
        white-space: nowrap;
    }

    .code-copy-tooltip.show {
        opacity: 1;
        pointer-events: auto;
    }
    ";

    // JavaScript
    $js = <<<JS
    document.addEventListener('DOMContentLoaded', function () {
        const clipboardSVG = `
            <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
                <path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
            </svg>`;
        const checkmarkSVG = `
            <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
                <path d="M9 16.2l-3.5-3.5-1.4 1.4L9 19 20.5 7.5l-1.4-1.4z"/>
            </svg>`;

        const codeBlocks = document.querySelectorAll('pre.wp-block-code code');

        codeBlocks.forEach(code => {
            const pre = code.closest('pre.wp-block-code');

            // Line numbering
            const lines = code.textContent.split('\\n');
            const newHTML = lines.map(line => {
                const span = document.createElement('span');
                span.textContent = line || '\\u00A0'; // visible empty lines
                return span.outerHTML;
            }).join('');
            pre.classList.add('has-line-numbers');
            code.innerHTML = newHTML;

            // Copy button and tooltip
            const button = document.createElement('button');
            button.className = 'code-copy-btn';
            button.type = 'button';
            button.setAttribute('aria-label', 'Copy code to clipboard');
            button.innerHTML = clipboardSVG;

            const tooltip = document.createElement('span');
            tooltip.className = 'code-copy-tooltip';
            tooltip.innerText = 'Copied!';

            pre.appendChild(button);
            pre.appendChild(tooltip);

            button.addEventListener('click', function () {
                const rawText = Array.from(code.querySelectorAll('span')).map(span => span.textContent).join('\\n');
                navigator.clipboard.writeText(rawText).then(function () {
                    button.innerHTML = checkmarkSVG;
                    tooltip.classList.add('show');
                    setTimeout(() => {
                        button.innerHTML = clipboardSVG;
                        tooltip.classList.remove('show');
                    }, 2000);
                }).catch(function (err) {
                    console.error('Copy failed: ', err);
                });
            });
        });
    });
JS;

    wp_add_inline_style( 'wp-block-library', $css );
    wp_add_inline_script( 'jquery-core', $js );
}
add_action( 'wp_enqueue_scripts', 'ewdt_enhance_code_blocks_with_copy' );

some text

Regular paragraph.