Files
wms-app/scripts/sdlc-seed/lib.mjs
T
Thanakorn 087e7b3958 docs(sdlc): reformat work products to audited reference layout
Replace the PHP/Markdown seeding with a data-driven generator in
scripts/sdlc-seed and regenerate all 59 work products.
2026-09-09 08:09:54 +07:00

61 lines
3.8 KiB
JavaScript
Raw 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.
// Shared helpers for the ISO/IEC 29110 work-product seed.
// Every document follows the layout of the audited 200-TAS-25-001-00 package:
// title, document-control block, Thai section headings, tables, three signature tables.
export const TH_MONTHS = ['มกราคม','กุมภาพันธ์','มีนาคม','เมษายน','พฤษภาคม','มิถุนายน','กรกฎาคม','สิงหาคม','กันยายน','ตุลาคม','พฤศจิกายน','ธันวาคม'];
export const TH_SHORT = ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.','ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'];
const parts = (iso) => iso.split('-').map(Number);
/** 2026-08-17 -> 25690817 (Buddhist compact, used in filenames and Release fields). */
export const bud = (iso) => { const [y, m, d] = parts(iso); return `${y + 543}${String(m).padStart(2, '0')}${String(d).padStart(2, '0')}`; };
/** 2026-08-17 -> 17 สิงหาคม 2569 */
export const thLong = (iso) => { const [y, m, d] = parts(iso); return `${d} ${TH_MONTHS[m - 1]} ${y + 543}`; };
/** 2026-08-17 -> 17 ส.ค. 69 */
export const thShort = (iso) => { const [y, m, d] = parts(iso); return `${d} ${TH_SHORT[m - 1]} ${String(y + 543).slice(2)}`; };
/** 2026-08-17 -> 17/08/2569 */
export const thNum = (iso) => { const [y, m, d] = parts(iso); return `${String(d).padStart(2, '0')}/${String(m).padStart(2, '0')}/${y + 543}`; };
/** Range in short Thai form: 10–14 ส.ค. 69 or 30 พ.ค.–31 ก.ค. 69 */
export const thRange = (a, b) => {
if (a === b) return thShort(a);
const [ya, ma, da] = parts(a); const [yb, mb, db] = parts(b);
if (ya === yb && ma === mb) return `${da}–${db} ${TH_SHORT[ma - 1]} ${String(ya + 543).slice(2)}`;
if (ya === yb) return `${da} ${TH_SHORT[ma - 1]}–${db} ${TH_SHORT[mb - 1]} ${String(ya + 543).slice(2)}`;
return `${thShort(a)}–${thShort(b)}`;
};
export const thRangeLong = (a, b) => `${thLong(a)} – ${thLong(b)}`;
export const daysBetween = (a, b) => Math.round((Date.parse(b) - Date.parse(a)) / 86400000) + 1;
const cell = (v) => String(v ?? '').replace(/\|/g, '\\|').replace(/\r?\n/g, ' ');
/** Markdown table. `align` is an optional array of 'l' | 'c' | 'r'. */
export function table(headers, rows, align) {
const sep = headers.map((_, i) => ({ c: ':---:', r: '---:' }[align?.[i]] ?? '---'));
const line = (r) => `| ${r.map(cell).join(' | ')} |`;
return [line(headers), line(sep), ...rows.map(line)].join('\n');
}
/** Document-control block. Each row is [label, value] or [label, value, label2, value2]. */
export function control(rows) {
return rows.map((r) => `| ${r.map(cell).join(' | ')} |`).join('\n');
}
/** A single signature table (ชื่อ / ตำแหน่ง / ลายเซ็น / วันที่). */
const sigTable = (people) => table(['ชื่อ', 'ตำแหน่ง', 'ลายเซ็น', 'วันที่'], people.map((p) => [p.th, p.role, '', '']));
/** The three signature blocks used by every work product. */
export function signatures(secretary, reviewer, approver) {
const list = (x) => (Array.isArray(x) ? x : [x]);
return [
'## ผู้จัดทำเอกสาร (Secretary)', sigTable(list(secretary)),
'## ผู้ตรวจสอบเอกสาร (Reviewer)', sigTable(list(reviewer)),
'## ผู้อนุมัติ (Approval)', sigTable(list(approver)),
].join('\n\n');
}
export const bullets = (items) => items.map((i) => `- ${i}`).join('\n');
export const numbered = (items) => items.map((i, n) => `${n + 1}. ${i}`).join('\n');
/** Join document parts with blank lines, dropping empty parts. */
export const doc = (...parts) => parts.flat().filter((p) => p !== undefined && p !== null && p !== '').join('\n\n') + '\n';