/** * AKSRT Code Block Enhancements * * Integrates EnlighterJS for syntax highlighting and adds * copy-to-clipboard buttons and language labels to code blocks. * No jQuery dependency — pure vanilla JS. * * @package AKSRT */ (function () { 'use strict'; var BASE_URI = (window.aksrtData && window.aksrtData.themeUri) || ''; var STYLE_ID = 'aksrt-enlighter-css'; var ENLIGHTER_LOADED = false; function getHighlightSettings() { return (window.aksrtData && window.aksrtData.codeHighlight) || {}; } function isDarkTheme(value) { if (typeof value === 'boolean') return value; return document.documentElement.classList.contains('dark') || document.documentElement.getAttribute('data-theme') === 'dark'; } function getThemeName(isDark) { var settings = getHighlightSettings(); return isDarkTheme(isDark) ? (settings.darkTheme || 'monokai') : (settings.lightTheme || 'enlighter'); } function applyEnlighterTheme(isDark) { var settings = getHighlightSettings(); if (settings.enabled === false) return; var theme = getThemeName(isDark); document.querySelectorAll('.enlighter-default').forEach(function (el) { el.className = el.className.replace(/\benlighter-t-[\w-]+\b/g, '').replace(/\s+/g, ' ').trim(); el.classList.add('enlighter-t-' + theme); }); } window.AksrtPrecodeApplyTheme = applyEnlighterTheme; // ── Copy Button Styles ── var COPY_STYLE_ID = 'aksrt-precode-style'; function injectCopyStyle() { if (document.getElementById(COPY_STYLE_ID)) return; var style = document.createElement('style'); style.id = COPY_STYLE_ID; style.textContent = '.aksrt-code-copy{position:absolute;top:6px;right:8px;border:none;background:rgba(255,255,255,0.08);color:#a6adc8;cursor:pointer;padding:3px 10px;border-radius:6px;font-size:12px;z-index:10;transition:all 0.2s;backdrop-filter:blur(4px);}' + '.aksrt-code-copy:hover{background:rgba(255,255,255,0.15);color:#cdd6f4;}' + '.aksrt-code-copy.is-copied{color:#a6e3a1;}' + '.enlighter-default{position:relative;}' + '.enlighter-default .aksrt-code-copy{top:4px;right:4px;}' + 'pre{position:relative;}' + 'pre .aksrt-code-copy{top:8px;right:8px;}'; document.head.appendChild(style); } // ── EnlighterJS CSS Injection ── function injectEnlighterCSS() { if (document.getElementById(STYLE_ID)) return; var link = document.createElement('link'); link.id = STYLE_ID; link.rel = 'stylesheet'; link.href = BASE_URI + '/assets/js/enlighter/enlighterjs.min.css'; document.head.appendChild(link); } // ── EnlighterJS Loader ── function loadEnlighterJS(callback) { if (ENLIGHTER_LOADED && window.EnlighterJS) { callback(); return; } injectEnlighterCSS(); var script = document.createElement('script'); script.src = BASE_URI + '/assets/js/enlighter/enlighterjs.min.js'; script.onload = function () { ENLIGHTER_LOADED = true; callback(); }; script.onerror = function () { // Fallback: just add copy buttons without highlighting addCopyButtonsPlain(); }; document.head.appendChild(script); } // ── Copy to Clipboard ── function copyToClipboard(text, btn) { if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).then(function () { showCopied(btn); }); } else { var ta = document.createElement('textarea'); ta.value = text; ta.style.cssText = 'position:fixed;left:-9999px;'; document.body.appendChild(ta); ta.select(); try { document.execCommand('copy'); showCopied(btn); } catch (e) { /* ignore */ } document.body.removeChild(ta); } } function showCopied(btn) { btn.textContent = '已复制'; btn.classList.add('is-copied'); setTimeout(function () { btn.textContent = '复制'; btn.classList.remove('is-copied'); }, 1500); } function createCopyButton(text) { var btn = document.createElement('button'); btn.className = 'aksrt-code-copy'; btn.textContent = '复制'; btn.type = 'button'; btn.addEventListener('click', function () { copyToClipboard(text, btn); }); return btn; } // ── EnlighterJS Integration ── function initEnlighter() { if (!window.EnlighterJS) return; // Get settings from aksrtData or use defaults var settings = getHighlightSettings(); if (settings.enabled === false) return; // 后台关闭代码高亮 var lineNumbers = settings.lineNumbers === true; var showButtons = settings.showButtons !== false; var maxHeight = settings.maxHeight || 400; var currentTheme = getThemeName(); // Find all code blocks that haven't been processed var blocks = document.querySelectorAll('pre > code:not(.enlighter-origin)'); if (blocks.length === 0) return; // Process each block blocks.forEach(function (code) { var pre = code.parentElement; if (!pre || pre.dataset.aksrtEnhanced) return; // Get raw text before EnlighterJS processes it var rawText = code.textContent; // Apply EnlighterJS try { EnlighterJS.enlight(code, { theme: currentTheme, linenumbers: lineNumbers, indent: 2, textOverflow: 'scroll', rawcodeDbclick: true, rawButton: showButtons, infoButton: showButtons, windowButton: showButtons }); } catch (e) { // If EnlighterJS fails, keep the plain block } // Add copy button after EnlighterJS processing var container = pre.querySelector('.enlighter-default') || pre; container.appendChild(createCopyButton(rawText)); pre.dataset.aksrtEnhanced = '1'; // Apply max-height if (maxHeight > 0) { pre.style.maxHeight = maxHeight + 'px'; pre.style.overflow = 'auto'; } }); applyEnlighterTheme(); } // ── Fallback: Plain code blocks with copy buttons ── function addCopyButtonsPlain() { var blocks = document.querySelectorAll('pre > code'); blocks.forEach(function (code) { var pre = code.parentElement; if (!pre || pre.dataset.aksrtEnhanced) return; pre.style.position = 'relative'; pre.appendChild(createCopyButton(code.textContent)); pre.dataset.aksrtEnhanced = '1'; }); } // ── Main Init ── function init() { injectCopyStyle(); // Check if there are any code blocks on the page var blocks = document.querySelectorAll('pre > code'); if (blocks.length === 0) return; // Load EnlighterJS and initialize loadEnlighterJS(initEnlighter); } window.AksrtFrontend.register('aksrt-precode', function () { init(); }); })();