Created
January 10, 2025 10:48
-
-
Save thepatrickniyo/912e9a6e1cc6a7e4cdb0d3d6ac1999a8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Prints text with support for bold sections (marked with **) and automatic line breaks | |
* @param {object} doc - The PDF document object | |
* @param {number} startY - The starting Y position | |
* @param {string} text - The input text with ** marking bold sections | |
* @param {object} options - Additional options for formatting | |
* @param {number} options.pageMargin - Page margin (default: 40) | |
* @param {number} options.innerPadding - Inner padding (default: 10) | |
* @param {number} options.lineSpacing - Spacing between lines (default: 10) | |
* @param {number} options.fontSize - Font size (default: 10) | |
* @param {number} options.pageWidth - Width of the page (default: 595) | |
*/ | |
interface LineSegment { | |
text: string; | |
isBold: boolean; | |
x: number; | |
} | |
// Define types for better type safety | |
interface FormattedTextOptions { | |
pageMargin?: number; | |
innerPadding?: number; | |
lineSpacing?: number; | |
fontSize?: number; | |
pageWidth?: number; | |
} | |
interface LineSegment { | |
text: string; | |
isBold: boolean; | |
x: number; | |
} | |
/** | |
* Prints text with support for bold sections (marked with **) and automatic line breaks | |
* @param doc - The PDF document object | |
* @param startY - The starting Y position | |
* @param text - The input text with ** marking bold sections | |
* @param options - Additional options for formatting | |
* @returns The final Y position after printing | |
*/ | |
export function printFormattedText( | |
doc: Record<string, any>, | |
startY: number, | |
text: string, | |
options: FormattedTextOptions | |
): number { | |
// Default values | |
const PAGE_MARGIN = options.pageMargin || 40; | |
const INNER_PADDING = options.innerPadding || 10; | |
const LINE_SPACING = options.lineSpacing || 6; // Reduced from 10 to 6 | |
const FONT_SIZE = options.fontSize || 10; | |
const PAGE_WIDTH = options.pageWidth || 595; | |
// Calculate maximum width for text | |
const bodyMaxWidth = PAGE_WIDTH - (2 * PAGE_MARGIN) - (2 * INNER_PADDING); | |
// Set initial font properties | |
doc.setFontSize(FONT_SIZE); | |
doc.setFont("helvetica", "normal"); | |
// Split text into bold and normal sections | |
const textSegments = text.split('**'); | |
// Current position tracking | |
let currentX = PAGE_MARGIN + INNER_PADDING; | |
let currentY = startY; | |
let lineSegments: LineSegment[] = []; | |
// Process each text segment | |
textSegments.forEach((segment, index) => { | |
if (!segment) return; // Skip empty segments | |
// Determine if this segment should be bold | |
const isBold = index % 2 === 1; | |
// Split segment into words | |
const words = segment.split(' '); | |
words.forEach((word, wordIndex) => { | |
// Add space before word (except for first word) | |
const wordWithSpace = wordIndex === 0 ? word : ' ' + word; | |
// Set font for measurement | |
doc.setFont("helvetica", isBold ? "bold" : "normal"); | |
const wordWidth = doc.getTextWidth(wordWithSpace); | |
// Check if adding this word would exceed the line width | |
if (currentX + wordWidth > PAGE_MARGIN + INNER_PADDING + bodyMaxWidth) { | |
// Print current line | |
printLine(doc, lineSegments, currentY); | |
// Reset for new line | |
currentY += LINE_SPACING; | |
currentX = PAGE_MARGIN + INNER_PADDING; | |
lineSegments = []; | |
} | |
// Add word to current line segments | |
lineSegments.push({ | |
text: wordWithSpace, | |
isBold, | |
x: currentX | |
}); | |
currentX += wordWidth; | |
}); | |
}); | |
// Print any remaining text | |
if (lineSegments.length > 0) { | |
printLine(doc, lineSegments, currentY); | |
} | |
// Return the final Y position | |
return currentY; | |
} | |
/** | |
* Helper function to print a single line with mixed bold/normal text | |
*/ | |
function printLine(doc: Record<string, any>, segments: LineSegment[], currentY: number): void { | |
segments.forEach(segment => { | |
doc.setFont("helvetica", segment.isBold ? "bold" : "normal"); | |
doc.text(segment.text, segment.x, currentY, {align: 'left'}); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment