mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-08-24 07:12:18 +10:00
refactor: ponytail audit
This commit is contained in:
@@ -43,27 +43,9 @@ function ptToTwips(pt: number): number {
|
||||
return Math.round(pt * 20);
|
||||
}
|
||||
|
||||
// --- Page size constants (in mm) ---
|
||||
|
||||
interface PageSize {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
const DEFAULT_PAGE_SIZE: PageSize = { width: 210, height: 297 };
|
||||
|
||||
const PAGE_SIZES = {
|
||||
a4: DEFAULT_PAGE_SIZE,
|
||||
letter: { width: 215.9, height: 279.4 },
|
||||
} satisfies Record<string, PageSize>;
|
||||
|
||||
type DocxPageFormat = keyof typeof PAGE_SIZES;
|
||||
|
||||
const resolveDocxPageFormat = (format: ResumeData["metadata"]["page"]["format"]): DocxPageFormat => {
|
||||
if (format === "letter") return "letter";
|
||||
|
||||
return "a4";
|
||||
};
|
||||
// DOCX has fixed pages; free-form resumes intentionally fall back to A4.
|
||||
const A4_PAGE_SIZE = { width: 210, height: 297 };
|
||||
const LETTER_PAGE_SIZE = { width: 215.9, height: 279.4 };
|
||||
|
||||
// --- Invisible border preset for table cells ---
|
||||
|
||||
@@ -103,12 +85,6 @@ const TEMPLATE_CONFIGS: Record<Template, TemplateConfig> = {
|
||||
scizor: { sidebarSide: "left", sidebarBackground: "none", headerPosition: "full-width" },
|
||||
};
|
||||
|
||||
const DEFAULT_TEMPLATE_CONFIG: TemplateConfig = {
|
||||
sidebarSide: "left",
|
||||
sidebarBackground: "none",
|
||||
headerPosition: "full-width",
|
||||
};
|
||||
|
||||
/**
|
||||
* Blends a hex color toward white at the given opacity (0-1).
|
||||
* Used to approximate CSS `background-color: rgba(r,g,b, 0.2)` on a white background.
|
||||
@@ -376,7 +352,7 @@ export function buildDocument(data: ResumeData, resolveTitle?: SectionTitleResol
|
||||
const lineSpacing = Math.round(data.metadata.typography.body.lineHeight * 240);
|
||||
|
||||
const { page } = data.metadata;
|
||||
const pageSize = PAGE_SIZES[resolveDocxPageFormat(page.format)];
|
||||
const pageSize = page.format === "letter" ? LETTER_PAGE_SIZE : A4_PAGE_SIZE;
|
||||
// Margins and gaps are defined in points (pt), not mm
|
||||
const marginXTwips = ptToTwips(page.marginX);
|
||||
const marginYTwips = ptToTwips(page.marginY);
|
||||
@@ -385,7 +361,7 @@ export function buildDocument(data: ResumeData, resolveTitle?: SectionTitleResol
|
||||
const sidebarWidth = data.metadata.layout.sidebarWidth;
|
||||
|
||||
// Template-aware layout config
|
||||
const templateConfig = TEMPLATE_CONFIGS[data.metadata.template] ?? DEFAULT_TEMPLATE_CONFIG;
|
||||
const templateConfig = TEMPLATE_CONFIGS[data.metadata.template];
|
||||
|
||||
// Compute sidebar background shading hex
|
||||
let sidebarShadingHex: string | undefined;
|
||||
|
||||
@@ -20,4 +20,11 @@ describe("buildDocx", () => {
|
||||
const blob = await buildDocx(data);
|
||||
expect(blob.size).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("returns a rejected Promise when document building fails synchronously", async () => {
|
||||
const promise = buildDocx(undefined as never);
|
||||
|
||||
expect(promise).toBeInstanceOf(Promise);
|
||||
await expect(promise).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@ import { buildDocument } from "./builder";
|
||||
* Builds a DOCX file from resume data and returns it as a Blob. Pass `resolveTitle` to fill in
|
||||
* locale-aware section headings (titles are stored empty and resolved at render time).
|
||||
*/
|
||||
// biome-ignore lint/suspicious/useAwait: keep synchronous renderer errors on the public Promise rejection path.
|
||||
export async function buildDocx(data: ResumeData, resolveTitle?: SectionTitleResolver): Promise<Blob> {
|
||||
const doc = buildDocument(data, resolveTitle);
|
||||
return Packer.toBlob(doc);
|
||||
|
||||
Reference in New Issue
Block a user