grhu
grhu

Reputation: 470

Extract styles from HTML string

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

Answers (3)

grhu
grhu

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

Mark Baijens
Mark Baijens

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:

  • Parse string to a DOM
  • Iterate over all elements that contain a style
  • Add found styles to the return array (split values on ; 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

n1koloza
n1koloza

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

Related Questions