0

I have a javascript object that contains descriptions for CSS styles.

This object comes from a third-party API, so I am not able to modify the object.

I'd like to parse and output the object to a string.

The string needs to be useable as a inline styles in the head of my HTML.

I need to be able to map "base" and "invalid" to custom class names. These can be provided as variables.

The invalid > color needs to be mapped to a border color. Basically it comes from the object as "color", but I need to use it as a border color.

I've tried nesting loops and have just been extremely stuck trying to figure out an elegant solve to this problem.

Please, if you need more detail, ask me and I'll answer as best I can to help clarify.

The JavaScript Object I receive:

{
    style: {
        base: {
            color: '#46a0ba',
            '::placeholder': {
                color: '#000'
            }
        },
        invalid: {
            color: 'yellow'
        }
    },
}

I need this to output as a sinlge-line string:

(I'm putting this on multiple lines to just make it easier to read here)

.baseClass { color: #46a0ba; }
.baseClass::placeholder {color: #000}
.invalidClass { border: 1px solid yellow; }

See CodePen of where I am at so far here:

https://codepen.io/fylzero/pen/gOOvdVp

8
  • 1
    Can you post what you got so far in terms of parsing? Commented Nov 4, 2019 at 22:30
  • 1
    a) is composing a longer string from a bunch of short strings / variables b) is accessing the values in the JS object. Where is the problem exactly? Doing a)? Doing b)? Where are you stuck? There's no parsing necessary at all here. Commented Nov 4, 2019 at 22:35
  • @AndreFeijo Here is about where I'm at so far: codepen.io/fylzero/pen/gOOvdVp Commented Nov 4, 2019 at 22:38
  • @ChrisG a) I need to convert the object values into the string provided. b) Yes, the class values are simply passed as const. I'm stuck on just how to get this converted. I'm wondering if there isn't n better way than using multiple loops as well. Commented Nov 4, 2019 at 22:48
  • Since I don't know how dynamic these API objects are going to be, here's a simple way: jsfiddle.net/khrismuc/2a53sytL Commented Nov 4, 2019 at 22:50

1 Answer 1

1

I'm separating the object data into properties that go into the main rule and nested stuff that needs separate rules. Using recursion for the second part and Array functions like map() and join(), we get:

const inputStyle = {
  base: {
    color: '#46a0ba',
    padding: '0.5em',
    'font-size': '14pt',
    '::placeholder': {
      color: '#000'
    },
    ':hover': {
      color: 'red'
    }
  },
  invalid: {
    color: 'yellow'
  }
};

function rules(className, obj) {
  const allProps = Object.entries(obj);
  const directProps = allProps.filter(([key, value]) => typeof value == 'string');
  const pseudoProps = allProps.filter(([key, value]) => typeof value == 'object');
  const directStyle = `.${className} { ${directProps.map(([key, value]) => `${key}: ${value};`).join(' ')} }`;
  const pseudoStyle = pseudoProps.map(([key, value]) => rules(className + key, value)).join(' ');
  return [directStyle, pseudoStyle].join(' ');
}

function appendStyle(baseName, invalidName, styleObj) {
  const styleElement = document.createElement("style");
  styleElement.textContent = [rules(baseName, styleObj.base), `.${invalidName} { border: 1px solid ${styleObj.invalid.color}; }`].join(' ');
  document.head.append(styleElement);
}

appendStyle("baseClass", "invalidClass", inputStyle);
body {
  background-color: #eee;
}
<input class="baseClass" placeholder="placeholder">
<input class="baseClass invalidClass" value="hello">

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.