tenta fix pdfservice.js

This commit is contained in:
rodrigo committed 2025-04-21 19:42:27 -03:00
1 parent 5786af03d5
commit 73b571be71
1 file changed
+91 -16
+91 -16
View File
@@ -247,29 +247,68 @@ export class PdfService {
const LINE_HEIGHT = FONT_SIZE * 1.5; const LINE_HEIGHT = FONT_SIZE * 1.5;
const MAX_WIDTH = PAGE_WIDTH - margens.left - margens.right; const MAX_WIDTH = PAGE_WIDTH - margens.left - margens.right;
// Processar variáveis do template // Função para decodificar entidades HTML comuns (acentuação e outros)
const texto = this.processarTemplate(conteudo, escritorio) function decodeHtmlEntities(str: string): string {
.replace(/<[^>]+>/g, '') // Remove tags HTML if (!str) return '';
.replace(/&nbsp;/g, ' ') return str
.replace(/&amp;/g, '&') .replace(/&aacute;/gi, 'á')
.replace(/&lt;/g, '<') .replace(/&eacute;/gi, 'é')
.replace(/&gt;/g, '>') .replace(/&iacute;/gi, 'í')
.replace(/&quot;/g, '"') .replace(/&oacute;/gi, 'ó')
.replace(/&uacute;/gi, 'ú')
.replace(/&Aacute;/g, 'Á')
.replace(/&Eacute;/g, 'É')
.replace(/&Iacute;/g, 'Í')
.replace(/&Oacute;/g, 'Ó')
.replace(/&Uacute;/g, 'Ú')
.replace(/&atilde;/gi, 'ã')
.replace(/&otilde;/gi, 'õ')
.replace(/&ntilde;/gi, 'ñ')
.replace(/&ccedil;/gi, 'ç')
.replace(/&Ccedil;/g, 'Ç')
.replace(/&acirc;/gi, 'â')
.replace(/&ecirc;/gi, 'ê')
.replace(/&icirc;/gi, 'î')
.replace(/&ocirc;/gi, 'ô')
.replace(/&ucirc;/gi, 'û')
.replace(/&agrave;/gi, 'à')
.replace(/&egrave;/gi, 'è')
.replace(/&igrave;/gi, 'ì')
.replace(/&ograve;/gi, 'ò')
.replace(/&ugrave;/gi, 'ù')
.replace(/&uuml;/gi, 'ü')
.replace(/&Uuml;/g, 'Ü')
.replace(/&nbsp;/gi, ' ')
.replace(/&amp;/gi, '&')
.replace(/&quot;/gi, '"')
.replace(/&#39;/g, "'") .replace(/&#39;/g, "'")
.replace(/&lt;/gi, '<')
.replace(/&gt;/gi, '>')
.replace(/&#(\d+);/g, (m, code) => String.fromCharCode(code));
}
// Processar variáveis do template e decodificar entidades HTML
const texto = decodeHtmlEntities(
this.processarTemplate(conteudo, escritorio)
.replace(/<br\s*\/?>/gi, '\n')
.replace(/<\/p>/gi, '\n\n')
.replace(/<[^>]+>/g, '') // Remove tags HTML
.replace(/\r\n/g, '\n') .replace(/\r\n/g, '\n')
.replace(/\r/g, '\n') .replace(/\r/g, '\n')
.replace(/\n{3,}/g, '\n\n') .replace(/\n{3,}/g, '\n\n')
.trim(); .trim()
);
// Quebra o texto em parágrafos // Quebra o texto em parágrafos (mantendo quebras de linha duplas como parágrafo)
const paragrafos = texto.split(/\n{2,}/).map(p => p.trim()).filter(Boolean); const paragrafos = texto.split(/\n{2,}/).map(p => p.trim()).filter(Boolean);
// Função para quebrar texto em linhas respeitando largura máxima // Função para quebrar texto em linhas respeitando largura máxima e manter quebras de linha simples
function wrapText(text: string, font: any, fontSize: number, maxWidth: number): string[] { function wrapText(text: string, font: any, fontSize: number, maxWidth: number): string[] {
// Remove quebras de linha internas para evitar erro de encoding // Mantém quebras de linha simples para espaçamento
const cleanText = text.replace(/\r?\n/g, ' '); const rawLines = text.split('\n');
const words = cleanText.split(' ');
const lines: string[] = []; const lines: string[] = [];
for (const rawLine of rawLines) {
const words = rawLine.split(' ');
let currentLine = ''; let currentLine = '';
for (const word of words) { for (const word of words) {
const testLine = currentLine ? currentLine + ' ' + word : word; const testLine = currentLine ? currentLine + ' ' + word : word;
@@ -282,6 +321,7 @@ export class PdfService {
} }
} }
if (currentLine) lines.push(currentLine); if (currentLine) lines.push(currentLine);
}
return lines; return lines;
} }
@@ -327,6 +367,7 @@ export class PdfService {
}); });
} }
let y = PAGE_HEIGHT - margens.top; let y = PAGE_HEIGHT - margens.top;
let firstLine = true;
// Escrever texto na página // Escrever texto na página
while (currentPar < paragrafos.length) { while (currentPar < paragrafos.length) {
const lines = wrapText(paragrafos[currentPar], font, FONT_SIZE, MAX_WIDTH); const lines = wrapText(paragrafos[currentPar], font, FONT_SIZE, MAX_WIDTH);
@@ -337,14 +378,48 @@ export class PdfService {
currentLine = lineIdx; currentLine = lineIdx;
break; break;
} }
page.drawText(lines[lineIdx], { // Justificado: calcula espaçamento extra entre palavras (exceto última linha do parágrafo)
x: margens.left, let text = lines[lineIdx];
let x = margens.left;
let options: any = {
x,
y,
size: FONT_SIZE,
font
};
if (text.trim().length > 0 && lineIdx < lines.length - 1) {
// Justificar (exceto última linha do parágrafo)
const words = text.split(' ');
if (words.length > 1) {
const textWidth = font.widthOfTextAtSize(text, FONT_SIZE);
const spaceWidth = font.widthOfTextAtSize(' ', FONT_SIZE);
const totalSpaces = words.length - 1;
const extraSpace = (MAX_WIDTH - textWidth) / totalSpaces;
let cursor = x;
for (let w = 0; w < words.length; w++) {
page.drawText(words[w], {
x: cursor,
y, y,
size: FONT_SIZE, size: FONT_SIZE,
font font
}); });
if (w < words.length - 1) {
cursor += font.widthOfTextAtSize(words[w], FONT_SIZE) + spaceWidth + extraSpace;
}
}
} else {
page.drawText(text, options);
}
} else {
page.drawText(text, options);
}
y -= LINE_HEIGHT; y -= LINE_HEIGHT;
currentLine = 0; currentLine = 0;
firstLine = false;
}
// Espaço extra entre parágrafos
if (lineIdx >= lines.length) {
y -= LINE_HEIGHT * 0.5;
} }
if (lineIdx < lines.length) { if (lineIdx < lines.length) {
break; break;