From 19a09bc7721576e3e2b14efd9a1c6a210faf83f8 Mon Sep 17 00:00:00 2001 From: mathuraditya724 Date: Sun, 22 Mar 2026 21:56:37 +0530 Subject: [PATCH 1/5] fix(badge): make text-width fallback less aggressive for consistent sizing --- .../api/registry/badge/[type]/[...pkg].get.ts | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/server/api/registry/badge/[type]/[...pkg].get.ts b/server/api/registry/badge/[type]/[...pkg].get.ts index 2ce404e381..f47dd312ac 100644 --- a/server/api/registry/badge/[type]/[...pkg].get.ts +++ b/server/api/registry/badge/[type]/[...pkg].get.ts @@ -41,9 +41,6 @@ const COLORS = { white: '#ffffff', } -const CHAR_WIDTH = 7 -const SHIELDS_CHAR_WIDTH = 6 - const BADGE_PADDING_X = 8 const MIN_BADGE_TEXT_WIDTH = 40 const SHIELDS_LABEL_PADDING_X = 5 @@ -53,6 +50,39 @@ const SHIELDS_FONT_SHORTHAND = 'normal normal 400 11px Verdana, Geneva, DejaVu S let cachedCanvasContext: SKRSContext2D | null | undefined +const NARROW_CHARS = new Set([' ', '!', '"', "'", '(', ')', '*', ',', '-', '.', ':', ';', '|']) +const MEDIUM_CHARS = new Set(['#', '$', '+', '/', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '}', '~']) + +function estimateTextWidth(text: string, fallbackFont: 'default' | 'shieldsio'): number { + let totalWidth = 0 + + for (const character of text) { + if (NARROW_CHARS.has(character)) { + totalWidth += 3 + continue + } + + if (MEDIUM_CHARS.has(character)) { + totalWidth += 5 + continue + } + + if (/\d/.test(character)) { + totalWidth += 6 + continue + } + + if (/[A-Z]/.test(character)) { + totalWidth += 7 + continue + } + + totalWidth += fallbackFont === 'shieldsio' ? 5.5 : 6 + } + + return Math.max(1, Math.round(totalWidth)) +} + function getCanvasContext(): SKRSContext2D | null { if (cachedCanvasContext !== undefined) { return cachedCanvasContext @@ -90,7 +120,7 @@ function measureDefaultTextWidth(text: string): number { return Math.max(MIN_BADGE_TEXT_WIDTH, measuredWidth + BADGE_PADDING_X * 2) } - return Math.max(MIN_BADGE_TEXT_WIDTH, Math.round(text.length * CHAR_WIDTH) + BADGE_PADDING_X * 2) + return Math.max(MIN_BADGE_TEXT_WIDTH, estimateTextWidth(text, 'default') + BADGE_PADDING_X * 2) } function escapeXML(str: string): string { @@ -125,7 +155,7 @@ function measureShieldsTextLength(text: string): number { return Math.max(1, measuredWidth) } - return Math.max(1, Math.round(text.length * SHIELDS_CHAR_WIDTH)) + return estimateTextWidth(text, 'shieldsio') } function renderDefaultBadgeSvg(params: { From 9c66f0129732db65bb56de778f1d3b70148c5b66 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 22 Mar 2026 16:33:33 +0000 Subject: [PATCH 2/5] [autofix.ci] apply automated fixes --- .../api/registry/badge/[type]/[...pkg].get.ts | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/server/api/registry/badge/[type]/[...pkg].get.ts b/server/api/registry/badge/[type]/[...pkg].get.ts index f47dd312ac..52808ce31c 100644 --- a/server/api/registry/badge/[type]/[...pkg].get.ts +++ b/server/api/registry/badge/[type]/[...pkg].get.ts @@ -51,7 +51,26 @@ const SHIELDS_FONT_SHORTHAND = 'normal normal 400 11px Verdana, Geneva, DejaVu S let cachedCanvasContext: SKRSContext2D | null | undefined const NARROW_CHARS = new Set([' ', '!', '"', "'", '(', ')', '*', ',', '-', '.', ':', ';', '|']) -const MEDIUM_CHARS = new Set(['#', '$', '+', '/', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '}', '~']) +const MEDIUM_CHARS = new Set([ + '#', + '$', + '+', + '/', + '<', + '=', + '>', + '?', + '@', + '[', + '\\', + ']', + '^', + '_', + '`', + '{', + '}', + '~', +]) function estimateTextWidth(text: string, fallbackFont: 'default' | 'shieldsio'): number { let totalWidth = 0 From a66454eafa1d8b1393029b081b07831aceb9096b Mon Sep 17 00:00:00 2001 From: mathuraditya724 Date: Sun, 22 Mar 2026 22:12:53 +0530 Subject: [PATCH 3/5] fix(badge): add breathing room for fallback value segment --- server/api/registry/badge/[type]/[...pkg].get.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/server/api/registry/badge/[type]/[...pkg].get.ts b/server/api/registry/badge/[type]/[...pkg].get.ts index 52808ce31c..711c6a75e8 100644 --- a/server/api/registry/badge/[type]/[...pkg].get.ts +++ b/server/api/registry/badge/[type]/[...pkg].get.ts @@ -43,6 +43,7 @@ const COLORS = { const BADGE_PADDING_X = 8 const MIN_BADGE_TEXT_WIDTH = 40 +const FALLBACK_VALUE_EXTRA_PADDING_X = 4 const SHIELDS_LABEL_PADDING_X = 5 const BADGE_FONT_SHORTHAND = 'normal normal 400 11px Geist, system-ui, -apple-system, sans-serif' @@ -132,14 +133,17 @@ function measureTextWidth(text: string, font: string): number | null { return null } -function measureDefaultTextWidth(text: string): number { +function measureDefaultTextWidth(text: string, fallbackExtraPadding = 0): number { const measuredWidth = measureTextWidth(text, BADGE_FONT_SHORTHAND) if (measuredWidth !== null) { return Math.max(MIN_BADGE_TEXT_WIDTH, measuredWidth + BADGE_PADDING_X * 2) } - return Math.max(MIN_BADGE_TEXT_WIDTH, estimateTextWidth(text, 'default') + BADGE_PADDING_X * 2) + return Math.max( + MIN_BADGE_TEXT_WIDTH, + estimateTextWidth(text, 'default') + BADGE_PADDING_X * 2 + fallbackExtraPadding, + ) } function escapeXML(str: string): string { @@ -188,7 +192,7 @@ function renderDefaultBadgeSvg(params: { const { finalColor, finalLabel, finalLabelColor, finalValue, labelTextColor, valueTextColor } = params const leftWidth = finalLabel.trim().length === 0 ? 0 : measureDefaultTextWidth(finalLabel) - const rightWidth = measureDefaultTextWidth(finalValue) + const rightWidth = measureDefaultTextWidth(finalValue, FALLBACK_VALUE_EXTRA_PADDING_X) const totalWidth = leftWidth + rightWidth const height = 20 const escapedLabel = escapeXML(finalLabel) From 3f6e41ca515b3be04551bacea902570daaad3ddf Mon Sep 17 00:00:00 2001 From: mathuraditya724 Date: Sun, 22 Mar 2026 22:17:05 +0530 Subject: [PATCH 4/5] chore(badge): resolve coderabbit nitpick by extracting fallback width constants --- .../api/registry/badge/[type]/[...pkg].get.ts | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/server/api/registry/badge/[type]/[...pkg].get.ts b/server/api/registry/badge/[type]/[...pkg].get.ts index 711c6a75e8..dd31cd1e03 100644 --- a/server/api/registry/badge/[type]/[...pkg].get.ts +++ b/server/api/registry/badge/[type]/[...pkg].get.ts @@ -73,31 +73,50 @@ const MEDIUM_CHARS = new Set([ '~', ]) +const FALLBACK_WIDTHS = { + default: { + narrow: 3, + medium: 5, + digit: 6, + uppercase: 7, + other: 6, + }, + shieldsio: { + narrow: 3, + medium: 5, + digit: 6, + uppercase: 7, + other: 5.5, + }, +} as const + function estimateTextWidth(text: string, fallbackFont: 'default' | 'shieldsio'): number { + // Heuristic coefficients tuned to keep fallback rendering close to canvas metrics. + const widths = FALLBACK_WIDTHS[fallbackFont] let totalWidth = 0 for (const character of text) { if (NARROW_CHARS.has(character)) { - totalWidth += 3 + totalWidth += widths.narrow continue } if (MEDIUM_CHARS.has(character)) { - totalWidth += 5 + totalWidth += widths.medium continue } if (/\d/.test(character)) { - totalWidth += 6 + totalWidth += widths.digit continue } if (/[A-Z]/.test(character)) { - totalWidth += 7 + totalWidth += widths.uppercase continue } - totalWidth += fallbackFont === 'shieldsio' ? 5.5 : 6 + totalWidth += widths.other } return Math.max(1, Math.round(totalWidth)) From 333d12b2c9c95d5a6a859f2f7d8d0711eedd1ee4 Mon Sep 17 00:00:00 2001 From: mathuraditya724 Date: Sun, 22 Mar 2026 22:18:36 +0530 Subject: [PATCH 5/5] chore: minor padding update --- server/api/registry/badge/[type]/[...pkg].get.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/api/registry/badge/[type]/[...pkg].get.ts b/server/api/registry/badge/[type]/[...pkg].get.ts index dd31cd1e03..194e89b3f6 100644 --- a/server/api/registry/badge/[type]/[...pkg].get.ts +++ b/server/api/registry/badge/[type]/[...pkg].get.ts @@ -43,7 +43,7 @@ const COLORS = { const BADGE_PADDING_X = 8 const MIN_BADGE_TEXT_WIDTH = 40 -const FALLBACK_VALUE_EXTRA_PADDING_X = 4 +const FALLBACK_VALUE_EXTRA_PADDING_X = 8 const SHIELDS_LABEL_PADDING_X = 5 const BADGE_FONT_SHORTHAND = 'normal normal 400 11px Geist, system-ui, -apple-system, sans-serif'