iasei-html-to-pdf 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,14 +1,16 @@
1
- # iasei-html-to-pdf 测试插件
1
+ # iasei-html-to-pdf
2
2
 
3
- 将 HTML 元素导出为 PDF 的浏览器端工具,基于 `html2canvas` + `jspdf`,支持自动分页与自定义纸张大小。
3
+ 将 HTML 元素导出为 PDF 的浏览器端工具,基于 `html2canvas` + `jspdf`,支持智能分页(避让文字、允许切图)与可视化分页标记。
4
4
 
5
5
  ## 特性
6
6
 
7
- - 通过元素 ID 一键导出 PDF
8
- - 自动按 A4 高度计算分页点并插入 `page-break` 标记,避免内容被截断
9
- - 支持自定义纸张大小与单位(`mm` / `pt` / `cm` / `in` / `px`)
7
+ - 通过元素 ID 一键导出 PDF,返回 `jsPDF` 实例,可继续追加内容或自定义保存
8
+ - 智能分页:自动识别块级原子单元,分页线穿过文字段落时上移避让,穿过图片时允许切断
9
+ - 全量截图后按分页点切片写入 PDF,避免逐页截图导致的样式/滚动错位
10
+ - 基于布局坐标(`offsetTop` / `offsetHeight`)测量,结果稳定可复现,不受滚动与 `transform` 影响
11
+ - 根据容器宽高自动选择 `portrait` / `landscape` 方向
12
+ - 提供 `insertSmartPageBreaks` / `clearPageBreaks` 用于在页面上叠加/移除可视化分页虚线与页码标签
10
13
  - 根据 `window.devicePixelRatio` 自适应缩放,保证清晰度
11
- - 返回 `jsPDF` 实例,可继续追加内容或自定义保存
12
14
 
13
15
  ## 安装
14
16
 
@@ -30,46 +32,61 @@ pnpm add iasei-html-to-pdf
30
32
  ### 基本用法
31
33
 
32
34
  ```ts
33
- import html2pdf from 'iasei-html-to-pdf';
35
+ import { html2pdf } from 'iasei-html-to-pdf';
34
36
 
35
37
  const pdf = await html2pdf({ id: 'myPrintHtml' });
36
38
  pdf.save('document.pdf');
37
39
  ```
38
40
 
39
- ### 自定义缩放与偏移
41
+ 不传 `pageHeight` 时,容器全部内容会被当作一页处理。
42
+
43
+ ### 自定义单页高度与边距
40
44
 
41
45
  ```ts
42
46
  const pdf = await html2pdf({
43
47
  id: 'myPrintHtml',
44
- scale: 2, // canvas 缩放比例
45
- vOffest: 20, // 页面顶部留白(pt)
48
+ pageHeight: 1123, // 单页内容高度(CSS px)
49
+ margin: 20, // 上下页边距(CSS px)
46
50
  });
47
51
  ```
48
52
 
49
- ### 自定义纸张大小
53
+ ### 自定义缩放与背景色
50
54
 
51
55
  ```ts
52
56
  const pdf = await html2pdf({
53
57
  id: 'myPrintHtml',
54
- pageSize: {
55
- width: 210,
56
- height: 297,
57
- },
58
+ scale: 2, // canvas 缩放比例
59
+ backgroundColor: '#fff', // 画布背景色
58
60
  });
59
61
  ```
60
62
 
63
+ ### 在页面上叠加可视化分页标记
64
+
65
+ ```ts
66
+ import { insertSmartPageBreaks, clearPageBreaks } from 'iasei-html-to-pdf';
67
+
68
+ // 在容器内绘制虚线 + 页码标签
69
+ insertSmartPageBreaks({ id: 'myPrintHtml', pageHeight: 1123 });
70
+
71
+ // 也可以指定标记挂载到另一个容器
72
+ insertSmartPageBreaks({ id: 'myPrintHtml', pageHeight: 1123 }, 'markerLayer');
73
+
74
+ // 清除分页标记
75
+ clearPageBreaks('myPrintHtml');
76
+ ```
77
+
61
78
  ## API
62
79
 
63
80
  ```ts
64
- function html2pdf(params: {
81
+ function html2pdf(options: Html2pdfOptions): Promise<jsPDF>;
82
+
83
+ interface Html2pdfOptions {
65
84
  id: string;
66
- vOffest?: number;
85
+ pageHeight?: number;
86
+ margin?: number;
67
87
  scale?: number;
68
- pageSize?: {
69
- width: number;
70
- height: number;
71
- };
72
- }): Promise<jsPDF>;
88
+ backgroundColor?: string;
89
+ }
73
90
  ```
74
91
 
75
92
  ### 参数
@@ -77,33 +94,47 @@ function html2pdf(params: {
77
94
  | 参数 | 类型 | 默认值 | 说明 |
78
95
  |------|------|--------|------|
79
96
  | `id` | `string` | — | 需要导出的 DOM 元素 ID(必填) |
80
- | `vOffest` | `number` | `15` | PDF 顶部垂直留白(pt) |
97
+ | `pageHeight` | `number` | 容器 `scrollHeight` | 单页内容高度(CSS px)。不传时容器全部内容进一页 |
98
+ | `margin` | `number` | `20` | 上下页边距(CSS px) |
81
99
  | `scale` | `number` | `min(2.5, 2 * devicePixelRatio)` | `html2canvas` 缩放比例,值越大越清晰 |
82
- | `pageSize` | `{ width, height }` | A4 | 自定义纸张大小,未传时使用 A4(`595×842pt`) |
100
+ | `backgroundColor` | `string` | `'#ffffff'` | 画布背景色 |
83
101
 
84
102
  ### 返回值
85
103
 
86
- 返回 `Promise<jsPDF>`,可调用 `.save(filename)` 下载,或继续操作 PDF 实例。
104
+ 返回 `Promise<jsPDF>`,可调用 `.save(filename)` 下载,或调用 `.output('arraybuffer' | 'blob' | 'dataurl')` 等继续处理。
87
105
 
88
- ## 分页机制
106
+ ## 导出函数
107
+
108
+ | 函数 | 说明 |
109
+ |------|------|
110
+ | `html2pdf(options)` | 将容器导出为 PDF,返回 `jsPDF` 实例 |
111
+ | `insertSmartPageBreaks(options, out?)` | 按 `pageHeight` 计算分页点,在容器(或 `out` 指定容器)内插入虚线 + 页码标签 |
112
+ | `clearPageBreaks(id)` | 清除目标容器内的所有可视化分页标记 |
89
113
 
90
- 1. 清理元素中历史的 `.page-break` 标记
91
- 2. 遍历子元素,当累计高度超过 A4 高度(`1123 - vOffest * 2 - 20` px)时,为该元素添加 `page-break` 类
92
- 3. 以每个 `page-break` 为分页点,将整张 canvas 切片后逐页写入 PDF
114
+ ## 智能分页机制
93
115
 
94
- 如需手动控制分页位置,可预先为目标元素添加 `page-break` 类。
116
+ 1. 容器设为非 `static` 定位,作为内部元素 `offsetParent` 链的终点
117
+ 2. 按 `ATOMIC_BLOCK_SELECTOR` 候选块级元素(`p` / `h1-h6` / `li` / `tr` / `blockquote` / 叶子 `div` 等),筛选出叶子型原子块
118
+ 3. 沿 `offsetParent` 链累加 `offsetTop` 得到每个原子块相对容器顶部的 CSS px 坐标
119
+ 4. 从 `0` 开始,每 `pageHeight - margin * 2` 设一个候选分页边界
120
+ 5. 若边界穿过非图片原子块,则上移到该块顶部;图片(`<img>`)允许被切断
121
+ 6. 处理嵌套:选取被边界穿过的最内层原子块作为避让单元
122
+ 7. 整容器一次性 `html2canvas` 截图,再按分页点切片逐页写入 PDF
95
123
 
96
124
  ## 注意事项
97
125
 
98
126
  - 仅适用于浏览器环境,需要 `document` / `window` 全局变量
99
- - 跨域图片需配置 CORS,否则 `html2canvas` 可能渲染失败
127
+ - 容器会被自动设为非 `static` 定位(若原为 `static` 则改为 `relative`),以保证分页标记与坐标测量正确
128
+ - 跨域图片需配置 CORS,否则 `html2canvas` 可能渲染失败(已默认开启 `useCORS: true`)
100
129
  - 导出前请确保目标元素已完整渲染(图片加载完成等)
130
+ - `pageHeight` 为 CSS px,无单位换算;PDF 使用 `unit: 'px'` 直接以同坐标系写入
101
131
 
102
132
  ## 开发
103
133
 
104
134
  ```bash
105
135
  pnpm install
106
136
  pnpm run build # tsc 构建 dist
137
+ pnpm test # vitest run
107
138
  ```
108
139
 
109
140
  ## License
package/dist/index.d.ts CHANGED
@@ -1,3 +1,7 @@
1
- import { html2pdf } from "./utils/html2pdf";
2
- export default html2pdf;
1
+ import { html2pdf, insertSmartPageBreaks, clearPageBreaks } from "./utils/html2pdf";
2
+ import type { Html2pdfOptions } from "./utils/html2pdf";
3
+ export { html2pdf };
4
+ export { type Html2pdfOptions };
5
+ export { insertSmartPageBreaks };
6
+ export { clearPageBreaks };
3
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;eAE7B,QAAQ"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,OAAO,EAAE,KAAK,eAAe,EAAE,CAAC;AAChC,OAAO,EAAE,qBAAqB,EAAE,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,6 @@
1
- import { html2pdf } from "./utils/html2pdf";
2
- export default html2pdf;
1
+ import { html2pdf, insertSmartPageBreaks, clearPageBreaks } from "./utils/html2pdf";
2
+ export { html2pdf };
3
+ export {};
4
+ export { insertSmartPageBreaks };
5
+ export { clearPageBreaks };
3
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGpF,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,OAAO,EAAwB,CAAC;AAChC,OAAO,EAAE,qBAAqB,EAAE,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -1,19 +1,53 @@
1
- import JsPDF from "jspdf";
2
1
  /**
3
- * @description: 导出html为pdf
4
- * @param {string} id: html元素id
5
- * @param {number} scale: 缩放比例
6
- * @param {string} filename: 文件名
7
- * @return {Promise}
2
+ * HTML 容器导出为 PDF
3
+ *
4
+ * 所有尺寸单位均为 CSS px,无单位换算。
8
5
  */
9
- export declare function html2pdf(params: {
6
+ import JsPDF from "jspdf";
7
+ /** 导出参数 */
8
+ export interface Html2pdfOptions {
9
+ /** 目标容器 id */
10
10
  id: string;
11
- vOffest?: number;
11
+ /** 单页内容高度(CSS px);不传则取容器 scrollHeight 作为单页高度(内容全部进一页) */
12
+ pageHeight?: number;
13
+ /** 上下页间距(CSS px),默认 20 */
14
+ margin?: number;
15
+ /** 截图缩放倍率,默认 min(2.5, 2 * devicePixelRatio) */
12
16
  scale?: number;
13
- pageSize?: {
14
- width: number;
15
- height: number;
16
- unit?: "mm" | "pt" | "cm" | "in" | "px";
17
- };
18
- }): Promise<JsPDF>;
17
+ /** 画布背景色,默认 '#ffffff' */
18
+ backgroundColor?: string;
19
+ }
20
+ /**
21
+ * 计算智能分页点(返回每页顶部 y 坐标数组,CSS px)。
22
+ * 规则:从 0 开始,每 pageHeight 设一个候选边界;
23
+ * 若边界穿过最内层非图片原子块,则上移到该元素顶部;图片允许切。
24
+ */
25
+ export declare function calculatePageBreaks(node: HTMLElement, pageHeight: number): number[];
26
+ /**
27
+ * 导出指定容器为 PDF
28
+ * @param options 导出参数
29
+ * @param options.id 目标容器 ID,必填
30
+ * @param options.pageHeight 单页高度,单位 px,默认取容器内容总高度
31
+ * @param options.margin 内边距,单位 px,默认 20
32
+ * @param options.scale 缩放比例,默认 2.5
33
+ * @param options.backgroundColor 背景颜色,默认 #ffffff
34
+ * @returns jsPDF 实例,可调用 .output('arraybuffer' | 'blob' | 'dataurl') 等
35
+ */
36
+ export declare function html2pdf(options: Html2pdfOptions): Promise<JsPDF>;
37
+ /**
38
+ * 在目标容器内插入智能分页标记(非图片块级元素上移,图片允许切)。
39
+ * @param options 导出参数
40
+ * @param options.id 目标容器 ID,必填
41
+ * @param options.pageHeight 单页高度,单位 px,默认取容器内容总高度
42
+ * @param options.margin 内边距,单位 px,默认 20
43
+ * @param options.scale 缩放比例,默认 2.5
44
+ * @param options.backgroundColor 背景颜色,默认 #ffffff
45
+ * @param out 目标容器 ID,可选,默认插入到目标容器内
46
+ * @returns void
47
+ */
48
+ export declare function insertSmartPageBreaks(options: Html2pdfOptions, out?: string): void;
49
+ /**
50
+ * 清除目标容器内的可视化分页标记
51
+ */
52
+ export declare function clearPageBreaks(id: string): void;
19
53
  //# sourceMappingURL=html2pdf.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"html2pdf.d.ts","sourceRoot":"","sources":["../../src/utils/html2pdf.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAgD1B;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE;QACT,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;KACzC,CAAC;CACH,GAAG,OAAO,CAAC,KAAK,CAAC,CAuIjB"}
1
+ {"version":3,"file":"html2pdf.d.ts","sourceRoot":"","sources":["../../src/utils/html2pdf.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,WAAW;AACX,MAAM,WAAW,eAAe;IAC9B,cAAc;IACd,EAAE,EAAE,MAAM,CAAC;IACX,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAkHD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAkCnF;AAED;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,CA4EvE;AAYD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAgClF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAIhD"}
@@ -1,162 +1,308 @@
1
- // 页面导出为pdf格式 //title表示为下载的标题,html表示document.querySelector('#myPrintHtml')
1
+ /**
2
+ * HTML 容器导出为 PDF
3
+ *
4
+ * 所有尺寸单位均为 CSS px,无单位换算。
5
+ */
2
6
  import html2Canvas from "html2canvas";
3
7
  import JsPDF from "jspdf";
4
- // 像素到点的转换函数
5
- function pxToPt(px) {
6
- // 1px = 0.75pt (96 DPI 标准)
7
- return px * 0.75;
8
+ /** 分页标记元素的统一 class,用于定位与清除 */
9
+ const PAGE_BREAK_CLASS = "html2pdf-page-break";
10
+ /**
11
+ * 原子块级元素选择器候选:可能成为"不可被分页线切断的最小内容单元"的元素。
12
+ * div 语义双面——既可能是容器(包裹其他块级元素,应允许跨页拆分),
13
+ * 也可能是叶子(直接含文字,不应被切断)。
14
+ * 最终是否视为原子单元由 collectBlockRects 按"是否包含其他原子块"动态判定。
15
+ */
16
+ const ATOMIC_BLOCK_SELECTOR = "strong,div,p,h1,h2,h3,h4,h5,h6,li,tr,td,th,caption,blockquote,pre,figure,figcaption,dl,dt,dd,address,video";
17
+ /**
18
+ * 判定元素是否为"叶子型原子块"——内部不再包含其他候选原子块。
19
+ * 容器型 div(含 p/h1-h6/li 等子块)返回 false,交由内部子块各自参与分页避让;
20
+ * 叶子型 div(仅含文本/行内元素)返回 true,整体作为一个不可切断单元。
21
+ */
22
+ function isLeafAtomicBlock(el) {
23
+ // 非 div 元素:直接视为叶子原子块(li/tr/td/p/h1-h6 等)
24
+ if (el.tagName !== "DIV")
25
+ return true;
26
+ // div:内部若包含其他候选原子块,则视为容器,不作为避让单元
27
+ return !el.querySelector(ATOMIC_BLOCK_SELECTOR);
8
28
  }
9
- function checkElementPositions(mParams, A4_HEIGHT) {
10
- const elements = document.getElementById(mParams.id);
11
- if (!elements)
12
- return;
13
- const parentRect = elements.getBoundingClientRect();
14
- let accumulatedHeight = 0;
15
- const accumulateHeight = (element) => {
16
- if (element.style.display == "none") {
17
- return;
18
- }
19
- const rect = element.getBoundingClientRect();
20
- const heightFromParentTop = rect.bottom - parentRect.top;
21
- const childElementNodes = Array.from(element.childNodes).filter((child) => child.nodeType === 1);
22
- if (heightFromParentTop - accumulatedHeight > A4_HEIGHT && childElementNodes.length) {
23
- childElementNodes.forEach((child) => accumulateHeight(child));
24
- }
25
- else if (heightFromParentTop - accumulatedHeight > A4_HEIGHT) {
26
- element.classList.add("page-break");
27
- console.log(element);
28
- accumulatedHeight = rect.top - parentRect.top;
29
+ /**
30
+ * 计算元素相对目标容器 padding box 顶部的布局坐标。
31
+ *
32
+ * 用 offsetTop 沿 offsetParent 链向上累加,而非 getBoundingClientRect:
33
+ * - offsetTop 是布局坐标,不受容器当前滚动位置影响(无需手工加 scrollTop);
34
+ * - 与 scrollHeight 同属布局坐标系,不会因滚动/transform 测量时机产生错位;
35
+ * - offsetTop 的原点是 offsetParent 的 padding box 顶部,
36
+ * 与分页标记 position:absolute 的 top 原点一致。
37
+ *
38
+ * @param el 目标元素
39
+ * @param container 容器(需已设为非 static 定位,保证在 offsetParent 链上)
40
+ * @returns 相对容器 padding box 顶部的 CSS px;元素不可定位时返回 null
41
+ */
42
+ function getOffsetTopWithin(el, container) {
43
+ let top = 0;
44
+ let current = el;
45
+ // 沿 offsetParent 链累加,直到抵达容器
46
+ while (current && current !== container) {
47
+ top += current.offsetTop;
48
+ current = current.offsetParent;
49
+ }
50
+ // 链未能抵达容器(如元素为 fixed 或在容器外),视为不可测量
51
+ if (current !== container) {
52
+ return null;
53
+ }
54
+ return top;
55
+ }
56
+ /**
57
+ * 收集容器内所有原子块级元素的位置(相对容器 padding box 顶部的 CSS px)。
58
+ * 全部基于布局坐标(offsetTop / offsetHeight),测量结果稳定可复现。
59
+ */
60
+ function collectBlockRects(node) {
61
+ // 容器必须为非 static,才能成为内部元素 offsetParent 链的终点
62
+ ensurePositionContext(node);
63
+ return Array.from(node.querySelectorAll(ATOMIC_BLOCK_SELECTOR))
64
+ .filter((el) => isLeafAtomicBlock(el))
65
+ .map((el) => {
66
+ const top = getOffsetTopWithin(el, node);
67
+ if (top === null) {
68
+ return null;
29
69
  }
30
- };
31
- accumulateHeight(elements);
70
+ const height = el.offsetHeight;
71
+ return {
72
+ top,
73
+ bottom: top + height,
74
+ isImg: el.tagName === "IMG" || !!el.querySelector("img"),
75
+ };
76
+ })
77
+ .filter((b) => b !== null)
78
+ .filter((b) => b.bottom > 0 && b.top < node.scrollHeight)
79
+ .sort((a, b) => a.top - b.top);
32
80
  }
33
81
  /**
34
- * @description: 导出html为pdf
35
- * @param {string} id: html元素id
36
- * @param {number} scale: 缩放比例
37
- * @param {string} filename: 文件名
38
- * @return {Promise}
82
+ * 在所有包含 cursor 的原子块中选取最内层元素。
83
+ * 嵌套元素在几何上 top ≥ 祖先、bottom ≤ 祖先,
84
+ * 因此 top 最大(相同时 bottom 最小)的即为最内层叶子单元。
85
+ *
86
+ * @param blocks 原子块位置数组
87
+ * @param cursor 分页边界(CSS px)
39
88
  */
40
- export function html2pdf(params) {
41
- const dpr = Math.max(window.devicePixelRatio || 1, 1);
42
- const mParams = Object.assign({ scale: Math.min(2.5, 2 * dpr), vOffest: 15 }, params);
43
- const A4_HEIGHT = 1123 - mParams.vOffest * 2 - 20; // A4 paper height in pixels at 96 DPI
44
- // 清理历史分页标记,避免重复累积
45
- Array.from(document.querySelectorAll(`#${params.id} .page-break`)).forEach((el) => el.classList.remove("page-break"));
46
- checkElementPositions(mParams, A4_HEIGHT);
47
- const node = document.getElementById(mParams.id);
48
- const mainRect = node.getBoundingClientRect();
49
- const elements = document.querySelectorAll(`#${mParams.id} .page-break`);
50
- let pages = [];
51
- if (node) {
52
- pages.push({ x: 0, y: 0, h: 0, w: mainRect.width });
53
- elements.forEach((item) => {
54
- const itemRect = item.getBoundingClientRect();
55
- pages.push({ x: 0, y: itemRect.top - mainRect.top, h: 0, w: mainRect.width });
56
- });
57
- for (let index = 0; index < pages.length; index++) {
58
- const item = pages[index];
59
- const nextItem = pages[index + 1];
60
- if (nextItem) {
61
- item.h = nextItem.y - item.y;
62
- }
63
- else {
64
- item.h = mainRect.height - item.y;
89
+ function pickInnermostBlock(blocks, cursor) {
90
+ let best = null;
91
+ for (const b of blocks) {
92
+ // 严格不等:元素 top 恰好等于 cursor 时已天然对齐,无需上移
93
+ if (b.top < cursor && b.bottom > cursor) {
94
+ if (best === null || b.top > best.top || (b.top === best.top && b.bottom < best.bottom)) {
95
+ best = b;
65
96
  }
66
97
  }
67
98
  }
68
- pages = pages.sort((a, b) => a.y - b.y);
69
- return new Promise((resolve, reject) => {
70
- if (!node) {
71
- reject(new Error(`html2pdf: 未找到元素 #${mParams.id}`));
72
- return;
99
+ return best;
100
+ }
101
+ /**
102
+ * 计算智能分页点(返回每页顶部 y 坐标数组,CSS px)。
103
+ * 规则:从 0 开始,每 pageHeight 设一个候选边界;
104
+ * 若边界穿过最内层非图片原子块,则上移到该元素顶部;图片允许切。
105
+ */
106
+ export function calculatePageBreaks(node, pageHeight) {
107
+ const totalHeight = node.scrollHeight;
108
+ const blocks = collectBlockRects(node);
109
+ // 每页顶部位置数组,第 1 页从 0 开始
110
+ const breaks = [0];
111
+ let cursor = pageHeight;
112
+ while (cursor < totalHeight) {
113
+ // 选取被 cursor 穿过的最内层原子块(处理块级元素互相嵌套的情况)
114
+ const hit = pickInnermostBlock(blocks, cursor);
115
+ let actualY;
116
+ if (hit && !hit.isImg) {
117
+ // 上移到该原子块顶部,避免切断文字
118
+ actualY = hit.top;
73
119
  }
74
- html2Canvas(node, {
75
- useCORS: true,
76
- allowTaint: false,
77
- backgroundColor: "#ffffff",
78
- logging: false,
79
- scale: mParams.scale,
80
- windowWidth: node.clientWidth + 200,
81
- windowHeight: node.clientHeight + 200,
82
- })
83
- .then((canvas) => {
84
- const pagesImage = pages.map((item) => {
85
- const x = Math.round(item.x * mParams.scale);
86
- const y = Math.round(item.y * mParams.scale);
87
- const h = Math.round(item.h * mParams.scale);
88
- const w = Math.round(item.w * mParams.scale);
89
- const tileCanvas = document.createElement("canvas");
90
- const tileCtx = tileCanvas.getContext("2d");
91
- tileCanvas.width = w;
92
- tileCanvas.height = h;
93
- if (tileCtx) {
94
- tileCtx.drawImage(canvas, x, y, w, h, 0, 0, w, h);
95
- }
96
- return { ...item, image: tileCanvas.toDataURL("image/jpeg", 1.0) };
97
- });
98
- // 创建 PDF,支持自定义纸张大小
99
- let pdf;
100
- if (mParams.pageSize) {
101
- const { width, height, unit = "mm" } = mParams.pageSize;
102
- if (unit === "px") {
103
- // 像素单位需要转换为点
104
- const widthPt = pxToPt(width);
105
- const heightPt = pxToPt(height);
106
- pdf = new JsPDF({
107
- orientation: "portrait",
108
- unit: "pt",
109
- format: [widthPt, heightPt],
110
- });
111
- }
112
- else {
113
- // 其他单位直接使用
114
- pdf = new JsPDF({
115
- orientation: "portrait",
116
- unit: unit,
117
- format: [width, height],
118
- });
119
- }
120
- }
121
- else {
122
- pdf = new JsPDF("p", "pt", "a4");
123
- }
124
- pagesImage.forEach((item, index) => {
125
- if (index > 0) {
126
- pdf.addPage();
127
- }
128
- // 根据纸张大小计算图片尺寸
129
- let imgWidth;
130
- let imgHeight;
131
- if (mParams.pageSize) {
132
- // 自定义纸张大小
133
- let pageWidth = mParams.pageSize.width;
134
- let pageHeight = mParams.pageSize.height;
135
- // 如果是像素单位,需要转换为点
136
- if (mParams.pageSize.unit === "px") {
137
- pageWidth = pxToPt(pageWidth);
138
- pageHeight = pxToPt(pageHeight);
139
- }
140
- imgWidth = pageWidth;
141
- imgHeight = (pageWidth / item.w) * item.h;
142
- // 如果图片高度超过页面高度,按比例缩放
143
- if (imgHeight > pageHeight) {
144
- imgHeight = pageHeight;
145
- imgWidth = (pageHeight / item.h) * item.w;
146
- }
147
- }
148
- else {
149
- // 默认 A4 纸张大小
150
- imgWidth = 595;
151
- imgHeight = (595 / item.w) * item.h;
152
- }
153
- pdf.addImage(item.image, "JPEG", 0, mParams.vOffest, imgWidth, imgHeight);
154
- });
155
- resolve(pdf);
156
- })
157
- .catch((error) => {
158
- reject(error);
159
- });
120
+ else {
121
+ // 图片、容器空隙或原子块之间的间隙:保持原始分页位置
122
+ actualY = cursor;
123
+ }
124
+ // 避免与上一个分页点重合(元素高度超过一页时)
125
+ if (actualY > breaks[breaks.length - 1]) {
126
+ breaks.push(actualY);
127
+ }
128
+ else {
129
+ // 整块下移一页,强制推进
130
+ breaks.push(cursor);
131
+ }
132
+ // 下一页起点 = 当前分页点 + pageHeight
133
+ cursor = breaks[breaks.length - 1] + pageHeight;
134
+ }
135
+ return breaks;
136
+ }
137
+ /**
138
+ * 导出指定容器为 PDF
139
+ * @param options 导出参数
140
+ * @param options.id 目标容器 ID,必填
141
+ * @param options.pageHeight 单页高度,单位 px,默认取容器内容总高度
142
+ * @param options.margin 内边距,单位 px,默认 20
143
+ * @param options.scale 缩放比例,默认 2.5
144
+ * @param options.backgroundColor 背景颜色,默认 #ffffff
145
+ * @returns jsPDF 实例,可调用 .output('arraybuffer' | 'blob' | 'dataurl') 等
146
+ */
147
+ export async function html2pdf(options) {
148
+ const { id, margin = 20, scale = Math.min(2.5, 2 * (window.devicePixelRatio || 1)), backgroundColor = "#ffffff" } = options;
149
+ const node = document.getElementById(id);
150
+ if (!node) {
151
+ throw new Error(`html2pdf: 未找到元素 #${id}`);
152
+ }
153
+ // 单页宽度固定为目标容器的实际 CSS 宽度,横向 1:1 渲染不溢出
154
+ const pageWidthPx = node.scrollWidth;
155
+ // 单页高度:未传则取容器内容总高度作为单页(内容全部进一页)
156
+ const pageHeight = options.pageHeight ?? node.scrollHeight;
157
+ const realPageHeight = options.pageHeight ? pageHeight - margin * 2 : pageHeight + margin * 2;
158
+ // 1. 计算智能分页点
159
+ const breaks = calculatePageBreaks(node, realPageHeight);
160
+ // 2. 整容器一次性截图
161
+ const canvas = await html2Canvas(node, {
162
+ useCORS: true,
163
+ allowTaint: false,
164
+ backgroundColor,
165
+ logging: false,
166
+ scale,
167
+ windowWidth: node.scrollWidth,
168
+ windowHeight: node.scrollHeight,
169
+ });
170
+ const canvasWidth = canvas.width;
171
+ const totalCanvasHeight = canvas.height;
172
+ // 3. 按分页点切片(分页点是 CSS px,乘以 scale 转为 canvas 像素)
173
+ const slices = breaks.map((y, index) => {
174
+ const yCanvas = Math.round(y * scale);
175
+ const nextYCanvas = index + 1 < breaks.length ? Math.round(breaks[index + 1] * scale) : totalCanvasHeight;
176
+ return {
177
+ y: yCanvas,
178
+ h: Math.max(1, Math.min(nextYCanvas - yCanvas, totalCanvasHeight - yCanvas)),
179
+ };
160
180
  });
181
+ // 4. 组装 PDF(统一 px 坐标系,内容贴满整页)
182
+ // 根据实际宽高决定方向:jsPDF 会对 portrait 强制 w<=h、landscape 强制 w>=h,
183
+ // 若写死 portrait 且容器更宽,format 会被自动交换导致图片贴错位置。
184
+ const orientation = pageWidthPx > (options.pageHeight ? pageHeight : realPageHeight) ? "landscape" : "portrait";
185
+ const pageFormat = [pageWidthPx, options.pageHeight ? pageHeight : realPageHeight];
186
+ const pdf = new JsPDF({
187
+ orientation,
188
+ unit: "px",
189
+ format: pageFormat,
190
+ });
191
+ slices.forEach((slice, index) => {
192
+ if (index > 0) {
193
+ // addPage 同样传入与尺寸一致的 orientation,避免宽>高时被交换
194
+ pdf.addPage(pageFormat, orientation);
195
+ }
196
+ // 切出当前页对应的 canvas 区域
197
+ const tile = document.createElement("canvas");
198
+ tile.width = canvasWidth;
199
+ tile.height = slice.h;
200
+ const ctx = tile.getContext("2d");
201
+ if (ctx) {
202
+ ctx.drawImage(canvas, 0, slice.y, canvasWidth, slice.h, 0, 0, canvasWidth, slice.h);
203
+ }
204
+ const dataUrl = tile.toDataURL("image/jpeg", 1.0);
205
+ // const img = document.createElement('img');
206
+ // img.src = dataUrl;
207
+ // node.appendChild(img);
208
+ pdf.addImage(dataUrl, "JPEG", 0, margin, pageWidthPx, slice.h / scale);
209
+ });
210
+ return pdf;
211
+ }
212
+ /**
213
+ * 确保容器为定位上下文,使 absolute 子元素相对于容器定位
214
+ */
215
+ function ensurePositionContext(node) {
216
+ const computedPos = getComputedStyle(node).position;
217
+ if (computedPos === "static") {
218
+ node.style.position = "relative";
219
+ }
220
+ }
221
+ /**
222
+ * 在目标容器内插入智能分页标记(非图片块级元素上移,图片允许切)。
223
+ * @param options 导出参数
224
+ * @param options.id 目标容器 ID,必填
225
+ * @param options.pageHeight 单页高度,单位 px,默认取容器内容总高度
226
+ * @param options.margin 内边距,单位 px,默认 20
227
+ * @param options.scale 缩放比例,默认 2.5
228
+ * @param options.backgroundColor 背景颜色,默认 #ffffff
229
+ * @param out 目标容器 ID,可选,默认插入到目标容器内
230
+ * @returns void
231
+ */
232
+ export function insertSmartPageBreaks(options, out) {
233
+ const { id, margin = 20 } = options;
234
+ let render;
235
+ const node = document.getElementById(id);
236
+ if (!node) {
237
+ throw new Error(`insertSmartPageBreaks: 未找到元素 #${id}`);
238
+ }
239
+ clearPageBreaks(id);
240
+ ensurePositionContext(node);
241
+ // 单页高度:未传则取容器内容总高度作为单页(即不强制分页,所有内容进一页)
242
+ const pageHeight = options.pageHeight ?? node.scrollHeight;
243
+ const realPageHeight = options.pageHeight ? pageHeight - margin * 2 : pageHeight + margin * 2;
244
+ // 复用与 html2pdf 相同的分页计算
245
+ const breaks = calculatePageBreaks(node, realPageHeight);
246
+ const markers = [];
247
+ // breaks[0] = 0 是第 1 页顶部,不插标识;从第 2 页开始
248
+ if (out) {
249
+ render = document.getElementById(out);
250
+ }
251
+ if (!out || !render) {
252
+ render = node;
253
+ }
254
+ for (let i = 1; i < breaks.length; i++) {
255
+ const marker = createPageBreakMarker(i + 1, breaks[i]);
256
+ render.appendChild(marker);
257
+ markers.push(marker);
258
+ }
259
+ }
260
+ /**
261
+ * 清除目标容器内的可视化分页标记
262
+ */
263
+ export function clearPageBreaks(id) {
264
+ const node = document.getElementById(id);
265
+ if (!node)
266
+ return;
267
+ node.querySelectorAll(`.${PAGE_BREAK_CLASS}`).forEach((el) => el.remove());
268
+ }
269
+ /**
270
+ * 创建一个分页标识元素:虚线 + 页码标签
271
+ */
272
+ function createPageBreakMarker(pageNo, topY) {
273
+ const marker = document.createElement("div");
274
+ marker.className = PAGE_BREAK_CLASS;
275
+ marker.style.cssText = `
276
+ position: absolute;
277
+ left: 0;
278
+ top: ${topY}px;
279
+ width: 100%;
280
+ height: 0;
281
+ z-index: 10;
282
+ pointer-events: none;
283
+ `;
284
+ const line = document.createElement("div");
285
+ line.style.cssText = `
286
+ width: 100%;
287
+ border-top: 1px dashed var(--common-color-primary, #409eff);
288
+ box-shadow: 0 0 0 0.5px var(--common-color-primary, #409eff);
289
+ `;
290
+ const label = document.createElement("span");
291
+ label.textContent = `第 ${pageNo} 页`;
292
+ label.style.cssText = `
293
+ position: absolute;
294
+ top: -10px;
295
+ left: 8px;
296
+ padding: 0 6px;
297
+ font-size: 11px;
298
+ line-height: 18px;
299
+ color: #fff;
300
+ background: var(--common-color-primary, #409eff);
301
+ border-radius: 9px;
302
+ white-space: nowrap;
303
+ `;
304
+ marker.appendChild(line);
305
+ marker.appendChild(label);
306
+ return marker;
161
307
  }
162
308
  //# sourceMappingURL=html2pdf.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"html2pdf.js","sourceRoot":"","sources":["../../src/utils/html2pdf.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"html2pdf.js","sourceRoot":"","sources":["../../src/utils/html2pdf.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iasei-html-to-pdf",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "将html转换为pdf 测试插件",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,6 +8,12 @@
8
8
  "files": [
9
9
  "dist"
10
10
  ],
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "test": "vitest run",
14
+ "test:watch": "vitest",
15
+ "prepublishOnly": "npm run build"
16
+ },
11
17
  "keywords": [
12
18
  "typescript",
13
19
  "npm"
@@ -31,10 +37,5 @@
31
37
  "dependencies": {
32
38
  "html2canvas": "^1.4.1",
33
39
  "jspdf": "^4.2.1"
34
- },
35
- "scripts": {
36
- "build": "tsc",
37
- "test": "vitest run",
38
- "test:watch": "vitest"
39
40
  }
40
- }
41
+ }