tenta fix pdfservice.js
This commit is contained in:
1 parent
287ed34abf
commit
eeeae75919
1 file changed
+70
-23
@@ -329,38 +329,56 @@ export class PdfService {
|
|||||||
.replace(/<!--[\s\S]*?-->/g, '');
|
.replace(/<!--[\s\S]*?-->/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Função para renderizar texto com formatação inline (negrito, itálico, ambos) e controle de quebra de linha
|
// Função para renderizar texto com formatação inline (negrito, itálico, sublinhado) e controle de quebra de linha e recuo
|
||||||
function renderInlineFormattedParagraph(page, text: string, x: number, y: number, font, fontBold, fontItalic, fontBoldItalic, fontSize: number, color, align: string, maxWidth: number) {
|
function renderInlineFormattedParagraph(
|
||||||
// Divide o texto em tokens de formatação (<b>, <i>, etc)
|
page,
|
||||||
let regex = /(<\/?(b|strong|i|em)>)/gi;
|
text: string,
|
||||||
let tokens: { text: string, bold: boolean, italic: boolean }[] = [];
|
x: number,
|
||||||
|
y: number,
|
||||||
|
font,
|
||||||
|
fontBold,
|
||||||
|
fontItalic,
|
||||||
|
fontBoldItalic,
|
||||||
|
fontSize: number,
|
||||||
|
color,
|
||||||
|
align: string,
|
||||||
|
maxWidth: number,
|
||||||
|
indent: boolean
|
||||||
|
) {
|
||||||
|
// Divide o texto em tokens de formatação (<b>, <i>, <u>, etc)
|
||||||
|
let regex = /(<\/?(b|strong|i|em|u)>)/gi;
|
||||||
|
let tokens: { text: string, bold: boolean, italic: boolean, underline: boolean }[] = [];
|
||||||
let lastIndex = 0;
|
let lastIndex = 0;
|
||||||
let match;
|
let match;
|
||||||
let currentStyle = { bold: false, italic: false };
|
let currentStyle = { bold: false, italic: false, underline: false };
|
||||||
while ((match = regex.exec(text)) !== null) {
|
while ((match = regex.exec(text)) !== null) {
|
||||||
if (match.index > lastIndex) {
|
if (match.index > lastIndex) {
|
||||||
tokens.push({
|
tokens.push({
|
||||||
text: text.substring(lastIndex, match.index),
|
text: text.substring(lastIndex, match.index),
|
||||||
bold: currentStyle.bold,
|
bold: currentStyle.bold,
|
||||||
italic: currentStyle.italic
|
italic: currentStyle.italic,
|
||||||
|
underline: currentStyle.underline
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (/^<(b|strong)>$/i.test(match[0])) currentStyle.bold = true;
|
if (/^<(b|strong)>$/i.test(match[0])) currentStyle.bold = true;
|
||||||
if (/^<\/(b|strong)>$/i.test(match[0])) currentStyle.bold = false;
|
if (/^<\/(b|strong)>$/i.test(match[0])) currentStyle.bold = false;
|
||||||
if (/^<(i|em)>$/i.test(match[0])) currentStyle.italic = true;
|
if (/^<(i|em)>$/i.test(match[0])) currentStyle.italic = true;
|
||||||
if (/^<\/(i|em)>$/i.test(match[0])) currentStyle.italic = false;
|
if (/^<\/(i|em)>$/i.test(match[0])) currentStyle.italic = false;
|
||||||
|
if (/^<u>$/i.test(match[0])) currentStyle.underline = true;
|
||||||
|
if (/^<\/u>$/i.test(match[0])) currentStyle.underline = false;
|
||||||
lastIndex = regex.lastIndex;
|
lastIndex = regex.lastIndex;
|
||||||
}
|
}
|
||||||
if (lastIndex < text.length) {
|
if (lastIndex < text.length) {
|
||||||
tokens.push({
|
tokens.push({
|
||||||
text: text.substring(lastIndex),
|
text: text.substring(lastIndex),
|
||||||
bold: currentStyle.bold,
|
bold: currentStyle.bold,
|
||||||
italic: currentStyle.italic
|
italic: currentStyle.italic,
|
||||||
|
underline: currentStyle.underline
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Junta todos os tokens em uma lista de palavras com formatação
|
// Junta todos os tokens em uma lista de palavras com formatação
|
||||||
let words: { text: string, font: any }[] = [];
|
let words: { text: string, font: any, underline: boolean }[] = [];
|
||||||
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;
|
||||||
@@ -370,19 +388,24 @@ export class PdfService {
|
|||||||
const split = token.text.split(/(\s+)/);
|
const split = token.text.split(/(\s+)/);
|
||||||
for (const part of split) {
|
for (const part of split) {
|
||||||
if (part.length > 0) {
|
if (part.length > 0) {
|
||||||
words.push({ text: part, font: usedFont });
|
words.push({ text: part, font: usedFont, underline: token.underline });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Monta linhas respeitando largura máxima
|
// Monta linhas respeitando largura máxima
|
||||||
let lines: { text: string, tokens: { text: string, font: any }[] }[] = [];
|
let lines: { text: string, tokens: { text: string, font: any, underline: boolean }[] }[] = [];
|
||||||
let currentLine = '';
|
let currentLine = '';
|
||||||
let currentTokens: { text: string, font: any }[] = [];
|
let currentTokens: { text: string, font: any, underline: boolean }[] = [];
|
||||||
let currentWidth = 0;
|
let currentWidth = 0;
|
||||||
for (const word of words) {
|
for (const [i, word] of words.entries()) {
|
||||||
|
// Aplica recuo de parágrafo na primeira linha
|
||||||
|
let recuo = 0;
|
||||||
|
if (indent && lines.length === 0 && currentLine === '') {
|
||||||
|
recuo = fontSize * 2;
|
||||||
|
}
|
||||||
const wordWidth = word.font.widthOfTextAtSize(word.text, fontSize);
|
const wordWidth = word.font.widthOfTextAtSize(word.text, fontSize);
|
||||||
if (currentWidth + wordWidth > maxWidth && currentLine.trim() !== '') {
|
if (currentWidth + wordWidth + recuo > maxWidth && currentLine.trim() !== '') {
|
||||||
lines.push({ text: currentLine, tokens: currentTokens });
|
lines.push({ text: currentLine, tokens: currentTokens });
|
||||||
currentLine = word.text;
|
currentLine = word.text;
|
||||||
currentTokens = [word];
|
currentTokens = [word];
|
||||||
@@ -403,6 +426,13 @@ export class PdfService {
|
|||||||
let drawX = x;
|
let drawX = x;
|
||||||
let totalWidth = line.tokens.reduce((acc, t) => acc + t.font.widthOfTextAtSize(t.text, fontSize), 0);
|
let totalWidth = line.tokens.reduce((acc, t) => acc + t.font.widthOfTextAtSize(t.text, fontSize), 0);
|
||||||
|
|
||||||
|
// Aplica recuo de parágrafo na primeira linha
|
||||||
|
let recuo = 0;
|
||||||
|
if (indent && i === 0) {
|
||||||
|
recuo = fontSize * 2;
|
||||||
|
drawX += recuo;
|
||||||
|
}
|
||||||
|
|
||||||
// Centralizado
|
// Centralizado
|
||||||
if (align === 'center') {
|
if (align === 'center') {
|
||||||
drawX = x + (maxWidth - totalWidth) / 2;
|
drawX = x + (maxWidth - totalWidth) / 2;
|
||||||
@@ -420,13 +450,23 @@ export class PdfService {
|
|||||||
font: t.font,
|
font: t.font,
|
||||||
color
|
color
|
||||||
});
|
});
|
||||||
|
// Sublinhado
|
||||||
|
if (t.underline && t.text.trim() !== '') {
|
||||||
|
const underlineY = y - 1.5;
|
||||||
|
page.drawLine({
|
||||||
|
start: { x: drawX, y: underlineY },
|
||||||
|
end: { x: drawX + t.font.widthOfTextAtSize(t.text, fontSize), y: underlineY },
|
||||||
|
thickness: 0.75,
|
||||||
|
color
|
||||||
|
});
|
||||||
|
}
|
||||||
if (/^\s+$/.test(t.text)) {
|
if (/^\s+$/.test(t.text)) {
|
||||||
drawX += t.font.widthOfTextAtSize(t.text, fontSize) + extraSpace;
|
drawX += t.font.widthOfTextAtSize(t.text, fontSize) + extraSpace;
|
||||||
} else {
|
} else {
|
||||||
drawX += t.font.widthOfTextAtSize(t.text, fontSize);
|
drawX += t.font.widthOfTextAtSize(t.text, fontSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
y -= fontSize * 1.25;
|
y -= fontSize * 1.5;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,9 +479,19 @@ export class PdfService {
|
|||||||
font: t.font,
|
font: t.font,
|
||||||
color
|
color
|
||||||
});
|
});
|
||||||
|
// Sublinhado
|
||||||
|
if (t.underline && t.text.trim() !== '') {
|
||||||
|
const underlineY = y - 1.5;
|
||||||
|
page.drawLine({
|
||||||
|
start: { x: drawX, y: underlineY },
|
||||||
|
end: { x: drawX + t.font.widthOfTextAtSize(t.text, fontSize), y: underlineY },
|
||||||
|
thickness: 0.75,
|
||||||
|
color
|
||||||
|
});
|
||||||
|
}
|
||||||
drawX += t.font.widthOfTextAtSize(t.text, fontSize);
|
drawX += t.font.widthOfTextAtSize(t.text, fontSize);
|
||||||
}
|
}
|
||||||
y -= fontSize * 1.25;
|
y -= fontSize * 1.5;
|
||||||
}
|
}
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
@@ -512,12 +562,8 @@ export class PdfService {
|
|||||||
// Renderiza o parágrafo inteiro com recuo (não só a primeira linha)
|
// Renderiza o parágrafo inteiro com recuo (não só a primeira linha)
|
||||||
let x = margens.left;
|
let x = margens.left;
|
||||||
let parWidth = MAX_WIDTH;
|
let parWidth = MAX_WIDTH;
|
||||||
if (indent) {
|
|
||||||
x += FONT_SIZE * 2;
|
|
||||||
parWidth -= FONT_SIZE * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Renderiza texto com formatação inline (negrito, itálico, ambos) e controle de linhas
|
// Renderiza texto com formatação inline (negrito, itálico, sublinhado, ambos) e controle de linhas
|
||||||
let yAfter = renderInlineFormattedParagraph(
|
let yAfter = renderInlineFormattedParagraph(
|
||||||
page,
|
page,
|
||||||
text,
|
text,
|
||||||
@@ -530,12 +576,13 @@ export class PdfService {
|
|||||||
FONT_SIZE,
|
FONT_SIZE,
|
||||||
rgb(0, 0, 0),
|
rgb(0, 0, 0),
|
||||||
align,
|
align,
|
||||||
parWidth
|
parWidth,
|
||||||
|
indent
|
||||||
);
|
);
|
||||||
y = yAfter - 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.5) break;
|
||||||
}
|
}
|
||||||
pageIndex++;
|
pageIndex++;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user