将CSS文本转换为JavaScript对象

Oma*_*bid 15 javascript css

我有以下文本作为JavaScript字符串

.mybox {
 display: block; 
 width: 20px; 
 height: 20px;
 background-color: rgb(204, 204, 204);
 }
Run Code Online (Sandbox Code Playgroud)

我想转换为JavaScript对象

var mybox = {
 'display': 'block',
 'width': '20px',
 'height': '20px';
 'background-color': 'rgb(204, 204, 204)';
};
Run Code Online (Sandbox Code Playgroud)

任何想法或已经制作的脚本?

7vu*_*0hy 10

2017年答案

function parseCSSText(cssText) {
    var cssTxt = cssText.replace(/\/\*(.|\s)*?\*\//g, " ").replace(/\s+/g, " ");
    var style = {}, [,ruleName,rule] = cssTxt.match(/ ?(.*?) ?{([^}]*)}/)||[,,cssTxt];
    var cssToJs = s => s.replace(/\W+\w/g, match => match.slice(-1).toUpperCase());
    var properties = rule.split(";").map(o => o.split(":").map(x => x && x.trim()));
    for (var [property, value] of properties) style[cssToJs(property)] = value;
    return {cssText, ruleName, style};
} /* updated 2017-09-28 */
Run Code Online (Sandbox Code Playgroud)

描述

将以下cssText(字符串)传递给函数:

.mybox {
     display: block; 
     width: 20px; 
     height: 20px;
     background-color: rgb(204, 204, 204);
 }
Run Code Online (Sandbox Code Playgroud)

...将给出以下对象:

{   cssText: ... /* the original string including new lines, tabs and spaces */, 
    ruleName: ".mybox",
    style: {
        "": undefined,
        display: "block",
        width: "20px",
        height: "20px",
        backgroundColor: "rgb(204, 204, 204)"
     }
}
Run Code Online (Sandbox Code Playgroud)

用户还可以传递cssText如下:

display: block; width: 20px; height: 20px; background-color: rgb(204, 204, 204);
Run Code Online (Sandbox Code Playgroud)

特征:

  • 适用于CSSRule.cssTextCSSStyleDeclaration.cssText.
  • 将CSS属性名称(background-color)转换为JS属性名称(backgroundColor).它处理甚至非常不稳定的名称,例如back%gr- -ound---color: red;(转换为backGrOundColor).
  • 允许使用单个调用批量修改现有 CSSStyleDeclarations(例如document.body.style) Object.assign(document.body.style, parseCSSText(cssText).style).
  • 难道不是在属性名都是有值(不带冒号的条目)甚至也不是失败,反之亦然.
  • 更新2017-09-28:在规则名称中处理新行,折叠空格.
  • 更新2017-09-28:处理评论(/*...*/).

怪癖:

  • 如果规则中的最后一个CSS声明以分号结尾,则返回的样式将包含一个具有空名称的属性""和一个undefined反映分号后面的空字符串的值.我认为这是一种正确的行为.
  • 例如,如果属性值(字符串文字)包括冒号或分号或CSS注释,则该函数将返回错误结果 div::before {content: 'test:test2;/*test3*/';}.我不知道如何避免这种情况.
  • 目前,它将带有前缀的属性名称转换为-somebrowser-someproperty不正确SomebrowserSomeproperty 而不是somebrowserSomeproperty.我想要一种不会破坏代码简洁的补救措施,因此我会花时间找一个.

实例

function parseCSSText(cssText) {
    var cssTxt = cssText.replace(/\/\*(.|\s)*?\*\//g, " ").replace(/\s+/g, " ");
    var style = {}, [,ruleName,rule] = cssTxt.match(/ ?(.*?) ?{([^}]*)}/)||[,,cssTxt];
    var cssToJs = s => s.replace(/\W+\w/g, match => match.slice(-1).toUpperCase());
    var properties = rule.split(";").map(o => o.split(":").map(x => x && x.trim()));
    for (var [property, value] of properties) style[cssToJs(property)] = value;
    return {cssText, ruleName, style};
} /* updated 2017-09-28 */

Example:
    var sty = document.getElementById("mystyle");
    var out = document.getElementById("outcome");
    var styRule = parseCSSText(sty.innerHTML);
    var outRule = parseCSSText(out.style.cssText);
    out.innerHTML = 
        "<b>? CSS in #mystyle</b>: " + JSON.stringify(styRule) + "<br>" +
        "<b>? CSS of #outcome</b>: " + JSON.stringify(outRule);
    console.log(styRule, outRule); /* Inspect result in the console. */
Run Code Online (Sandbox Code Playgroud)
<style id="mystyle">
.mybox1, /* a comment
    and new lines 
    to step up the game */
    .mybox 
{
    display: block; 
    width: 20px; height: 20px;
    background-color: /* a comment
        and a new line */ 
        rgb(204, 204, 204);
    -somebrowser-someproperty: somevalue;
}
</style>

<div id="outcome" style="
    display: block; padding: 0.5em;
    background-color: rgb(144, 224, 224);
">...</div>

<b style="color: red;">Also inspect the browser console.</b>
Run Code Online (Sandbox Code Playgroud)


pis*_*hio 6

这是解析器的开始,可以做你想要的.当然它需要工作,特别是如果你想处理可能提供的任何通用CSS.这假定输入css是按照您提供的方式编写的,第一行是属性的名称,最后一行是'}',依此类推.

如果您不想只处理基本属性,编写复杂的解析器并不是一件容易的事.例如,如果您声明如下内容,该怎么办?

input[type="text"],
table > tr:nth-child(2),
#link a:hover {
    -webkit-transition: width 2s; /* Safari and Chrome */
}
Run Code Online (Sandbox Code Playgroud)

这是有效的CSS,但是如何从中提取有效的javascript变量名?如何转换-webkit-transition成有意义的属性名称?整个任务闻起来像是你做错了.我没有在解析器上工作,而是在一个更稳定的解决方案上工作.

顺便说一句,这是您可以从以下开始的代码:

    var s = '.mybox {\n';
    s += 'display: block;\n';
    s += 'width: 20px;\n';
    s += 'height: 20px;\n';
    s += 'background-color: rgb(204, 204, 204);\n';
    s += '}\n';

    // split css by line
    var css_rows = s.split('\n'); 

    // filter out empty elements and strip ';'      
    css_rows = css_rows.filter(function(x){ return x != '' }).map(function(x){ return x.trim().replace(';', '') });

    // create object
    var json_name = css_rows[0].trim().replace(/[\.\{\ \#]/g, '');
    eval('var ' + json_name + ' = {};');
    // remove first and last element
    css_rows = css_rows.splice(1, css_rows.length-2)

    for (elem in css_rows)
    {
        var elem_parts = css_rows[elem].split(':');
        var property_name = elem_parts[0].trim().replace('-', '');
        var property_value = elem_parts[1].trim();
        eval(json_name + '.' + property_name + ' = "' + property_value + '";');
    }
Run Code Online (Sandbox Code Playgroud)