tenta fix pdfservice.js
This commit is contained in:
1 parent
bf277416ff
commit
17078adc45
1 file changed
+66
-48
@@ -341,11 +341,51 @@ export class PdfService {
|
||||
}
|
||||
|
||||
// Fonte padrão do pdf-lib: TimesRoman, TimesBold, TimesItalic
|
||||
// Usa apenas as fontes padrão do pdf-lib, sem try/catch, pois são SEMPRE válidas
|
||||
const font = await pdfDoc.embedFont(StandardFonts.TimesRoman);
|
||||
const fontBold = await pdfDoc.embedFont(StandardFonts.TimesBold);
|
||||
const fontItalic = await pdfDoc.embedFont(StandardFonts.TimesItalic);
|
||||
const fontBoldItalic = fontBold; // pdf-lib não tem TimesBoldItalic, usa bold
|
||||
// Usa apenas as fontes padrão do pdf-lib, sem try/catch, e SEM VARIÁVEL UNDEFINED
|
||||
const font = await pdfDoc.embedFont(StandardFonts.TimesRoman as string);
|
||||
const fontBold = await pdfDoc.embedFont(StandardFonts.TimesBold as string);
|
||||
const fontItalic = await pdfDoc.embedFont(StandardFonts.TimesItalic as string);
|
||||
const fontBoldItalic = fontBold;
|
||||
|
||||
// Função para quebrar texto em linhas respeitando largura máxima e manter quebras de linha simples
|
||||
function wrapTextStyled(text: string, font: any, fontBold: any, fontItalic: any, fontBoldItalic: any, fontSize: number, maxWidth: number, indent: boolean, align: string, bold: boolean, italic: boolean): { text: string, font: any, indent: boolean, align: string, bold: boolean, italic: boolean }[] {
|
||||
// Mantém quebras de linha simples para espaçamento
|
||||
const rawLines = text.split('\n');
|
||||
const lines: { text: string, font: any, indent: boolean, align: string, bold: boolean, italic: boolean }[] = [];
|
||||
for (const rawLine of rawLines) {
|
||||
let line = rawLine;
|
||||
// Detecta negrito e itálico inline
|
||||
let isBold = bold, isItalic = italic;
|
||||
if (/^<b>|^<strong>/.test(line)) { isBold = true; line = line.replace(/^<b>|^<strong>/, ''); }
|
||||
if (/^<i>|^<em>/.test(line)) { isItalic = true; line = line.replace(/^<i>|^<em>/, ''); }
|
||||
if (/<\/b>$|<\/strong>$/.test(line)) { isBold = true; line = line.replace(/<\/b>$|<\/strong>$/, ''); }
|
||||
if (/<\/i>$|<\/em>$/.test(line)) { isItalic = true; line = line.replace(/<\/i>$|<\/em>$/, ''); }
|
||||
line = line.replace(/<\/?(b|strong|i|em)>/gi, '');
|
||||
|
||||
// Seleciona fonte correta
|
||||
let usedFont = font;
|
||||
if (isBold && isItalic && fontBoldItalic) usedFont = fontBoldItalic;
|
||||
else if (isBold && fontBold) usedFont = fontBold;
|
||||
else if (isItalic && fontItalic) usedFont = fontItalic;
|
||||
|
||||
// Quebra em palavras para justificar
|
||||
const words = line.split(' ');
|
||||
let currentLine = '';
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
const word = words[i];
|
||||
const testLine = currentLine ? currentLine + ' ' + word : word;
|
||||
const width = usedFont.widthOfTextAtSize(testLine, fontSize);
|
||||
if (width > maxWidth && currentLine) {
|
||||
lines.push({ text: currentLine, font: usedFont, indent, align, bold: isBold, italic: isItalic });
|
||||
currentLine = word;
|
||||
} else {
|
||||
currentLine = testLine;
|
||||
}
|
||||
}
|
||||
if (currentLine) lines.push({ text: currentLine, font: usedFont, indent, align, bold: isBold, italic: isItalic });
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
// Quebrar o texto em páginas
|
||||
let currentPar = 0;
|
||||
@@ -366,6 +406,7 @@ export class PdfService {
|
||||
let y = PAGE_HEIGHT - margens.top;
|
||||
let firstLine = true;
|
||||
while (currentPar < paragrafos.length) {
|
||||
// Detecta recuo e alinhamento por marcação
|
||||
let indent = paragrafos[currentPar].startsWith('§§INDENT§§');
|
||||
let center = paragrafos[currentPar].startsWith('§§CENTER§§');
|
||||
let align = center ? 'center' : 'justify';
|
||||
@@ -375,45 +416,22 @@ export class PdfService {
|
||||
let bold = /^<b>|^<strong>/.test(text);
|
||||
let italic = /^<i>|^<em>/.test(text);
|
||||
|
||||
// Remove tags de formatação para o texto puro
|
||||
let cleanText = text.replace(/<\/?(b|strong|i|em)>/gi, '');
|
||||
|
||||
// Seleciona fonte correta
|
||||
let usedFont = font;
|
||||
if (bold && italic) usedFont = fontBoldItalic;
|
||||
else if (bold) usedFont = fontBold;
|
||||
else if (italic) usedFont = fontItalic;
|
||||
|
||||
// Quebra em linhas respeitando largura máxima
|
||||
const words = cleanText.split(' ');
|
||||
let lines: string[] = [];
|
||||
let current = '';
|
||||
for (let i = 0; i < words.length; i++) {
|
||||
const word = words[i];
|
||||
const testLine = current ? current + ' ' + word : word;
|
||||
const width = usedFont.widthOfTextAtSize(testLine, FONT_SIZE);
|
||||
if (width > MAX_WIDTH - (indent ? FONT_SIZE * 2 : 0) && current) {
|
||||
lines.push(current);
|
||||
current = word;
|
||||
} else {
|
||||
current = testLine;
|
||||
}
|
||||
}
|
||||
if (current) lines.push(current);
|
||||
|
||||
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
||||
const styledLines = wrapTextStyled(text, font, fontBold, fontItalic, fontBoldItalic, FONT_SIZE, MAX_WIDTH - (indent ? FONT_SIZE * 2 : 0), indent, align, bold, italic);
|
||||
let lineIdx = 0;
|
||||
if (currentLine > 0) lineIdx = currentLine;
|
||||
for (; lineIdx < styledLines.length; lineIdx++) {
|
||||
if (y < margens.bottom + LINE_HEIGHT) {
|
||||
currentLine = lineIdx;
|
||||
break;
|
||||
}
|
||||
let line = lines[lineIdx];
|
||||
let { text, font: usedFont, indent, align, bold, italic } = styledLines[lineIdx];
|
||||
let x = margens.left + (indent ? FONT_SIZE * 2 : 0);
|
||||
|
||||
// Centralizado
|
||||
if (align === 'center') {
|
||||
const textWidth = usedFont.widthOfTextAtSize(line, FONT_SIZE);
|
||||
const textWidth = usedFont.widthOfTextAtSize(text, FONT_SIZE);
|
||||
x = margens.left + ((MAX_WIDTH - (indent ? FONT_SIZE * 2 : 0) - textWidth) / 2) + (indent ? FONT_SIZE * 2 : 0);
|
||||
page.drawText(line, {
|
||||
page.drawText(text, {
|
||||
x,
|
||||
y,
|
||||
size: FONT_SIZE,
|
||||
@@ -422,39 +440,39 @@ export class PdfService {
|
||||
});
|
||||
}
|
||||
// Justificado (exceto última linha do parágrafo e centralizado)
|
||||
else if (line.trim().length > 0 && lineIdx < lines.length - 1 && align === 'justify') {
|
||||
const lineWords = line.split(' ');
|
||||
if (lineWords.length > 1) {
|
||||
const textWidth = usedFont.widthOfTextAtSize(line, FONT_SIZE);
|
||||
else if (text.trim().length > 0 && lineIdx < styledLines.length - 1 && align === 'justify') {
|
||||
const words = text.split(' ');
|
||||
if (words.length > 1) {
|
||||
const textWidth = usedFont.widthOfTextAtSize(text, FONT_SIZE);
|
||||
const spaceWidth = usedFont.widthOfTextAtSize(' ', FONT_SIZE);
|
||||
const totalSpaces = lineWords.length - 1;
|
||||
const totalSpaces = words.length - 1;
|
||||
const extraSpace = (MAX_WIDTH - (indent ? FONT_SIZE * 2 : 0) - textWidth) / totalSpaces;
|
||||
let cursor = x;
|
||||
for (let w = 0; w < lineWords.length; w++) {
|
||||
page.drawText(lineWords[w], {
|
||||
for (let w = 0; w < words.length; w++) {
|
||||
page.drawText(words[w], {
|
||||
x: cursor,
|
||||
y,
|
||||
size: FONT_SIZE,
|
||||
font: usedFont
|
||||
});
|
||||
if (w < lineWords.length - 1) {
|
||||
cursor += usedFont.widthOfTextAtSize(lineWords[w], FONT_SIZE) + spaceWidth + extraSpace;
|
||||
if (w < words.length - 1) {
|
||||
cursor += usedFont.widthOfTextAtSize(words[w], FONT_SIZE) + spaceWidth + extraSpace;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
page.drawText(line, { x, y, size: FONT_SIZE, font: usedFont });
|
||||
page.drawText(text, { x, y, size: FONT_SIZE, font: usedFont });
|
||||
}
|
||||
} else {
|
||||
page.drawText(line, { x, y, size: FONT_SIZE, font: usedFont });
|
||||
page.drawText(text, { x, y, size: FONT_SIZE, font: usedFont });
|
||||
}
|
||||
y -= FONT_SIZE * 1.25; // espaçamento entre linhas 1,25
|
||||
currentLine = 0;
|
||||
firstLine = false;
|
||||
}
|
||||
if (lines.length > 0) {
|
||||
if (lineIdx >= styledLines.length) {
|
||||
y -= FONT_SIZE * 0.5;
|
||||
}
|
||||
if (currentLine > 0) {
|
||||
if (lineIdx < styledLines.length) {
|
||||
break;
|
||||
}
|
||||
currentPar++;
|
||||
|
||||
Reference in new issue
Block a user