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 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(/ /g, ' ')
|
return str
|
||||||
.replace(/&/g, '&')
|
.replace(/á/gi, 'á')
|
||||||
.replace(/</g, '<')
|
.replace(/é/gi, 'é')
|
||||||
.replace(/>/g, '>')
|
.replace(/í/gi, 'í')
|
||||||
.replace(/"/g, '"')
|
.replace(/ó/gi, 'ó')
|
||||||
.replace(/'/g, "'")
|
.replace(/ú/gi, 'ú')
|
||||||
.replace(/\r\n/g, '\n')
|
.replace(/Á/g, 'Á')
|
||||||
.replace(/\r/g, '\n')
|
.replace(/É/g, 'É')
|
||||||
.replace(/\n{3,}/g, '\n\n')
|
.replace(/Í/g, 'Í')
|
||||||
.trim();
|
.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);
|
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[] = [];
|
||||||
let currentLine = '';
|
for (const rawLine of rawLines) {
|
||||||
for (const word of words) {
|
const words = rawLine.split(' ');
|
||||||
const testLine = currentLine ? currentLine + ' ' + word : word;
|
let currentLine = '';
|
||||||
const width = font.widthOfTextAtSize(testLine, fontSize);
|
for (const word of words) {
|
||||||
if (width > maxWidth && currentLine) {
|
const testLine = currentLine ? currentLine + ' ' + word : word;
|
||||||
lines.push(currentLine);
|
const width = font.widthOfTextAtSize(testLine, fontSize);
|
||||||
currentLine = word;
|
if (width > maxWidth && currentLine) {
|
||||||
} else {
|
lines.push(currentLine);
|
||||||
currentLine = testLine;
|
currentLine = word;
|
||||||
|
} else {
|
||||||
|
currentLine = testLine;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
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,
|
y,
|
||||||
size: FONT_SIZE,
|
size: FONT_SIZE,
|
||||||
font
|
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;
|
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;
|
||||||
|
|||||||
Reference in new issue
Block a user