@@ -20,9 +20,51 @@ function renderResultCard(result) {
2020 const heading = itemNode ( result . output_name , result . output_path ) ; heading . firstChild && ( heading . firstChild . className = "" ) ;
2121 title . append ( heading , badge ( result . success ? t ( "result.success" ) : t ( "result.failed" ) , result . success ? "ok" : "danger" ) ) ; card . append ( title ) ;
2222 const counts = element ( "div" , "count-row" ) ; counts . append ( badge ( result . verified ? t ( "result.verified" ) : t ( "result.notVerified" ) , result . verified ? "ok" : "warn" ) , badge ( countText ( result . warnings . length , "count.warning.one" , "count.warning.other" ) , result . warnings . length ? "warn" : "info" ) ) ; card . append ( counts ) ;
23+ const warnNode = renderWarnings ( result . warnings ) ;
24+ if ( warnNode ) card . append ( warnNode ) ;
2325 if ( result . error ) card . append ( element ( "div" , "inline-error" , `${ result . error_code ? `[${ result . error_code } ] ` : "" } ${ result . error } ` ) ) ; return card ;
2426}
2527
28+ // Render a collapsible, human-readable list of job warnings. Previously the UI
29+ // only showed the warning *count*, so users could not tell what the warnings
30+ // actually meant.
31+ function renderWarnings ( warnings ) {
32+ if ( ! warnings || ! warnings . length ) return null ;
33+ const details = element ( "details" , "result-warnings" ) ;
34+ details . append ( element ( "summary" , "" , t ( "result.warnings" ) ) ) ;
35+ const list = element ( "ul" , "warning-list" ) ;
36+ for ( const warning of warnings ) {
37+ list . append ( element ( "li" , "warning-item" , humanizeWarning ( warning ) ) ) ;
38+ }
39+ details . append ( list ) ;
40+ return details ;
41+ }
42+
43+ // Turn machine-readable warning codes (e.g. "font_codepoints_missing:...")
44+ // into text a user can understand.
45+ function humanizeWarning ( text ) {
46+ if ( ! text ) return "" ;
47+ const idx = text . indexOf ( ":" ) ;
48+ const code = idx === - 1 ? text . trim ( ) : text . slice ( 0 , idx ) ;
49+ const rest = idx === - 1 ? "" : text . slice ( idx + 1 ) . trim ( ) ;
50+ switch ( code ) {
51+ case "font_codepoints_missing" : {
52+ const m = rest . match ( / : \s * ( .+ ) $ / ) ;
53+ return t ( "warning.fontCodepointsMissing" , { font : m ? m [ 1 ] . trim ( ) : rest } ) ;
54+ }
55+ case "font_subset_fallback_all" :
56+ return t ( "warning.fontSubsetFallbackAll" ) ;
57+ case "subset_fallback_full_font" :
58+ return t ( "warning.subsetFallbackFullFont" , { detail : rest } ) ;
59+ case "font_family_missing" :
60+ return t ( "warning.fontFamilyMissing" , { family : rest } ) ;
61+ case "font_match_ambiguous" :
62+ return t ( "warning.fontMatchAmbiguous" , { family : rest } ) ;
63+ default :
64+ return text ;
65+ }
66+ }
67+
2668
2769
2870function localizeEnum ( prefix , value ) {
0 commit comments