feat(md-print): add timestamp footer option
This commit is contained in:
@@ -48,7 +48,7 @@ Nest with more colons (`::::`, `:::::`).
|
|||||||
| `:md-dice` | dice formula | `key` |
|
| `:md-dice` | dice formula | `key` |
|
||||||
| `:md-table` | CSV path or inline id | `roll`, `remix` |
|
| `:md-table` | CSV path or inline id | `roll`, `remix` |
|
||||||
| `:md-deck` | CSV path | `size`, `grid`, `layers` |
|
| `:md-deck` | CSV path | `size`, `grid`, `layers` |
|
||||||
| `:md-print` | markdown path, optional #section | `columns`, `margin`, `gap`, `font`, `title`, `pageNumbers`, `cutMarks` |
|
| `:md-print` | markdown path, optional #section | `columns`, `margin`, `gap`, `font`, `title`, `pageNumbers`, `timestamp`, `cutMarks` |
|
||||||
| `:md-link` | path, optional #section | — |
|
| `:md-link` | path, optional #section | — |
|
||||||
| `:md-embed` | path, optional #section | `headingBase` |
|
| `:md-embed` | path, optional #section | `headingBase` |
|
||||||
| `:md-bg` | image path or CSS color | `fit` |
|
| `:md-bg` | image path or CSS color | `fit` |
|
||||||
@@ -116,15 +116,19 @@ 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.
|
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`, `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).
|
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, `timestamp` appends the export time to that 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).
|
||||||
|
|
||||||
- Body: markdown path, optional #section
|
- Body: markdown path, optional #section
|
||||||
- Attributes: `columns`, `margin`, `gap`, `font`, `title`, `pageNumbers`, `cutMarks`
|
- Attributes: `columns`, `margin`, `gap`, `font`, `title`, `pageNumbers`, `timestamp`, `cutMarks`
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
:md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"}
|
:md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
:md-print[./rules.md]{timestamp=true}
|
||||||
|
```
|
||||||
|
|
||||||
````markdown
|
````markdown
|
||||||
```yaml role=tag
|
```yaml role=tag
|
||||||
tag: md-print
|
tag: md-print
|
||||||
@@ -134,6 +138,7 @@ margin: 10
|
|||||||
gap: 5
|
gap: 5
|
||||||
font: 3
|
font: 3
|
||||||
title: 规则书
|
title: 规则书
|
||||||
|
timestamp: true
|
||||||
```
|
```
|
||||||
````
|
````
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -471,7 +471,7 @@ data-config:
|
|||||||
- 自动分页:内容按块级元素流入 A5 页面,段落、列表和表格可在分页处拆分
|
- 自动分页:内容按块级元素流入 A5 页面,段落、列表和表格可在分页处拆分
|
||||||
- 每张 A4 横版放两个 A5 页面,每个 A5 页面默认两列
|
- 每张 A4 横版放两个 A5 页面,每个 A5 页面默认两列
|
||||||
- 预览中可直接打印或另存为 PDF
|
- 预览中可直接打印或另存为 PDF
|
||||||
- 支持页眉标题、页码和中缝裁切线
|
- 支持页眉标题、页码、导出时间戳和中缝裁切线
|
||||||
|
|
||||||
**属性:**
|
**属性:**
|
||||||
|
|
||||||
@@ -483,6 +483,7 @@ data-config:
|
|||||||
| `font` | number | `3` | 正文字号(毫米) |
|
| `font` | number | `3` | 正文字号(毫米) |
|
||||||
| `title` | string | - | 页眉标题 |
|
| `title` | string | - | 页眉标题 |
|
||||||
| `pageNumbers` | boolean | `true` | 是否在页面外侧角落显示页码 |
|
| `pageNumbers` | boolean | `true` | 是否在页面外侧角落显示页码 |
|
||||||
|
| `timestamp` | boolean | `false` | 是否在页码旁边显示导出时间 |
|
||||||
| `cutMarks` | boolean | `true` | 是否显示 A4 中缝裁切线 |
|
| `cutMarks` | boolean | `true` | 是否显示 A4 中缝裁切线 |
|
||||||
|
|
||||||
**YAML 写法:**
|
**YAML 写法:**
|
||||||
@@ -495,8 +496,17 @@ margin: 10
|
|||||||
gap: 5
|
gap: 5
|
||||||
font: 3
|
font: 3
|
||||||
title: 规则书
|
title: 规则书
|
||||||
|
timestamp: true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**导出时间戳:**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
:md-print[./rules.md]{timestamp=true}
|
||||||
|
```
|
||||||
|
|
||||||
|
开启后页脚会显示类似 `3 / 12 · 2026-10-23 14:05` 的内容。页码位于页面外侧底角:左侧 A5 在左下角,右侧 A5 在右下角。
|
||||||
|
|
||||||
**打印设置:** 在浏览器打印对话框中选择 A4、横向、无边距、100% 缩放。
|
**打印设置:** 在浏览器打印对话框中选择 A4、横向、无边距、100% 缩放。
|
||||||
|
|
||||||
### 🧶 叙事线组件 (md-yarn-spinner)
|
### 🧶 叙事线组件 (md-yarn-spinner)
|
||||||
|
|||||||
+8
-3
@@ -48,7 +48,7 @@ Nest with more colons (`::::`, `:::::`).
|
|||||||
| `:md-dice` | dice formula | `key` |
|
| `:md-dice` | dice formula | `key` |
|
||||||
| `:md-table` | CSV path or inline id | `roll`, `remix` |
|
| `:md-table` | CSV path or inline id | `roll`, `remix` |
|
||||||
| `:md-deck` | CSV path | `size`, `grid`, `layers` |
|
| `:md-deck` | CSV path | `size`, `grid`, `layers` |
|
||||||
| `:md-print` | markdown path, optional #section | `columns`, `margin`, `gap`, `font`, `title`, `pageNumbers`, `cutMarks` |
|
| `:md-print` | markdown path, optional #section | `columns`, `margin`, `gap`, `font`, `title`, `pageNumbers`, `timestamp`, `cutMarks` |
|
||||||
| `:md-link` | path, optional #section | — |
|
| `:md-link` | path, optional #section | — |
|
||||||
| `:md-embed` | path, optional #section | `headingBase` |
|
| `:md-embed` | path, optional #section | `headingBase` |
|
||||||
| `:md-bg` | image path or CSS color | `fit` |
|
| `:md-bg` | image path or CSS color | `fit` |
|
||||||
@@ -116,15 +116,19 @@ 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.
|
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`, `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).
|
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, `timestamp` appends the export time to that 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).
|
||||||
|
|
||||||
- Body: markdown path, optional #section
|
- Body: markdown path, optional #section
|
||||||
- Attributes: `columns`, `margin`, `gap`, `font`, `title`, `pageNumbers`, `cutMarks`
|
- Attributes: `columns`, `margin`, `gap`, `font`, `title`, `pageNumbers`, `timestamp`, `cutMarks`
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
:md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"}
|
:md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
:md-print[./rules.md]{timestamp=true}
|
||||||
|
```
|
||||||
|
|
||||||
````markdown
|
````markdown
|
||||||
```yaml role=tag
|
```yaml role=tag
|
||||||
tag: md-print
|
tag: md-print
|
||||||
@@ -134,6 +138,7 @@ margin: 10
|
|||||||
gap: 5
|
gap: 5
|
||||||
font: 3
|
font: 3
|
||||||
title: 规则书
|
title: 规则书
|
||||||
|
timestamp: true
|
||||||
```
|
```
|
||||||
````
|
````
|
||||||
|
|
||||||
|
|||||||
@@ -77,16 +77,18 @@ export const KNOWN_ELEMENTS: readonly ElementSpec[] = [
|
|||||||
"font",
|
"font",
|
||||||
"title",
|
"title",
|
||||||
"pageNumbers",
|
"pageNumbers",
|
||||||
|
"timestamp",
|
||||||
"cutMarks",
|
"cutMarks",
|
||||||
],
|
],
|
||||||
summary:
|
summary:
|
||||||
"Paginates a markdown document into A4 landscape sheets for printing.",
|
"Paginates a markdown document into A4 landscape sheets for printing.",
|
||||||
details:
|
details:
|
||||||
"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).",
|
"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, `timestamp` appends the export time to that 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).",
|
||||||
refKind: "md",
|
refKind: "md",
|
||||||
examples: [
|
examples: [
|
||||||
':md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"}',
|
':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```",
|
':md-print[./rules.md]{timestamp=true}',
|
||||||
|
"```yaml role=tag\ntag: md-print\nbody: ./rules.md\ncolumns: 2\nmargin: 10\ngap: 5\nfont: 3\ntitle: 规则书\ntimestamp: true\n```",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ import {
|
|||||||
} from "./paginate";
|
} from "./paginate";
|
||||||
import { exportPrintPDF } from "./print-export";
|
import { exportPrintPDF } from "./print-export";
|
||||||
|
|
||||||
|
function formatTimestamp(date: Date): string {
|
||||||
|
const pad = (n: number) => String(n).padStart(2, "0");
|
||||||
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
||||||
|
}
|
||||||
|
|
||||||
export interface PrintPreviewProps {
|
export interface PrintPreviewProps {
|
||||||
src: string;
|
src: string;
|
||||||
section?: string;
|
section?: string;
|
||||||
@@ -69,6 +74,23 @@ export function PrintPreview(props: PrintPreviewProps) {
|
|||||||
articlePath: props.articlePath,
|
articlePath: props.articlePath,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const applyFooter = (pageList: HTMLElement[], timestamp: string) => {
|
||||||
|
pageList.forEach((page, index) => {
|
||||||
|
const footer = page.querySelector(".md-print-footer");
|
||||||
|
if (!footer) return;
|
||||||
|
const pageLabel = props.config.pageNumbers
|
||||||
|
? `${index + 1} / ${pageList.length}`
|
||||||
|
: "";
|
||||||
|
footer.textContent = [pageLabel, timestamp].filter(Boolean).join(" · ");
|
||||||
|
// 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",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const runPagination = async () => {
|
const runPagination = async () => {
|
||||||
const md = content();
|
const md = content();
|
||||||
const source = sourceEl();
|
const source = sourceEl();
|
||||||
@@ -88,18 +110,10 @@ export function PrintPreview(props: PrintPreviewProps) {
|
|||||||
await waitForStableSize(source, 300, 4000);
|
await waitForStableSize(source, 300, 4000);
|
||||||
|
|
||||||
const result = paginate(source, options(), mount);
|
const result = paginate(source, options(), mount);
|
||||||
result.pages.forEach((page, index) => {
|
applyFooter(
|
||||||
const footer = page.querySelector(".md-print-footer");
|
result.pages,
|
||||||
if (footer) {
|
props.config.timestamp ? formatTimestamp(new Date()) : "",
|
||||||
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);
|
setPages(result.pages);
|
||||||
setWarnings(result.warnings);
|
setWarnings(result.warnings);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -164,6 +178,10 @@ export function PrintPreview(props: PrintPreviewProps) {
|
|||||||
|
|
||||||
const handleExport = async () => {
|
const handleExport = async () => {
|
||||||
try {
|
try {
|
||||||
|
// Refresh the timestamp so the exported file records the export time.
|
||||||
|
if (props.config.timestamp) {
|
||||||
|
applyFooter(pages(), formatTimestamp(new Date()));
|
||||||
|
}
|
||||||
await exportPrintPDF(pages(), props.config, title(), props.articlePath);
|
await exportPrintPDF(pages(), props.config, title(), props.articlePath);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setError(e instanceof Error ? e.message : String(e));
|
setError(e instanceof Error ? e.message : String(e));
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ describe("normalizePrintConfig", () => {
|
|||||||
gap: "-5",
|
gap: "-5",
|
||||||
font: "20",
|
font: "20",
|
||||||
pageNumbers: "false",
|
pageNumbers: "false",
|
||||||
|
timestamp: "true",
|
||||||
cutMarks: "no",
|
cutMarks: "no",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -20,6 +21,7 @@ describe("normalizePrintConfig", () => {
|
|||||||
expect(config.gap).toBe(0);
|
expect(config.gap).toBe(0);
|
||||||
expect(config.font).toBe(6);
|
expect(config.font).toBe(6);
|
||||||
expect(config.pageNumbers).toBe(false);
|
expect(config.pageNumbers).toBe(false);
|
||||||
|
expect(config.timestamp).toBe(true);
|
||||||
expect(config.cutMarks).toBe(false);
|
expect(config.cutMarks).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -41,6 +43,7 @@ describe("normalizePrintConfig", () => {
|
|||||||
font: 3,
|
font: 3,
|
||||||
title: "规则书",
|
title: "规则书",
|
||||||
pageNumbers: true,
|
pageNumbers: true,
|
||||||
|
timestamp: true,
|
||||||
cutMarks: false,
|
cutMarks: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -51,7 +54,13 @@ describe("normalizePrintConfig", () => {
|
|||||||
font: 3,
|
font: 3,
|
||||||
title: "规则书",
|
title: "规则书",
|
||||||
pageNumbers: true,
|
pageNumbers: true,
|
||||||
|
timestamp: true,
|
||||||
cutMarks: false,
|
cutMarks: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("timestamp defaults to false", () => {
|
||||||
|
expect(normalizePrintConfig().timestamp).toBe(false);
|
||||||
|
expect(normalizePrintConfig({ timestamp: "false" }).timestamp).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export const PRINT_DEFAULTS: PrintConfig = {
|
|||||||
font: 3,
|
font: 3,
|
||||||
title: "",
|
title: "",
|
||||||
pageNumbers: true,
|
pageNumbers: true,
|
||||||
|
timestamp: false,
|
||||||
cutMarks: true,
|
cutMarks: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -47,6 +48,7 @@ export function normalizePrintConfig(
|
|||||||
title:
|
title:
|
||||||
typeof input.title === "string" ? input.title : PRINT_DEFAULTS.title,
|
typeof input.title === "string" ? input.title : PRINT_DEFAULTS.title,
|
||||||
pageNumbers: toBoolean(input.pageNumbers, PRINT_DEFAULTS.pageNumbers),
|
pageNumbers: toBoolean(input.pageNumbers, PRINT_DEFAULTS.pageNumbers),
|
||||||
|
timestamp: toBoolean(input.timestamp, PRINT_DEFAULTS.timestamp),
|
||||||
cutMarks: toBoolean(input.cutMarks, PRINT_DEFAULTS.cutMarks),
|
cutMarks: toBoolean(input.cutMarks, PRINT_DEFAULTS.cutMarks),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ customElement<PrintProps>(
|
|||||||
font: "3",
|
font: "3",
|
||||||
title: "",
|
title: "",
|
||||||
pageNumbers: "true",
|
pageNumbers: "true",
|
||||||
|
timestamp: "false",
|
||||||
cutMarks: "true",
|
cutMarks: "true",
|
||||||
},
|
},
|
||||||
(props, { element }) => {
|
(props, { element }) => {
|
||||||
|
|||||||
@@ -2,7 +2,42 @@
|
|||||||
* @jest-environment jsdom
|
* @jest-environment jsdom
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { splitTextElementAt } from "./paginate";
|
import { PRINT_DEFAULTS } from "./config";
|
||||||
|
import { createPageElement, splitTextElementAt } from "./paginate";
|
||||||
|
|
||||||
|
describe("createPageElement", () => {
|
||||||
|
const base = { ...PRINT_DEFAULTS, articlePath: "rules.md" };
|
||||||
|
|
||||||
|
test("adds a footer when page numbers are enabled", () => {
|
||||||
|
const { page } = createPageElement({
|
||||||
|
...base,
|
||||||
|
pageNumbers: true,
|
||||||
|
timestamp: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(page.querySelector(".md-print-footer")).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("adds a footer when only the timestamp is enabled", () => {
|
||||||
|
const { page } = createPageElement({
|
||||||
|
...base,
|
||||||
|
pageNumbers: false,
|
||||||
|
timestamp: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(page.querySelector(".md-print-footer")).not.toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("omits the footer when both are disabled", () => {
|
||||||
|
const { page } = createPageElement({
|
||||||
|
...base,
|
||||||
|
pageNumbers: false,
|
||||||
|
timestamp: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(page.querySelector(".md-print-footer")).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("splitTextElementAt", () => {
|
describe("splitTextElementAt", () => {
|
||||||
test("splits at a word boundary", () => {
|
test("splits at a word boundary", () => {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export function createPageElement(opts: PaginateOptions): {
|
|||||||
flow.style.width = "100%";
|
flow.style.width = "100%";
|
||||||
page.appendChild(flow);
|
page.appendChild(flow);
|
||||||
|
|
||||||
if (opts.pageNumbers) {
|
if (opts.pageNumbers || opts.timestamp) {
|
||||||
const footer = document.createElement("div");
|
const footer = document.createElement("div");
|
||||||
footer.className = "md-print-footer";
|
footer.className = "md-print-footer";
|
||||||
page.appendChild(footer);
|
page.appendChild(footer);
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ export interface PrintConfig {
|
|||||||
title: string;
|
title: string;
|
||||||
/** Show `n / total` in the page footer. */
|
/** Show `n / total` in the page footer. */
|
||||||
pageNumbers: boolean;
|
pageNumbers: boolean;
|
||||||
|
/** Append the export timestamp to the page footer. */
|
||||||
|
timestamp: boolean;
|
||||||
/** Draw the centre cut line between the two A5 pages. */
|
/** Draw the centre cut line between the two A5 pages. */
|
||||||
cutMarks: boolean;
|
cutMarks: boolean;
|
||||||
}
|
}
|
||||||
@@ -22,5 +24,6 @@ export interface PrintProps {
|
|||||||
font?: string | number;
|
font?: string | number;
|
||||||
title?: string;
|
title?: string;
|
||||||
pageNumbers?: string | boolean;
|
pageNumbers?: string | boolean;
|
||||||
|
timestamp?: string | boolean;
|
||||||
cutMarks?: string | boolean;
|
cutMarks?: string | boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ title: 打印版式
|
|||||||
:md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"}
|
:md-print[./rules.md]{columns="2" margin="10" gap="5" font="3"}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**在页脚显示导出时间:**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
:md-print[./rules.md]{timestamp=true}
|
||||||
|
```
|
||||||
|
|
||||||
**YAML 写法:**
|
**YAML 写法:**
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -30,6 +36,7 @@ margin: 10
|
|||||||
gap: 5
|
gap: 5
|
||||||
font: 3
|
font: 3
|
||||||
title: 规则书
|
title: 规则书
|
||||||
|
timestamp: true
|
||||||
```
|
```
|
||||||
|
|
||||||
点击组件上的「打印预览 / 导出 PDF」按钮打开预览。预览中会显示分页后的 A4 横版页面,可以直接打印或另存为 PDF。
|
点击组件上的「打印预览 / 导出 PDF」按钮打开预览。预览中会显示分页后的 A4 横版页面,可以直接打印或另存为 PDF。
|
||||||
@@ -44,8 +51,11 @@ title: 规则书
|
|||||||
| `font` | number | `3` | 正文字号(毫米) |
|
| `font` | number | `3` | 正文字号(毫米) |
|
||||||
| `title` | string | — | 页眉标题 |
|
| `title` | string | — | 页眉标题 |
|
||||||
| `pageNumbers` | boolean | `true` | 是否在页面外侧角落显示 `n / 总数` 页码 |
|
| `pageNumbers` | boolean | `true` | 是否在页面外侧角落显示 `n / 总数` 页码 |
|
||||||
|
| `timestamp` | boolean | `false` | 是否在页码旁边显示导出时间 |
|
||||||
| `cutMarks` | boolean | `true` | 是否显示 A4 中缝裁切线 |
|
| `cutMarks` | boolean | `true` | 是否显示 A4 中缝裁切线 |
|
||||||
|
|
||||||
|
页码位于页面外侧底角:左侧 A5 在左下角,右侧 A5 在右下角。开启 `timestamp` 后,页脚会显示类似 `3 / 12 · 2026-10-23 14:05` 的内容。
|
||||||
|
|
||||||
## 打印设置
|
## 打印设置
|
||||||
|
|
||||||
在浏览器打印对话框中:
|
在浏览器打印对话框中:
|
||||||
|
|||||||
@@ -274,9 +274,12 @@ icon.big .icon-label-stroke {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 3mm;
|
bottom: 3mm;
|
||||||
left: 3mm;
|
left: 3mm;
|
||||||
|
max-width: calc(100% - 6mm);
|
||||||
font-size: 8pt;
|
font-size: 8pt;
|
||||||
color: #6b7280;
|
color: #6b7280;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
.md-print-footer--left {
|
.md-print-footer--left {
|
||||||
|
|||||||
Reference in New Issue
Block a user