Функції JScript
і стилізація CSS
коментарів для блоків коду в статтях з темною темою.
Реалізовано можливість копіювання множинних блоків коду на одній сторінці.
Стилізація коментарів залежить від типу кодового блоку і визначається CSS-класами, що додаються.
/* Основні стилі для контейнера з кодом*/ .code-container { font-family: "Fira Code", monospace; background-color: #2d2d2d; color: #ccc; padding: 10px; border-radius: 5px; white-space: pre-wrap; overflow-x: auto; } .html-comment { color: #6a9955; font-style: italic; } .css-comment { color: #6bbc45; font-style: italic; } .js-comment { color: #808080; font-style: italic; } .hash-comment { color: #b5cea8; font-style: italic; } .brace { color: #6bbc45; font-weight: bold; }
Основний скрипт розбирає текст контейнера за допомогою регулярного виразу, розділяє коментарі за типом (HTML, CSS, JS) і огортає відповідними класами CSS для їх колоризації.
function highlightComments(container) { if (container.classList.contains('highlighted')) return; container.classList.add('highlighted'); const code = container.textContent; const fragment = document.createDocumentFragment(); // Регулярний вираз const parts = code.split( /(https?:\/\/[^\s]+|<!--[\s\S]*?-->|\/\*[\s\S]*?\*\/|\/\/.*$|(^|\s)#(?![a-fA-F0-9]{3,6}\b).*|[{}])/gm ).filter(Boolean); parts.forEach(part => { const span = document.createElement('span'); let matched = false; if (/^https?:\/\/[^\s]+$/.test(part)) { span.className = 'url'; } else if (/^<!--[\s\S]*?-->$/.test(part)) { span.className = 'html-comment'; } else if (/^\/\*[\s\S]*?\*\/$/.test(part)) { span.className = 'css-comment'; } else if (/^\/\/.*$/.test(part)) { span.className = 'js-comment'; } else if (/^(\s*)#(?![a-fA-F0-9]{3,6}\b).*$/.test(part)) { // # коментар тільки якщо не перед кольором span.className = 'hash-comment'; } else if (/^[{}]$/.test(part)) { span.className = 'brace'; } else { span.textContent = part; fragment.appendChild(span); return; } span.textContent = part; fragment.appendChild(span); }); container.innerHTML = ''; container.appendChild(fragment); } // Ініціалізація підсвічування для всіх контейнерів з класом .code-container function setupHighlighting() { document.querySelectorAll('.code-container').forEach(container => { highlightComments(container); }); } // Виклик підсвічування під час завантаження сторінки window.addEventListener('load', setupHighlighting);
Для додавання властивостей підсвічування коментарів, слід лише прописати клас code-container
у відповідних тегах. Варто нагадати ще раз: властивість розповсюджується на текст лише у межах наступного блоку, до якого прописаний клас.
<pre class="code-container"> <!-- HTML .html-comment --> /* CSS .css-comment */ // JS .js-comment # Hash .hash-comment $100 {...} </pre>
Пропонуються дві функції, які виконують одну й ту ж дію - копіювання в буфер обміну, але по-різному виконують це на сторінці в браузері. Перший спосіб є традиійним, з використанням кнопки копіювання тексту, а другий здійснює копіювання після кліку на відповідному блоці без відображення додаткових елементів.
У функції copyToClipboard
використовується button.nextElementSibling
для пошуку наступного елемента, який відповідає блоку тексту. Така прив'язка, яка не задіює id
для ідентифікації елемента та виконується автоматично.
// Копіювання тексту в буфер обміну через кнопку function copyToClipboard(button) { const container = button.nextElementSibling; // Знаходження наступного блоку коду const code = container.textContent; // Створення виділення для копіювання const range = document.createRange(); range.selectNodeContents(container); const selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); navigator.clipboard.writeText(code) // Копіювання тексту .then(() => { alert('Код успішно скопійовано в буфер обміну!'); setTimeout(() => selection.removeAllRanges(), 500); // Скинути виділення }) .catch(err => console.error('Помилка копіювання:', err)); }
Для додавання в HTML, слід прописати клас class="copy-button"
та локатор події onclick="copyToClipboard(this)"
у тегах самої кнопки. Не слід забувати, що: властивість розповсюджується на текст лише у межах наступного блоку, до якого відноситься кнопка.
<!-- Демо копіювання в HTML --> <button class="copy-button" onclick="copyToClipboard(this)">Копіювати</button> <pre>.. тут текст .. </pre>
У функції copyCode
використовується element.parentElement
для пошуку наступного елемента, який відповідає блоку тексту. Така прив'язка, яка не задіює id
для ідентифікації елемента та виконується автоматично.
// Копіювання тексту в буфер обміну через виділення function copyCode(element) { const codeContainer = element.parentElement; // Знайти батьківський тег const code = codeContainer.textContent.trim(); // Виділення тексту const range = document.createRange(); range.selectNodeContents(codeContainer); const selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); // Копіювання тексту navigator.clipboard.writeText(code) .then(() => { alert('Код успішно скопійовано в буфер обміну!'); setTimeout(() => selection.removeAllRanges(), 500); // Скинути виділення }) .catch(err => console.error('Помилка копіювання:', err)); }
Для додавання в HTML, слід прописати клас class="code-container"
та локатор події onclick="copyCode(this)"
у відповідних тегах. Не слід забувати, що: властивість розповсюджується на текст лише у межах наступного блоку, до якого відноситься кнопка.
<!-- Демо копіювання в HTML --> <pre class="code-container" style="cursor: pointer" title="Натисніть, щоб скопіювати" onclick="copyCode(this)"> .. тут текст .. </pre>
Тепер, навівшись на блок з текстом, і зробивши на ньому лівий клік, отримаємо його вміст буфері обміну. Додатково, можна візалізувати дію додавши вказівник style="cursor: pointer"
та спливаючу тайтл-підказку.
Задля економії місця на сторінці - простий варіант незалежних блоків тексту, з використанням nextElementSibling
для пошуку наступного.
// Функція згортання/розгортання блоку function togglePre(button) { const wrapper = button.nextElementSibling; // Відповідний контейнер const isHidden = wrapper.style.display === 'none'; wrapper.style.display = isHidden ? 'block' : 'none'; // Перемикання видимості button.textContent = isHidden ? 'Сховати демо' : 'Показати демо'; } // Додавання обробників подій для кнопок згортання/розгортання window.addEventListener('load', function () { document.querySelectorAll('.toggle-button').forEach(button => { button.addEventListener('click', () => togglePre(button)); }); });