I am trying to implement a box-shadow CSS parser for my project. Initially, I tried to split the CSS using , but this is not an appropriate solution. Cause some box shadow has RGB color code and some have hex color code. I need the correct Regex code and javascript code snippets for this task. I can't figure out how can I make this array.
My box shadow CSS is:
rgb(165, 33, 33) 5px 4px 20px 0px, inset rgb(0, 80, 255, 0.3) 15px 21px 36px 6px, #000000 5px 4px 20px 0px;
My desired output is:
[
{
color: {
value: 'rgb(165, 33, 33)'
},
x: {
value: 5,
unit: 'px'
},
y: {
value: 4,
unit: 'px'
},
blur: {
value: 20,
unit: 'px'
},
spread: {
value: 0,
unit: 'px'
},
placement: {
value: 'outset'
}
},
{
color: {
value: 'rgb(0, 80, 255, 0.3)'
},
x: {
value: 15,
unit: 'px'
},
y: {
value: 21,
unit: 'px'
},
blur: {
value: 36,
unit: 'px'
},
spread: {
value: 6,
unit: 'px'
},
placement: {
value: 'inset'
}
},
{
color: {
value: '#000000'
},
x: {
value: 5,
unit: 'px'
},
y: {
value: 4,
unit: 'px'
},
blur: {
value: 20,
unit: 'px'
},
spread: {
value: 6,
unit: 'px'
},
placement: {
value: 'outset'
}
}
]
My code:
const getValueAndUnit = (val = '') => {
if (!specialValues.has(val.toLowerCase())) {
const propRegx = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;
const matches = val.match(propRegx);
let value = 0;
let unit = 'px';
if (Array.isArray(matches)) [, value, unit] = matches;
return {
value: Number(value),
unit,
};
}
return { value: 'auto', unit: 'auto' };
}
const getBoxShadowArray = (boxshadow) => {
let shadow_arr = [];
boxshadow
.trim()
.split(',')
.forEach((v) => {
let styleObj = {};
let styleArray = v.trim().split(' ');
if (styleArray.length === 6) {
const [placementValue, colorValue, xValue, yValue, blurValue, spreadValue] = styleArray;
styleObj.placement = { value: placementValue };
styleObj.color = { value: colorValue };
styleObj.x = { ...getValueAndUnit(xValue) };
styleObj.y = { ...getValueAndUnit(yValue) };
styleObj.blur = { ...getValueAndUnit(blurValue) };
styleObj.spread = { ...getValueAndUnit(spreadValue) };
} else {
const [colorValue, xValue, yValue, blurValue, spreadValue] = styleArray;
styleObj.placement = { value: 'outset' };
styleObj.color = { value: colorValue };
styleObj.x = { ...getValueAndUnit(xValue) };
styleObj.y = { ...getValueAndUnit(yValue) };
styleObj.blur = { ...getValueAndUnit(blurValue) };
styleObj.spread = { ...getValueAndUnit(spreadValue) };
}
shadow_arr.push(styleObj);
});
return shadow_arr;
}
getBoxShadowArray('rgb(165, 33, 33) 5px 4px 20px 0px, inset rgb(0, 80, 255, 0.3) 15px 21px 36px 6px, #000000 5px 4px 20px 0px;');
As @AKX says in comment, you can't reliably do this simply by using a regex, because the CSS format can be in many formats.
However, if you still want to try, you can use this regex, which won't split in the middle of colors:
Explanation:
(?<!- negative look behind forrgb\(\s*\d+- literalrgb(followed by zero or more whitespaces and 1 or more digits(?:- non capturing group,\s*\d+- comma (,) followed by zero or more whitespaces and 1 or more digits(?:\.\d+)?optionally a dot (.) followed by one or more digits)*zero or more of this group)- end group,- finally match comma (,)This at least works on the example you gave, splitting into this: