Skip to content
Draft
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
57 changes: 54 additions & 3 deletions lib/LaTeXML/resources/CSS/ltx-listings.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,56 @@

.ltx_listing_data {
float:right; }
float: right;
}
.ltx_listing_data a {
text-decoration:none; }
text-decoration: none;
}
.ltx_listing_copy2clip {
position: absolute;
}
.ltx_listing_button {
appearance: none;
background-color: #FAFBFC;
border: 1px solid rgba(27, 31, 35, 0.15);
border-radius: 6px;
box-shadow: rgba(27, 31, 35, 0.04) 0 1px 0, rgba(255, 255, 255, 0.25) 0 1px 0 inset;
box-sizing: border-box;
color: #24292E;
cursor: pointer;
height: 36px;
padding: 6px;
position: relative;
overflow: hidden;
width: 36px
}
.ltx_listing_button::before,
.ltx_listing_button::after {
content: "";
position: absolute;
inset: 0;
background-position: center;
background-repeat: no-repeat;
background-size: 60%;
transition: opacity 0.6s ease-in-out;
}
.ltx_listing_button::before {
opacity: 1;
/* copy icon */
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 359 444' fill='none'><defs><clipPath id='clip1'><path d='M0 0h359v444H0zM37 97v310h225V97z'/></clipPath><clipPath id='clip2'><path d='M0 0h359v444H0zM97 37v310h225V37z'/></clipPath></defs><rect x='37' y='97' width='225' height='310' fill='white'/><rect x='37' y='97' width='225' height='310' fill='none' stroke='gray' stroke-linecap='round' stroke-linejoin='round' stroke-width='72' clip-path='url(%23clip1)'/><rect x='97' y='37' width='225' height='310' fill='white'/><rect x='97' y='37' width='225' height='310' fill='none' stroke='gray' stroke-linecap='round' stroke-linejoin='round' stroke-width='72' clip-path='url(%23clip2)'/></svg>");
}
.ltx_listing_button::after {
opacity: 0;
}
.ltx_listing_button.success::after {
opacity: 1;
/* success icon */
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 359 444'><circle cx='179.5' cy='222' r='178.3' fill='%2300a337'/><path d='M235.3 109.5 L123.6 308.2 L155.7 305.4 L110.7 245.6 L96.7 227.7 L65.8 267.7 L80.5 283.0 L125.3 340.5 L143.7 364.9 L158.5 338.1 L270.2 138.8 L281.8 117.8 L247.0 87.9 Z' fill='white'/></svg>");
}
.ltx_listing_button.error::after {
opacity: 1;
/* error icon */
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 359 444'><circle cx='179.5' cy='222' r='178.3' fill='%23c33641'/><line x1='110.3' y1='138.3' x2='245.6' y2='305.4' stroke='white' stroke-linecap='square' stroke-width='56.1'/><line x1='247.0' y1='136.0' x2='111.6' y2='303.7' stroke='white' stroke-linecap='square' stroke-width='56.1'/></svg>");
}
.ltx_listing_button.success::before,
.ltx_listing_button.error::before {
opacity: 0;
}
39 changes: 39 additions & 0 deletions lib/LaTeXML/resources/javascript/lstlisting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// replace download links in lstlisting environments by copy to clipboard button
// requires images/copy.svg and images/ok.svg
// (c) Christoph Hauert 2025

function copy2clip(button) {
try {
// temporarily hide line numbers in code listing
const style = document.createElement('style');
document.head.appendChild(style);
const styleSheet = style.sheet;
var hideLine = styleSheet.insertRule(".ltx_tag_listingline { display: none; }");
var hideCopy = styleSheet.insertRule(".ltx_listing_data { display: none; }");
const textToCopy = button.parentNode.parentNode.parentNode.innerText;
navigator.clipboard.writeText(textToCopy);
styleSheet.deleteRule(hideCopy);
styleSheet.deleteRule(hideLine);
button.classList.remove("error");
button.classList.add("success");
} catch (e) {
button.classList.remove("success");
button.classList.add("error");
}
setTimeout(() => {
button.classList.remove("success", "error");
}, 1200);
}

window.addEventListener("load", () => {
const elements = document.getElementsByClassName("ltx_listing_data");
const copyButton = '<div class="ltx_listing_copy2clip">' +
'<button class="ltx_listing_button" onclick="copy2clip(this)" title="Copy to clipboard">' +
'</button></div>';
Array.from(elements).forEach(el => {
if (el.firstChild) {
el.removeChild(el.firstChild);
}
el.insertAdjacentHTML('afterbegin', copyButton);
});
});
Loading