diff --git a/_config.yml b/_config.yml index f9f78f2..16cf395 100644 --- a/_config.yml +++ b/_config.yml @@ -27,6 +27,7 @@ highlight_theme: light # darker / pale night / light / ocean / mac / mac light highlight_copy: true # copy button highlight_lang: true # show the code language highlight_shrink: false # true: shrink the code blocks / false: expand the code blocks | none: expand code blocks and hide the button +highlight_height_limit: false # unit: px code_word_wrap: false # copy settings diff --git a/layout/includes/head/config.pug b/layout/includes/head/config.pug index 710345d..9dd4f3b 100644 --- a/layout/includes/head/config.pug +++ b/layout/includes/head/config.pug @@ -78,7 +78,8 @@ highlight = JSON.stringify({ plugin: config.highlight.enable ? 'highlighjs' : 'prismjs', highlightCopy: theme.highlight_copy, - highlightLang: theme.highlight_lang + highlightLang: theme.highlight_lang, + highlightHeightLimit: theme.highlight_height_limit }) } diff --git a/layout/includes/header/menu_item.pug b/layout/includes/header/menu_item.pug index a10071c..5a63994 100644 --- a/layout/includes/header/menu_item.pug +++ b/layout/includes/header/menu_item.pug @@ -20,7 +20,7 @@ if theme.menu ul.menus_item_child each val,lab in value li - a.site-page(href=url_for(trim(val.split('||')[0]))) + a.site-page.child(href=url_for(trim(val.split('||')[0]))) if val.split('||')[1] i.fa-fw(class=trim(val.split('||')[1])) span=' '+ lab \ No newline at end of file diff --git a/layout/includes/third-party/pjax.pug b/layout/includes/third-party/pjax.pug index e07371a..853c627 100644 --- a/layout/includes/third-party/pjax.pug +++ b/layout/includes/third-party/pjax.pug @@ -45,7 +45,7 @@ script. // google analytics typeof gtag === 'function' && gtag('config', '!{theme.google_analytics}', {'page_path': window.location.pathname}); - //- // baidu analytics + // baidu analytics typeof _hmt === 'object' && _hmt.push(['_trackPageview',window.location.pathname]); typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting() diff --git a/package.json b/package.json index 79403d0..2ec0ed4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hexo-theme-butterfly", - "version": "3.7.0-b6", + "version": "3.7.0-b7", "description": "A Simple and Card UI Design theme for Hexo", "main": "package.json", "scripts": { diff --git a/source/css/_highlight/highlight.styl b/source/css/_highlight/highlight.styl index 29e9f27..5f82677 100644 --- a/source/css/_highlight/highlight.styl +++ b/source/css/_highlight/highlight.styl @@ -1,4 +1,3 @@ -// https://github.com/equinusocio/vsc-material-theme $highlight_theme = hexo-config('highlight_theme') $highlighEnable = hexo-config('highlight_settings') && hexo-config('highlight_settings.enable') $prismjsEnable = hexo-config('prismjs_settings') && hexo-config('prismjs_settings.enable') @@ -6,6 +5,16 @@ wordWrap = !hexo-config('highlight_settings.line_number') && hexo-config('code_w @require 'theme' +:root + --hl-color: $highlight-foreground + --hl-bg: $highlight-background + --hltools-bg: $highlight-tools.bg-color + --hltools-color: $highlight-tools.color + --hlnumber-bg: $highlight-gutter.bg-color + --hlnumber-color: $highlight-gutter.color + --hlscrollbar-bg: $highlight-scrollbar + --hlexpand-bg: linear-gradient(180deg, rgba($highlight-background, .6), rgba($highlight-background, .9)) + if $highlighEnable @require 'highlight/index' @@ -16,8 +25,8 @@ $code-block overflow: auto margin: 0 0 1rem padding: 0 - background: $highlight-background - color: $highlight-foreground + background: var(--hl-bg) + color: var(--hl-color) line-height: $line-height-code-block if wordWrap @@ -56,9 +65,6 @@ blockquote padding: .1rem .2rem background: $code-background color: $code-foreground - word-wrap: break-word - word-break: break-word - overflow-wrap: break-word pre @extend $code-block @@ -67,7 +73,7 @@ blockquote code padding: 0 background: none - color: $highlight-foreground + color: var(--hl-color) text-shadow: none figure.highlight @@ -88,10 +94,10 @@ blockquote a float: right padding-right: 10px - color: $highlight-foreground + color: var(--hl-color) &:hover - border-bottom-color: $highlight-foreground + border-bottom-color: var(--hl-color) .highlight-tools position: relative @@ -100,8 +106,8 @@ blockquote overflow: hidden min-height: 1.2rem height: 2.15em - background: $highlight-tools.bg-color - color: $highlight-tools.color + background: var(--hltools-bg) + color: var(--hltools-color) font-size: $code-font-size &.closed + table @@ -185,3 +191,38 @@ blockquote .code-lang left: 3.8rem !important + + if hexo-config('highlight_height_limit') + .code-expand-btn + position: absolute + bottom: 0 + z-index: 10 + width: 100% + background: var(--hlexpand-bg) + text-align: center + font-size: $code-font-size + cursor: pointer + + i + padding: .3rem 0 + color: var(--hlnumber-color) + animation: code-expand-key 1.2s infinite + + &.expand-done + display: none !important + + &:not(.expand-done) + & ~ table, + & ~ pre + overflow: hidden + height: unit(hexo-config('highlight_height_limit'), px) + +@keyframes code-expand-key + 0% + opacity: .6 + + 50% + opacity: .1 + + 100% + opacity: .6 \ No newline at end of file diff --git a/source/css/_highlight/highlight/diff.styl b/source/css/_highlight/highlight/diff.styl index 486754c..6a6eefe 100644 --- a/source/css/_highlight/highlight/diff.styl +++ b/source/css/_highlight/highlight/diff.styl @@ -1,7 +1,7 @@ figure.highlight table &::-webkit-scrollbar-thumb - background: $highlight-scrollbar + background: var(--hlscrollbar-bg) pre .deletion color: $highlight-deletion diff --git a/source/css/_highlight/highlight/index.styl b/source/css/_highlight/highlight/index.styl index 9c3d4f9..cb214c0 100644 --- a/source/css/_highlight/highlight/index.styl +++ b/source/css/_highlight/highlight/index.styl @@ -9,7 +9,7 @@ if $highlight_theme != false display: inline-block padding: 0 .3rem 0 0 min-width: 1.6rem - color: $highlight-gutter.color + color: var(--hlnumber-color) content: counter(line) counter-increment: line text-align: left @@ -29,8 +29,8 @@ if $highlight_theme != false .gutter pre padding-right: .5rem padding-left: .5rem - background-color: $highlight-gutter.bg-color - color: $highlight-gutter.color + background-color: var(--hlnumber-bg) + color: var(--hlnumber-color) text-align: right .code pre diff --git a/source/css/_highlight/prismjs/index.styl b/source/css/_highlight/prismjs/index.styl index 5ac7f4f..b21c5bf 100644 --- a/source/css/_highlight/prismjs/index.styl +++ b/source/css/_highlight/prismjs/index.styl @@ -7,7 +7,7 @@ if $highlight_theme != false #article-container pre[class*='language-'] &::-webkit-scrollbar-thumb - background: $highlight-scrollbar + background: var(--hlscrollbar-bg) &:not(.line-numbers) padding: 10px 20px diff --git a/source/css/_highlight/prismjs/line-number.styl b/source/css/_highlight/prismjs/line-number.styl index a6bd858..69f2787 100644 --- a/source/css/_highlight/prismjs/line-number.styl +++ b/source/css/_highlight/prismjs/line-number.styl @@ -8,9 +8,16 @@ > code position: relative - white-space: inherit line-height: $line-height-code-block + if hexo-config('code_word_wrap') + white-space: pre-wrap + else + white-space: inherit + word-wrap: normal + word-break: normal + overflow-wrap: normal + .line-numbers-rows position: absolute top: 0 @@ -29,6 +36,6 @@ &:before display: block padding-right: .8em - color: $highlight-gutter.color + color: var(--hlnumber-color) content: counter(linenumber) text-align: right diff --git a/source/css/_layout/head.styl b/source/css/_layout/head.styl index 37ca649..d9cb609 100644 --- a/source/css/_layout/head.styl +++ b/source/css/_layout/head.styl @@ -303,22 +303,6 @@ _:future, padding: 4px transition: transform .3s - & > a - &:after - position: absolute - bottom: 0 - left: 0 - z-index: -1 - width: 0 - height: 3px - background-color: lighten($theme-color, 30%) - content: '' - transition: all .3s ease-in-out - - &:hover - &:after - width: 100% - .menus_item_child position: absolute right: 0 @@ -377,3 +361,19 @@ _:future, text-shadow: .05rem .05rem .1rem rgba($dark-black, .3) font-size: .78em cursor: pointer + + &:not(.child) + &:after + position: absolute + bottom: 0 + left: 0 + z-index: -1 + width: 0 + height: 3px + background-color: lighten($theme-color, 30%) + content: '' + transition: all .3s ease-in-out + + &:hover + &:after + width: 100% diff --git a/source/css/_mode/darkmode.styl b/source/css/_mode/darkmode.styl index 02e3a82..da9b673 100644 --- a/source/css/_mode/darkmode.styl +++ b/source/css/_mode/darkmode.styl @@ -27,6 +27,14 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark' --blockquote-bg: lighten(#121212, 10) --reward-pop: lighten(#121212, 10) --toc-link-color: alpha(#FFFFFF, .6) + --hl-color: alpha(#FFFFFF, .7) + --hl-bg: lighten(#121212, 2) + --hltools-bg: lighten(#121212, 3) + --hltools-color: #90a4ae + --hlnumber-bg: lighten(#121212, 2) + --hlnumber-color: alpha(#FFFFFF, .4) + --hlscrollbar-bg: lighten(#121212, 5) + --hlexpand-bg: linear-gradient(180deg, rgba(lighten(#121212, 2), .6), rgba(lighten(#121212, 2), .9)) #web_bg:before, #footer:before, @@ -42,7 +50,10 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark' background: #2c2c2c pre > code - background: 0 + background: lighten(#121212, 2) + + figure.highlight + box-shadow: none .note code @@ -63,33 +74,6 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark' background: alpha(#121212, .8) box-shadow: 0 5px 6px -5px rgba(133, 133, 133, 0) - // 代碼框 - #article-container - pre, - .highlight:not(.js-file-line-container) - background-color: lighten(#121212, 2) !important - color: alpha(#FFFFFF, .7) !important - - figure.highlight - box-shadow: none - - if hexo-config('highlight_settings') && hexo-config('highlight_settings.enable') - table::-webkit-scrollbar-thumb - background: lighten(#121212, 5) - - .line:before - color: alpha(#FFFFFF, .7) !important - - .hljs - background-color: lighten(#121212, 2) !important - - pre[class*='language-']::-webkit-scrollbar-thumb - background: lighten(#121212, 5) - - .highlight-tools - background: lighten(#121212, 3) !important - color: #90a4ae !important - #post-comment #comment-switch if hexo-config('comments.text') @@ -118,16 +102,6 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark' #aside-content .aside-list > .aside-list-item:not(:last-child) border-bottom: 1px dashed alpha(#FFFFFF, .1) - // 第三方 - // 插件 hexo-blog-encrypt - #hexo-blog-encrypt - label, - input - color: alpha(#FFFFFF, .7) !important - - input - background-color: #121212 - // Gitalk #gitalk-container filter: brightness(.8) @@ -135,7 +109,7 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark' svg fill: alpha(#FFFFFF, .9) !important - // Disqus and Disqusjs + // Disqusjs 反代模式下的適配 #disqus_thread #dsqjs .dsqjs-tab-active, diff --git a/source/css/var.styl b/source/css/var.styl index f3f0267..87e1503 100644 --- a/source/css/var.styl +++ b/source/css/var.styl @@ -28,7 +28,7 @@ $title-prefix-icon = $beautifyEnable ? hexo-config('beautify.title-prefix-icon') $title-prefix-icon-color = $beautifyEnable ? convert(hexo-config('beautify.title-prefix-icon-color')) : $light-red // Global Variables $font-size = hexo-config('font.global-font-size') ? convert(hexo-config('font.global-font-size')) : 14px -$code-font-size = hexo-config('font.code-font-size') ? convert(hexo-config('font.code-font-size')) : $font-size +$code-font-size = hexo-config('font.code-font-size') ? convert(hexo-config('font.code-font-size')) : var(--global-font-size) $font-color = #1F2D3D $rem = 20px $text-line-height = 2 diff --git a/source/js/main.js b/source/js/main.js index da5be46..197dddb 100644 --- a/source/js/main.js +++ b/source/js/main.js @@ -81,123 +81,142 @@ document.addEventListener('DOMContentLoaded', function () { * 只適用於Hexo默認的代碼渲染 */ const addHighlightTool = function () { - const isHighlightCopy = GLOBAL_CONFIG.highlight.highlightCopy - const isHighlightLang = GLOBAL_CONFIG.highlight.highlightLang + const highLight = GLOBAL_CONFIG.highlight + if (!highLight) return + + const isHighlightCopy = highLight.highlightCopy + const isHighlightLang = highLight.highlightLang const isHighlightShrink = GLOBAL_CONFIG_SITE.isHighlightShrink + const highlightHeightLimit = highLight.highlightHeightLimit const isShowTool = isHighlightCopy || isHighlightLang || isHighlightShrink !== undefined - const $figureHighlight = GLOBAL_CONFIG.highlight.plugin === 'highlighjs' ? document.querySelectorAll('figure.highlight') : document.querySelectorAll('pre[class*="language-"]') + const $figureHighlight = highLight.plugin === 'highlighjs' ? document.querySelectorAll('figure.highlight') : document.querySelectorAll('pre[class*="language-"]') - if (isShowTool && $figureHighlight.length) { - const isPrismjs = GLOBAL_CONFIG.highlight.plugin === 'prismjs' + if (!((isShowTool || highlightHeightLimit) && $figureHighlight.length)) return - let highlightShrinkEle = '' - let highlightCopyEle = '' - const highlightShrinkClass = isHighlightShrink === true ? 'closed' : '' + const isPrismjs = highLight.plugin === 'prismjs' - if (isHighlightShrink !== undefined) { - highlightShrinkEle = `` - } + let highlightShrinkEle = '' + let highlightCopyEle = '' + const highlightShrinkClass = isHighlightShrink === true ? 'closed' : '' - if (isHighlightCopy) { - highlightCopyEle = '
' - } + if (isHighlightShrink !== undefined) { + highlightShrinkEle = `` + } - const copy = (text, ctx) => { - if (document.queryCommandSupported && document.queryCommandSupported('copy')) { - document.execCommand('copy') - if (GLOBAL_CONFIG.Snackbar !== undefined) { - btf.snackbarShow(GLOBAL_CONFIG.copy.success) - } else { - const prevEle = ctx.previousElementSibling - prevEle.innerText = GLOBAL_CONFIG.copy.success - prevEle.style.opacity = 1 - setTimeout(() => { prevEle.style.opacity = 0 }, 700) - } + if (isHighlightCopy) { + highlightCopyEle = '
' + } + + const copy = (text, ctx) => { + if (document.queryCommandSupported && document.queryCommandSupported('copy')) { + document.execCommand('copy') + if (GLOBAL_CONFIG.Snackbar !== undefined) { + btf.snackbarShow(GLOBAL_CONFIG.copy.success) } else { - if (GLOBAL_CONFIG.Snackbar !== undefined) { - btf.snackbarShow(GLOBAL_CONFIG.copy.noSupport) - } else { - ctx.previousElementSibling.innerText = GLOBAL_CONFIG.copy.noSupport - } - } - } - - // click events - const highlightCopyFn = (ele) => { - const $buttonParent = ele.parentNode - $buttonParent.classList.add('copy-true') - const selection = window.getSelection() - const range = document.createRange() - if (isPrismjs) range.selectNodeContents($buttonParent.querySelectorAll('pre code')[0]) - else range.selectNodeContents($buttonParent.querySelectorAll('table .code pre')[0]) - selection.removeAllRanges() - selection.addRange(range) - const text = selection.toString() - copy(text, ele.lastChild) - selection.removeAllRanges() - $buttonParent.classList.remove('copy-true') - } - - const highlightShrinkFn = (ele) => { - const $nextEle = [...ele.parentNode.children].slice(1) - ele.firstChild.classList.toggle('closed') - if (btf.isHidden($nextEle[0])) { - $nextEle.forEach(e => { e.style.display = 'block' }) - } else { - $nextEle.forEach(e => { e.style.display = 'none' }) - } - } - - const highlightToolsFn = function (e) { - const $target = e.target.classList - if ($target.contains('expand')) highlightShrinkFn(this) - else if ($target.contains('copy-button')) highlightCopyFn(this) - } - - const createEle = () => { - const newEle = document.createElement('div') - newEle.className = `highlight-tools ${highlightShrinkClass}` - newEle.addEventListener('click', highlightToolsFn) - return newEle - } - - if (isHighlightLang) { - if (isPrismjs) { - $figureHighlight.forEach(function (item) { - const langName = item.getAttribute('data-language') !== undefined ? item.getAttribute('data-language') : 'Code' - const highlightLangEle = `
${langName}
` - btf.wrap(item, 'figure', '', 'highlight') - const newEle = createEle() - newEle.innerHTML = highlightShrinkEle + highlightLangEle + highlightCopyEle - item.parentNode.insertBefore(newEle, item) - }) - } else { - $figureHighlight.forEach(function (item) { - let langName = item.getAttribute('class').split(' ')[1] - if (langName === 'plain' || langName === undefined) langName = 'Code' - const highlightLangEle = `
${langName}
` - const newEle = createEle() - newEle.innerHTML = highlightShrinkEle + highlightLangEle + highlightCopyEle - item.insertBefore(newEle, item.firstChild) - }) + const prevEle = ctx.previousElementSibling + prevEle.innerText = GLOBAL_CONFIG.copy.success + prevEle.style.opacity = 1 + setTimeout(() => { prevEle.style.opacity = 0 }, 700) } } else { - if (isPrismjs) { - $figureHighlight.forEach(function (item) { - btf.wrap(item, 'figure', '', 'highlight') - const newEle = createEle() - newEle.innerHTML = highlightShrinkEle + highlightCopyEle - item.parentNode.insertBefore(newEle, item) - }) + if (GLOBAL_CONFIG.Snackbar !== undefined) { + btf.snackbarShow(GLOBAL_CONFIG.copy.noSupport) } else { - $figureHighlight.forEach(function (item) { - const newEle = createEle() - newEle.innerHTML = highlightShrinkEle + highlightCopyEle - item.insertBefore(newEle, item.firstChild) - }) + ctx.previousElementSibling.innerText = GLOBAL_CONFIG.copy.noSupport } } } + + // click events + const highlightCopyFn = (ele) => { + const $buttonParent = ele.parentNode + $buttonParent.classList.add('copy-true') + const selection = window.getSelection() + const range = document.createRange() + if (isPrismjs) range.selectNodeContents($buttonParent.querySelectorAll('pre code')[0]) + else range.selectNodeContents($buttonParent.querySelectorAll('table .code pre')[0]) + selection.removeAllRanges() + selection.addRange(range) + const text = selection.toString() + copy(text, ele.lastChild) + selection.removeAllRanges() + $buttonParent.classList.remove('copy-true') + } + + const highlightShrinkFn = (ele) => { + const $nextEle = [...ele.parentNode.children].slice(1) + ele.firstChild.classList.toggle('closed') + if (btf.isHidden($nextEle[0])) { + $nextEle.forEach(e => { e.style.display = 'block' }) + } else { + $nextEle.forEach(e => { e.style.display = 'none' }) + } + } + + const highlightToolsFn = function (e) { + const $target = e.target.classList + if ($target.contains('expand')) highlightShrinkFn(this) + else if ($target.contains('copy-button')) highlightCopyFn(this) + } + + const expandCode = function () { + this.classList.toggle('expand-done') + } + + function createEle (lang, item, service) { + const fragment = document.createDocumentFragment() + + if (isShowTool) { + const hlTools = document.createElement('div') + hlTools.className = `highlight-tools ${highlightShrinkClass}` + hlTools.innerHTML = highlightShrinkEle + lang + highlightCopyEle + hlTools.addEventListener('click', highlightToolsFn) + fragment.appendChild(hlTools) + } + + if (highlightHeightLimit && item.offsetHeight > highlightHeightLimit + 30) { + const ele = document.createElement('div') + ele.className = 'code-expand-btn' + ele.innerHTML = '' + ele.addEventListener('click', expandCode) + fragment.appendChild(ele) + } + + if (service === 'hl') { + item.insertBefore(fragment, item.firstChild) + } else { + item.parentNode.insertBefore(fragment, item) + } + } + + if (isHighlightLang) { + if (isPrismjs) { + $figureHighlight.forEach(function (item) { + const langName = item.getAttribute('data-language') ? item.getAttribute('data-language') : 'Code' + const highlightLangEle = `
${langName}
` + btf.wrap(item, 'figure', '', 'highlight') + createEle(highlightLangEle, item) + }) + } else { + $figureHighlight.forEach(function (item) { + let langName = item.getAttribute('class').split(' ')[1] + if (langName === 'plain' || langName === undefined) langName = 'Code' + const highlightLangEle = `
${langName}
` + createEle(highlightLangEle, item, 'hl') + }) + } + } else { + if (isPrismjs) { + $figureHighlight.forEach(function (item) { + btf.wrap(item, 'figure', '', 'highlight') + createEle('', item) + }) + } else { + $figureHighlight.forEach(function (item) { + createEle('', item, 'hl') + }) + } + } } /** @@ -819,7 +838,7 @@ document.addEventListener('DOMContentLoaded', function () { sidebarFn() GLOBAL_CONFIG_SITE.isHome && scrollDownInIndex() - GLOBAL_CONFIG.highlight && addHighlightTool() + addHighlightTool() GLOBAL_CONFIG.isPhotoFigcaption && addPhotoFigcaption() jqLoadAndRun() GLOBAL_CONFIG.lightbox === 'mediumZoom' && addMediumZoom()