@@ -41,9 +41,6 @@ const COLORS = {
4141 white : '#ffffff' ,
4242}
4343
44- const CHAR_WIDTH = 7
45- const SHIELDS_CHAR_WIDTH = 6
46-
4744const BADGE_PADDING_X = 8
4845const MIN_BADGE_TEXT_WIDTH = 40
4946const SHIELDS_LABEL_PADDING_X = 5
@@ -53,6 +50,39 @@ const SHIELDS_FONT_SHORTHAND = 'normal normal 400 11px Verdana, Geneva, DejaVu S
5350
5451let cachedCanvasContext : SKRSContext2D | null | undefined
5552
53+ const NARROW_CHARS = new Set ( [ ' ' , '!' , '"' , "'" , '(' , ')' , '*' , ',' , '-' , '.' , ':' , ';' , '|' ] )
54+ const MEDIUM_CHARS = new Set ( [ '#' , '$' , '+' , '/' , '<' , '=' , '>' , '?' , '@' , '[' , '\\' , ']' , '^' , '_' , '`' , '{' , '}' , '~' ] )
55+
56+ function estimateTextWidth ( text : string , fallbackFont : 'default' | 'shieldsio' ) : number {
57+ let totalWidth = 0
58+
59+ for ( const character of text ) {
60+ if ( NARROW_CHARS . has ( character ) ) {
61+ totalWidth += 3
62+ continue
63+ }
64+
65+ if ( MEDIUM_CHARS . has ( character ) ) {
66+ totalWidth += 5
67+ continue
68+ }
69+
70+ if ( / \d / . test ( character ) ) {
71+ totalWidth += 6
72+ continue
73+ }
74+
75+ if ( / [ A - Z ] / . test ( character ) ) {
76+ totalWidth += 7
77+ continue
78+ }
79+
80+ totalWidth += fallbackFont === 'shieldsio' ? 5.5 : 6
81+ }
82+
83+ return Math . max ( 1 , Math . round ( totalWidth ) )
84+ }
85+
5686function getCanvasContext ( ) : SKRSContext2D | null {
5787 if ( cachedCanvasContext !== undefined ) {
5888 return cachedCanvasContext
@@ -90,7 +120,7 @@ function measureDefaultTextWidth(text: string): number {
90120 return Math . max ( MIN_BADGE_TEXT_WIDTH , measuredWidth + BADGE_PADDING_X * 2 )
91121 }
92122
93- return Math . max ( MIN_BADGE_TEXT_WIDTH , Math . round ( text . length * CHAR_WIDTH ) + BADGE_PADDING_X * 2 )
123+ return Math . max ( MIN_BADGE_TEXT_WIDTH , estimateTextWidth ( text , 'default' ) + BADGE_PADDING_X * 2 )
94124}
95125
96126function escapeXML ( str : string ) : string {
@@ -125,7 +155,7 @@ function measureShieldsTextLength(text: string): number {
125155 return Math . max ( 1 , measuredWidth )
126156 }
127157
128- return Math . max ( 1 , Math . round ( text . length * SHIELDS_CHAR_WIDTH ) )
158+ return estimateTextWidth ( text , 'shieldsio' )
129159}
130160
131161function renderDefaultBadgeSvg ( params : {
0 commit comments