Reputation: 470
So I have a string representing DIV innerHTML and I want to extract all styles from spans to an array. Here are example strings:
string1 = <span style="background-color: #808080">U posljednji čas. 123</span>
string2 = <span style="background-color: #808080">U <span style="font-style: italic">posljednji</span> čas. 123</span>
And I want the output to look something like this:
string1output1 = ['background-color: #808080']
string1output2 = ['background-color: #808080', 'font-style: italic']
Or:
string2output1 = ['<span style="background-color: #808080">']
string2output2 = ['<span style="background-color: #808080">', '<span style="font-style: italic">']
What would be the easiest and most effective way to do this, having in mind that there may be more than 1 span with styling inside string? Also I would need to replace the span with something, so second method would be easier for that because I could just call replace on string with items from array.
Thanks for your help
Upvotes: 4
Views: 2841
Reputation: 470
Thanks @Mark Baijens and @Chris G for the suggestions, I've managed to do something like this:
const mockDiv = document.createElement('div');
mockDiv.innerHTML = html;
const styles = flatten(Array.from(mockDiv.children).map((child: HTMLElement) => child.style.cssText).map(item => {
const stylesArray = item.split(';');
const object = {};
stylesArray.filter(style => style.length > 0).map(style => style.replace(/\s/g, '')).forEach(style => {
const getRgbValues = (string: string): number[] => {
return string.replace('rgb(', '').replace(')', '').split(',').map(a => Number(a));
};
object[`${style.split(':')[0].split('-')[0]}${_.upperFirst(style.split(':')[0].split('-')[1])}`]
= style.split(':')[1].includes('rgb')
? rgbToHex(getRgbValues(style.split(':')[1]))
: style.split(':')[1];
});
return object;
}));
const text = html.split(`<br>`).join('@n').replace(/<span[^>]*>/g, '@s').replace(/<\/span>/g, '');
Works like it should, even if it's not pretty :)
Upvotes: 1
Reputation: 13222
As mentioned by others you can parse the string and get the style attribute information from that.
I'm not sure if you want styles split if 1 element contains more then 1 style but the example below does take that into account by default. However that can be switched off by the second function parameter as you can see in the 4th example.
So steps are:
;
unless paramter split is set to false)string1 = '<span style="background-color: #808080">U posljednji čas. 123</span>';
string2 = '<span style="background-color: #808080">U <span style="font-style: italic">posljednji</span> čas. 123</span>';
string3 = '<span style="background-color: #808080;font-style: italic">U posljednji čas. 123</span>';
console.log(stringToStyleArray(string1));
console.log(stringToStyleArray(string2));
console.log(stringToStyleArray(string3));
console.log(stringToStyleArray(string3, false));
function stringToStyleArray(string, split = true) {
let styles = [];
dom = (new DOMParser()).parseFromString(string, "text/html");
dom.querySelectorAll('[style]').forEach((el) => {
if(split) {
styles = [...styles, ...el.getAttribute("style").split(';')];
}
else {
styles.push(el.getAttribute("style"));
}
});
return styles;
}
Upvotes: 2
Reputation: 1185
i think you can split the string with spaces like
let splitedStringArr = '<span style="background-color: #808080">U posljednji čas. 123</span>'.split(" ")
which returns array, than you can use find to find styles string
let stylesString = splitedStringArr.find(str => str.includes("style"));
than you will have string like this: 'style="background-color:", "#808080">'
and one more split for clear styles string
let justStylesString = stylesString.split("=")[1]
you should have string like this: '"background-color:", "#808080">'
and then you should do it ...
Upvotes: -1