generated from halo-dev/plugin-starter
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: improve compatibility of the copy code feature (#28)
优化复制代码功能的兼容性。 ```release-note 优化复制代码功能的兼容性。 ```
- Loading branch information
Showing
5 changed files
with
145 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
.hljs-copy-wrapper { | ||
position: relative; | ||
overflow: hidden; | ||
} | ||
.hljs-copy-wrapper:hover .hljs-copy-button, | ||
.hljs-copy-button:focus { | ||
transform: translateX(0); | ||
} | ||
.hljs-copy-button { | ||
position: absolute; | ||
transform: translateX(calc(100% + 1.125em)); | ||
top: 0.5em; | ||
right: 0.5em; | ||
width: 2rem; | ||
height: 2rem; | ||
text-indent: -9999px; | ||
color: var(--hljs-theme-color); | ||
border-radius: 0.25rem; | ||
border: 1px solid; | ||
border-color: color-mix(in srgb, var(--hljs-theme-color), transparent 80%); | ||
background-color: var(--hljs-theme-background); | ||
transition: background-color 200ms ease, transform 200ms ease-out; | ||
overflow: hidden; | ||
} | ||
.hljs-copy-button:not([data-copied="true"])::before { | ||
content: ""; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
position: absolute; | ||
background-color: currentColor; | ||
mask: url('data:image/svg+xml;utf-8,<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M6 5C5.73478 5 5.48043 5.10536 5.29289 5.29289C5.10536 5.48043 5 5.73478 5 6V20C5 20.2652 5.10536 20.5196 5.29289 20.7071C5.48043 20.8946 5.73478 21 6 21H18C18.2652 21 18.5196 20.8946 18.7071 20.7071C18.8946 20.5196 19 20.2652 19 20V6C19 5.73478 18.8946 5.48043 18.7071 5.29289C18.5196 5.10536 18.2652 5 18 5H16C15.4477 5 15 4.55228 15 4C15 3.44772 15.4477 3 16 3H18C18.7956 3 19.5587 3.31607 20.1213 3.87868C20.6839 4.44129 21 5.20435 21 6V20C21 20.7957 20.6839 21.5587 20.1213 22.1213C19.5587 22.6839 18.7957 23 18 23H6C5.20435 23 4.44129 22.6839 3.87868 22.1213C3.31607 21.5587 3 20.7957 3 20V6C3 5.20435 3.31607 4.44129 3.87868 3.87868C4.44129 3.31607 5.20435 3 6 3H8C8.55228 3 9 3.44772 9 4C9 4.55228 8.55228 5 8 5H6Z" fill="black"/><path fill-rule="evenodd" clip-rule="evenodd" d="M7 3C7 1.89543 7.89543 1 9 1H15C16.1046 1 17 1.89543 17 3V5C17 6.10457 16.1046 7 15 7H9C7.89543 7 7 6.10457 7 5V3ZM15 3H9V5H15V3Z" fill="black"/></svg>'); | ||
mask-repeat: no-repeat; | ||
mask-size: 1rem; | ||
mask-position: center center; | ||
} | ||
.hljs-copy-button:hover { | ||
background-color: color-mix(in srgb, var(--hljs-theme-color), transparent 90%); | ||
} | ||
.hljs-copy-button:active { | ||
border-color: color-mix(in srgb, var(--hljs-theme-color), transparent 60%); | ||
} | ||
.hljs-copy-button[data-copied="true"] { | ||
text-indent: 0; | ||
width: auto; | ||
} | ||
@media (prefers-reduced-motion) { | ||
.hljs-copy-button { | ||
transition: none; | ||
} | ||
} | ||
.hljs-copy-alert { | ||
clip: rect(0 0 0 0); | ||
clip-path: inset(50%); | ||
height: 1px; | ||
overflow: hidden; | ||
position: absolute; | ||
white-space: nowrap; | ||
width: 1px; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
class CopyButtonPlugin { | ||
constructor(options = {}) { | ||
self.hook = options.hook; | ||
self.callback = options.callback; | ||
self.lang = options.lang || document.documentElement.lang || "en"; | ||
} | ||
"after:highlightElement"({ el, text }) { | ||
let button = Object.assign(document.createElement("button"), { | ||
innerHTML: locales[lang]?.[0] || "Copy", | ||
className: "hljs-copy-button", | ||
}); | ||
button.dataset.copied = false; | ||
el.parentElement.classList.add("hljs-copy-wrapper"); | ||
el.parentElement.appendChild(button); | ||
el.parentElement.style.setProperty("--hljs-theme-background", window.getComputedStyle(el).backgroundColor); | ||
el.parentElement.style.setProperty("--hljs-theme-color", window.getComputedStyle(el).color); | ||
button.onclick = function () { | ||
let newText = text; | ||
|
||
if (hook && typeof hook === "function") { | ||
newText = hook(text, el) || text; | ||
} | ||
|
||
const copyText = () => { | ||
if (navigator.clipboard) { | ||
return navigator.clipboard.writeText(newText); | ||
} else { | ||
const textArea = document.createElement("textarea"); | ||
textArea.value = newText; | ||
textArea.style.position = "fixed"; | ||
document.body.appendChild(textArea); | ||
textArea.focus(); | ||
textArea.select(); | ||
|
||
try { | ||
const successful = document.execCommand("copy"); | ||
document.body.removeChild(textArea); | ||
return successful ? Promise.resolve() : Promise.reject(); | ||
} catch (err) { | ||
document.body.removeChild(textArea); | ||
return Promise.reject(err); | ||
} | ||
} | ||
}; | ||
|
||
copyText() | ||
.then(function () { | ||
button.innerHTML = locales[lang]?.[1] || "Copied!"; | ||
button.dataset.copied = true; | ||
let alert = Object.assign(document.createElement("div"), { | ||
role: "status", | ||
className: "hljs-copy-alert", | ||
innerHTML: locales[lang]?.[2] || "Copied to clipboard", | ||
}); | ||
el.parentElement.appendChild(alert); | ||
setTimeout(() => { | ||
button.innerHTML = locales[lang]?.[0] || "Copy"; | ||
button.dataset.copied = false; | ||
el.parentElement.removeChild(alert); | ||
alert = null; | ||
}, 2e3); | ||
}) | ||
.then(function () { | ||
if (typeof callback === "function") return callback(newText, el); | ||
}); | ||
}; | ||
} | ||
} | ||
if (typeof module != "undefined") { | ||
module.exports = CopyButtonPlugin; | ||
} | ||
const locales = { | ||
en: ["Copy", "Copied!", "Copied to clipboard"], | ||
es: ["Copiar", "¡Copiado!", "Copiado al portapapeles"], | ||
fr: ["Copier", "Copié !", "Copié dans le presse-papier"], | ||
de: ["Kopieren", "Kopiert!", "In die Zwischenablage kopiert"], | ||
ja: ["コピー", "コピーしました!", "クリップボードにコピーしました"], | ||
ko: ["복사", "복사됨!", "클립보드에 복사됨"], | ||
ru: ["Копировать", "Скопировано!", "Скопировано в буфер обмена"], | ||
zh: ["复制", "已复制!", "已复制到剪贴板"], | ||
"zh-tw": ["複製", "已複製!", "已複製到剪貼簿"], | ||
}; |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.