Skip to content

Commit cad6196

Browse files
authored
refactor(generator): hoist ghostLayout to module-level GHOST_LAYOUT constant (JhaSourav07#897)
refactor: fix theme icon duplication, simplify error handling, and clean up unused imports Co-authored-by: Sourav Jha <souravkjha2007@gmail.com>
2 parents ab318a4 + 8764052 commit cad6196

1 file changed

Lines changed: 83 additions & 58 deletions

File tree

lib/svg/generator.ts

Lines changed: 83 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,88 @@ function generateAutoThemeMonthlySVG(stats: MonthlyStats, params: BadgeParams):
528528
`;
529529
}
530530

531+
/**
532+
* Generates a fallback SVG badge for users that do not exist
533+
* or when contribution data cannot be loaded.
534+
*
535+
* The SVG renders a ghost-style city layout with an animated
536+
* error-state design while preserving the standard badge layout.
537+
*
538+
* @param username - GitHub username displayed in the error badge.
539+
* @param bg - Background color used for the SVG container.
540+
* @param accent - Accent color used for highlights, outlines,
541+
* and animated elements.
542+
* @param text - Primary text color used throughout the badge.
543+
* @param radius - Border radius applied to the SVG background.
544+
* @param speed - Animation speed for the radar scan effect.
545+
* Defaults to '8s'.
546+
*
547+
* @returns A generated SVG string representing the not-found state.
548+
*
549+
* @example
550+
* const svg = generateNotFoundSVG(
551+
* 'octocat',
552+
* '#0d1117',
553+
* '#00ffaa',
554+
* '#ffffff',
555+
* 8,
556+
* '8s'
557+
* );
558+
*/
559+
// Fixed isometric tower layout for the not-found ghost city.
560+
// Heights are deterministic so the silhouette always looks like a real city
561+
// regardless of the username or theme passed to generateNotFoundSVG.
562+
const GHOST_LAYOUT: { col: number; row: number; h: number }[] = [
563+
{ col: 0, row: 0, h: 8 },
564+
{ col: 1, row: 0, h: 20 },
565+
{ col: 2, row: 0, h: 12 },
566+
{ col: 3, row: 0, h: 30 },
567+
{ col: 4, row: 0, h: 16 },
568+
{ col: 5, row: 0, h: 10 },
569+
{ col: 6, row: 0, h: 24 },
570+
{ col: 7, row: 0, h: 8 },
571+
{ col: 0, row: 1, h: 6 },
572+
{ col: 1, row: 1, h: 14 },
573+
{ col: 2, row: 1, h: 36 },
574+
{ col: 3, row: 1, h: 22 },
575+
{ col: 4, row: 1, h: 44 },
576+
{ col: 5, row: 1, h: 18 },
577+
{ col: 6, row: 1, h: 10 },
578+
{ col: 7, row: 1, h: 28 },
579+
{ col: 0, row: 2, h: 10 },
580+
{ col: 1, row: 2, h: 26 },
581+
{ col: 2, row: 2, h: 16 },
582+
{ col: 3, row: 2, h: 38 },
583+
{ col: 4, row: 2, h: 20 },
584+
{ col: 5, row: 2, h: 32 },
585+
{ col: 6, row: 2, h: 14 },
586+
{ col: 7, row: 2, h: 6 },
587+
{ col: 0, row: 3, h: 4 },
588+
{ col: 1, row: 3, h: 18 },
589+
{ col: 2, row: 3, h: 28 },
590+
{ col: 3, row: 3, h: 12 },
591+
{ col: 4, row: 3, h: 34 },
592+
{ col: 5, row: 3, h: 8 },
593+
{ col: 6, row: 3, h: 22 },
594+
{ col: 7, row: 3, h: 16 },
595+
{ col: 0, row: 4, h: 8 },
596+
{ col: 1, row: 4, h: 30 },
597+
{ col: 2, row: 4, h: 10 },
598+
{ col: 3, row: 4, h: 20 },
599+
{ col: 4, row: 4, h: 16 },
600+
{ col: 5, row: 4, h: 40 },
601+
{ col: 6, row: 4, h: 12 },
602+
{ col: 7, row: 4, h: 24 },
603+
{ col: 0, row: 5, h: 14 },
604+
{ col: 1, row: 5, h: 8 },
605+
{ col: 2, row: 5, h: 22 },
606+
{ col: 3, row: 5, h: 32 },
607+
{ col: 4, row: 5, h: 10 },
608+
{ col: 5, row: 5, h: 18 },
609+
{ col: 6, row: 5, h: 28 },
610+
{ col: 7, row: 5, h: 6 },
611+
];
612+
531613
export function generateNotFoundSVG(
532614
username: string,
533615
bg: string,
@@ -537,65 +619,8 @@ export function generateNotFoundSVG(
537619
speed: string = '8s'
538620
): string {
539621
const safeName = escapeXML(username.toUpperCase());
540-
541-
const ghostLayout: { col: number; row: number; h: number }[] = [
542-
{ col: 0, row: 0, h: 8 },
543-
{ col: 1, row: 0, h: 20 },
544-
{ col: 2, row: 0, h: 12 },
545-
{ col: 3, row: 0, h: 30 },
546-
{ col: 4, row: 0, h: 16 },
547-
{ col: 5, row: 0, h: 10 },
548-
{ col: 6, row: 0, h: 24 },
549-
{ col: 7, row: 0, h: 8 },
550-
551-
{ col: 0, row: 1, h: 6 },
552-
{ col: 1, row: 1, h: 14 },
553-
{ col: 2, row: 1, h: 36 },
554-
{ col: 3, row: 1, h: 22 },
555-
{ col: 4, row: 1, h: 44 },
556-
{ col: 5, row: 1, h: 18 },
557-
{ col: 6, row: 1, h: 10 },
558-
{ col: 7, row: 1, h: 28 },
559-
560-
{ col: 0, row: 2, h: 10 },
561-
{ col: 1, row: 2, h: 26 },
562-
{ col: 2, row: 2, h: 16 },
563-
{ col: 3, row: 2, h: 38 },
564-
{ col: 4, row: 2, h: 20 },
565-
{ col: 5, row: 2, h: 32 },
566-
{ col: 6, row: 2, h: 14 },
567-
{ col: 7, row: 2, h: 6 },
568-
569-
{ col: 0, row: 3, h: 4 },
570-
{ col: 1, row: 3, h: 18 },
571-
{ col: 2, row: 3, h: 28 },
572-
{ col: 3, row: 3, h: 12 },
573-
{ col: 4, row: 3, h: 34 },
574-
{ col: 5, row: 3, h: 8 },
575-
{ col: 6, row: 3, h: 22 },
576-
{ col: 7, row: 3, h: 16 },
577-
578-
{ col: 0, row: 4, h: 8 },
579-
{ col: 1, row: 4, h: 30 },
580-
{ col: 2, row: 4, h: 10 },
581-
{ col: 3, row: 4, h: 20 },
582-
{ col: 4, row: 4, h: 16 },
583-
{ col: 5, row: 4, h: 40 },
584-
{ col: 6, row: 4, h: 12 },
585-
{ col: 7, row: 4, h: 24 },
586-
587-
{ col: 0, row: 5, h: 14 },
588-
{ col: 1, row: 5, h: 8 },
589-
{ col: 2, row: 5, h: 22 },
590-
{ col: 3, row: 5, h: 32 },
591-
{ col: 4, row: 5, h: 10 },
592-
{ col: 5, row: 5, h: 18 },
593-
{ col: 6, row: 5, h: 28 },
594-
{ col: 7, row: 5, h: 6 },
595-
];
596-
597622
let ghostTowers = '';
598-
for (const { col, row, h } of ghostLayout) {
623+
for (const { col, row, h } of GHOST_LAYOUT) {
599624
const tx = 300 + (col - row) * 16;
600625
const ty = 120 + (col + row) * 9;
601626

0 commit comments

Comments
 (0)