如何将嵌套的 javascript 对象转换为 CSS 样式的内联字符串?

How can I convert a nested javascript object into an inline string of CSS styles?

我有一个 javascript 对象,其中包含 CSS 样式的描述。

这个对象来自第三方API,所以我无法修改这个对象。

我想解析对象并将其输出为字符串。

字符串需要在我的 HTML 的头部用作内联样式。

我需要能够将 "base" 和 "invalid" 映射到自定义 class 名称。这些可以作为变量提供。

无效的 > 颜色需要映射到边框颜色。基本上它来自对象 "color",但我需要将它用作边框颜色。

我已经尝试过嵌套循环,但在试图找到解决这个问题的优雅解决方案时一直非常困惑。

如果您需要更多详细信息,请问我,我会尽我所能回答以帮助澄清。

我收到的JavaScript对象:

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

我需要它作为单行字符串输出:

(我把它放在多行中只是为了让这里更容易阅读)

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

在此处查看我目前所在位置的 CodePen:

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

我将对象数据分成进入主规则的属性和需要单独规则的嵌套内容。对第二部分使用递归和数组函数,如 map()join(),我们得到:

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">