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
+106 -31
+106 -31
View File
@@ -247,41 +247,81 @@ export class PdfService {
const LINE_HEIGHT = FONT_SIZE * 1.5;
const MAX_WIDTH = PAGE_WIDTH - margens.left - margens.right;
// Processar variáveis do template
const texto = this.processarTemplate(conteudo, escritorio)
.replace(/<[^>]+>/g, '') // Remove tags HTML
.replace(/&nbsp;/g, ' ')
.replace(/&amp;/g, '&')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
.replace(/&quot;/g, '"')
.replace(/&#39;/g, "'")
.replace(/\r\n/g, '\n')
.replace(/\r/g, '\n')
.replace(/\n{3,}/g, '\n\n')
.trim();
// Função para decodificar entidades HTML comuns (acentuação e outros)
function decodeHtmlEntities(str: string): string {
if (!str) return '';
return str
.replace(/&aacute;/gi, 'á')
.replace(/&eacute;/gi, 'é')
.replace(/&iacute;/gi, 'í')
.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(/&lt;/gi, '<')
.replace(/&gt;/gi, '>')
.replace(/&#(\d+);/g, (m, code) => String.fromCharCode(code));
}
// Quebra o texto em parágrafos
// 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/g, '\n')
.replace(/\n{3,}/g, '\n\n')
.trim()
);
// 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);
// 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[] {
// Remove quebras de linha internas para evitar erro de encoding
const cleanText = text.replace(/\r?\n/g, ' ');
const words = cleanText.split(' ');
// Mantém quebras de linha simples para espaçamento
const rawLines = text.split('\n');
const lines: string[] = [];
let currentLine = '';
for (const word of words) {
const testLine = currentLine ? currentLine + ' ' + word : word;
const width = font.widthOfTextAtSize(testLine, fontSize);
if (width > maxWidth && currentLine) {
lines.push(currentLine);
currentLine = word;
} else {
currentLine = testLine;
for (const rawLine of rawLines) {
const words = rawLine.split(' ');
let currentLine = '';
for (const word of words) {
const testLine = currentLine ? currentLine + ' ' + word : word;
const width = font.widthOfTextAtSize(testLine, fontSize);
if (width > maxWidth && currentLine) {
lines.push(currentLine);
currentLine = word;
} else {
currentLine = testLine;
}
}
if (currentLine) lines.push(currentLine);
}
if (currentLine) lines.push(currentLine);
return lines;
}
@@ -327,6 +367,7 @@ export class PdfService {
});
}
let y = PAGE_HEIGHT - margens.top;
let firstLine = true;
// Escrever texto na página
while (currentPar < paragrafos.length) {
const lines = wrapText(paragrafos[currentPar], font, FONT_SIZE, MAX_WIDTH);
@@ -337,14 +378,48 @@ export class PdfService {
currentLine = lineIdx;
break;
}
page.drawText(lines[lineIdx], {
x: margens.left,
// Justificado: calcula espaçamento extra entre palavras (exceto última linha do parágrafo)
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,
size: FONT_SIZE,
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;
currentLine = 0;
firstLine = false;
}
// Espaço extra entre parágrafos
if (lineIdx >= lines.length) {
y -= LINE_HEIGHT * 0.5;
}
if (lineIdx < lines.length) {
break;