tenta fix pdfservice.js
This commit is contained in:
1 parent
bd67cf49cc
commit
287ed34abf
1 file changed
+72
-57
@@ -329,14 +329,11 @@ export class PdfService {
|
|||||||
.replace(/<!--[\s\S]*?-->/g, '');
|
.replace(/<!--[\s\S]*?-->/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Função para renderizar texto com formatação inline (negrito, itálico, ambos)
|
// Função para renderizar texto com formatação inline (negrito, itálico, ambos) e controle de quebra de linha
|
||||||
function renderInlineFormattedText(page, text: string, x: number, y: number, font, fontBold, fontItalic, fontBoldItalic, fontSize: number, color, align: string, maxWidth: number) {
|
function renderInlineFormattedParagraph(page, text: string, x: number, y: number, font, fontBold, fontItalic, fontBoldItalic, fontSize: number, color, align: string, maxWidth: number) {
|
||||||
// Divide por tags <b>, <strong>, <i>, <em> e combinações
|
// Divide o texto em tokens de formatação (<b>, <i>, etc)
|
||||||
// Exemplo: "Texto <i>itálico <b>negrito-itálico</b></i> normal"
|
|
||||||
let cursor = x;
|
|
||||||
let tokens: { text: string, bold: boolean, italic: boolean }[] = [];
|
|
||||||
let regex = /(<\/?(b|strong|i|em)>)/gi;
|
let regex = /(<\/?(b|strong|i|em)>)/gi;
|
||||||
let stack: { bold: boolean, italic: boolean }[] = [];
|
let tokens: { text: string, bold: boolean, italic: boolean }[] = [];
|
||||||
let lastIndex = 0;
|
let lastIndex = 0;
|
||||||
let match;
|
let match;
|
||||||
let currentStyle = { bold: false, italic: false };
|
let currentStyle = { bold: false, italic: false };
|
||||||
@@ -361,31 +358,80 @@ export class PdfService {
|
|||||||
italic: currentStyle.italic
|
italic: currentStyle.italic
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Renderiza cada token com a fonte correta
|
|
||||||
let line = '';
|
// Junta todos os tokens em uma lista de palavras com formatação
|
||||||
let lineTokens: { text: string, font: any }[] = [];
|
let words: { text: string, font: any }[] = [];
|
||||||
for (const token of tokens) {
|
for (const token of tokens) {
|
||||||
let usedFont = font;
|
let usedFont = font;
|
||||||
if (token.bold && token.italic) usedFont = fontBoldItalic;
|
if (token.bold && token.italic) usedFont = fontBoldItalic;
|
||||||
else if (token.bold) usedFont = fontBold;
|
else if (token.bold) usedFont = fontBold;
|
||||||
else if (token.italic) usedFont = fontItalic;
|
else if (token.italic) usedFont = fontItalic;
|
||||||
// Quebra em palavras para respeitar largura máxima
|
// Divide token.text em palavras, mantendo espaços
|
||||||
const words = token.text.split(' ');
|
const split = token.text.split(/(\s+)/);
|
||||||
for (let i = 0; i < words.length; i++) {
|
for (const part of split) {
|
||||||
let word = words[i];
|
if (part.length > 0) {
|
||||||
let testLine = line ? line + ' ' + word : word;
|
words.push({ text: part, font: usedFont });
|
||||||
let testWidth = 0;
|
|
||||||
let tempLineTokens = [...lineTokens, { text: (line ? ' ' : '') + word, font: usedFont }];
|
|
||||||
for (const t of tempLineTokens) {
|
|
||||||
testWidth += t.font.widthOfTextAtSize(t.text, fontSize);
|
|
||||||
}
|
}
|
||||||
if (testWidth > maxWidth && line) {
|
}
|
||||||
// Renderiza a linha atual
|
}
|
||||||
|
|
||||||
|
// Monta linhas respeitando largura máxima
|
||||||
|
let lines: { text: string, tokens: { text: string, font: any }[] }[] = [];
|
||||||
|
let currentLine = '';
|
||||||
|
let currentTokens: { text: string, font: any }[] = [];
|
||||||
|
let currentWidth = 0;
|
||||||
|
for (const word of words) {
|
||||||
|
const wordWidth = word.font.widthOfTextAtSize(word.text, fontSize);
|
||||||
|
if (currentWidth + wordWidth > maxWidth && currentLine.trim() !== '') {
|
||||||
|
lines.push({ text: currentLine, tokens: currentTokens });
|
||||||
|
currentLine = word.text;
|
||||||
|
currentTokens = [word];
|
||||||
|
currentWidth = wordWidth;
|
||||||
|
} else {
|
||||||
|
currentLine += word.text;
|
||||||
|
currentTokens.push(word);
|
||||||
|
currentWidth += wordWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentLine.trim() !== '' || currentTokens.length > 0) {
|
||||||
|
lines.push({ text: currentLine, tokens: currentTokens });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renderiza cada linha
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
let line = lines[i];
|
||||||
let drawX = x;
|
let drawX = x;
|
||||||
|
let totalWidth = line.tokens.reduce((acc, t) => acc + t.font.widthOfTextAtSize(t.text, fontSize), 0);
|
||||||
|
|
||||||
|
// Centralizado
|
||||||
if (align === 'center') {
|
if (align === 'center') {
|
||||||
drawX = x + (maxWidth - testWidth + usedFont.widthOfTextAtSize(word, fontSize)) / 2;
|
drawX = x + (maxWidth - totalWidth) / 2;
|
||||||
}
|
}
|
||||||
for (const t of lineTokens) {
|
// Justificado (exceto última linha)
|
||||||
|
else if (align === 'justify' && i < lines.length - 1 && line.text.trim().length > 0) {
|
||||||
|
// Conta espaços
|
||||||
|
const spaceCount = line.tokens.filter(t => /^\s+$/.test(t.text)).length;
|
||||||
|
const extraSpace = spaceCount > 0 ? (maxWidth - totalWidth) / spaceCount : 0;
|
||||||
|
for (const t of line.tokens) {
|
||||||
|
page.drawText(t.text, {
|
||||||
|
x: drawX,
|
||||||
|
y,
|
||||||
|
size: fontSize,
|
||||||
|
font: t.font,
|
||||||
|
color
|
||||||
|
});
|
||||||
|
if (/^\s+$/.test(t.text)) {
|
||||||
|
drawX += t.font.widthOfTextAtSize(t.text, fontSize) + extraSpace;
|
||||||
|
} else {
|
||||||
|
drawX += t.font.widthOfTextAtSize(t.text, fontSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
y -= fontSize * 1.25;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Esquerda ou última linha justificada
|
||||||
|
for (const t of line.tokens) {
|
||||||
page.drawText(t.text, {
|
page.drawText(t.text, {
|
||||||
x: drawX,
|
x: drawX,
|
||||||
y,
|
y,
|
||||||
@@ -396,36 +442,6 @@ export class PdfService {
|
|||||||
drawX += t.font.widthOfTextAtSize(t.text, fontSize);
|
drawX += t.font.widthOfTextAtSize(t.text, fontSize);
|
||||||
}
|
}
|
||||||
y -= fontSize * 1.25;
|
y -= fontSize * 1.25;
|
||||||
line = word;
|
|
||||||
lineTokens = [{ text: word, font: usedFont }];
|
|
||||||
} else {
|
|
||||||
if (line) {
|
|
||||||
line += ' ' + word;
|
|
||||||
lineTokens.push({ text: ' ' + word, font: usedFont });
|
|
||||||
} else {
|
|
||||||
line = word;
|
|
||||||
lineTokens.push({ text: word, font: usedFont });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Renderiza última linha
|
|
||||||
if (line) {
|
|
||||||
let drawX = x;
|
|
||||||
let totalWidth = lineTokens.reduce((acc, t) => acc + t.font.widthOfTextAtSize(t.text, fontSize), 0);
|
|
||||||
if (align === 'center') {
|
|
||||||
drawX = x + (maxWidth - totalWidth) / 2;
|
|
||||||
}
|
|
||||||
for (const t of lineTokens) {
|
|
||||||
page.drawText(t.text, {
|
|
||||||
x: drawX,
|
|
||||||
y,
|
|
||||||
size: fontSize,
|
|
||||||
font: t.font,
|
|
||||||
color
|
|
||||||
});
|
|
||||||
drawX += t.font.widthOfTextAtSize(t.text, fontSize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
@@ -470,7 +486,6 @@ export class PdfService {
|
|||||||
|
|
||||||
// Quebrar o texto em páginas
|
// Quebrar o texto em páginas
|
||||||
let currentPar = 0;
|
let currentPar = 0;
|
||||||
let currentLine = 0;
|
|
||||||
let pageIndex = 0;
|
let pageIndex = 0;
|
||||||
|
|
||||||
while (currentPar < paragrafos.length) {
|
while (currentPar < paragrafos.length) {
|
||||||
@@ -502,8 +517,8 @@ export class PdfService {
|
|||||||
parWidth -= FONT_SIZE * 2;
|
parWidth -= FONT_SIZE * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderiza texto com formatação inline (negrito, itálico, ambos)
|
// Renderiza texto com formatação inline (negrito, itálico, ambos) e controle de linhas
|
||||||
y = renderInlineFormattedText(
|
let yAfter = renderInlineFormattedParagraph(
|
||||||
page,
|
page,
|
||||||
text,
|
text,
|
||||||
x,
|
x,
|
||||||
@@ -517,7 +532,7 @@ export class PdfService {
|
|||||||
align,
|
align,
|
||||||
parWidth
|
parWidth
|
||||||
);
|
);
|
||||||
y -= FONT_SIZE * 0.5;
|
y = yAfter - FONT_SIZE * 0.5;
|
||||||
|
|
||||||
currentPar++;
|
currentPar++;
|
||||||
if (y < margens.bottom + FONT_SIZE * 1.25) break;
|
if (y < margens.bottom + FONT_SIZE * 1.25) break;
|
||||||
|
|||||||
Reference in new issue
Block a user