All checks were successful
Deploy eCourt Note Web to Server / Validate Database Schema (Drizzle) (push) Successful in 3s
Deploy eCourt Note Web to Server / Build Web Docker Image (push) Successful in 52s
Deploy eCourt Note Web to Server / Deploy eCourt Note Web to Server (push) Successful in 13s
Deploy eCourt Note Web to Server / Notify Deployment Status (push) Successful in 1s
เตรียม basePath /docedit เป็นพื้นที่กลางให้แอปพี่น้อง (wordaddin ใน อนาคต) — เดิม basePath ครอบ /docedit/note ทั้งหมดจนแชร์ prefix ไม่ได้ (Next มี basePath ได้ทางเดียว) และจัด API แยกต้นไม้ตามที่ผู้ใช้ขอ (1) โครงสร้างใหม่: basePath = /docedit + route หน้าทั้งหมดย้ายเข้า app/note/** + API 4 เส้นย้ายเข้า app/api/note/** + statics ย้ายเข้า public/note/** (samples, uploads, pdf.worker) — หน้า/statics URL ปลายทาง คงเดิมเป๊ะ (/docedit/note/…) ส่วน URL API เปลี่ยนเป็น /docedit/api/note/… ตามคำขอผู้ใช้ (N10 endpoint เปลี่ยน — ต้องแจ้ง backend e-Court ก่อนใช้) (2) กลไก: withBasePath (utils/base-path.ts) เติม base + app path /note ยกเว้น path ที่ขึ้นต้น /api/ เติมแค่ base (caller เขียน /api/note/… เต็ม); resolvePublicPdfPath root ที่ public/note (traversal guard เดิม); middleware matcher ยกเว้นใหม่ (note/login, api/note, note/uploads, note/samples, note/pdf.worker, _next, fonts, favicon) + redirect /note/login; next.config เพิ่ม redirects /docedit -> /docedit/note; navigation ภายใน 19 จุด + revalidatePath 3 จุด ใส่ prefix /note; pdf_url ใน DB เป็น logical path ไม่แก้แม้แต่ตัวเดียว (seed/upload เขียนค่าเดิม, browser เติมผ่าน withBasePath, disk เติมผ่าน guard) (3) ตามแก้: patch-pdf-worker (DEST public/note + mkdirSync ปลายทาง), seed-samples (SAMPLES_DIR), uploadFile (UPLOAD_DIR), Dockerfile/ .dockerignore/.gitignore/docker-compose.test.yml, tests 2 ไฟล์ที่อ้าง disk path จริง, sync เอกสารทั้งหมด (CLAUDE.md invariant #6/#12 + tree, README, docs/API-DOCUMENTS.md, .claude/rules/*, sync-db skill) (4) !! ตอน deploy ต้องย้าย volume ตาม: mount /app/public/uploads -> /app/public/note/uploads + ย้ายไฟล์ใน volume ให้ตรงตำแหน่ง ไม่งั้นไฟล์ ที่เคยอัปโหลด (พร้อม annotation ที่ผูกอยู่) 404 ทันทีที่สลับ image (5) verify: build ผ่าน (route table /api/note/** + /note/** ครบ), tsc, vitest 215/215, curl ครบทุก endpoint (login/redirect chain, worker, samples, uploads, SSE, api/pdf, export, N8 register, N10 bundle + deep link), Playwright browser จริง (canvas + textLayer ไทย render, browser ยิง URL ใหม่ทั้งหมดไม่มี request ไป URL เก่า), plan-reviewer + code-reviewer 3 รายงาน 0 blocking Co-Authored-By: Claude Code <noreply@anthropic.com>
48 lines
3.9 KiB
JavaScript
48 lines
3.9 KiB
JavaScript
// คัดลอก pdf.worker.min.mjs จาก node_modules ไป public/ แล้ว patch heuristic
|
||
// การแทรก fake space กลางคำไทย (bug report 2026-09-24):
|
||
//
|
||
// pdf.js (ทั้ง v4.10 จนถึง master ปัจจุบัน) เก็บตำแหน่งอ้างอิงของ glyph ก่อนหน้า
|
||
// เฉพาะ glyph ที่มีความกว้าง ≠ 0 เท่านั้น:
|
||
// if (scaledDim) { textChunk.prevTransform = getCurrentTextTransform(); }
|
||
// สระบน-ล่าง/วรรณยุกต์ไทยเป็น glyph กว้าง 0 แต่ charSpacing ของ glyph เหล่านั้น
|
||
// ยังขยับตำแหน่ง x อยู่ — พอข้าม glyph กว้าง 0 ตั้งแต่ 2 ตัวขึ้นไป gap สะสม
|
||
// (charSpacing ต่อ glyph × จำนวน) จะเกิน spaceInFlowMin จน addFakeSpaces แทรก
|
||
// " " กลางคำ ("ฉะนั้ น ให้ ท่ าน") ทั้งที่บนกระดาษตัวอักษรติดกันสนิท
|
||
//
|
||
// แก้โดยถอดเงื่อนไข if ให้อัปเดต prevTransform ทุก glyph — glyph กว้าง 0 ที่
|
||
// charSpacing = 0 ไม่ขยับตำแหน่งอยู่แล้ว (compareWithLastPosition early-return)
|
||
// จึงไม่มีผลกับเอกสารทั่วไป ส่วน space จริง (glyph SPACE) ไปทาง saveLastChar
|
||
// ซึ่งไม่เกี่ยวกับจุดนี้ จึงยังคงอยู่ครบ
|
||
//
|
||
// ทำบนไฟล์ minified ด้วย pattern จำเพาะ (ชื่อตัวแปร minify อาจเปลี่ยนตามเวอร์ชัน):
|
||
// เจอ ≠ 1 จุด = โครงสร้างโค้ดเปลี่ยนหลังอัปเกรด pdfjs-dist → fail ดัง ๆ ทันที
|
||
// ไม่ปล่อยให้ patch หลุดเงียบ ๆ แล้ว fake space กลับมาโดยไม่มีใครรู้ตัว
|
||
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||
import { dirname } from "node:path";
|
||
|
||
const SRC = "node_modules/pdfjs-dist/build/pdf.worker.min.mjs";
|
||
// statics ของแอปอยู่ใต้ public/note/** (URL /docedit/note/… — basePath /docedit + route prefix /note)
|
||
const DEST = "public/note/pdf.worker.min.mjs";
|
||
|
||
const code = readFileSync(SRC, "utf8");
|
||
|
||
// src/core/evaluator.js: if (scaledDim) { textChunk.prevTransform = getCurrentTextTransform(); }
|
||
// minified (v4.10.38): C&&(h.prevTransform=getCurrentTextTransform());
|
||
// lookbehind (?<![.\w$]) กันจับ identifier ต่อท้าย member expression ผิด ๆ หลังอัปเกรด
|
||
// (เช่น a.b&&(...) จะ match แค่ b&& แล้ว replace ได้ a.h.prevTransform=… พัดเงียบ)
|
||
const PATCH_RE =
|
||
/(?<![.\w$])[A-Za-z$_][\w$]*&&\(([A-Za-z$_][\w$]*\.prevTransform=getCurrentTextTransform\(\))\);/g;
|
||
|
||
const found = [...code.matchAll(PATCH_RE)];
|
||
if (found.length !== 1) {
|
||
console.error(
|
||
`[patch-pdf-worker] หา pattern ไม่ได้ตามที่คาด (เจอ ${found.length} จุด ต้องการ 1) — ` +
|
||
`pdfjs-dist อัปเกรดแล้วโครงสร้างโค้ดเปลี่ยน ปรับ PATCH_RE ใน scripts/patch-pdf-worker.mjs`,
|
||
);
|
||
process.exit(1);
|
||
}
|
||
|
||
// Dockerfile mkdir แค่ public/ เปล่า ๆ — script ต้องสร้าง dir ปลายทางเอง
|
||
mkdirSync(dirname(DEST), { recursive: true });
|
||
writeFileSync(DEST, code.replace(PATCH_RE, "$1;"));
|
||
console.log("[patch-pdf-worker] คัดลอก worker + patch fake-space ไทยเรียบร้อย");
|