@@ -3,9 +3,34 @@ import { type CSSObject } from "@emotion/react";
3
3
export type ExternalImageMode = keyof ExternalImageModeStyles ;
4
4
5
5
export interface ExternalImageModeStyles {
6
+ /**
7
+ * monochrome icons will be flattened to a neutral, theme-appropriate color.
8
+ * eg. white, light gray, dark gray, black
9
+ */
6
10
monochrome ?: CSSObject ;
11
+ /**
12
+ * @default
13
+ * fullcolor icons should look their best of any background, with distinct colors
14
+ * and good contrast. This is the default, and won't alter the image.
15
+ */
7
16
fullcolor ?: CSSObject ;
17
+ /**
18
+ * whiteWithColor is useful for icons that are primarily white, or contain white text,
19
+ * which are hard to see or look incorrect on light backgrounds. This setting will apply
20
+ * a color-respecting inversion filter to turn white into black when appropriate to
21
+ * improve contrast.
22
+ * You can also specify a `brightness` level if your icon still doesn't look quite right.
23
+ * eg. /icon/aws.svg?blackWithColor&brightness=1.5
24
+ */
8
25
whiteWithColor ?: CSSObject ;
26
+ /**
27
+ * blackWithColor is useful for icons that are primarily black, or contain black text,
28
+ * which are hard to see or look incorrect on dark backgrounds. This setting will apply
29
+ * a color-respecting inversion filter to turn black into white when appropriate to
30
+ * improve contrast.
31
+ * You can also specify a `brightness` level if your icon still doesn't look quite right.
32
+ * eg. /icon/aws.svg?blackWithColor&brightness=1.5
33
+ */
9
34
blackWithColor ?: CSSObject ;
10
35
}
11
36
@@ -31,16 +56,29 @@ export const forLightThemes: ExternalImageModeStyles = {
31
56
blackWithColor : undefined ,
32
57
} ;
33
58
34
- const parseExtraParams = ( params : URLSearchParams , baseStyles ?: CSSObject ) => {
59
+ // multiplier matches the beginning of the string (^), a number, optionally followed
60
+ // followed by a decimal portion, optionally followed by a percent symbol, and the
61
+ // end of the string ($).
62
+ const multiplier = / ^ \d + ( \. \d + ) ? % ? $ / ;
63
+
64
+ /**
65
+ * Used with `whiteWithColor` and `blackWithColor` to allow for finer tuning
66
+ */
67
+ const parseInvertFilterParameters = (
68
+ params : URLSearchParams ,
69
+ baseStyles ?: CSSObject ,
70
+ ) => {
71
+ // Only apply additional styles if the current theme supports this mode
35
72
if ( ! baseStyles ) {
36
73
return ;
37
74
}
38
75
39
76
let extraStyles : CSSObject | undefined ;
40
77
41
- if ( params . has ( "brightness" ) ) {
78
+ const brightness = params . get ( "brightness" ) ;
79
+ if ( multiplier . test ( brightness ! ) ) {
42
80
let filter = baseStyles . filter ?? "" ;
43
- filter += `brightness(${ params . get ( " brightness" ) } )` ;
81
+ filter += ` brightness(${ brightness } )` ;
44
82
extraStyles = { ...extraStyles , filter } ;
45
83
}
46
84
@@ -54,7 +92,7 @@ const parseExtraParams = (params: URLSearchParams, baseStyles?: CSSObject) => {
54
92
} ;
55
93
} ;
56
94
57
- export function parseModeParameters (
95
+ export function parseImageParameters (
58
96
modes : ExternalImageModeStyles ,
59
97
searchString : string ,
60
98
) : CSSObject | undefined {
@@ -64,18 +102,43 @@ export function parseModeParameters(
64
102
65
103
if ( params . has ( "monochrome" ) ) {
66
104
styles = modes . monochrome ;
105
+ } else if ( params . has ( "whiteWithColor" ) ) {
106
+ styles = parseInvertFilterParameters ( params , modes . whiteWithColor ) ;
107
+ } else if ( params . has ( "blackWithColor" ) ) {
108
+ styles = parseInvertFilterParameters ( params , modes . blackWithColor ) ;
67
109
}
68
- if ( params . has ( "whiteWithColor" ) ) {
69
- styles = parseExtraParams ( params , modes . whiteWithColor ) ;
110
+
111
+ return styles ;
112
+ }
113
+
114
+ export function getExternalImageStylesFromUrl (
115
+ modes : ExternalImageModeStyles ,
116
+ urlString : string ,
117
+ ) {
118
+ const url = new URL ( urlString , location . origin ) ;
119
+
120
+ if ( url . search ) {
121
+ return parseImageParameters ( modes , url . search ) ;
70
122
}
71
- if ( params . has ( "blackWithColor" ) ) {
72
- styles = parseExtraParams ( params , modes . blackWithColor ) ;
123
+
124
+ if (
125
+ url . origin === location . origin &&
126
+ defaultParametersForBuiltinIcons . has ( url . pathname )
127
+ ) {
128
+ return parseImageParameters (
129
+ modes ,
130
+ defaultParametersForBuiltinIcons . get ( url . pathname ) ! ,
131
+ ) ;
73
132
}
74
133
75
- return parseExtraParams ( params , styles ) ;
134
+ return undefined ;
76
135
}
77
136
78
- export const defaultModeForBuiltinIcons = new Map < string , string > ( [
137
+ /**
138
+ * defaultModeForBuiltinIcons contains modes for all of our built-in icons that
139
+ * don't look their best in all of our themes with the default fullcolor mode.
140
+ */
141
+ export const defaultParametersForBuiltinIcons = new Map < string , string > ( [
79
142
[ "/icon/apple-black.svg" , "monochrome" ] ,
80
143
[ "/icon/aws.png" , "whiteWithColor&brightness=1.5" ] ,
81
144
[ "/icon/aws.svg" , "blackWithColor&brightness=1.5" ] ,
@@ -87,6 +150,7 @@ export const defaultModeForBuiltinIcons = new Map<string, string>([
87
150
[ "/icon/folder.svg" , "monochrome" ] ,
88
151
[ "/icon/github.svg" , "monochrome" ] ,
89
152
[ "/icon/image.svg" , "monochrome" ] ,
153
+ [ "/icon/jupyter.svg" , "blackWithColor" ] ,
90
154
[ "/icon/kasmvnc.svg" , "whiteWithColor" ] ,
91
155
[ "/icon/memory.svg" , "monochrome" ] ,
92
156
[ "/icon/rust.svg" , "monochrome" ] ,
0 commit comments