tenta fix pdfservice.js

This commit is contained in:
rodrigo committed 2025-04-22 14:44:00 -03:00
1 parent 045124be2f
commit 6fdfc99e7d
1 file changed
+99 -35
+99 -35
View File
@@ -377,6 +377,12 @@ export class PdfService {
let currentLine: Array<{text: string, font: any, width: number}> = [];
let currentLineWidth = 0;
// Verifica se o texto parece ser um título (todo em maiúsculas ou curto)
const isTitle = text.toUpperCase() === text || text.length < 50;
// Se for título, centralizar independente do alinhamento fornecido
const effectiveAlign = isTitle ? 'center' : align;
// Processa texto com formatação - remover tags HTML e aplicar estilos
let currentFont = normalFont;
let boldActive = false;
@@ -470,6 +476,17 @@ export class PdfService {
return null; // Não há espaço suficiente para renderizar
}
// Aumentar ligeiramente o espaçamento de linhas para títulos
const effectiveLineHeight = isTitle ? lineHeight * 1.3 : lineHeight;
// Aumentar o tamanho da fonte para títulos
const effectiveFontSize = isTitle ? fontSize * 1.2 : fontSize;
// Se for um título, adicionar um espaço extra antes
if (isTitle && y < startY) {
y -= lineHeight * 0.5;
}
// Agora, renderizar as palavras em linhas
for (let i = 0; i < words.length; i++) {
const word = words[i];
@@ -481,18 +498,23 @@ export class PdfService {
currentLineWidth += word.width;
} else {
// Renderizar a linha atual
if (y - lineHeight < marginBottom) {
if (y - effectiveLineHeight < 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 ?
// Para justificado, calcular espaçamentos extras entre palavras
// Mas não justificar a última linha de um parágrafo ou títulos
const isLastLine = i === words.length - 1;
const shouldJustify = effectiveAlign === 'justify' && !isLastLine && !isTitle && currentLine.length > 1;
const extraSpacing = shouldJustify ?
(maxWidth - currentLineWidth) / (currentLine.length - 1) : 0;
if (align === 'center') {
if (effectiveAlign === 'center') {
lineX = x + (maxWidth - currentLineWidth) / 2;
} else if (align === 'right') {
} else if (effectiveAlign === 'right') {
lineX = x + maxWidth - currentLineWidth;
}
@@ -500,11 +522,13 @@ export class PdfService {
let posX = lineX;
for (let j = 0; j < currentLine.length; j++) {
const item = currentLine[j];
const itemFontSize = isTitle ? effectiveFontSize : fontSize;
page.drawText(item.text, {
x: posX,
y: y,
font: item.font,
size: fontSize,
size: itemFontSize,
color
});
@@ -512,18 +536,18 @@ export class PdfService {
posX += item.width;
// Adicionar espaço extra se for justificado (exceto no final da linha)
if (align === 'justify' && j < currentLine.length - 1) {
posX += spacingFactor;
if (shouldJustify && j < currentLine.length - 1) {
posX += extraSpacing;
}
}
// Avançar para a próxima linha
y -= lineHeight;
y -= effectiveLineHeight;
currentLine = [word];
currentLineWidth = word.width;
// Verificar se ainda temos espaço
if (y - lineHeight < marginBottom) {
if (y - effectiveLineHeight < marginBottom) {
return null;
}
}
@@ -531,41 +555,37 @@ export class PdfService {
// Renderizar a última linha, se houver
if (currentLine.length > 0) {
// Ajustar X baseado no alinhamento (última linha nunca é justificada)
// Ajustar X baseado no alinhamento (última linha nunca é justificada, exceto se for curta)
let lineX = x;
if (align === 'center') {
// Se for título ou alinhado ao centro/direita, ajustar posição
if (effectiveAlign === 'center') {
lineX = x + (maxWidth - currentLineWidth) / 2;
} else if (align === 'right') {
} else if (effectiveAlign === 'right') {
lineX = x + maxWidth - currentLineWidth;
}
// Desenhar a linha
let posX = lineX;
for (const item of currentLine) {
const itemFontSize = isTitle ? effectiveFontSize : fontSize;
page.drawText(item.text, {
x: posX,
y: y,
font: item.font,
size: fontSize,
size: itemFontSize,
color
});
posX += item.width;
}
y -= lineHeight;
y -= effectiveLineHeight;
}
// 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
});
// Se for título, adicionar um espaço extra depois
if (isTitle) {
y -= lineHeight * 0.5;
}
return y;
@@ -581,22 +601,49 @@ export class PdfService {
const paragrafos = texto.split(/\n{2,}/).map(p => {
let paragraph = p.trim();
if (!paragraph) return '';
// Extrair informações de formatação
let align = 'left'; // padrão é justificado
const alignMatch = paragraph.match(/§§ALIGN=(center|right|justify)§§/);
let align = 'justify'; // Padrão agora é justificado para texto normal
// Verifica se o texto parece ser um título por diversos critérios:
// 1. Começa com '#' (estilo markdown)
// 2. Todo em maiúsculas e relativamente curto
// 3. Começa com números seguidos de ponto (como "1. Título")
// 4. Termina com dois pontos e é curto (como "Considerando:")
const isTitle =
paragraph.startsWith('#') ||
(paragraph.toUpperCase() === paragraph && paragraph.length < 100) ||
/^\d+\.\s+\S+/.test(paragraph) ||
(paragraph.endsWith(':') && paragraph.length < 70);
// Se for um título, centraliza
if (isTitle) {
align = 'center';
paragraph = paragraph.replace(/^#+\s*/, ''); // Remove marcadores de título estilo markdown
}
// Processa alinhamentos explícitos (têm precedência)
const alignMatch = paragraph.match(/§§ALIGN=(center|right|justify|left)§§/);
if (alignMatch) {
align = alignMatch[1];
paragraph = paragraph.replace(/§§ALIGN=(center|right|justify)§§/, '');
paragraph = paragraph.replace(/§§ALIGN=(center|right|justify|left)§§/, '');
}
let indent = 0;
const indentMatch = paragraph.match(/§§INDENT=(\d+)(pt|px|em)§§/);
const indentMatch = paragraph.match(/§§INDENT=(\d+)(pt|px|em)?§§/);
if (indentMatch) {
indent = parseInt(indentMatch[1]);
if (indentMatch[2] === 'em') indent *= 12; // Converter em para pontos aproximadamente
paragraph = paragraph.replace(/§§INDENT=\d+(pt|px|em)§§/, '');
paragraph = paragraph.replace(/§§INDENT=\d+(pt|px|em)?§§/, '');
}
return { text: paragraph.trim(), align, indent };
}).filter(Boolean);
return {
text: paragraph.trim(),
align: align as 'left' | 'center' | 'right' | 'justify',
indent,
isTitle
};
}).filter(p => p.text);
let currentPar = 0;
let pageIndex = 0;
console.log(`Gerando PDF com ${paragrafos.length} parágrafos`);
@@ -621,18 +668,35 @@ export class PdfService {
while (currentPar < paragrafos.length) {
const paraObj = paragrafos[currentPar];
const text = paraObj.text;
const align = paraObj.align || 'justify'; // Por padrão, justifica o texto
const align = paraObj.align;
const indent = paraObj.indent || 0;
const isTitle = paraObj.isTitle || false;
let x = margens.left + indent;
let parWidth = MAX_WIDTH - indent;
// Se o texto for muito curto, avance para o próximo parágrafo
if (text.length < 2) {
currentPar++;
processedAnyParagraph = true;
continue;
}
console.log(`Tentando renderizar parágrafo ${currentPar + 1} em y=${y} com alinhamento ${align}`);
// Ajuste o tamanho da fonte para títulos
const fontSizeToUse = isTitle ? FONT_SIZE * 1.2 : FONT_SIZE;
// Adicionar espaço extra antes de títulos (exceto para o primeiro parágrafo da página)
if (isTitle && processedAnyParagraph) {
y -= FONT_SIZE * 0.8;
// Se não caber na página depois do espaço, vá para a próxima página
if (y < margens.bottom + fontSizeToUse * 2) {
break;
}
}
console.log(`Tentando renderizar parágrafo ${currentPar + 1} em y=${y} com alinhamento ${align}${isTitle ? ' (título)' : ''}`);
let yAfter = renderInlineFormattedParagraph(
page,
text,
@@ -642,7 +706,7 @@ export class PdfService {
fontBold,
fontItalic,
fontBoldItalic,
FONT_SIZE,
fontSizeToUse,
rgb(0, 0, 0),
align,
parWidth,