tenta fix pdfservice.js
This commit is contained in:
1 parent
5786af03d5
commit
73b571be71
1 file changed
+106
-31
@@ -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(/ /g, ' ')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/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(/á/gi, 'á')
|
||||
.replace(/é/gi, 'é')
|
||||
.replace(/í/gi, 'í')
|
||||
.replace(/ó/gi, 'ó')
|
||||
.replace(/ú/gi, 'ú')
|
||||
.replace(/Á/g, 'Á')
|
||||
.replace(/É/g, 'É')
|
||||
.replace(/Í/g, 'Í')
|
||||
.replace(/Ó/g, 'Ó')
|
||||
.replace(/Ú/g, 'Ú')
|
||||
.replace(/ã/gi, 'ã')
|
||||
.replace(/õ/gi, 'õ')
|
||||
.replace(/ñ/gi, 'ñ')
|
||||
.replace(/ç/gi, 'ç')
|
||||
.replace(/Ç/g, 'Ç')
|
||||
.replace(/â/gi, 'â')
|
||||
.replace(/ê/gi, 'ê')
|
||||
.replace(/î/gi, 'î')
|
||||
.replace(/ô/gi, 'ô')
|
||||
.replace(/û/gi, 'û')
|
||||
.replace(/à/gi, 'à')
|
||||
.replace(/è/gi, 'è')
|
||||
.replace(/ì/gi, 'ì')
|
||||
.replace(/ò/gi, 'ò')
|
||||
.replace(/ù/gi, 'ù')
|
||||
.replace(/ü/gi, 'ü')
|
||||
.replace(/Ü/g, 'Ü')
|
||||
.replace(/ /gi, ' ')
|
||||
.replace(/&/gi, '&')
|
||||
.replace(/"/gi, '"')
|
||||
.replace(/'/g, "'")
|
||||
.replace(/</gi, '<')
|
||||
.replace(/>/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;
|
||||
|
||||
Reference in new issue
Block a user