Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.