-
I'd like to be able to render a prefix for lines in a code block to indicate the environment (docker, venv, etc.) but would like this prefix to not be copyable by the "copy to clipboard" button. Is this already possible today with some configuration? |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 13 replies
-
You probably mean something like |
Beta Was this translation helpful? Give feedback.
-
as a possible feature request, do you think it would make sense / be possible to edit the Something like:
Which renders to: (venv)$ def bubble_sort(items):
(venv)$ for i in range(len(items)):
(venv)$ for j in range(len(items) - 1 - i):
(venv)$ if items[j] > items[j + 1]:
(venv)$ items[j], items[j + 1] = items[j + 1], items[j] but the |
Beta Was this translation helpful? Give feedback.
-
@facelessuser helped me (mostly) accomplish this, as discussed here. extra.css
somepage.md
This produces output like this. The copy button copies everything, but if you click and drag to highlight the code, it will not copy the prompt ( |
Beta Was this translation helpful? Give feedback.
-
You can do this with the following added TypeScript -- you'll need to compile before using. Define styles for Example output: Only commands are selectable: Copying omits the comments, output, and prefix. This is what's copied:
const codeBlocks = [...document.querySelectorAll(".highlight > pre > code")];
const rules = [
// shell commands
{
prefix: "$ ",
classes: ["code-noselect", "console-input"],
},
// comments
{
prefix: "# ",
plainText: true,
entireLine: true,
classes: ["code-noselect", "c1"],
},
// standard output
{
prefix: "<< ",
plainText: true,
entireLine: true,
deletePrefix: true,
classes: ["code-noselect", "console-output"],
},
];
const zip = (a, b) => a.map((k, i) => [k, b[i]]);
// update code blocks with the mappings defined above
codeBlocks.forEach((block) => {
let text = (block.textContent || "").split("\n");
let html = block.innerHTML.split("\n");
let lines = zip(text, html);
lines = lines.map((line) => {
const lineText = line[0];
const lineHtml = line[1];
const matches = rules.filter((rule) => lineText.startsWith(rule.prefix));
if (matches.length > 1) {
throw new Error("multiple rule matches");
}
if (matches.length === 1) {
const matchingRule = matches[0];
const classes = matchingRule.classes.join(" ");
let newContent: string;
if (matchingRule.plainText) {
newContent = lineText;
} else {
newContent = lineHtml;
newContent = newContent.replace(
matchingRule.prefix.replace(" ", `<span class="w"> </span>`),
matchingRule.prefix
);
}
if (matchingRule.entireLine) {
newContent = `<span class="${classes}">${newContent}</span>`;
} else {
newContent = newContent.replace(
matchingRule.prefix,
`<span class="${classes}">${matchingRule.prefix}</span>`
);
}
if (matchingRule.deletePrefix) {
newContent = newContent.replace(matchingRule.prefix, "");
}
return newContent;
} else {
return lineHtml;
}
});
block.innerHTML = lines.join("\n").trim();
});
// Update html attributes to remove elements with `code-noselect` when copying to clipboard
window.addEventListener("load", () => {
const ids = document.querySelectorAll("*[data-clipboard-target]");
ids.forEach((id) => {
const attr = id.getAttribute("data-clipboard-target");
if (!attr) {
return;
}
const node = document.querySelector(attr);
if (!node) {
return;
}
let text: string[] = [];
node.childNodes.forEach((child) => {
if (child.nodeName === "#text") {
text.push(child.textContent || "");
} else if (!(child as any).classList.contains("code-noselect")) {
text.push((child as any).innerText);
}
});
let joinedText = text.join("");
id.setAttribute(
"data-clipboard-text",
joinedText.trim().replace(/(?:\h*\n){2,}/g, "\n")
);
id.removeAttribute("data-clipboard-target");
});
}); |
Beta Was this translation helpful? Give feedback.
as a possible feature request, do you think it would make sense / be possible to edit the
linenumber
feature of code blocks and instead add arbitrary strings instead?Something like:
Which renders to:
but the
(venv)$
is not…