docs(sdlc): match reference PDF layout and company CI

This commit is contained in:
Thanakorn
2026-09-09 13:54:45 +07:00
parent 087e7b3958
commit 6255b31591
81 changed files with 149 additions and 156 deletions
+16 -11
View File
@@ -87,7 +87,8 @@ function renderTable(lines, className = '') {
const attr = classFor(column);
return `<${tag}${attr ? ` class="${attr}"` : ''}>${renderInline(cell)}</${tag}>`;
}).join('');
return `<table${className ? ` class="${className}"` : ''}><thead><tr>${cells('th', header)}</tr></thead><tbody>${data.map((row) => `<tr>${cells('td', row)}</tr>`).join('')}</tbody></table>`;
const classes = [className, header.length >= 8 ? 'dense' : ''].filter(Boolean).join(' ');
return `<table${classes ? ` class="${classes}"` : ''}><thead><tr>${cells('th', header)}</tr></thead><tbody>${data.map((row) => `<tr>${cells('td', row)}</tr>`).join('')}</tbody></table>`;
}
function renderParagraph(lines) {
@@ -200,28 +201,32 @@ async function main() {
fs.readFile(path.join(assets, 'LeelawadeeUI.ttf'))
]);
const { title, footer, metadata, body } = extractDocument(markdown);
// Wide reference tables (schedule, register, test cases, traceability) need landscape;
// ordinary 8-column status tables still read well in portrait.
const widestTable = Math.max(0, ...markdown.split('\n').filter(isTableLine).map((line) => tableCells(line).length));
const LANDSCAPE_TITLES = new Set(['Work Schedule', 'Traceability Record', 'Traceability Record Table']);
const isLandscape = LANDSCAPE_TITLES.has(title) || widestTable >= 9;
// The reference package prints every work product portrait except the
// evidence index and the summary traceability matrix.
const LANDSCAPE_TITLES = new Set(['List of Evidence', 'Traceability Record Table']);
const isLandscape = LANDSCAPE_TITLES.has(title);
const values = {
logoPath: `data:image/svg+xml;base64,${logo.toString('base64')}`,
documentTitle: title,
documentType: metadata['Document No'] ?? title,
ciBlue: '#0797d5',
ciGrey: '#60656a',
standard: 'ISO/IEC 29110-4-1:2018',
footerTag: footer,
release: metadata['Release, Version, By:'] ?? '',
projectName: metadata['Project Name'] ?? 'BRN WMS',
projectCode: metadata['Project Code'] ?? '200-WMS-26-001-00',
footerNote: footer ? `ISO/IEC 29110-4-1:2018 ${footer}` : 'ISO/IEC 29110-4-1:2018',
pageNumber: '<span class="pageNumber"></span>',
totalPages: '<span class="totalPages"></span>'
};
const pdfHeader = applyTemplate(headerTemplate, values);
const pdfFooter = applyTemplate(footerTemplate, values);
const fontFace = `@font-face { font-family: "BRN Thai"; src: url(data:font/ttf;base64,${thaiFont.toString('base64')}) format("truetype"); font-weight: 400 700; }`;
const pageLayout = isLandscape
? '@page { size: A4 landscape; margin: 18mm 16mm 28mm; }'
? '@page { size: A4 landscape; margin: 32mm 15mm 24mm 15mm; }'
: '';
const html = `<!doctype html><html><head><meta charset="utf-8"><style>${fontFace}${css}${pageLayout}</style></head><body><main class="delivery-document">${applyTemplate(headerTemplate, values)}${markdownToHtml(body)}</main></body></html>`;
const templateFont = `<style>${fontFace}</style>`;
const html = `<!doctype html><html><head><meta charset="utf-8"><style>${fontFace}${css}${pageLayout}</style></head><body><main class="delivery-document">${markdownToHtml(body)}</main></body></html>`;
await fs.mkdir(path.dirname(destination), { recursive: true });
const browser = await chromium.launch({ headless: true });
@@ -234,8 +239,8 @@ async function main() {
printBackground: true,
preferCSSPageSize: true,
displayHeaderFooter: true,
headerTemplate: '<div></div>',
footerTemplate: pdfFooter
headerTemplate: `${templateFont}${pdfHeader}`,
footerTemplate: `${templateFont}${pdfFooter}`
});
} finally {
await browser.close();