danihazler
danihazler

Reputation: 409

Function that parses CSS styles string into JS inline style

I need to create a function that parses a CSS string, that will be used on a inline js style.

E.g: what I get is something like const styles = "background-color:#FFFFFF;color:#000000" and I need to transform in:

      <h1
        className={classes}
        style={{ color: fontColor, background: backgroundColor }}
      >
        {copy}
      </h1>

what I do for now is this

const [backgroundColor, setBackgroundColor] = useState();
  const [fontColor, setFontColor] = useState();
  const colors = styles?.match(/(#)([^;]*)/g);

  useEffect(() => {
    if (colors) {
      if (colors.length > 1) {
        setBackgroundColor(colors[0]);
        setFontColor(colors[1]);
      }

      if (colors.length === 1) {
        setFontColor(colors[0]);
      }
    }
  }, [colors]);

But I was asked to create pure seperate function that parses the styles string.

So I was wondering if there's a solution where I don't need to "regex" each specific selector and then its value. If there's something like whatever is before the colon is the selector than after that until the semicolon is its value.

Any tips?

Thanks

Upvotes: 0

Views: 1494

Answers (2)

Humpff
Humpff

Reputation: 328

Maybe something like this (which converts the css string to an object) (doesn't work on Safari):

const convertCssToObject = value => {
    
  const regex = /(?<=^|;)\s*([^:]+)\s*:\s*([^;]+)\s*/g, o = {};
  value.replace(regex, (m,p,v) => o[p] = v);
  return o;
    
}

console.log( convertCssToObject("background-color:#FFFFFF;color:#000000;") )

I've edited the regex so it works also on Safari:

const convertCssToObject = value => {
  // Without the look behind
  const regex = /([\w-.]+)\s*:([^;]+);?/g, o = {}; // Heck I think this should also work for Chrome as well
  value.replace(regex, (m,p,v) => o[p] = v);
  return o;
}

console.log( convertCssToObject("background-color:#FFFFFF;color:#000000;") )





Upvotes: 2

Nisharg Shah
Nisharg Shah

Reputation: 19652

You can do it like this and after that map your function with it

const styles = "background-color:#FFFFFF;color:#000000";

const css = styles.split(';').map(cur => cur.split(':'));

console.log(css);

const cssInObject = styles.split(';').map(cur => cur.split(':')).reduce((acc, val) => {
    let [key, value] = val;
    key = key.replace(/-./g, css => css.toUpperCase()[1])
    acc[key] = value;
    return acc;
}, {});

console.log(cssInObject);

Upvotes: 2

Related Questions