Skip to content

Commit 6acfee6

Browse files
committed
docs: Preserve markdown when copying prompt blocks
Add prompt-copy.js that intercepts sphinx-copybutton on prompt admonitions and reconstructs inline markdown from the DOM. Wraps <code> elements in backticks so copied text preserves formatting like `make test` instead of plain "make test".
1 parent b16a136 commit 6acfee6

2 files changed

Lines changed: 64 additions & 0 deletions

File tree

docs/_static/js/prompt-copy.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Markdown-preserving copy for prompt blocks.
3+
*
4+
* sphinx-copybutton uses innerText which strips HTML. This script
5+
* intercepts copy on .admonition.prompt buttons and reconstructs
6+
* inline markdown (backtick-wrapping <code> elements) before copying.
7+
*/
8+
(function () {
9+
function toMarkdown(el) {
10+
var text = "";
11+
for (var i = 0; i < el.childNodes.length; i++) {
12+
var node = el.childNodes[i];
13+
if (node.nodeType === Node.TEXT_NODE) {
14+
text += node.textContent;
15+
} else if (node.nodeType === Node.ELEMENT_NODE) {
16+
if (node.tagName === "CODE") {
17+
text += "`" + node.textContent + "`";
18+
} else {
19+
text += toMarkdown(node);
20+
}
21+
}
22+
}
23+
return text;
24+
}
25+
26+
function init() {
27+
var buttons = document.querySelectorAll(
28+
"div.admonition.prompt button.copybtn"
29+
);
30+
buttons.forEach(function (btn) {
31+
btn.addEventListener(
32+
"click",
33+
function (e) {
34+
e.stopImmediatePropagation();
35+
e.preventDefault();
36+
37+
var targetId = btn.getAttribute("data-clipboard-target");
38+
var target = document.querySelector(targetId);
39+
if (!target) return;
40+
41+
var markdown = toMarkdown(target);
42+
navigator.clipboard.writeText(markdown).then(function () {
43+
btn.setAttribute("data-tooltip", "Copied!");
44+
btn.classList.add("success");
45+
setTimeout(function () {
46+
btn.setAttribute("data-tooltip", "Copy");
47+
btn.classList.remove("success");
48+
}, 2000);
49+
});
50+
},
51+
true
52+
);
53+
});
54+
}
55+
56+
if (document.readyState === "loading") {
57+
document.addEventListener("DOMContentLoaded", function () {
58+
setTimeout(init, 100);
59+
});
60+
} else {
61+
setTimeout(init, 100);
62+
}
63+
})();

docs/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,4 +291,5 @@ def remove_tabs_js(app: Sphinx, exc: Exception) -> None:
291291
def setup(app: Sphinx) -> None:
292292
"""Configure Sphinx app hooks."""
293293
app.add_js_file("js/spa-nav.js", loading_method="defer")
294+
app.add_js_file("js/prompt-copy.js", loading_method="defer")
294295
app.connect("build-finished", remove_tabs_js)

0 commit comments

Comments
 (0)