XWX-AI commited on
Commit
38f9bb7
·
1 Parent(s): 6800ea9

fix(pdf): tagged PDF显式关闭+容器CJK字体换静态TrueType——PDF体积3倍竞品根因修复(2026-10-04)——①server.js page.pdf显式tagged:false+outline:false:Puppeteer24 parsePDFOptions把tagged默认翻true(node_modules/puppeteer-core/common/util.js),每文字运行产StructElem(436轮NotebookLM实测63,171个5.65MB,xref 79,817);②Dockerfile弃装fonts-noto-cjk(CFF-in-OTC无法子集→全部汉字逐页Type3,745字典2.4MB CharProcs),改构建期从google/fonts(commit固定a85815a)下载SC/TC/JP/KR/HK变量字体+fonttools实例化400/700静态TrueType装系统(--update-name-table防family名带Thin致fontconfig miss;--no-install-recommends下需显式ca-certificates+fontconfig;fonttools走python3 -m入口);emoji字体保留(位图Type3残余0.02MB,视觉优先);真实容器端到端:同会话HTML POST实测26.66MB→8.69MB(-67%)低于竞品9.41MB,xref→3,182,Type3→45,图片5.19MB→0.69MB与竞品同量级,文本保真98.15%字符级一致,嵌入字体全TTF子集;本机pdf-test(17861)/pdf-prod(7860)已重建验证字节级一致;12平台API契约零改动,新旧插件全兼容;证据链XWXExporter/temp/test/notebooklm/2026-10-04/与解决方案API/111;HF Space待用户手动push部署

Browse files
Files changed (2) hide show
  1. Dockerfile +33 -2
  2. server.js +9 -0
Dockerfile CHANGED
@@ -1,16 +1,47 @@
1
  # Use Node.js 20 on Debian Bookworm (Chromium 149, fixes SVG context-stroke support)
 
 
 
 
 
 
 
 
 
 
 
 
2
  FROM node:20-bookworm-slim
3
 
4
- # Install Chrome Dependencies
5
  RUN apt-get update && apt-get install -y \
6
  chromium \
7
- fonts-noto-cjk \
8
  fonts-noto-core \
9
  fonts-noto-color-emoji \
 
 
 
 
10
  libxss1 \
11
  --no-install-recommends \
12
  && rm -rf /var/lib/apt/lists/*
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  # Set working directory
15
  WORKDIR /app
16
 
 
1
  # Use Node.js 20 on Debian Bookworm (Chromium 149, fixes SVG context-stroke support)
2
+ #
3
+ # ── CJK 字体策略(2026-10-04 PDF 体积根因修复,勿回退到 fonts-noto-cjk)──
4
+ # Debian 的 fonts-noto-cjk 是 CFF 轮廓的 OTC 集合封装,Skia/PDF 无法对它做
5
+ # 子集嵌入,print-to-PDF 时每个 CJK 字形都退化为 Type3 逐页画(436 轮会话实测:
6
+ # 745 个 Type3 字体字典 + 2.4MB CharProcs + 每页重复字形,韩文/康熙部首同样中招;
7
+ # 变量字体也触发 Type3,已实测)。TrueType 轮廓的静态实例则正常以 TTF 子集嵌入,
8
+ # 全文档共享一份。证据链见 XWXExporter 仓库 temp/test/notebooklm/2026-10-04/。
9
+ # 因此:构建期从 google/fonts 下载变量字体(commit 固定可复现),用 fontTools
10
+ # 实例化 400/700 两个 weight 装为系统字体;不装 fonts-noto-cjk。
11
+ # 插件 document-export-css.js 的字体栈已按语言对齐静态家族名
12
+ # (Noto Sans SC/TC/JP/KR/HK 优先于 CJK OTC 名)。
13
+ # emoji 仍用 fonts-noto-color-emoji(CBDT 位图,少量 Type3 残留,视觉优先)。
14
  FROM node:20-bookworm-slim
15
 
 
16
  RUN apt-get update && apt-get install -y \
17
  chromium \
 
18
  fonts-noto-core \
19
  fonts-noto-color-emoji \
20
+ python3-fonttools \
21
+ fontconfig \
22
+ curl \
23
+ ca-certificates \
24
  libxss1 \
25
  --no-install-recommends \
26
  && rm -rf /var/lib/apt/lists/*
27
 
28
+ # google/fonts 仓库 commit 固定(2026-10-04 取)
29
+ ARG NOTO_FONTS_COMMIT=a85815a42757630ce188fdad368c2dfc444d4773
30
+ RUN set -eux; \
31
+ mkdir -p /usr/local/share/fonts/noto-sans-static; \
32
+ for fam in notosanssc:NotoSansSC notosanstc:NotoSansTC notosansjp:NotoSansJP notosanskr:NotoSansKR notosanshk:NotoSansHK; do \
33
+ dir="${fam%%:*}"; stem="${fam##*:}"; \
34
+ curl -fsSL -o "/tmp/${stem}-Var.ttf" \
35
+ "https://raw.githubusercontent.com/google/fonts/${NOTO_FONTS_COMMIT}/ofl/${dir}/${stem}%5Bwght%5D.ttf"; \
36
+ for w in 400 700; do \
37
+ python3 -m fontTools.varLib.instancer --update-name-table \
38
+ -o "/usr/local/share/fonts/noto-sans-static/${stem}-${w}.ttf" \
39
+ "/tmp/${stem}-Var.ttf" "wght=${w}"; \
40
+ done; \
41
+ rm -f "/tmp/${stem}-Var.ttf"; \
42
+ done; \
43
+ fc-cache -f
44
+
45
  # Set working directory
46
  WORKDIR /app
47
 
server.js CHANGED
@@ -545,10 +545,19 @@ app.post('/api/generate_pdf', async (req, res) => {
545
  // timeout: 0 = 禁用 page.pdf() 内部超时(默认 30s)
546
  // 参考: https://stackoverflow.com/questions/69436420
547
  // 应用层用 Promise.race 做超时控制
 
 
 
 
 
 
 
548
  const pdfPromise = page.pdf({
549
  format: 'A4',
550
  printBackground: true,
551
  preferCSSPageSize: true,
 
 
552
  displayHeaderFooter: true,
553
  headerTemplate: '<div></div>',
554
  footerTemplate: `
 
545
  // timeout: 0 = 禁用 page.pdf() 内部超时(默认 30s)
546
  // 参考: https://stackoverflow.com/questions/69436420
547
  // 应用层用 Promise.race 做超时控制
548
+ //
549
+ // tagged/outline 必须显式关闭:Puppeteer v24 起 parsePDFOptions 把 tagged 默认
550
+ // 翻成 true(node_modules/puppeteer-core/common/util.js),每段文字运行都会生成
551
+ // 一个 StructElem 结构元素(436 轮 NotebookLM 实测 6.3 万个对象 ≈ 5.7MB + xref
552
+ // 膨胀),这是 2026-10 PDF 体积为竞品 3 倍的三大根因之一(temp/test/notebooklm/
553
+ // 2026-10-04 实测关掉省 7.3MB/32MB)。无障碍标签对下载交付物无价值,outline
554
+ // 隐含 tagged,一并锁死,防止未来 puppeteer 升级再翻转默认值。
555
  const pdfPromise = page.pdf({
556
  format: 'A4',
557
  printBackground: true,
558
  preferCSSPageSize: true,
559
+ tagged: false,
560
+ outline: false,
561
  displayHeaderFooter: true,
562
  headerTemplate: '<div></div>',
563
  footerTemplate: `