Files
documenso/scripts/generate-overflow-test-pdf.mjs
2026-05-08 15:14:27 +10:00

261 lines
8.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// scripts/generate-overflow-test-pdf.mjs
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { chromium } from 'playwright';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// --- Helper functions to generate HTML for each page ---
function box(left, top, width, height) {
return `left:${left}%;top:${top}%;width:${width}%;height:${height}%;`;
}
function labelStyle(left, top) {
return `left:${left}%;top:${top}%;`;
}
function makeBox(left, top, width, height, label, { labelBelow = false } = {}) {
const labelTop = labelBelow ? top + height + 0.5 : top - 1.5;
return `
<div class="label" style="${labelStyle(left, labelTop)}">${label}</div>
<div class="box" style="${box(left, top, width, height)}"></div>`;
}
// --- Pages 1-2: Date / Email (3×3 multi-line grid with text align variants) ---
function makeFieldOverflowPageWithGrid(title) {
const startX = 10;
const boxWidth = 35;
// Section A: Single-line height
const slHeight = 1.75;
const slStartY = 15;
const slRowSpacing = 8;
const sectionARows = [
{ y: slStartY, label: 'M_AUTO TA_LEFT VA_MIDDLE' },
{ y: slStartY + slRowSpacing, label: 'M_AUTO TA_LEFT VA_MIDDLE' },
{ y: slStartY + 2 * slRowSpacing, label: 'M_AUTO TA_LEFT VA_MIDDLE' },
];
// Section B: Multi-line height — 3×3 grid
// Rows: TA_LEFT, TA_CENTER, TA_RIGHT
// Columns: short, medium, long text
const mlHeight = 12;
const mlBoxWidth = 30;
const mlColumnX = [2.5, 35, 67.5];
const mlRowY = [45, 63, 83];
const mlTextAligns = ['LEFT', 'CENTER', 'RIGHT'];
let content = `
<div class="title" style="top:3%;left:10%;">${title}</div>`;
for (const r of sectionARows) {
content += makeBox(startX, r.y, boxWidth, slHeight, r.label);
}
for (let ri = 0; ri < 3; ri++) {
for (let ci = 0; ci < 3; ci++) {
const label = `M_AUTO TA_${mlTextAligns[ri]} VA_MIDDLE`;
content += makeBox(mlColumnX[ci], mlRowY[ri], mlBoxWidth, mlHeight, label);
}
}
return content;
}
// --- Page 3: Signature (stacked multi-line, no text align control) ---
function makeSignatureOverflowPage(title) {
const startX = 10;
const boxWidth = 35;
// Section A: Single-line height
const slHeight = 1.75;
const slStartY = 15;
const slRowSpacing = 8;
const sectionARows = [
{ y: slStartY, label: 'M_AUTO TA_CENTER VA_MIDDLE' },
{ y: slStartY + slRowSpacing, label: 'M_AUTO TA_CENTER VA_MIDDLE' },
{ y: slStartY + 2 * slRowSpacing, label: 'M_AUTO TA_CENTER VA_MIDDLE' },
];
// Section B: Multi-line height — stacked single column
const mlHeight = 12;
const mlStartY = 45;
const mlRowSpacing = 18;
const sectionBRows = [
{ y: mlStartY, label: 'M_AUTO TA_CENTER VA_MIDDLE' },
{ y: mlStartY + mlRowSpacing, label: 'M_AUTO TA_CENTER VA_MIDDLE' },
{ y: mlStartY + 2 * mlRowSpacing, label: 'M_AUTO TA_CENTER VA_MIDDLE' },
];
let content = `
<div class="title" style="top:3%;left:10%;">${title}</div>`;
for (const r of sectionARows) {
content += makeBox(startX, r.y, boxWidth, slHeight, r.label);
}
for (const r of sectionBRows) {
content += makeBox(startX, r.y, boxWidth, mlHeight, r.label);
}
return content;
}
// --- Pages 4-5: Text Field Auto Mode ---
function makeTextAutoPage(title, boxHeight, isSingleLine) {
const boxWidth = 28;
const columns = [
{ col: 0, x: 5, textAlign: 'left' },
{ col: 1, x: 35.5, textAlign: 'center' },
{ col: 2, x: 66, textAlign: 'right' },
];
const verticalAligns = ['top', 'middle', 'bottom'];
let content = `
<div class="title" style="top:3%;left:5%;">${title}</div>`;
if (isSingleLine) {
// Single-line: stagger all 9 items evenly down the page.
// Each item gets its own Y position to avoid horizontal overflow collision.
const itemCount = 9; // 3 rows × 3 columns
const startY = 10;
const endY = 92;
const spacing = (endY - startY) / (itemCount - 1);
let itemIndex = 0;
for (let ri = 0; ri < 3; ri++) {
for (let ci = 0; ci < columns.length; ci++) {
const col = columns[ci];
const y = startY + itemIndex * spacing;
const label = `M_AUTO TA_${col.textAlign.toUpperCase()} VA_${verticalAligns[ri].toUpperCase()}`;
content += makeBox(col.x, y, boxWidth, boxHeight, label);
itemIndex++;
}
}
} else {
// Multi-line: 3 rows evenly spaced, bottom row near page bottom.
// Box is 12% tall. Top of last box at 80% so bottom edge is at 92%.
const startY = 10;
const lastRowY = 80; // 80 + 12 = 92% (page bottom with padding)
const midY = (startY + lastRowY) / 2; // 45%
const rowYPositions = [startY, midY, lastRowY];
for (let ri = 0; ri < 3; ri++) {
const labelBelow = verticalAligns[ri] === 'bottom';
for (const col of columns) {
const label = `M_AUTO TA_${col.textAlign.toUpperCase()} VA_${verticalAligns[ri].toUpperCase()}`;
content += makeBox(col.x, rowYPositions[ri], boxWidth, boxHeight, label, { labelBelow });
}
}
}
return content;
}
// --- Page 6: Explicit Modes ---
function makePage6() {
const boxWidth = 25;
let content = `
<div class="title" style="top:3%;left:5%;">Text Field Explicit Modes</div>
`;
// Section A: Horizontal mode — centered on page, staggered vertically
const centeredX = (100 - boxWidth) / 2; // 37.5%
const horizontalRows = [
{ x: centeredX, y: 15, label: 'M_HORIZONTAL TA_LEFT VA_TOP' },
{ x: centeredX, y: 21, label: 'M_HORIZONTAL TA_CENTER VA_TOP' },
{ x: centeredX, y: 27, label: 'M_HORIZONTAL TA_RIGHT VA_TOP' },
];
for (const r of horizontalRows) {
content += makeBox(r.x, r.y, boxWidth, 1.75, r.label);
}
// Section B: Vertical mode — place side by side so vertical overflow has room below
content += '';
const verticalCols = [
{ x: 5, y: 43, label: 'M_VERTICAL TA_LEFT VA_TOP', labelBelow: false },
{ x: 37.5, y: 43, label: 'M_VERTICAL TA_LEFT VA_MIDDLE', labelBelow: false },
{ x: 70, y: 43, label: 'M_VERTICAL TA_LEFT VA_BOTTOM', labelBelow: true },
];
for (const c of verticalCols) {
content += makeBox(c.x, c.y, boxWidth, 12, c.label, { labelBelow: c.labelBelow });
}
return content;
}
// --- Page 7: Crop Mode ---
function makePage7() {
return `
<div class="title" style="top:3%;left:10%;">Crop Mode (no overflow)</div>
${makeBox(10, 15, 25, 1.75, 'M_CROP TA_LEFT VA_TOP')}
${makeBox(10, 30, 25, 12, 'M_CROP TA_LEFT VA_TOP')}`;
}
// --- Assemble all pages ---
function buildPage(contentFn) {
return `<div class="page">${typeof contentFn === 'string' ? contentFn : contentFn}</div>`;
}
const html = `<!DOCTYPE html>
<html>
<head>
<style>
@page { size: A4; margin: 0; }
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: sans-serif; font-size: 10px; }
.page { width: 210mm; height: 297mm; position: relative; page-break-after: always; }
.page:last-child { page-break-after: auto; }
.title { position: absolute; font-size: 18px; font-weight: bold; }
.section-label { position: absolute; font-size: 12px; font-weight: bold; color: #666; }
.box { position: absolute; border: 1px solid black; box-sizing: border-box; }
.label { position: absolute; font-size: 9px; color: red; font-weight: bold; z-index: 9999; }
</style>
</head>
<body>
${buildPage(makeFieldOverflowPageWithGrid('Date Field Overflow Tests'))}
${buildPage(makeFieldOverflowPageWithGrid('Email Field Overflow Tests'))}
${buildPage(makeSignatureOverflowPage('Signature Field Overflow Tests'))}
${buildPage(makeTextAutoPage('Text Field Auto - Single-line Height', 1.75, true))}
${buildPage(makeTextAutoPage('Text Field Auto - Multi-line Height', 12, false))}
${buildPage(makeTextAutoPage('Text Field Auto - Multi-line Height Overflow', 12, false))}
${buildPage(makePage6())}
${buildPage(makePage7())}
</body>
</html>`;
async function main() {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.setContent(html, { waitUntil: 'networkidle' });
const outputPath = path.join(__dirname, '../assets/field-overflow.pdf');
await page.pdf({
path: outputPath,
format: 'A4',
printBackground: true,
margin: { top: '0', right: '0', bottom: '0', left: '0' },
});
await browser.close();
console.log(`PDF generated: assets/field-overflow.pdf`);
}
main().catch(console.error);