fix(pdf): preserve accented names in revised CV and letter headings

This commit is contained in:
cesnimda
2026-10-29 23:38:43 +01:00
parent 38d7133d20
commit 154a9e89f5
13 changed files with 235 additions and 13 deletions
@@ -0,0 +1,27 @@
// Run in the preview frame after fonts/pagination settle, rather than using text-cell tops.
export function minimumNameInkClearance(selector: string): number {
const name = document.querySelector(selector);
const flow = document.querySelector('[data-cv-preview-flow]');
const context = document.createElement('canvas').getContext('2d');
if (!name || !flow || !context) throw new Error('Missing name or settled print fragment');
const clipTop = flow.getBoundingClientRect().top;
const clearance: number[] = [];
const walker = document.createTreeWalker(name, NodeFilter.SHOW_TEXT);
let node;
while ((node = walker.nextNode())) {
const style = getComputedStyle(node.parentElement!);
context.font = `${style.fontStyle} ${style.fontWeight} ${style.fontSize} ${style.fontFamily}`;
let offset = 0;
for (const character of node.textContent || '') {
const range = document.createRange();
range.setStart(node, offset); range.setEnd(node, offset + character.length);
offset += character.length;
if (!character.trim()) continue;
const rect = range.getClientRects()[0], glyph = context.measureText(character);
if (!rect) throw new Error('Name glyph has no rendered position');
clearance.push(rect.top + glyph.fontBoundingBoxAscent - glyph.actualBoundingBoxAscent - clipTop);
}
}
if (!clearance.length) throw new Error('Empty name cannot qualify glyph clearance');
return Math.min(...clearance);
}