Fix mermaid copy button

This commit is contained in:
Mimi 2024-05-12 12:19:22 +08:00
parent da8db69422
commit 5c024800e6
3 changed files with 57 additions and 45 deletions

View File

@ -25,7 +25,7 @@ labels:
- name: Wontfix - name: Wontfix
labeled: labeled:
issue: issue:
body: This will not be worked on but we appreciate your contribution. body: There wasn't enough interest from the team or community to implement this change. Thanks for contributing and we appreciate your understanding.
action: close action: close
- name: Configurations - name: Configurations
labeled: labeled:

View File

@ -7,11 +7,17 @@ document.addEventListener('page:loaded', () => {
condition: window.mermaid condition: window.mermaid
}).then(() => { }).then(() => {
mermaidElements.forEach(element => { mermaidElements.forEach(element => {
const box = document.createElement('div');
box.className = 'code-container';
const newElement = document.createElement('div'); const newElement = document.createElement('div');
newElement.innerHTML = element.innerHTML; newElement.innerHTML = element.innerHTML;
newElement.className = element.className; newElement.className = 'mermaid';
box.appendChild(newElement);
if (CONFIG.copycode.enable) {
NexT.utils.registerCopyButton(box, box, element.innerText);
}
const parent = element.parentNode; const parent = element.parentNode;
parent.parentNode.replaceChild(newElement, parent); parent.parentNode.replaceChild(box, parent);
}); });
mermaid.initialize({ mermaid.initialize({
theme : CONFIG.darkmode && window.matchMedia('(prefers-color-scheme: dark)').matches ? CONFIG.mermaid.theme.dark : CONFIG.mermaid.theme.light, theme : CONFIG.darkmode && window.matchMedia('(prefers-color-scheme: dark)').matches ? CONFIG.mermaid.theme.dark : CONFIG.mermaid.theme.light,

View File

@ -39,6 +39,45 @@ NexT.utils = {
}); });
}, },
registerCopyButton(target, element, code) {
// One-click copy code support.
target.insertAdjacentHTML('beforeend', '<div class="copy-btn"><i class="fa fa-copy fa-fw"></i></div>');
const button = target.querySelector('.copy-btn');
button.addEventListener('click', () => {
if (navigator.clipboard) {
// https://caniuse.com/mdn-api_clipboard_writetext
navigator.clipboard.writeText(code).then(() => {
button.querySelector('i').className = 'fa fa-check-circle fa-fw';
}, () => {
button.querySelector('i').className = 'fa fa-times-circle fa-fw';
});
} else {
const ta = document.createElement('textarea');
ta.style.top = window.scrollY + 'px'; // Prevent page scrolling
ta.style.position = 'absolute';
ta.style.opacity = '0';
ta.readOnly = true;
ta.value = code;
document.body.append(ta);
ta.select();
ta.setSelectionRange(0, code.length);
ta.readOnly = false;
const result = document.execCommand('copy');
button.querySelector('i').className = result ? 'fa fa-check-circle fa-fw' : 'fa fa-times-circle fa-fw';
ta.blur(); // For iOS
button.blur();
document.body.removeChild(ta);
}
});
// If copycode.style is not mac, element is larger than target
// So we need to accept both of them as parameters
element.addEventListener('mouseleave', () => {
setTimeout(() => {
button.querySelector('i').className = 'fa fa-copy fa-fw';
}, 300);
});
},
registerCodeblock(element) { registerCodeblock(element) {
const inited = !!element; const inited = !!element;
let figure; let figure;
@ -48,6 +87,8 @@ NexT.utils = {
figure = document.querySelectorAll('pre'); figure = document.querySelectorAll('pre');
} }
figure.forEach(element => { figure.forEach(element => {
// Skip pre > .mermaid for folding and copy button
if (element.querySelector('.mermaid')) return;
if (!inited) { if (!inited) {
let span = element.querySelectorAll('.code .line span'); let span = element.querySelectorAll('.code .line span');
if (span.length === 0) { if (span.length === 0) {
@ -61,9 +102,7 @@ NexT.utils = {
}); });
} }
const height = parseInt(window.getComputedStyle(element).height, 10); const height = parseInt(window.getComputedStyle(element).height, 10);
// Skip pre > .mermaid for folding but keep the copy button const needFold = CONFIG.fold.enable && (height > CONFIG.fold.height);
// Note that it only works before mermaid.js loaded (race condition)
const needFold = CONFIG.fold.enable && (height > CONFIG.fold.height) && !element.querySelector('.mermaid');
if (!needFold && !CONFIG.copycode.enable) return; if (!needFold && !CONFIG.copycode.enable) return;
let target; let target;
if (CONFIG.hljswrap && CONFIG.copycode.style === 'mac') { if (CONFIG.hljswrap && CONFIG.copycode.style === 'mac') {
@ -91,43 +130,10 @@ NexT.utils = {
target.classList.add('unfold'); target.classList.add('unfold');
}); });
} }
if (inited || !CONFIG.copycode.enable) return; if (!inited && CONFIG.copycode.enable) {
// One-click copy code support.
target.insertAdjacentHTML('beforeend', '<div class="copy-btn"><i class="fa fa-copy fa-fw"></i></div>');
const button = target.querySelector('.copy-btn');
button.addEventListener('click', () => {
const lines = element.querySelector('.code') || element.querySelector('code'); const lines = element.querySelector('.code') || element.querySelector('code');
const code = lines.innerText; this.registerCopyButton(target, element, lines.innerText);
if (navigator.clipboard) { }
// https://caniuse.com/mdn-api_clipboard_writetext
navigator.clipboard.writeText(code).then(() => {
button.querySelector('i').className = 'fa fa-check-circle fa-fw';
}, () => {
button.querySelector('i').className = 'fa fa-times-circle fa-fw';
});
} else {
const ta = document.createElement('textarea');
ta.style.top = window.scrollY + 'px'; // Prevent page scrolling
ta.style.position = 'absolute';
ta.style.opacity = '0';
ta.readOnly = true;
ta.value = code;
document.body.append(ta);
ta.select();
ta.setSelectionRange(0, code.length);
ta.readOnly = false;
const result = document.execCommand('copy');
button.querySelector('i').className = result ? 'fa fa-check-circle fa-fw' : 'fa fa-times-circle fa-fw';
ta.blur(); // For iOS
button.blur();
document.body.removeChild(ta);
}
});
element.addEventListener('mouseleave', () => {
setTimeout(() => {
button.querySelector('i').className = 'fa fa-copy fa-fw';
}, 300);
});
}); });
}, },
@ -162,12 +168,12 @@ NexT.utils = {
}, },
updateActiveNav() { updateActiveNav() {
if (!Array.isArray(NexT.utils.sections)) return; if (!Array.isArray(this.sections)) return;
let index = NexT.utils.sections.findIndex(element => { let index = this.sections.findIndex(element => {
return element && element.getBoundingClientRect().top > 10; return element && element.getBoundingClientRect().top > 10;
}); });
if (index === -1) { if (index === -1) {
index = NexT.utils.sections.length - 1; index = this.sections.length - 1;
} else if (index > 0) { } else if (index > 0) {
index--; index--;
} }