tenta fix pdfservice.js
This commit is contained in:
1 parent
8c3cd7a3bf
commit
045124be2f
1 file changed
+178
-1
@@ -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
|
||||
|
||||
Reference in new issue
Block a user