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 words: Array<{text: string, font: any, width: number}> = [];
|
||||||
let currentLine: Array<{text: string, font: any, width: number}> = [];
|
let currentLine: Array<{text: string, font: any, width: number}> = [];
|
||||||
let currentLineWidth = 0;
|
let currentLineWidth = 0;
|
||||||
let textParts = [];
|
|
||||||
|
|
||||||
// Processa texto com formatação - remover tags HTML e aplicar estilos
|
// Processa texto com formatação - remover tags HTML e aplicar estilos
|
||||||
let currentFont = normalFont;
|
let currentFont = normalFont;
|
||||||
@@ -392,6 +391,184 @@ export class PdfService {
|
|||||||
.replace(/<(?!\/?(?:b|i|strong|em)(?!\w)[^>]*>)[^>]*>/gi, ''); // Manter apenas b, i, strong, em
|
.replace(/<(?!\/?(?:b|i|strong|em)(?!\w)[^>]*>)[^>]*>/gi, ''); // Manter apenas b, i, strong, em
|
||||||
|
|
||||||
// Primeiro, extrair partes do texto com suas formatações
|
// 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
|
// Processe o texto com as novas funções melhoradas
|
||||||
|
|||||||
Reference in new issue
Block a user