feat: 新增設置代碼行數限制,顯示展開按鈕

improvement: prismjs 可以配置 code_word_wrap
improvement: 搜索 hover 效果與其它目錄一致
improvement: css 優化
fix: 修復prismjs 無法識別的語言 顯示 null 而不是顯示 code 的 bug
fix: 修復默認代碼大小不會隨着字體放大/放小而改變的bug
fix: 修復prismjs 在ios safari 下自動換行的bug
This commit is contained in:
Jerry
2021-03-14 23:25:58 +08:00
Unverified
parent 2f3094cc0a
commit 7bc46c47ed
14 changed files with 225 additions and 182 deletions

View File

@@ -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 = `<i class="fas fa-angle-down expand ${highlightShrinkClass}"></i>`
}
let highlightShrinkEle = ''
let highlightCopyEle = ''
const highlightShrinkClass = isHighlightShrink === true ? 'closed' : ''
if (isHighlightCopy) {
highlightCopyEle = '<div class="copy-notice"></div><i class="fas fa-paste copy-button"></i>'
}
if (isHighlightShrink !== undefined) {
highlightShrinkEle = `<i class="fas fa-angle-down expand ${highlightShrinkClass}"></i>`
}
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 = '<div class="copy-notice"></div><i class="fas fa-paste copy-button"></i>'
}
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 = `<div class="code-lang">${langName}</div>`
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 = `<div class="code-lang">${langName}</div>`
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 = '<i class="fas fa-angle-double-down"></i>'
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 = `<div class="code-lang">${langName}</div>`
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 = `<div class="code-lang">${langName}</div>`
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()