单个html文件,使用 $$$ 作为多图分隔标记
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>Markdown → 自动切图</title>
<script src="https://cdn.jsdelivr.net/npm/markdown-it@14/dist/markdown-it.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js"></script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/highlight.js/styles/github.css"
/>
<style>
body {
margin: 0;
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI",
"Microsoft YaHei", sans-serif;
background: #f6f8fa;
color: #24292f;
display: flex;
height: 100vh;
}
textarea {
width: 35%;
padding: 16px;
border: none;
outline: none;
font-size: 14px;
resize: none;
background: #ffffff;
color: #24292f;
border-right: 1px solid #d0d7de;
}
#preview {
flex: 1;
overflow-y: auto;
padding: 32px;
}
.card {
background: #ffffff;
border-radius: 0;
padding: 32px;
margin-bottom: 32px;
border: 1px solid #d0d7de;
}
h2 {
font-size: 34px;
margin-bottom: 16px;
color: #1f2328;
}
p,
li {
font-size: 20px;
line-height: 1.7;
color: #24292f;
}
button {
position: fixed;
right: 24px;
bottom: 24px;
padding: 14px 24px;
font-size: 16px;
border-radius: 12px;
border: none;
background: #38bdf8;
cursor: pointer;
}
table {
border-collapse: collapse;
width: 100%;
margin: 24px 0;
font-size: 18px; /* 关键:整体放大 */
}
th,
td {
border: 1px solid #d0d7de;
padding: 12px 16px; /* 关键:拉开空间 */
line-height: 1.6; /* 关键:行高 */
white-space: nowrap; /* 数字不换行 */
}
th {
background: #f6f8fa;
font-weight: 600;
text-align: center;
}
td {
text-align: right; /* 金额、数字右对齐 */
}
/* 第一列(年份)左对齐 */
td:first-child,
th:first-child {
text-align: left;
}
/* 最后一列强调 */
td:last-child {
font-weight: 600;
color: #1f2328;
}
</style>
</head>
<body>
<textarea
id="mdInput"
placeholder="粘贴 Markdown,这里使用 ## 标题 自动切图"
></textarea>
<div id="preview"></div>
<button onclick="exportImages()">导出图片</button>
<script>
const md = window.markdownit({ html: true, linkify: true });
md.enable("table");
const input = document.getElementById("mdInput");
const preview = document.getElementById("preview");
input.addEventListener("input", render);
function render() {
const text = input.value;
preview.innerHTML = "";
const sections = text
.split("$$$")
.slice(1)
.map((s) => s.trim());
sections.forEach((section) => {
const div = document.createElement("div");
div.className = "card";
div.innerHTML = md.render(section);
preview.appendChild(div);
});
}
async function exportImages() {
const cards = document.querySelectorAll(".card");
let index = 1;
for (const card of cards) {
const canvas = await html2canvas(card, { scale: 2 });
const link = document.createElement("a");
link.download = String(index).padStart(2, "0") + ".png";
link.href = canvas.toDataURL();
link.click();
index++;
}
}
</script>
</body>
</html>