110 lines
4.0 KiB
JavaScript
110 lines
4.0 KiB
JavaScript
/* global KEEP */
|
|
|
|
KEEP.initCodeBlockTools = () => {
|
|
HTMLElement.prototype.wrap = function (wrapper) {
|
|
this.parentNode.insertBefore(wrapper, this)
|
|
this.parentNode.removeChild(this)
|
|
wrapper.appendChild(this)
|
|
}
|
|
|
|
const { style: codeCopyStyle } = KEEP.theme_config?.code_copy
|
|
const { style: codeBlockStyle } = KEEP.theme_config?.code_block
|
|
const isMac = (codeBlockStyle || codeCopyStyle || 'default') === 'mac'
|
|
const foldedIconClassName = isMac ? 'fas fa-chevron-left' : 'fas fa-chevron-right'
|
|
const {
|
|
copy: copyLang,
|
|
copied: copiedLang,
|
|
fold: foldLang,
|
|
folded: foldedLang
|
|
} = KEEP.language_code_block
|
|
const foldDom = `<span class="tool fold tooltip" data-content="${foldLang}" data-offset-y="-2px"><i class="fas fa-chevron-down"></i></span>`
|
|
|
|
document.querySelectorAll('figure.highlight').forEach((element) => {
|
|
let codeLang = element.classList.length ? element.classList[1].toUpperCase() : ''
|
|
if (codeLang === 'PLAINTEXT') {
|
|
codeLang = ''
|
|
}
|
|
const highlightContainer = document.createElement('div')
|
|
highlightContainer.classList.add('highlight-container')
|
|
element.wrap(highlightContainer)
|
|
|
|
const codeLangDom = `${codeLang ? '<span class="code-lang">' + codeLang + '</span>' : ''}`
|
|
|
|
highlightContainer.insertAdjacentHTML(
|
|
'afterbegin',
|
|
`<div class="code-tools-box">
|
|
${isMac ? foldDom + codeLangDom : '<span>' + foldDom + codeLangDom + '</span>'}
|
|
<span class="tool copy tooltip" data-content="${copyLang}" data-offset-y="-2px"><i class="fas fa-copy"></i></span>
|
|
</div>`
|
|
)
|
|
const codeToolsBox = element.parentNode.querySelector('.code-tools-box')
|
|
const copyDom = codeToolsBox.querySelector('.copy')
|
|
const targetFoldDom = codeToolsBox.querySelector('.fold')
|
|
|
|
copyDom.addEventListener('click', (event) => {
|
|
const target = event.currentTarget
|
|
const code = [...element.querySelectorAll('.code .line')]
|
|
.map((line) => line.innerText)
|
|
.join('\n')
|
|
const tta = document.createElement('textarea')
|
|
tta.style.top = window.scrollY + 'px'
|
|
tta.style.position = 'absolute'
|
|
tta.style.opacity = '0'
|
|
tta.readOnly = true
|
|
tta.value = code
|
|
document.body.append(tta)
|
|
const selection = document.getSelection()
|
|
const selected = selection.rangeCount > 0 ? selection.getRangeAt(0) : false
|
|
tta.select()
|
|
tta.setSelectionRange(0, code.length)
|
|
tta.readOnly = false
|
|
const result = document.execCommand('copy')
|
|
|
|
const copyIconDom = target.querySelector('i')
|
|
const copyTooltipDom = codeToolsBox.querySelector('.copy .tooltip-content')
|
|
|
|
if (result) {
|
|
copyIconDom.className = 'fas fa-check'
|
|
copyTooltipDom && (copyTooltipDom.innerHTML = copiedLang)
|
|
} else {
|
|
copyIconDom.className = 'fas fa-times'
|
|
}
|
|
|
|
tta.blur()
|
|
target.blur()
|
|
if (selected) {
|
|
selection.removeAllRanges()
|
|
selection.addRange(selected)
|
|
}
|
|
document.body.removeChild(tta)
|
|
})
|
|
|
|
copyDom.addEventListener('mouseleave', (event) => {
|
|
setTimeout(() => {
|
|
event.target.querySelector('i').className = 'fas fa-copy'
|
|
const copyTooltipDom = codeToolsBox.querySelector('.copy .tooltip-content')
|
|
copyTooltipDom && (copyTooltipDom.innerHTML = copyLang)
|
|
}, 500)
|
|
})
|
|
|
|
let isFold = false
|
|
targetFoldDom.addEventListener('click', (event) => {
|
|
const target = event.currentTarget
|
|
const icon = target.querySelector('i')
|
|
const foldTooltipDom = codeToolsBox.querySelector('.fold .tooltip-content')
|
|
isFold = !isFold
|
|
if (isFold) {
|
|
icon.className = foldedIconClassName
|
|
element.classList.add('folded')
|
|
codeToolsBox.classList.add('folded')
|
|
foldTooltipDom && (foldTooltipDom.innerHTML = foldedLang)
|
|
} else {
|
|
icon.className = 'fas fa-chevron-down'
|
|
element.classList.remove('folded')
|
|
codeToolsBox.classList.remove('folded')
|
|
foldTooltipDom && (foldTooltipDom.innerHTML = foldLang)
|
|
}
|
|
})
|
|
})
|
|
}
|