Skip to content

Commit 09dbe23

Browse files
js parse changes
1 parent 07bd24e commit 09dbe23

File tree

3 files changed

+125
-6
lines changed

3 files changed

+125
-6
lines changed

packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,15 @@ type RadialGradientValue = {
777777
}>,
778778
};
779779

780-
export type BackgroundImageValue = LinearGradientValue | RadialGradientValue;
780+
export type URLBackgroundImageValue = {
781+
type: 'url',
782+
uri: string,
783+
};
784+
785+
export type BackgroundImageValue =
786+
| LinearGradientValue
787+
| RadialGradientValue
788+
| URLBackgroundImageValue;
781789

782790
export type BackgroundSizeValue =
783791
| {

packages/react-native/Libraries/StyleSheet/__tests__/processBackgroundImage-test.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,10 @@ describe('processBackgroundImage', () => {
361361
{color: 'blue', positions: ['100%']},
362362
],
363363
},
364+
{
365+
type: 'url',
366+
uri: 'https://example.com',
367+
},
364368
];
365369
const result = processBackgroundImage(input);
366370
expect(result).toEqual([
@@ -372,6 +376,10 @@ describe('processBackgroundImage', () => {
372376
{color: processColor('blue'), position: '100%'},
373377
],
374378
},
379+
{
380+
type: 'url',
381+
uri: 'https://example.com',
382+
},
375383
]);
376384
});
377385

@@ -1153,4 +1161,68 @@ describe('processBackgroundImage', () => {
11531161
expect(result1).toEqual([]);
11541162
expect(result2).toEqual([]);
11551163
});
1164+
1165+
it('should handle url background image', () => {
1166+
const input = 'url(https://example.com)';
1167+
const result = processBackgroundImage(input);
1168+
expect(result).toEqual([
1169+
{
1170+
type: 'url',
1171+
uri: 'https://example.com',
1172+
},
1173+
]);
1174+
});
1175+
1176+
it('should handle url background image with quotes', () => {
1177+
const input = 'url("https://example.com")';
1178+
const result = processBackgroundImage(input);
1179+
expect(result).toEqual([
1180+
{
1181+
type: 'url',
1182+
uri: 'https://example.com',
1183+
},
1184+
]);
1185+
const input1 = "url('https://example.com')";
1186+
const result1 = processBackgroundImage(input1);
1187+
expect(result1).toEqual([
1188+
{
1189+
type: 'url',
1190+
uri: 'https://example.com',
1191+
},
1192+
]);
1193+
});
1194+
1195+
it('should handle url background image with mixed gradient and url', () => {
1196+
const input =
1197+
'radial-gradient(circle at top left, red, blue), url(https://example.com?q=JonDoe12), url(https://example2.com), linear-gradient(to bottom, green, yellow)';
1198+
const result = processBackgroundImage(input);
1199+
expect(result).toEqual([
1200+
{
1201+
type: 'radial-gradient',
1202+
shape: 'circle',
1203+
position: {top: '0%', left: '0%'},
1204+
size: 'farthest-corner',
1205+
colorStops: [
1206+
{color: processColor('red'), position: null},
1207+
{color: processColor('blue'), position: null},
1208+
],
1209+
},
1210+
{
1211+
type: 'url',
1212+
uri: 'https://example.com?q=JonDoe12',
1213+
},
1214+
{
1215+
type: 'url',
1216+
uri: 'https://example2.com',
1217+
},
1218+
{
1219+
type: 'linear-gradient',
1220+
direction: {type: 'angle', value: 180},
1221+
colorStops: [
1222+
{color: processColor('green'), position: null},
1223+
{color: processColor('yellow'), position: null},
1224+
],
1225+
},
1226+
]);
1227+
});
11561228
});

packages/react-native/Libraries/StyleSheet/processBackgroundImage.js

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,20 @@ type RadialGradientBackgroundImage = {
6363
}>,
6464
};
6565

66+
type URLBackgroundImage = {
67+
type: 'url',
68+
uri: string,
69+
};
70+
6671
// null color indicate that the transition hint syntax is used. e.g. red, 20%, blue
6772
type ColorStopColor = ProcessedColorValue | null;
6873
// percentage or pixel value
6974
type ColorStopPosition = number | string | null;
7075

7176
type ParsedBackgroundImageValue =
7277
| LinearGradientBackgroundImage
73-
| RadialGradientBackgroundImage;
78+
| RadialGradientBackgroundImage
79+
| URLBackgroundImage;
7480

7581
export default function processBackgroundImage(
7682
backgroundImage: ?($ReadOnlyArray<BackgroundImageValue> | string),
@@ -84,6 +90,19 @@ export default function processBackgroundImage(
8490
result = parseBackgroundImageCSSString(backgroundImage.replace(/\n/g, ' '));
8591
} else if (Array.isArray(backgroundImage)) {
8692
for (const bgImage of backgroundImage) {
93+
if (bgImage.type === 'url') {
94+
if (bgImage.uri != null && typeof bgImage.uri === 'string') {
95+
result = result.concat({
96+
type: 'url',
97+
uri: bgImage.uri,
98+
});
99+
continue;
100+
} else {
101+
// If the URI is invalid, return an empty array. Same as web.
102+
return [];
103+
}
104+
}
105+
87106
const processedColorStops = processColorStops(bgImage);
88107
if (processedColorStops == null) {
89108
// If a color stop is invalid, return an empty array and do not apply any gradient. Same as web.
@@ -250,13 +269,33 @@ function processColorStops(bgImage: BackgroundImageValue): $ReadOnlyArray<{
250269
function parseBackgroundImageCSSString(
251270
cssString: string,
252271
): $ReadOnlyArray<ParsedBackgroundImageValue> {
253-
const gradients = [];
272+
const backgroundImages = [];
254273
const bgImageStrings = splitGradients(cssString);
255274

256275
for (const bgImageString of bgImageStrings) {
276+
// url syntax supports - url(x), url("x"), url('x')
277+
const urlRegex = /^url\((.*)\)$/i;
278+
const urlMatch = urlRegex.exec(bgImageString);
279+
if (urlMatch) {
280+
let uri = urlMatch[1].trim();
281+
// string single or double quotes
282+
if (
283+
(uri.startsWith('"') && uri.endsWith('"')) ||
284+
(uri.startsWith("'") && uri.endsWith("'"))
285+
) {
286+
uri = uri.slice(1, -1);
287+
}
288+
if (uri.length > 0) {
289+
backgroundImages.push({
290+
type: 'url',
291+
uri,
292+
});
293+
}
294+
continue;
295+
}
296+
257297
const bgImage = bgImageString.toLowerCase();
258298
const gradientRegex = /^(linear|radial)-gradient\(((?:\([^)]*\)|[^()])*)\)/;
259-
260299
const match = gradientRegex.exec(bgImage);
261300
if (match) {
262301
const [, type, gradientContent] = match;
@@ -266,11 +305,11 @@ function parseBackgroundImageCSSString(
266305
: parseLinearGradientCSSString(gradientContent);
267306

268307
if (gradient != null) {
269-
gradients.push(gradient);
308+
backgroundImages.push(gradient);
270309
}
271310
}
272311
}
273-
return gradients;
312+
return backgroundImages;
274313
}
275314

276315
function parseRadialGradientCSSString(

0 commit comments

Comments
 (0)