@@ -48,6 +48,26 @@ function createScaler(sf: number): Scaler {
4848 return ( n : number ) : number => Math . round ( n * sf ) ;
4949}
5050
51+ /**
52+ * Escapes special XML characters in a string so it can be safely
53+ * embedded inside SVG or XML markup.
54+ *
55+ * Converts:
56+ * - & to &
57+ * - < to <
58+ * - > to >
59+ * - " to "
60+ * - ' to '
61+ *
62+ * @param str - Raw string that may contain XML-sensitive characters.
63+ *
64+ * @returns An XML-safe escaped string.
65+ *
66+ * @example
67+ * const safe = escapeXML('<text>Hello & Welcome</text>');
68+ * // Returns:
69+ * // '<text>Hello & Welcome</text>'
70+ */
5171export function escapeXML ( str : string ) : string {
5272 return str
5373 . replace ( / & / g, '&' )
@@ -185,6 +205,42 @@ function renderFooter(
185205}
186206
187207// ── Main static-theme renderer ────────────────────────────────────────────
208+
209+ /**
210+ * Generates the main CommitPulse SVG badge using contribution
211+ * calendar data and streak statistics.
212+ *
213+ * The SVG includes animated contribution towers, statistics,
214+ * theme styling, and optional auto-theme support.
215+ *
216+ * @param stats - Contribution streak statistics including current streak,
217+ * longest streak, total contributions, and today's date.
218+ * @param params - Badge customization options such as colors, fonts,
219+ * animations, scaling, visibility toggles, and theme settings.
220+ * @param params.autoTheme - Enables automatic switching between
221+ * light and dark themes based on the user's system color scheme.
222+ * @param calendar - Contribution calendar data containing weekly
223+ contribution entries and per-day contribution counts used to
224+ generate the tower layout.
225+ *
226+ * @returns A fully generated SVG badge string.
227+ *
228+ * @example
229+ * const svg = generateSVG(
230+ * {
231+ * currentStreak: 12,
232+ * longestStreak: 30,
233+ * totalContributions: 542,
234+ * todayDate: '2026-05-27',
235+ * },
236+ * {
237+ * user: 'octocat',
238+ * autoTheme: true,
239+ * accent: '00ffaa',
240+ * },
241+ * calendar
242+ * );
243+ */
188244export function generateSVG (
189245 stats : StreakStats ,
190246 params : BadgeParams ,
@@ -509,6 +565,34 @@ function generateAutoThemeMonthlySVG(stats: MonthlyStats, params: BadgeParams):
509565` ;
510566}
511567
568+ /**
569+ * Generates a fallback SVG badge for users that do not exist
570+ * or when contribution data cannot be loaded.
571+ *
572+ * The SVG renders a ghost-style city layout with an animated
573+ * error-state design while preserving the standard badge layout.
574+ *
575+ * @param username - GitHub username displayed in the error badge.
576+ * @param bg - Background color used for the SVG container.
577+ * @param accent - Accent color used for highlights, outlines,
578+ * and animated elements.
579+ * @param text - Primary text color used throughout the badge.
580+ * @param radius - Border radius applied to the SVG background.
581+ * @param speed - Animation speed for the radar scan effect.
582+ * Defaults to '8s'.
583+ *
584+ * @returns A generated SVG string representing the not-found state.
585+ *
586+ * @example
587+ * const svg = generateNotFoundSVG(
588+ * 'octocat',
589+ * '#0d1117',
590+ * '#00ffaa',
591+ * '#ffffff',
592+ * 8,
593+ * '8s'
594+ * );
595+ */
512596export function generateNotFoundSVG (
513597 username : string ,
514598 bg : string ,
0 commit comments