diff --git a/.agents/skills/tttk-authoring/reference.md b/.agents/skills/tttk-authoring/reference.md index ed0975d..bad7c6a 100644 --- a/.agents/skills/tttk-authoring/reference.md +++ b/.agents/skills/tttk-authoring/reference.md @@ -116,13 +116,13 @@ Prefer the `yaml role=tag` form — it is the only form that supports template l Paginates a markdown document into A4 landscape sheets for printing. -Each sheet holds two A5 pages side by side, and each A5 page flows the markdown into `columns` columns. `margin` and `gap` are in millimetres, `font` is in points. `pageNumbers` adds an `n / total` footer and `cutMarks` draws the centre cut line. The preview modal exports through the browser's print dialog (choose A4 landscape, no margins, 100% scale). +Each sheet holds two A5 pages side by side, and each A5 page flows the markdown into `columns` columns. `margin`, `gap`, and `font` are in millimetres (the body font defaults to 3mm). `pageNumbers` adds an `n / total` footer in the outer corner and `cutMarks` draws the centre cut line. The preview modal exports through the browser's print dialog (choose A4 landscape, no margins, 100% scale). - Body: markdown path, optional #section - Attributes: `columns`, `margin`, `gap`, `font`, `title`, `pageNumbers`, `cutMarks` ```markdown -:md-print[./rules.md]{columns="2" margin="10" gap="5" font="9"} +:md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"} ``` ````markdown @@ -132,7 +132,7 @@ body: ./rules.md columns: 2 margin: 10 gap: 5 -font: 9 +font: 3 title: 规则书 ``` ```` diff --git a/docs/markdown.md b/docs/markdown.md index 809f5bc..d44c83c 100644 --- a/docs/markdown.md +++ b/docs/markdown.md @@ -464,7 +464,7 @@ data-config: ```markdown :md-print[./rules.md] -:md-print[./rules.md]{columns="2" margin="10" gap="5" font="9"} +:md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"} ``` **功能:** @@ -480,9 +480,9 @@ data-config: | `columns` | number | `2` | 每个 A5 页面的列数(1–4) | | `margin` | number | `10` | 页面边距(毫米) | | `gap` | number | `5` | 列间距(毫米) | -| `font` | number | `9` | 正文字号(磅) | +| `font` | number | `3` | 正文字号(毫米) | | `title` | string | - | 页眉标题 | -| `pageNumbers` | boolean | `true` | 是否显示页码 | +| `pageNumbers` | boolean | `true` | 是否在页面外侧角落显示页码 | | `cutMarks` | boolean | `true` | 是否显示 A4 中缝裁切线 | **YAML 写法:** @@ -493,7 +493,7 @@ body: ./rules.md columns: 2 margin: 10 gap: 5 -font: 9 +font: 3 title: 规则书 ``` diff --git a/docs/reference.md b/docs/reference.md index ed0975d..bad7c6a 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -116,13 +116,13 @@ Prefer the `yaml role=tag` form — it is the only form that supports template l Paginates a markdown document into A4 landscape sheets for printing. -Each sheet holds two A5 pages side by side, and each A5 page flows the markdown into `columns` columns. `margin` and `gap` are in millimetres, `font` is in points. `pageNumbers` adds an `n / total` footer and `cutMarks` draws the centre cut line. The preview modal exports through the browser's print dialog (choose A4 landscape, no margins, 100% scale). +Each sheet holds two A5 pages side by side, and each A5 page flows the markdown into `columns` columns. `margin`, `gap`, and `font` are in millimetres (the body font defaults to 3mm). `pageNumbers` adds an `n / total` footer in the outer corner and `cutMarks` draws the centre cut line. The preview modal exports through the browser's print dialog (choose A4 landscape, no margins, 100% scale). - Body: markdown path, optional #section - Attributes: `columns`, `margin`, `gap`, `font`, `title`, `pageNumbers`, `cutMarks` ```markdown -:md-print[./rules.md]{columns="2" margin="10" gap="5" font="9"} +:md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"} ``` ````markdown @@ -132,7 +132,7 @@ body: ./rules.md columns: 2 margin: 10 gap: 5 -font: 9 +font: 3 title: 规则书 ``` ```` diff --git a/src/cli/validate/known.ts b/src/cli/validate/known.ts index c17ec69..1f46cff 100644 --- a/src/cli/validate/known.ts +++ b/src/cli/validate/known.ts @@ -82,11 +82,11 @@ export const KNOWN_ELEMENTS: readonly ElementSpec[] = [ summary: "Paginates a markdown document into A4 landscape sheets for printing.", details: - "Each sheet holds two A5 pages side by side, and each A5 page flows the markdown into `columns` columns. `margin` and `gap` are in millimetres, `font` is in points. `pageNumbers` adds an `n / total` footer and `cutMarks` draws the centre cut line. The preview modal exports through the browser's print dialog (choose A4 landscape, no margins, 100% scale).", + "Each sheet holds two A5 pages side by side, and each A5 page flows the markdown into `columns` columns. `margin`, `gap`, and `font` are in millimetres (the body font defaults to 3mm). `pageNumbers` adds an `n / total` footer in the outer corner and `cutMarks` draws the centre cut line. The preview modal exports through the browser's print dialog (choose A4 landscape, no margins, 100% scale).", refKind: "md", examples: [ - ':md-print[./rules.md]{columns="2" margin="10" gap="5" font="9"}', - "```yaml role=tag\ntag: md-print\nbody: ./rules.md\ncolumns: 2\nmargin: 10\ngap: 5\nfont: 9\ntitle: 规则书\n```", + ':md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"}', + "```yaml role=tag\ntag: md-print\nbody: ./rules.md\ncolumns: 2\nmargin: 10\ngap: 5\nfont: 3\ntitle: 规则书\n```", ], }, { diff --git a/src/components/md-print/PrintPreview.tsx b/src/components/md-print/PrintPreview.tsx index 6f55f93..dba2c20 100644 --- a/src/components/md-print/PrintPreview.tsx +++ b/src/components/md-print/PrintPreview.tsx @@ -90,7 +90,15 @@ export function PrintPreview(props: PrintPreviewProps) { const result = paginate(source, options(), mount); result.pages.forEach((page, index) => { const footer = page.querySelector(".md-print-footer"); - if (footer) footer.textContent = `${index + 1} / ${result.pages.length}`; + if (footer) { + footer.textContent = `${index + 1} / ${result.pages.length}`; + // Left A5 gets the left corner, right A5 gets the right corner. + footer.classList.add( + index % 2 === 0 + ? "md-print-footer--left" + : "md-print-footer--right", + ); + } }); setPages(result.pages); setWarnings(result.warnings); @@ -224,7 +232,7 @@ export function PrintPreview(props: PrintPreviewProps) { class="md-print-content prose" style={{ width: `${columnWidthMm(props.config)}mm`, - "--md-print-font-size": `${props.config.font}pt`, + "--md-print-font-size": `${props.config.font}mm`, position: "absolute", left: "-99999px", top: "0", diff --git a/src/components/md-print/config.test.ts b/src/components/md-print/config.test.ts index 3b13d42..77bb068 100644 --- a/src/components/md-print/config.test.ts +++ b/src/components/md-print/config.test.ts @@ -18,11 +18,16 @@ describe("normalizePrintConfig", () => { expect(config.columns).toBe(3); expect(config.margin).toBe(40); expect(config.gap).toBe(0); - expect(config.font).toBe(16); + expect(config.font).toBe(6); expect(config.pageNumbers).toBe(false); expect(config.cutMarks).toBe(false); }); + test("clamps font to 2..6mm", () => { + expect(normalizePrintConfig({ font: "1" }).font).toBe(2); + expect(normalizePrintConfig({ font: "20" }).font).toBe(6); + }); + test("clamps columns to 1..4", () => { expect(normalizePrintConfig({ columns: "0" }).columns).toBe(1); expect(normalizePrintConfig({ columns: "9" }).columns).toBe(4); @@ -33,7 +38,7 @@ describe("normalizePrintConfig", () => { columns: 2, margin: 12, gap: 6, - font: 10, + font: 3, title: "规则书", pageNumbers: true, cutMarks: false, @@ -43,7 +48,7 @@ describe("normalizePrintConfig", () => { columns: 2, margin: 12, gap: 6, - font: 10, + font: 3, title: "规则书", pageNumbers: true, cutMarks: false, diff --git a/src/components/md-print/config.ts b/src/components/md-print/config.ts index f9d5c61..a4e156f 100644 --- a/src/components/md-print/config.ts +++ b/src/components/md-print/config.ts @@ -4,7 +4,7 @@ export const PRINT_DEFAULTS: PrintConfig = { columns: 2, margin: 10, gap: 5, - font: 9, + font: 3, title: "", pageNumbers: true, cutMarks: true, @@ -43,7 +43,7 @@ export function normalizePrintConfig( ), margin: clamp(toNumber(input.margin, PRINT_DEFAULTS.margin), 5, 40), gap: clamp(toNumber(input.gap, PRINT_DEFAULTS.gap), 0, 20), - font: clamp(toNumber(input.font, PRINT_DEFAULTS.font), 6, 16), + font: clamp(toNumber(input.font, PRINT_DEFAULTS.font), 2, 6), title: typeof input.title === "string" ? input.title : PRINT_DEFAULTS.title, pageNumbers: toBoolean(input.pageNumbers, PRINT_DEFAULTS.pageNumbers), diff --git a/src/components/md-print/index.tsx b/src/components/md-print/index.tsx index a6dc781..82e2cc3 100644 --- a/src/components/md-print/index.tsx +++ b/src/components/md-print/index.tsx @@ -12,7 +12,7 @@ customElement( columns: "2", margin: "10", gap: "5", - font: "9", + font: "3", title: "", pageNumbers: "true", cutMarks: "true", diff --git a/src/components/md-print/paginate.ts b/src/components/md-print/paginate.ts index bc24ae1..685fd84 100644 --- a/src/components/md-print/paginate.ts +++ b/src/components/md-print/paginate.ts @@ -54,7 +54,7 @@ export function createPageElement(opts: PaginateOptions): { page.style.position = "relative"; page.style.overflow = "hidden"; page.style.background = "white"; - page.style.setProperty("--md-print-font-size", `${opts.font}pt`); + page.style.setProperty("--md-print-font-size", `${opts.font}mm`); if (opts.title) { const header = document.createElement("div"); diff --git a/src/components/md-print/types.ts b/src/components/md-print/types.ts index 10c0a5a..3f72630 100644 --- a/src/components/md-print/types.ts +++ b/src/components/md-print/types.ts @@ -5,7 +5,7 @@ export interface PrintConfig { margin: number; /** Column gap in millimetres. */ gap: number; - /** Body font size in points. */ + /** Body font size in millimetres. */ font: number; /** Running header text. Empty hides the header. */ title: string; diff --git a/src/doc-entries/md-print.md b/src/doc-entries/md-print.md index 08895e2..6bffaad 100644 --- a/src/doc-entries/md-print.md +++ b/src/doc-entries/md-print.md @@ -17,7 +17,7 @@ title: 打印版式 **自定义版式:** ```markdown -:md-print[./rules.md]{columns="2" margin="10" gap="5" font="9"} +:md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"} ``` **YAML 写法:** @@ -28,7 +28,7 @@ body: ./rules.md columns: 2 margin: 10 gap: 5 -font: 9 +font: 3 title: 规则书 ``` @@ -41,9 +41,9 @@ title: 规则书 | `columns` | number | `2` | 每个 A5 页面的列数(1–4) | | `margin` | number | `10` | 页面边距(毫米) | | `gap` | number | `5` | 列间距(毫米) | -| `font` | number | `9` | 正文字号(磅) | +| `font` | number | `3` | 正文字号(毫米) | | `title` | string | — | 页眉标题 | -| `pageNumbers` | boolean | `true` | 是否显示 `n / 总数` 页码 | +| `pageNumbers` | boolean | `true` | 是否在页面外侧角落显示 `n / 总数` 页码 | | `cutMarks` | boolean | `true` | 是否显示 A4 中缝裁切线 | ## 打印设置 diff --git a/src/styles.css b/src/styles.css index e6dfb91..5dc72a1 100644 --- a/src/styles.css +++ b/src/styles.css @@ -204,7 +204,7 @@ icon.big .icon-label-stroke { } .md-print-content { - font-size: var(--md-print-font-size, 9pt); + font-size: var(--md-print-font-size, 3mm); line-height: 1.45; color: #000; max-width: none; @@ -257,11 +257,11 @@ icon.big .icon-label-stroke { pointer-events: none; } -.md-print-header, -.md-print-footer { +.md-print-header { position: absolute; left: 0; right: 0; + top: 3mm; text-align: center; font-size: 8pt; color: #6b7280; @@ -270,12 +270,25 @@ icon.big .icon-label-stroke { text-overflow: ellipsis; } -.md-print-header { - top: 3mm; +.md-print-footer { + position: absolute; + bottom: 3mm; + left: 3mm; + font-size: 8pt; + color: #6b7280; + white-space: nowrap; } -.md-print-footer { - bottom: 3mm; +.md-print-footer--left { + left: 3mm; + right: auto; + text-align: left; +} + +.md-print-footer--right { + left: auto; + right: 3mm; + text-align: right; } @media print {