|
|
@@ -18,6 +18,16 @@
|
|
|
border: 1px solid color-mix(in srgb, currentColor 30%, transparent);
|
|
|
background: canvas; color: inherit; border-radius: 4px; }
|
|
|
#copybtn:hover { opacity: 1; }
|
|
|
+ /* per-block copy buttons in rendered markdown: hidden until the block
|
|
|
+ is hovered; while a block copy is visible, the full-text button hides
|
|
|
+ so the two never compete for the cursor */
|
|
|
+ body:has(article pre:hover) #copybtn { opacity: 0; pointer-events: none; }
|
|
|
+ .copyblk { position: absolute; top: 6px; right: 8px; opacity: 0; cursor: pointer;
|
|
|
+ padding: 1px 8px; border: 1px solid color-mix(in srgb, currentColor 30%, transparent);
|
|
|
+ background: canvas; color: inherit; border-radius: 4px;
|
|
|
+ font: 11px system-ui, sans-serif; transition: opacity .15s; }
|
|
|
+ article pre:hover .copyblk, .copyblk:focus-visible { opacity: 1; }
|
|
|
+ .copyblk:hover { background: color-mix(in srgb, currentColor 12%, canvas); }
|
|
|
#tabs button { padding: 2px 10px; cursor: pointer; border: 1px solid color-mix(in srgb, currentColor 30%, transparent);
|
|
|
background: canvas; color: inherit; border-radius: 4px 0 0 4px; }
|
|
|
#tabs button + button { border-radius: 0 4px 4px 0; border-left: 0; }
|
|
|
@@ -29,7 +39,7 @@
|
|
|
article th, article td { border: 1px solid color-mix(in srgb, currentColor 25%, transparent); padding: 3px 10px; }
|
|
|
article th { background: color-mix(in srgb, currentColor 8%, canvas); }
|
|
|
article code { font: 12px ui-monospace, monospace; background: color-mix(in srgb, currentColor 10%, canvas); padding: 1px 4px; border-radius: 3px; }
|
|
|
- article pre { background: color-mix(in srgb, currentColor 8%, canvas); padding: 10px 12px; border-radius: 6px; }
|
|
|
+ article pre { background: color-mix(in srgb, currentColor 8%, canvas); padding: 10px 12px; border-radius: 6px; position: relative; }
|
|
|
article pre code { background: none; padding: 0; }
|
|
|
article blockquote { margin: 0.6em 0; padding: 4px 14px; border-left: 3px solid color-mix(in srgb, currentColor 35%, transparent); color: color-mix(in srgb, currentColor 75%, canvas); }
|
|
|
article li { margin: 2px 0; }
|
|
|
@@ -95,7 +105,7 @@ function mdBlocks(lines) {
|
|
|
if (/^```/.test(l)) {
|
|
|
let j = i + 1;
|
|
|
while (j < lines.length && !/^```/.test(lines[j])) j++;
|
|
|
- out.push("<pre><code>" + esc(lines.slice(i + 1, j).join("\n")) + "</code></pre>");
|
|
|
+ out.push('<pre><button class="copyblk" title="copy block">⧉</button><code>' + esc(lines.slice(i + 1, j).join("\n")) + "</code></pre>");
|
|
|
i = j + 1; continue;
|
|
|
}
|
|
|
if (/^\s*\|.*\|\s*$/.test(l) && i + 1 < lines.length && /^\s*\|[\s:|-]+\|\s*$/.test(lines[i + 1])) {
|
|
|
@@ -196,6 +206,18 @@ cpBtn.onclick = () => {
|
|
|
if (navigator.clipboard) navigator.clipboard.writeText(META.content).then(() => done(true), () => done(fallbackCopy(META.content)));
|
|
|
else done(fallbackCopy(META.content));
|
|
|
};
|
|
|
+// per-block copy: copies the block's code text, feedback swaps the glyph
|
|
|
+document.getElementById("out").addEventListener("click", (e) => {
|
|
|
+ const b = e.target.closest(".copyblk");
|
|
|
+ if (!b) return;
|
|
|
+ const text = b.parentElement.querySelector("code").textContent;
|
|
|
+ const done = (ok) => {
|
|
|
+ b.textContent = ok ? "✓" : "✗";
|
|
|
+ setTimeout(() => (b.textContent = "⧉"), 900);
|
|
|
+ };
|
|
|
+ if (navigator.clipboard) navigator.clipboard.writeText(text).then(() => done(true), () => done(fallbackCopy(text)));
|
|
|
+ else done(fallbackCopy(text));
|
|
|
+});
|
|
|
|
|
|
// ---------- render ----------
|
|
|
let mode = EXT === "md" ? "rendered" : "raw";
|