Підсвічування коментарів

Функції JScript і стилізація CSS коментарів для блоків коду в статтях з темною темою. Реалізовано можливість копіювання множинних блоків коду на одній сторінці.

    Виокремлення коментарів

    Стилізація коментарів залежить від типу кодового блоку і визначається CSS-класами, що додаються.

    <style>
    	.html-comment { color: #607C3C; }	/* HTML коментарі */
    	.js-comment { color: #909090; }		/* JScript коментарі */
    	.css-comment { color: #B184BD; }	/* CSS коментарі */
    </style>
    

    Основний скрипт розбирає текст контейнера за допомогою регулярного виразу, розділяє коментарі за типом(HTML, CSS, JS) і огортає відповідними класами CSS для їх колоризаії.

    <script>
    // Функція підсвічування коментарів у контейнері
    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(/(<!--[\s\S]*?-->|\/\*[\s\S]*?\*\/|\/\/.*)/g);
    
    	parts.forEach(part => {
    		let span;
    		if (part.match(/^<!--[\s\S]*?-->$/)) {
    			span = document.createElement('span');
    			span.className = 'html-comment'; // HTML коментар
    		} else if (part.match(/^\/\*[\s\S]*?\*\/$/)) {
    			span = document.createElement('span');
    			span.className = 'css-comment'; // CSS багаторядковий коментар
    		} else if (part.match(/^\/\/.*/)) {
    			span = document.createElement('span');
    			span.className = 'js-comment'; // JS однорядковий коментар
    		}
    
    		if (span) {
    			span.textContent = part;
    			fragment.appendChild(span);
    		} else {
    			fragment.appendChild(document.createTextNode(part)); // Інший текст
    		}
    	});
    
    	container.innerHTML = ''; // Очищення контейнера перед вставкою
    	container.appendChild(fragment); // Додавання підсвіченого коду
    }
    
    // Ініціалізація підсвічування для всіх контейнерів з класом .code-container
    function setupHighlighting() {
    	document.querySelectorAll('.code-container').forEach(container => {
    		highlightComments(container);
    	});
    }
    
    // Виклик підсвічування під час завантаження сторінки
    window.addEventListener('load', setupHighlighting);
    </script>
    

    Для додавання властивостей підсвічування коментарів, слід лише прописати клас code-container у відповідних тегах. Варто нагадати ще раз: властивість розповсюджується на текст лише у межах наступного блоку, до якого прописаний клас.

    <pre class="code-container">
    	<!-- HTML коментарі -->
    	
    	// JScript коментарі
    	
    	/* CSS коментарі */
    </pre>
    

    Копіювання блоків коду

    Пропонються дві функції, які виконують одну й ту ж дію - копіювання в буфер обміну, але по-різному виконують це на сторінці в браузері. Перший спосіб є традиійним, з використанням кнопки копіювання тексту, а другий здійснює копіювання після кліку на відповідному блоці без відображення додаткових елементів.

    З допомогою кнопки

    У функції copyToClipboard використовується button.nextElementSibling для пошуку наступного елемента, який відповідає блоку тексту. Така прив'язка, яка не задіює id для ідентифікації елемента та виконується автоматично.

    <script>
    	/* Копіювання тексту в буфер обміну через кнопку */
    	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));
    	}
    </script>
    

    Для додавання в HTML, слід прописати клас class="copy-button" та локатор події onclick="copyToClipboard(this)" у тегах самої кнопки. Не слід забувати, що: властивість розповсюджується на текст лише у межах наступного блоку, до якого відноситься кнопка.

    <!-- Демо копіювання в HTML -->
    <button class="copy-button" onclick="copyToClipboard(this)">Копіювати</button>
    <pre>.. тут текст .. </pre>				
    

    З допомогою виділення

    У функції copyCode використовується element.parentElement для пошуку наступного елемента, який відповідає блоку тексту. Така прив'язка, яка не задіює id для ідентифікації елемента та виконується автоматично.

    <script>
    	/* Копіювання тексту в буфер обміну через виділення */
    	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));
    	}
    </script>				
    

    Для додавання в HTML, слід прописати клас class="code-container" та локатор події onclick="copyCode(this)" у відповідних тегах. Не слід забувати, що: властивість розповсюджується на текст лише у межах наступного блоку, до якого відноситься кнопка.

    <!-- Демо копіювання в HTML -->
    <pre class="code-container" style="cursor: pointer" title="Натисніть, щоб скопіювати" onclick="copyCode(this)">
    	.. тут текст .. 
    </pre>				
    

    Тепер, навівшись на блок з текстом, і зробивши на ньому лівий клік, отримаємо його вміст буфері обміну. Додатково, можна візалізувати дію додавши вказівник style="cursor: pointer" та спливаючу тайтл-підказку.

    Функція згортання/розгортання блоку

    Задля економії місця на сторінці - простий варіант незалежних блоків тексту, з використанням nextElementSibling для пошуку наступного.

    <script>
    		// Функція згортання/розгортання блоку
    		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));
    			});
    		});
    </script>
    

    Оформлення згортання/розгортання в HTML