Skip to content

Commit

Permalink
feat: improve compatibility of the copy code feature (#28)
Browse files Browse the repository at this point in the history
优化复制代码功能的兼容性。

```release-note
优化复制代码功能的兼容性。
```
  • Loading branch information
ruibaby authored Sep 13, 2024
1 parent 1317b98 commit 1f7af04
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ private String highlightJsScript(BasicConfig basicConfig) {
<script defer src="/plugins/PluginHighlightJS/assets/static/highlight.min.js"></script>
<th:block th:if="${config.showCopyButton}">
<link href="/plugins/PluginHighlightJS/assets/static/plugins/highlightjs-copy.min.css" rel="stylesheet"/>
<script defer src="/plugins/PluginHighlightJS/assets/static/plugins/highlightjs-copy.min.js"></script>
<link href="/plugins/PluginHighlightJS/assets/static/plugins/highlightjs-copy.css" rel="stylesheet"/>
<script defer src="/plugins/PluginHighlightJS/assets/static/plugins/highlightjs-copy.js"></script>
</th:block>
<link href="/plugins/PluginHighlightJS/assets/static/plugins/override.css" rel="stylesheet"/>
Expand Down
61 changes: 61 additions & 0 deletions src/main/resources/static/plugins/highlightjs-copy.css
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;
}
82 changes: 82 additions & 0 deletions src/main/resources/static/plugins/highlightjs-copy.js
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": ["複製", "已複製!", "已複製到剪貼簿"],
};
1 change: 0 additions & 1 deletion src/main/resources/static/plugins/highlightjs-copy.min.css

This file was deleted.

1 change: 0 additions & 1 deletion src/main/resources/static/plugins/highlightjs-copy.min.js

This file was deleted.

0 comments on commit 1f7af04

Please sign in to comment.