tenta fix pdfservice.js

This commit is contained in:
rodrigo committed 2025-04-22 14:25:13 -03:00
1 parent 8c3cd7a3bf
commit 045124be2f
1 file changed
+178 -1
+178 -1
View File
@@ -376,7 +376,6 @@ export class PdfService {
let words: Array<{text: string, font: any, width: number}> = [];
let currentLine: Array<{text: string, font: any, width: number}> = [];
let currentLineWidth = 0;
let textParts = [];
// Processa texto com formatação - remover tags HTML e aplicar estilos
let currentFont = normalFont;
@@ -392,6 +391,184 @@ export class PdfService {
.replace(/<(?!\/?(?:b|i|strong|em)(?!\w)[^>]*>)[^>]*>/gi, ''); // Manter apenas b, i, strong, em
// Primeiro, extrair partes do texto com suas formatações
let remainingText = text;
let textParts: Array<{text: string, bold: boolean, italic: boolean}> = [];
while (remainingText.length > 0) {
const boldStartMatch = remainingText.match(/<b>|<strong>/i);
const italicStartMatch = remainingText.match(/<i>|<em>/i);
const boldEndMatch = remainingText.match(/<\/b>|<\/strong>/i);
const italicEndMatch = remainingText.match(/<\/i>|<\/em>/i);
// Encontrar a próxima tag
const matches = [boldStartMatch, italicStartMatch, boldEndMatch, italicEndMatch]
.filter(m => m !== null);
if (matches.length === 0) {
// Não há mais tags, adicionar o texto restante
if (remainingText.length > 0) {
textParts.push({
text: remainingText,
bold: boldActive,
italic: italicActive
});
}
break;
}
// Ordenar matches por índice
matches.sort((a, b) => a!.index! - b!.index!);
const nextMatch = matches[0]!;
const matchIndex = nextMatch.index!;
// Texto antes da próxima tag
if (matchIndex > 0) {
textParts.push({
text: remainingText.substring(0, matchIndex),
bold: boldActive,
italic: italicActive
});
}
// Atualizar estado de formatação
if (nextMatch[0].match(/<b>|<strong>/i)) boldActive = true;
else if (nextMatch[0].match(/<\/b>|<\/strong>/i)) boldActive = false;
else if (nextMatch[0].match(/<i>|<em>/i)) italicActive = true;
else if (nextMatch[0].match(/<\/i>|<\/em>/i)) italicActive = false;
// Remover o texto processado e a tag
remainingText = remainingText.substring(matchIndex + nextMatch[0].length);
}
// Processar as partes extraídas
for (const part of textParts) {
// Determinar a fonte baseado na formatação
let font = normalFont;
if (part.bold && part.italic) font = boldItalicFont;
else if (part.bold) font = boldFont;
else if (part.italic) font = italicFont;
// Dividir em palavras
const partWords = part.text.split(/\s+/);
for (const wordText of partWords) {
if (!wordText) continue;
const width = font.widthOfTextAtSize(wordText, fontSize);
words.push({ text: wordText, font, width });
words.push({ text: ' ', font, width: font.widthOfTextAtSize(' ', fontSize) });
}
// Remove o último espaço adicionado
if (words.length > 0) {
words.pop();
}
}
// Verificar se há espaço suficiente na página para pelo menos uma linha
if (y - lineHeight < marginBottom) {
return null; // Não há espaço suficiente para renderizar
}
// Agora, renderizar as palavras em linhas
for (let i = 0; i < words.length; i++) {
const word = words[i];
// Verificar se a palavra cabe na linha atual
if (currentLineWidth + word.width <= maxWidth || currentLine.length === 0) {
// Adicionar palavra à linha atual
currentLine.push(word);
currentLineWidth += word.width;
} else {
// Renderizar a linha atual
if (y - lineHeight < marginBottom) {
return null; // Não há mais espaço na página
}
// Ajustar X baseado no alinhamento
let lineX = x;
const spacingFactor = align === 'justify' && currentLine.length > 1 ?
(maxWidth - currentLineWidth) / (currentLine.length - 1) : 0;
if (align === 'center') {
lineX = x + (maxWidth - currentLineWidth) / 2;
} else if (align === 'right') {
lineX = x + maxWidth - currentLineWidth;
}
// Desenhar a linha
let posX = lineX;
for (let j = 0; j < currentLine.length; j++) {
const item = currentLine[j];
page.drawText(item.text, {
x: posX,
y: y,
font: item.font,
size: fontSize,
color
});
// Avançar posição X
posX += item.width;
// Adicionar espaço extra se for justificado (exceto no final da linha)
if (align === 'justify' && j < currentLine.length - 1) {
posX += spacingFactor;
}
}
// Avançar para a próxima linha
y -= lineHeight;
currentLine = [word];
currentLineWidth = word.width;
// Verificar se ainda temos espaço
if (y - lineHeight < marginBottom) {
return null;
}
}
}
// Renderizar a última linha, se houver
if (currentLine.length > 0) {
// Ajustar X baseado no alinhamento (última linha nunca é justificada)
let lineX = x;
if (align === 'center') {
lineX = x + (maxWidth - currentLineWidth) / 2;
} else if (align === 'right') {
lineX = x + maxWidth - currentLineWidth;
}
// Desenhar a linha
let posX = lineX;
for (const item of currentLine) {
page.drawText(item.text, {
x: posX,
y: y,
font: item.font,
size: fontSize,
color
});
posX += item.width;
}
y -= lineHeight;
}
// Se estiver em modo debug, desenhar uma caixa ao redor do texto
if (debug) {
page.drawRectangle({
x,
y: y + lineHeight,
width: maxWidth,
height: startY - y,
borderColor: rgb(0.8, 0.8, 0.8),
borderWidth: 0.5,
opacity: 0.1
});
}
return y;
}
// Processe o texto com as novas funções melhoradas