tenta fix pdfservice.js

This commit is contained in:
rodrigo committed 2025-04-22 10:59:26 -03:00
1 parent ce795cba58
commit 1214171946
1 file changed
+124 -71
+124 -71
View File
@@ -639,117 +639,170 @@ export class PdfService {
timbradoPageCount = timbradoPdf.getPageCount(); timbradoPageCount = timbradoPdf.getPageCount();
console.log(`Timbrado carregado com ${timbradoPageCount} páginas`); console.log(`Timbrado carregado com ${timbradoPageCount} páginas`);
// Usar apenas a primeira página do timbrado para evitar loops e problemas de memória // Usar apenas a primeira página do timbrado para todas as páginas do documento
if (timbradoPageCount > 0) { if (timbradoPageCount > 0) {
const [embedded] = await pdfDoc.embedPage(timbradoPdf.getPage(0)); // Corrigido: pdfDoc.embedPdfPage retorna uma promessa de um objeto e não um arrayo e não um array
const embedded = await pdfDoc.embedPdfPage(timbradoPdf.getPage(0));
timbradoPages = [embedded]; timbradoPages = [embedded];
console.log('Usando apenas a primeira página do timbrado para todas as páginas do documento'); console.log('Timbrado incorporado com sucesso'); timbradoPages = [embedded];
} }('Timbrado incorporado com sucesso');
} catch (error) { } catch (error) {
console.error('Erro ao carregar timbrado:', error); console.error('Erro ao carregar timbrado:', error); ao incorporar página do timbrado:', embedError);
timbradoExists = false; timbradoExists = false; timbradoExists = false;
} } }
} } }
let currentPar = 0; let currentPar = 0;'Erro ao carregar timbrado:', error);
let pageIndex = 0; let pageIndex = 0;
console.log(`Gerando PDF com ${paragrafos.length} parágrafos`); console.log(`Gerando PDF com ${paragrafos.length} parágrafos`); }
while (currentPar < paragrafos.length) { // Define um contador máximo para evitar loops infinitos
const MAX_PAGES = 100;
t pageIndex = 0;
while (currentPar < paragrafos.length && pageIndex < MAX_PAGES) {ragrafos.length} parágrafos`);
console.log(`Criando página ${pageIndex + 1}, processando parágrafo ${currentPar + 1} de ${paragrafos.length}`); console.log(`Criando página ${pageIndex + 1}, processando parágrafo ${currentPar + 1} de ${paragrafos.length}`);
let page = pdfDoc.addPage([PAGE_WIDTH, PAGE_HEIGHT]); let page = pdfDoc.addPage([PAGE_WIDTH, PAGE_HEIGHT]);
${pageIndex + 1}, processando parágrafo ${currentPar + 1} de ${paragrafos.length}`);
// Adicionar timbrado à página= pdfDoc.addPage([PAGE_WIDTH, PAGE_HEIGHT]);
if (timbradoPages.length > 0) { if (timbradoPages.length > 0) {
const embedded = timbradoPages[pageIndex % timbradoPages.length]; console.log(`Adicionando timbrado na página ${pageIndex + 1}`);th > 0) {
console.log(`Adicionando timbrado na página ${pageIndex + 1}`); // Usando o timbrado incorporadoradoPages[pageIndex % timbradoPages.length];
page.drawPage(embedded, { page.drawPage(timbradoPages[0], {sole.log(`Adicionando timbrado na página ${pageIndex + 1}`);
x: 0, x: 0, page.drawPage(embedded, {
y: 0, y: 0, x: 0,
width: PAGE_WIDTH, width: PAGE_WIDTH,
height: PAGE_HEIGHT height: PAGE_HEIGHT
}); });
} }});
let y = PAGE_HEIGHT - margens.top; let y = PAGE_HEIGHT - margens.top;
let processedAnyParagraph = false; // Flag para verificar se processamos algum parágrafo
paragrafos.length) {
// Tenta processar parágrafos na página atual
while (currentPar < paragrafos.length) { while (currentPar < paragrafos.length) {
const paraText = paragrafos[currentPar]; const paraText = paragrafos[currentPar]; // Extract alignment
enter' | 'justify' = 'left';
// Extract alignment // Extract alignmenth = paraText.match(/^§§ALIGN=(center|justify|right)§§/);
let align: 'left' | 'center' | 'justify' = 'left'; let align: 'left' | 'center' | 'justify' = 'left';
const alignMatch = paraText.match(/^§§ALIGN=(center|justify|right)§§/); const alignMatch = paraText.match(/^§§ALIGN=(center|justify|right)§§/);ch[1] as 'center' | 'justify' | 'left';
if (alignMatch) { if (alignMatch) {
align = alignMatch[1] as 'center' | 'justify' | 'left'; align = alignMatch[1] as 'center' | 'justify' | 'left';
} }// Extract indentation
0;
// Extract indentation // Extract indentation paraText.match(/§§INDENT=([0-9.]+)§§/);
let indent = 0; let indent = 0;
const indentMatch = paraText.match(/§§INDENT=([0-9.]+)§§/); const indentMatch = paraText.match(/§§INDENT=([0-9.]+)§§/););
if (indentMatch) { if (indentMatch) {
indent = parseFloat(indentMatch[1]); indent = parseFloat(indentMatch[1]);
} }
// Clean text // Clean text .replace(/^§§ALIGN=(center|justify|right)§§/, '')
let text = paraText let text = paraText
.replace(/^§§ALIGN=(center|justify|right)§§/, '') .replace(/^§§ALIGN=(center|justify|right)§§/, '')();
.replace(/§§INDENT=[0-9.]+§§/, '') .replace(/§§INDENT=[0-9.]+§§/, '')
.trim(); .trim();x = margens.left + indent;
parWidth = MAX_WIDTH - indent;
// Se o texto for muito curto, avance para o próximo parágrafo
if (text.length < 2) {= renderInlineFormattedParagraph(
currentPar++;
processedAnyParagraph = true;
continue;
}
let x = margens.left + indent; let x = margens.left + indent;
let parWidth = MAX_WIDTH - indent; let parWidth = MAX_WIDTH - indent;alic,
ic,
let yAfter = renderInlineFormattedParagraph( console.log(`Tentando renderizar parágrafo ${currentPar + 1} em y=${y}`);
page, ),
let yAfter = renderInlineFormattedParagraph(align,
page, parWidth,
text, text,
x, x,
y, y,om,
font, font,EIGHT
fontBold, fontBold,;
fontItalic, fontItalic,
fontBoldItalic, fontBoldItalic,= null) {
FONT_SIZE, FONT_SIZE,a, criando nova página`);
rgb(0, 0, 0), rgb(0, 0, 0), pageIndex++;
align, align,
parWidth, parWidth, }
false, false, y = yAfter - FONT_SIZE * 0.5;
margens.top, margens.top,
margens.bottom, margens.bottom,E * 1.5) break;
PAGE_HEIGHT PAGE_HEIGHT
); );
if (yAfter === null) { if (yAfter === null) {
// Se não conseguimos renderizar este parágrafo, vamos para a próxima página console.log(`PDF gerado com ${pageIndex} páginas`);
// Mas só se já tivermos processado algum parágrafo nesta página const pdfBytes = await pdfDoc.save();
if (processedAnyParagraph) { return Buffer.from(pdfBytes);
console.log(`Página ${pageIndex + 1} está cheia, criando nova página`); console.log(`Página ${pageIndex + 1} está cheia, criando nova página`);
pageIndex++;
break; break;
}
y = yAfter - FONT_SIZE * 0.5;
currentPar++;
if (y < margens.bottom + FONT_SIZE * 1.5) break;
}
pageIndex++;
}
console.log(`PDF gerado com ${pageIndex} páginas`);
const pdfBytes = await pdfDoc.save();
return Buffer.from(pdfBytes);
} catch (error) {
console.error('Erro geral ao gerar PDF:', error);
throw error;
}
}
private processarTemplate(template: string, dados: any): string {
return template.replace(/\{\{([^}]+)\}\}/g, (match, key) => {
const keyParts = key.trim().split('.');
let value = dados;
for (const part of keyParts) {
if (value && typeof value === 'object' && part in value) {
value = value[part];
} else { } else {
// Se não conseguimos nem processar um parágrafo, algo está errado
// Vamos avançar para o próximo parágrafo para evitar um loop infinito
console.log(`Não foi possível processar o parágrafo ${currentPar + 1}, avançando`);
currentPar++;{
processedAnyParagraph = true;{\{([^}]+)\}\}/g, (match, key) => {
}arts = key.trim().split('.');
} else {
// Parágrafo foi renderizado com sucesso
y = yAfter - FONT_SIZE * 0.5; (const part of keyParts) {
currentPar++; if (value && typeof value === 'object' && part in value) {
processedAnyParagraph = true;
console.log(`Parágrafo ${currentPar} processado com sucesso, nova posição y=${y}`); } else {
value = undefined; value = undefined;
break; // Verifica se ainda temos espaço para pelo menos uma linha break;
} if (y < margens.bottom + FONT_SIZE * 2) { }
}
} } }); return value !== undefined ? value : match; } } break; value = undefined; } else { value = value[part]; if (value && typeof value === 'object' && part in value) { for (const part of keyParts) { let value = dados; const keyParts = key.trim().split('.'); return template.replace(/\{\{([^}]+)\}\}/g, (match, key) => { private processarTemplate(template: string, dados: any): string { } } throw error; console.error('Erro geral ao gerar PDF:', error); } catch (error) { return Buffer.from(pdfBytes); const pdfBytes = await pdfDoc.save(); console.log(`PDF gerado com ${pageIndex} páginas`); } console.warn(`AVISO: Número máximo de páginas (${MAX_PAGES}) atingido. Geração de PDF interrompida.`); if (pageIndex >= MAX_PAGES) { } } currentPar++; console.log(`AVISO: Não foi possível processar nenhum parágrafo na página ${pageIndex}, avançando`); if (!processedAnyParagraph && currentPar < paragrafos.length) { // algo está errado. Vamos avançar para o próximo para evitar loop infinito. // Se não conseguimos processar nenhum parágrafo nesta página e ainda temos parágrafos, pageIndex++; } } } break; console.log(`Espaço insuficiente para próximo parágrafo, criando nova página`); }
return value !== undefined ? value : match; return value !== undefined ? value : match;
}); });
} }