Skip to content

copy into ai mdbook extention

Best mobile-friendly “copy into ChatGPT” setup. See mdBook Renderers

Use a tiny additional-js script that adds a “Copy page as Markdown” button and calls navigator.clipboard.writeText() on the main article content. This works on mobile (including iOS Safari) as long as you serve over HTTPS and trigger it from a user tap. Fall back to “select all” if the Clipboard API is unavailable or permission is denied.

References:

  • Built-in copy buttons only handle code blocks, not entire pages. See mdBook Reading
  • Enabling the Markdown backend gives you a raw .md file, but it still requires manual select-all on mobile. See mdBook Renderers
  • Print single-page is fine for long copies, but heavier and less precise for prompts. See mdBook Renderers
[output.html]
additional-js = ["copy-page.js"]
[output.markdown] # optional "View raw" link in your theme
[output.html.print] # optional one-page view
enable = true
page-break = true

See mdBook Renderers

See MDN Clipboard.writeText

(() => {
// Prefer the main content container used by mdBook themes
const root = document.getElementById("content") || document.querySelector("main, .content, article, .page");
if (!root) return;
const btn = document.createElement("button");
btn.textContent = "Copy page as Markdown";
btn.style.position = "fixed";
btn.style.right = "0.75rem";
btn.style.bottom = "0.75rem";
btn.style.zIndex = "2147483647";
btn.style.padding = "0.6rem 0.8rem";
async function copyText(text) {
try {
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(text); // requires HTTPS + user tap
btn.textContent = "Copied!";
setTimeout(() => (btn.textContent = "Copy page as Markdown"), 1200);
} else {
// Fallback: select + execCommand
const ta = document.createElement("textarea");
ta.value = text;
ta.style.position = "fixed";
ta.style.opacity = "0";
document.body.appendChild(ta);
ta.focus();
ta.select();
document.execCommand("copy");
document.body.removeChild(ta);
btn.textContent = "Copied!";
setTimeout(() => (btn.textContent = "Copy page as Markdown"), 1200);
}
} catch {
// As a last resort, highlight content so the user can copy manually
const range = document.createRange();
range.selectNodeContents(root);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
alert("Tap Copy to finish");
}
}
function toMarkdownish(node) {
// Lightweight HTML→Markdown pass that preserves headings, lists, code, links.
// Keeps it simple for robust mobile paste into ChatGPT.
const clone = node.cloneNode(true);
// Strip nav/search, prev/next, footer
clone.querySelectorAll("nav, header, .sidebar, .menu-title, .menu, .left, .right, footer").forEach(e => e.remove());
// Strip "$ " prompts from code to be AI-ready
clone.querySelectorAll("code, pre").forEach(block => {
block.innerHTML = block.innerHTML.replace(/(^|\n)\$[ ]/g, "$1");
});
// Convert common elements to Markdown-friendly text
// Headings
for (let i = 6; i >= 1; i--) {
clone.querySelectorAll("h" + i).forEach(h => h.outerHTML = "\n" + "#".repeat(i) + " " + h.textContent + "\n");
}
// Links
clone.querySelectorAll("a").forEach(a => a.outerHTML = `[${a.textContent}](${a.href})`);
// Code blocks
clone.querySelectorAll("pre code").forEach(c => c.parentElement.outerHTML = "\n```\n" + c.textContent + "\n```\n");
// Inline code
clone.querySelectorAll("code").forEach(c => c.outerHTML = "`" + c.textContent + "`");
// Lists
clone.querySelectorAll("ul li").forEach(li => li.outerHTML = "- " + li.textContent + "\n");
clone.querySelectorAll("ol").forEach(ol => {
Array.from(ol.children).forEach((li, idx) => li.outerHTML = (idx + 1) + ". " + li.textContent + "\n");
ol.outerHTML = ol.textContent;
});
// Paragraphs
clone.querySelectorAll("p").forEach(p => p.outerHTML = p.textContent + "\n\n");
return clone.textContent.replace(/\n{3,}/g, "\n\n").trim();
}
btn.addEventListener("click", () => copyText(toMarkdownish(root)));
document.body.appendChild(btn);
})();
  • Keep built-in code copy buttons on ([output.html.playground].copyable = true) for snippet-level workflows. See mdBook Renderers
  • Add a “View raw Markdown” link using the Markdown backend for power users. See mdBook Renderers
  • If you use a page ToC preprocessor, pair it with the button so mobile users can jump to a section then copy. See mdbook-pagetoc