{"_id":"@akira1ce/html2pdf","_rev":"4-92c7662a599174a01f7e0abfd1c63ab9","name":"@akira1ce/html2pdf","dist-tags":{"latest":"2.0.0"},"versions":{"1.0.0":{"name":"@akira1ce/html2pdf","version":"1.0.0","keywords":["pdf","html"],"author":{"name":"akiraice","email":"akiraice@163.com"},"license":"MIT","_id":"@akira1ce/html2pdf@1.0.0","maintainers":[{"name":"akira1ce","email":"akira1ce@163.com"}],"homepage":"https://github.com/akira1ce/html2pdf#readme","bugs":{"url":"https://github.com/akira1ce/html2pdf/issues"},"dist":{"shasum":"ffb837ad87ddbff7b49c18c4c2dd6f46785001c3","tarball":"https://registry.npmjs.org/@akira1ce/html2pdf/-/html2pdf-1.0.0.tgz","fileCount":8,"integrity":"sha512-09uuoxwK+dudCvcVwZ2vk3bhNhLgFEjncpHSyDAhHDoZkWpO1MPEVpzBrjYJKzNIiymXAMs8+5vy6SnF7x4x+g==","signatures":[{"sig":"MEYCIQCncunIDH/bQu0Zn3qCx820X6XRMYPxDAssp2o6lEinwAIhAOCXx6JIZ2Luf41exkz4I7atPxMoJO0hxuBdWWqUujmd","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":72267},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.esm.js","gitHead":"081a24548cc77817d1a1fda7946b037b224738e7","scripts":{"dev":"rollup -c -w","build":"rollup -c","clean":"rimraf dist"},"_npmUser":{"name":"akira1ce","email":"akira1ce@163.com"},"repository":{"url":"git+https://github.com/akira1ce/html2pdf.git","type":"git"},"_npmVersion":"10.7.0","description":"html2pdf","directories":{},"_nodeVersion":"18.20.3","dependencies":{"jspdf":"^2.5.2","dom-to-image":"^2.6.0","@types/dom-to-image":"^2.6.7"},"_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.6.2","rimraf":"^5.0.5","rollup":"^4.12.0","typescript":"^5.3.3","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-typescript":"^11.1.6","@rollup/plugin-node-resolve":"^15.2.3"},"peerDependencies":{"jspdf":"^2.5.2","dom-to-image":"^2.6.0"},"_npmOperationalInternal":{"tmp":"tmp/html2pdf_1.0.0_1737082937705_0.3519943012759157","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@akira1ce/html2pdf","version":"1.0.1","keywords":["pdf","html"],"author":{"name":"akiraice","email":"akiraice@163.com"},"license":"MIT","_id":"@akira1ce/html2pdf@1.0.1","maintainers":[{"name":"akira1ce","email":"akira1ce@163.com"}],"homepage":"https://github.com/akira1ce/html2pdf#readme","bugs":{"url":"https://github.com/akira1ce/html2pdf/issues"},"dist":{"shasum":"564fab82ad90af03365aa042609bc1d188f96bb0","tarball":"https://registry.npmjs.org/@akira1ce/html2pdf/-/html2pdf-1.0.1.tgz","fileCount":8,"integrity":"sha512-QdAwJh43mgyG1YM2qI1/2KHPSq+4GXazfqVg5eOEr0li8i5kTGn0SmeASAFtiyCube/zmnEhEHTBiBWpM3mfrg==","signatures":[{"sig":"MEUCIQCG9aX+fm2wryTe5hj6hPN1TtSYegVqod5w+0xxuh43JAIgVS1I1h9LqGQw5I0nGZqAByrOA8EEtUhepbckGaGLbTE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":76929},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.esm.js","gitHead":"de7267a45327bf875e3bf2a89cbf8fd8855c9ea2","scripts":{"dev":"rollup -c -w","build":"rollup -c","clean":"rimraf dist"},"_npmUser":{"name":"akira1ce","email":"akira1ce@163.com"},"repository":{"url":"git+https://github.com/akira1ce/html2pdf.git","type":"git"},"_npmVersion":"10.7.0","description":"html2pdf","directories":{},"_nodeVersion":"18.20.3","dependencies":{"jspdf":"^2.5.2","dom-to-image":"^2.6.0","@types/dom-to-image":"^2.6.7"},"_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.6.2","rimraf":"^5.0.5","rollup":"^4.12.0","typescript":"^5.3.3","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-typescript":"^11.1.6","@rollup/plugin-node-resolve":"^15.2.3"},"peerDependencies":{"jspdf":"^2.5.2","dom-to-image":"^2.6.0"},"_npmOperationalInternal":{"tmp":"tmp/html2pdf_1.0.1_1737442896450_0.2643210684314403","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@akira1ce/html2pdf","version":"1.1.0","keywords":["pdf","html"],"author":{"name":"akiraice","email":"akiraice@163.com"},"license":"MIT","_id":"@akira1ce/html2pdf@1.1.0","maintainers":[{"name":"akira1ce","email":"akira1ce@163.com"}],"homepage":"https://github.com/akira1ce/html2pdf#readme","bugs":{"url":"https://github.com/akira1ce/html2pdf/issues"},"dist":{"shasum":"33e2ad264091882514bfc6fdb5c4d1228e984697","tarball":"https://registry.npmjs.org/@akira1ce/html2pdf/-/html2pdf-1.1.0.tgz","fileCount":11,"integrity":"sha512-owgbbzgJc5lnv45ZVcXwpsoZ1BucySH0MsovgkrkXV4GsFGQVnyiW4acBuCV9titlsjTp68uXLvAaSObLXa6HA==","signatures":[{"sig":"MEYCIQDIl4KoQDxjRGqvPeRiuNAQRuPya5s3Sf5HYvDNsPw2dgIhAOnsuWAZBZoDDZZV6CDrc1bz/QpGYHm1wqYuyoNSpRdk","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":88769},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.esm.js","gitHead":"20cf8e0d89e00ae0b63d949bc3f25a801e805f59","scripts":{"dev":"rollup -c -w","build":"rollup -c","clean":"rimraf dist"},"_npmUser":{"name":"akira1ce","email":"akira1ce@163.com"},"repository":{"url":"git+https://github.com/akira1ce/html2pdf.git","type":"git"},"_npmVersion":"10.8.2","description":"html2pdf","directories":{},"_nodeVersion":"20.19.4","dependencies":{"jspdf":"^2.5.2","dom-to-image":"^2.6.0","@types/dom-to-image":"^2.6.7"},"_hasShrinkwrap":false,"devDependencies":{"tslib":"^2.6.2","rimraf":"^5.0.5","rollup":"^4.12.0","typescript":"^5.3.3","@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-typescript":"^11.1.6","@rollup/plugin-node-resolve":"^15.2.3"},"peerDependencies":{"jspdf":"^2.5.2","dom-to-image":"^2.6.0"},"_npmOperationalInternal":{"tmp":"tmp/html2pdf_1.1.0_1760346255429_0.5128483426326729","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@akira1ce/html2pdf","version":"2.0.0","type":"module","main":"dist/index.js","module":"dist/index.esm.js","types":"dist/index.d.ts","license":"MIT","scripts":{"build":"rollup -c","dev":"rollup -c -w","clean":"rimraf dist"},"keywords":["pdf","html"],"repository":{"type":"git","url":"git+https://github.com/akira1ce/html2pdf.git"},"author":{"name":"akiraice","email":"akiraice@163.com"},"description":"html2pdf","dependencies":{"@types/dom-to-image":"^2.6.7","dom-to-image":"^2.6.0","jspdf":"^2.5.2"},"devDependencies":{"@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-node-resolve":"^15.2.3","@rollup/plugin-typescript":"^11.1.6","rimraf":"^5.0.5","rollup":"^4.12.0","tslib":"^2.6.2","typescript":"^5.3.3"},"peerDependencies":{"dom-to-image":"^2.6.0","jspdf":"^2.5.2"},"_id":"@akira1ce/html2pdf@2.0.0","gitHead":"20cf8e0d89e00ae0b63d949bc3f25a801e805f59","bugs":{"url":"https://github.com/akira1ce/html2pdf/issues"},"homepage":"https://github.com/akira1ce/html2pdf#readme","_nodeVersion":"22.22.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-tM5B+2FcjdWmZho5CG/yEsRZgbZ4HMmoOBdE5duuuOuam26Z/7f8j/VvNYYB2ExE1F/Sgn5Q6Re68GsG/Ox+6A==","shasum":"c833ae6f4d2ab65e7dd750e6c4b4ced4baa4a95d","tarball":"https://registry.npmjs.org/@akira1ce/html2pdf/-/html2pdf-2.0.0.tgz","fileCount":11,"unpackedSize":92088,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDP6jWSCUVsQqe2t+/e3U9583ZVI1zqtN0+k7mc0OydxQIhAO+NvpvRmGA7SobEQP57peVigiBuz5yPmlnms1nijdHo"}]},"_npmUser":{"name":"akira1ce","email":"akira1ce@163.com"},"directories":{},"maintainers":[{"name":"akira1ce","email":"akira1ce@163.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/html2pdf_2.0.0_1776525897259_0.60048168776289"},"_hasShrinkwrap":false}},"time":{"created":"2025-01-17T03:02:17.600Z","modified":"2026-04-18T15:24:57.511Z","1.0.0":"2025-01-17T03:02:17.892Z","1.0.1":"2025-01-21T07:01:36.637Z","1.1.0":"2025-10-13T09:04:15.626Z","2.0.0":"2026-04-18T15:24:57.396Z"},"bugs":{"url":"https://github.com/akira1ce/html2pdf/issues"},"author":{"name":"akiraice","email":"akiraice@163.com"},"license":"MIT","homepage":"https://github.com/akira1ce/html2pdf#readme","keywords":["pdf","html"],"repository":{"type":"git","url":"git+https://github.com/akira1ce/html2pdf.git"},"description":"html2pdf","maintainers":[{"name":"akira1ce","email":"akira1ce@163.com"}],"readme":"# @akira1ce/html2pdf\n\n一个智能的 HTML 转 PDF 工具，专注于解决分页切割问题。\n\n## 特性\n\n- 🎯 智能分页：自动计算并分割内容到多个 A4 页面\n- 📦 零配置：开箱即用，只需标记最小单元节点\n- 🎨 样式保留：完整保留 CSS 样式和布局\n- ⚡ 高性能：支持并发渲染，大文档也能快速生成\n- 🔧 灵活配置：支持自定义页边距、图片质量等参数\n\n## 安装\n\n```bash\nnpm install @akira1ce/html2pdf\n# or\nyarn add @akira1ce/html2pdf\n# or\npnpm add @akira1ce/html2pdf\n```\n\n## 快速开始\n\n```tsx\nimport { transfer2Pdf } from '@akira1ce/html2pdf';\n\nexport default function App() {\n  const handleDownload = async () => {\n    await transfer2Pdf('.container', {\n      unitSelector: '.item',\n      filename: 'document.pdf',\n    });\n  };\n\n  return (\n    <>\n      <button onClick={handleDownload}>导出 PDF</button>\n\n      <div className=\"container\" style={{ width: 794 }}>\n        <div className=\"item\">内容块 1</div>\n        <div className=\"item\">内容块 2</div>\n        <div className=\"item\">内容块 3</div>\n      </div>\n    </>\n  );\n}\n```\n\n## API\n\n### `transfer2Pdf(element, options)`\n\n将 HTML 元素转换为 PDF 文件。\n\n#### 参数\n\n- `element`: `HTMLElement | string` - 容器元素或 CSS 选择器\n- `options`: `PdfOptions` - 配置选项\n\n#### PdfOptions\n\n```ts\ninterface PdfOptions {\n  /** CSS 选择器，用于标记需要分页的最小单元 */\n  unitSelector: string;\n  \n  /** 页面包装器的类名（默认：'pdf-page-wrapper'） */\n  wrapperClassName?: string;\n  \n  /** 每页的垂直内边距（默认：20） */\n  py?: number;\n  \n  /** 输出的 PDF 文件名（默认：'document.pdf'） */\n  filename?: string;\n  \n  /** 图片质量 0-1（默认：0.95） */\n  quality?: number;\n  \n  /** 进度回调函数 */\n  onProgress?: (current: number, total: number) => void;\n  \n  /** 并发渲染的页面数（默认：3） */\n  concurrency?: number;\n}\n```\n\n## 完整示例\n\n```tsx\nimport { transfer2Pdf } from '@akira1ce/html2pdf';\n\nfunction ReportPage() {\n  const handleExport = async () => {\n    await transfer2Pdf('.report-container', {\n      unitSelector: '.report-section',\n      filename: 'report.pdf',\n      py: 20,\n      quality: 0.95,\n      concurrency: 3,\n      onProgress: (current, total) => {\n        console.log(`生成进度: ${current}/${total}`);\n      }\n    });\n  };\n\n  return (\n    <div>\n      <button onClick={handleExport}>导出报告</button>\n\n      <div className=\"report-container\" style={{ width: 794, padding: '40px' }}>\n        <div className=\"report-section\">\n          <h1>第一章</h1>\n          <p>这是第一章的内容...</p>\n        </div>\n\n        <div className=\"report-section\">\n          <h2>第二章</h2>\n          <p>这是第二章的内容...</p>\n        </div>\n\n        <div className=\"report-section\">\n          <h2>第三章</h2>\n          <p>这是第三章的内容...</p>\n        </div>\n      </div>\n    </div>\n  );\n}\n```\n\n## 使用指南\n\n### 1. 容器宽度\n\n容器必须有固定宽度，推荐使用 794px（对应 A4 纸张宽度）：\n\n```tsx\n<div className=\"container\" style={{ width: 794 }}>\n  {/* 内容 */}\n</div>\n```\n\n### 2. 标记最小单元\n\n使用 `unitSelector` 标记不可分割的内容块：\n\n```tsx\n// ✅ 正确：每个章节作为一个单元\n<div className=\"section\">章节内容</div>\n\n// ❌ 错误：没有标记单元，无法正确分页\n<div>内容 1</div>\n<div>内容 2</div>\n```\n\n### 3. 容器内边距\n\n容器的 padding 会自动应用到每一页：\n\n```tsx\n<div style={{ width: 794, padding: '40px 30px' }}>\n  {/* 每页都会有 40px 上下边距，30px 左右边距 */}\n</div>\n```\n\n### 4. 进度监听\n\n通过 `onProgress` 回调监听生成进度：\n\n```tsx\nawait transfer2Pdf('.container', {\n  unitSelector: '.item',\n  onProgress: (current, total) => {\n    const percent = Math.round((current / total) * 100);\n    console.log(`${percent}%`);\n  }\n});\n```\n\n## 注意事项\n\n- ⚠️ 单个单元节点高度不应超过一页高度\n- ⚠️ 单元节点不会被切割，会作为整体放在一页中\n- ⚠️ 容器必须有固定宽度\n- ⚠️ 生成过程中会临时修改 DOM 结构\n\n## 工作原理\n\n### 核心算法\n\n1. **收集单元节点** - 根据 `unitSelector` 获取所有需要分页的内容块\n2. **计算页面尺寸** - 根据容器宽度计算对应的 A4 页面高度\n3. **智能布局** - 自上而下遍历单元，判断当前页是否能容纳\n4. **创建页面** - 将内容分配到不同页面，填充空白区域\n5. **渲染图片** - 使用 dom-to-image 将每页转换为高质量图片\n6. **生成 PDF** - 使用 jsPDF 将图片组装成 PDF 文档\n\n### 分页示意图\n\n```\n┌─────────────────────┐\n│  Page 1             │\n│  ┌───────────────┐  │\n│  │ py padding    │  │\n│  ├───────────────┤  │\n│  │ Unit 1        │  │\n│  ├───────────────┤  │\n│  │ Unit 2        │  │\n│  ├───────────────┤  │\n│  │ blank space   │  │ ← Unit 3 放不下，填充空白\n│  └───────────────┘  │\n└─────────────────────┘\n\n┌─────────────────────┐\n│  Page 2             │\n│  ┌───────────────┐  │\n│  │ py padding    │  │\n│  ├───────────────┤  │\n│  │ Unit 3        │  │ ← 移到新页面\n│  ├───────────────┤  │\n│  │ Unit 4        │  │\n│  └───────────────┘  │\n└─────────────────────┘\n```\n\n## 工具函数\n\n库还导出了一些实用工具函数：\n\n```tsx\nimport { utils } from '@akira1ce/html2pdf';\n\n// 根据宽度计算 A4 高度\nconst height = utils.getA4Height(794); // 返回 1123\n\n// 获取元素高度（包含 margin）\nconst boxHeight = utils.getBoxHeight(element);\n\n// 深度克隆节点（支持 canvas）\nconst cloned = utils.deepCloneNode(node, true);\n```\n\n## 错误处理\n\n库提供了自定义错误类型：\n\n```tsx\nimport { transfer2Pdf, Html2PdfError } from '@akira1ce/html2pdf';\n\ntry {\n  await transfer2Pdf('.container', {\n    unitSelector: '.item'\n  });\n} catch (error) {\n  if (error instanceof Html2PdfError) {\n    console.error(`错误代码: ${error.code}`);\n    console.error(`错误信息: ${error.message}`);\n  }\n}\n```\n\n### 错误代码\n\n- `NO_CONTAINER` - 找不到容器元素\n- `NO_UNITS` - 没有找到匹配的单元节点\n- `NO_PAGES` - 布局计算后没有生成页面\n- `GENERATION_FAILED` - PDF 生成失败\n\n## 技术栈\n\n- [jsPDF](https://github.com/parallax/jsPDF) - PDF 文档生成\n- [dom-to-image](https://github.com/tsayen/dom-to-image) - DOM 转图片\n\n## License\n\nMIT © [akiraice](https://github.com/akira1ce)\n","readmeFilename":"README.md"}