diff --git a/blog.config.js b/blog.config.js index 24c2a049cf2..755b4d6b711 100644 --- a/blog.config.js +++ b/blog.config.js @@ -24,6 +24,8 @@ const BLOG = { BEI_AN_LINK: process.env.NEXT_PUBLIC_BEI_AN_LINK || 'https://beian.miit.gov.cn/', // 备案查询链接,如果用了萌备等备案请在这里填写 BEI_AN_GONGAN: process.env.NEXT_PUBLIC_BEI_AN_GONGAN || '', // 公安备案号,例如 '浙公网安备3xxxxxxxx8号' + CODE_COLLAPSE_MIN_LINES: 30,//“长代码”阈值 + // RSS订阅 ENABLE_RSS: process.env.NEXT_PUBLIC_ENABLE_RSS || true, // 是否开启RSS订阅功能 @@ -71,4 +73,4 @@ const BLOG = { UUID_REDIRECT: process.env.UUID_REDIRECT || false } -module.exports = BLOG \ No newline at end of file +module.exports = BLOG diff --git a/components/PrismMac.js b/components/PrismMac.js index a0aff890233..2b8d422b33e 100644 --- a/components/PrismMac.js +++ b/components/PrismMac.js @@ -108,30 +108,50 @@ const renderCollapseCode = (codeCollapse, codeCollapseExpandDefault) => { if (!codeCollapse) { return } + + const COLLAPSE_MIN_LINES = Number(siteConfig('CODE_COLLAPSE_MIN_LINES', 18)) const codeBlocks = document.querySelectorAll('.code-toolbar') + for (const codeBlock of codeBlocks) { - // 判断当前元素是否被包裹 if (codeBlock.closest('.collapse-wrapper')) { - continue // 如果被包裹了,跳过当前循环 + continue } const code = codeBlock.querySelector('code') - const language = code.getAttribute('class').match(/language-(\w+)/)[1] + if (!code) { + continue + } + + const className = code.getAttribute('class') || '' + const languageMatch = className.match(/language-([\w-]+)/) + const language = languageMatch ? languageMatch[1] : '' + + const text = code.textContent || '' + const lineCount = text ? text.split('\n').length : 0 + + // 方案 C:仅当代码行数超过阈值时才启用折叠 + if (lineCount && lineCount < COLLAPSE_MIN_LINES) { + continue + } const collapseWrapper = document.createElement('div') collapseWrapper.className = 'collapse-wrapper w-full py-2' + const panelWrapper = document.createElement('div') - panelWrapper.className = - 'border dark:border-gray-600 rounded-md hover:border-indigo-500 duration-200 transition-colors' + panelWrapper.className = 'collapse-panel-wrapper' + + const header = document.createElement('button') + header.type = 'button' + header.className = 'collapse-header' + + const label = language + ? `${language.toUpperCase()} · ${lineCount} lines` + : `${lineCount} lines` - const header = document.createElement('div') - header.className = - 'flex justify-between items-center px-4 py-2 cursor-pointer select-none' - header.innerHTML = `

${language}

` + header.innerHTML = `${label}` const panel = document.createElement('div') - panel.className = - 'invisible h-0 transition-transform duration-200 border-t border-gray-300' + panel.className = 'collapse-panel' panelWrapper.appendChild(header) panelWrapper.appendChild(panel) @@ -140,20 +160,18 @@ const renderCollapseCode = (codeCollapse, codeCollapseExpandDefault) => { codeBlock.parentNode.insertBefore(collapseWrapper, codeBlock) panel.appendChild(codeBlock) - function collapseCode() { - panel.classList.toggle('invisible') - panel.classList.toggle('h-0') - panel.classList.toggle('h-auto') - header.querySelector('svg').classList.toggle('rotate-180') - panelWrapper.classList.toggle('border-gray-300') + function setExpanded(expanded) { + panelWrapper.classList.toggle('is-expanded', expanded) + panel.classList.toggle('is-expanded', expanded) + header.setAttribute('aria-expanded', expanded ? 'true' : 'false') } - // 点击后折叠展开代码 - header.addEventListener('click', collapseCode) - // 是否自动展开 - if (codeCollapseExpandDefault) { - header.click() - } + header.addEventListener('click', () => { + const expanded = panelWrapper.classList.contains('is-expanded') + setExpanded(!expanded) + }) + + setExpanded(Boolean(codeCollapseExpandDefault)) } } diff --git a/public/css/prism-mac-style.css b/public/css/prism-mac-style.css index 2162f359bce..0b72a92166b 100644 --- a/public/css/prism-mac-style.css +++ b/public/css/prism-mac-style.css @@ -1,58 +1,184 @@ /** * @author https://github.com/txs - * 当配置文件 CODE_MAC_BAR 开启时,此样式会被动态引入,将开启代码组件左上角的mac图标 + * 通用 Mac 风格代码块样式 (NotionNext Universal) **/ + +/* 1. Mac 窗口容器样式 */ .code-toolbar { position: relative; - padding-top: 0 !important; - padding-bottom: 0 !important; width: 100%; - border-radius: 0.5rem; - margin-bottom: 0.5rem; + margin: 1rem 0; + border-radius: 14px; + border: 1px solid rgba(0, 0, 0, 0.1); + background: rgba(27, 28, 32, 0.94); /* 浅色模式下默认暗底 */ + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12), 0 18px 44px rgba(0, 0, 0, 0.18); + overflow: hidden; + transition: box-shadow 0.3s ease, transform 0.3s ease; } -.collapse-wrapper .code-toolbar { - margin-bottom: 0; +/* 暗色模式适配 */ +html.dark .code-toolbar { + border-color: rgba(255, 255, 255, 0.12); + background: rgba(27, 28, 32, 0.72); + -webkit-backdrop-filter: saturate(140%) blur(12px); + backdrop-filter: saturate(140%) blur(12px); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 18px 44px rgba(0, 0, 0, 0.45); } -.toolbar-item{ - white-space: nowrap; +/* 2. Mac 三色点 */ +.pre-mac { + position: absolute; + left: 12px; + top: 11px; + z-index: 13; + display: flex; + gap: 7px; } -.toolbar-item > button { - margin-top: -0.1rem; +.pre-mac > span { + width: 10px; + height: 10px; + border-radius: 999px; } -pre[class*='language-'] { - margin-top: 0rem !important; - // margin-bottom: 0rem !important; - padding-top: 1.5rem !important; +.pre-mac > span:nth-child(1) { background: #ff5f57; } +.pre-mac > span:nth-child(2) { background: #febc2e; } +.pre-mac > span:nth-child(3) { background: #28c840; } +/* 3. Toolbar 工具栏 (复制按钮、语言标签) */ +.code-toolbar > .toolbar { + position: absolute; + top: 0; + right: 0; + height: 34px; + display: flex; + align-items: center; + gap: 8px; + padding: 0 10px; + z-index: 12; } -.pre-mac { - position: absolute; - left: 0.9rem; - top: 0.5rem; - z-index: 10; +.code-toolbar .toolbar-item > button { + font-size: 12px !important; + line-height: 1 !important; + padding: 6px 8px !important; + border-radius: 999px !important; + border: 1px solid rgba(255, 255, 255, 0.15) !important; + background: rgba(255, 255, 255, 0.1) !important; + color: rgba(255, 255, 255, 0.82) !important; + cursor: pointer; + transition: all 0.2s ease; } -.pre-mac > span { - width: 10px; - height: 10px; - border-radius: 50%; - margin-right: 5px; - float: left; +.code-toolbar .toolbar-item > button:hover { + background: rgba(255, 255, 255, 0.2) !important; + color: #fff !important; +} + +/* 4. 代码正文排版 */ +pre.notion-code { + font-size: 0.92em !important; + line-height: 1.6 !important; + margin: 0 !important; + padding: 46px 1.1rem 1rem !important; + border-radius: 0 !important; + border: none !important; + background: transparent !important; + color: rgba(255, 255, 255, 0.9) !important; + overflow: auto; + -webkit-overflow-scrolling: touch; +} + +/* 5. 智能折叠 S1 极简 UI */ +.collapse-wrapper { + margin: 1rem 0; } -.pre-mac > span:nth-child(1) { - background: red; +.collapse-panel-wrapper { + border-radius: 14px; + border: 1px solid rgba(0, 0, 0, 0.08); + background: rgba(255, 255, 255, 0.55); + -webkit-backdrop-filter: saturate(160%) blur(10px); + backdrop-filter: saturate(160%) blur(10px); + overflow: hidden; + transition: all 0.3s ease; } -.pre-mac > span:nth-child(2) { - background: sandybrown; +html.dark .collapse-panel-wrapper { + border-color: rgba(255, 255, 255, 0.12); + background: rgba(27, 28, 32, 0.6); } -.pre-mac > span:nth-child(3) { - background: limegreen; +.collapse-header { + width: 100%; + height: 36px; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 12px; + cursor: pointer; + user-select: none; + border: none; + background: transparent; + color: rgba(60, 60, 67, 0.6); +} + +html.dark .collapse-header { + color: rgba(235, 235, 245, 0.6); +} + +.collapse-label { + font-size: 13px; + letter-spacing: 0.02em; +} + +.collapse-chevron { + width: 18px; + height: 18px; + transition: transform 0.3s ease; + opacity: 0.8; +} + +.collapse-panel-wrapper.is-expanded .collapse-chevron { + transform: rotate(180deg); +} + +.collapse-panel { + max-height: 0; + overflow: hidden; + border-top: 1px solid rgba(0, 0, 0, 0.06); + transition: max-height 0.32s ease; +} + +html.dark .collapse-panel { + border-top-color: rgba(255, 255, 255, 0.08); +} + +.collapse-panel.is-expanded { + max-height: 3000px; } + +/* 6. Prism 代码高亮补丁 (暗底优化) */ +.code-toolbar .token.comment, +.code-toolbar .token.prolog, +.code-toolbar .token.doctype, +.code-toolbar .token.cdata { color: rgba(235, 235, 245, 0.46); } +.code-toolbar .token.punctuation { color: rgba(235, 235, 245, 0.6); } +.code-toolbar .token.property, +.code-toolbar .token.tag, +.code-toolbar .token.boolean, +.code-toolbar .token.number, +.code-toolbar .token.constant, +.code-toolbar .token.symbol, +.code-toolbar .token.deleted { color: #7ee787; } +.code-toolbar .token.selector, +.code-toolbar .token.attr-name, +.code-toolbar .token.string, +.code-toolbar .token.char, +.code-toolbar .token.builtin, +.code-toolbar .token.inserted { color: #a5d6ff; } +.code-toolbar .token.atrule, +.code-toolbar .token.attr-value, +.code-toolbar .token.keyword { color: #ff7ab2; } +.code-toolbar .token.function, +.code-toolbar .token.class-name { color: #ffd479; }