読み込み - CSSテキストをJavaScriptオブジェクトに変換する
jquery css (3)
JavaScriptの文字列として以下のテキストを持っています
.mybox {
display: block;
width: 20px;
height: 20px;
background-color: rgb(204, 204, 204);
}
JavaScriptオブジェクトに変換したい
var mybox = {
'display': 'block',
'width': '20px',
'height': '20px';
'background-color': 'rgb(204, 204, 204)';
};
任意のアイデアやすでに作られたスクリプト?
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 */
説明
次のcssText
(string)を関数に渡します。
.mybox {
display: block;
width: 20px;
height: 20px;
background-color: rgb(204, 204, 204);
}
...次のようなオブジェクトになります。
{ 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)"
}
}
ユーザーはcssText
ようなcssText
渡すこともできます。
display: block; width: 20px; height: 20px; background-color: rgb(204, 204, 204);
特徴:
- CSSRule.cssTextとCSSStyleDeclaration.cssText両方でCSSRule.cssTextしCSSStyleDeclaration.cssText 。
- CSSプロパティ名(
background-color
)をJSプロパティ名(backgroundColor
)に変換します。back%gr- -ound---color: red;
ような非常に不安定な名前でもback%gr- -ound---color: red;
(backGrOundColor
変換しbackGrOundColor
)。 - 単一の呼び出し
Object.assign(document.body.style, parseCSSText(cssText).style)
を使用して、既存のCSSStyleDeclarations (document.body.style
など)の一括変更を有効にします。 - プロパティ名が値なし(コロンなしのエントリ)であっても失敗しません。逆も同様です。
- 更新2017-09-28:ルール名でも新しい行を処理し、空白を折りたたみます。
- 更新2017-09-28:コメントを処理します(
/*...*/
)。
癖:
- ルール内の最後のCSS宣言がセミコロンで終わっている場合、返されるスタイルには空の名前
""
と、セミコロンに続くNULL文字列を反映したundefined
値を持つプロパティが含まれます。 それは正しい振る舞いだと思います。 - プロパティ値(文字列リテラル)にコロン、セミコロン、CSSのコメントが含まれている場合、関数は誤った結果を返し
div::before {content: 'test:test2;/*test3*/';}
例えばdiv::before {content: 'test:test2;/*test3*/';}
ます。 これを回避する方法がわかりません。 - 現時点では、
-somebrowser-someproperty
などの接頭辞を持つプロパティ名をSomebrowserSomeproperty
ではなく-somebrowser-someproperty
誤って変換します。 コードの簡潔さを損なわないような解決策が必要です。そのため、見つけるのに時間がかかります。
実例
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. */
<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>
CSSドキュメントがhtmlドキュメントに含まれていて、スタイル宣言が実際に読み込まれるようになっている場合は、Javascriptですべてのスタイルを次のように進めることができます。
// Get all style sheet documents in this html document
var allSheets = document.styleSheets;
for (var i = 0; i < allSheets.length; ++i) {
var sheet = allSheets[i];
// Get all CSS rules in the current style sheet document
var rules = sheet.cssRules || sheet.rules;
for (var j = 0; j < rules.length; ++j) {
var rule = rules[j];
// Get the selector definition ("div > p:first-child" for example)
var selector = rule.selectorText;
// Create an empty object to put the style definitions in
var result = {};
var style = rule.style;
for (var key in style) {
if (style.hasOwnProperty(key)) {
result[key] = style.cssText;
}
}
// At this point, you have the selector in the
// selector variable (".mybox" for example)
// You also have a javascript object in the
// result variable, containing what you need.
// If you need to output this as json, there
// are several options for this.
}
}
CSSドキュメントを解析してJavaScriptソースファイルを作成したい場合のように、これが望まない場合は、字句解析プログラム、CSSドキュメントオブジェクトモデル、JSONシリアライゼーションなどを検討する必要があります。
私はLeafLetがJavaScriptコードからCSSスタイルを分離しようとしているのと同じ問題を抱えています...私はこれで終わります:
var css = {};
for (var i = 0; i < document.styleSheets.length; ++i) {
var sheet = document.styleSheets[i];
for (var j = 0; j < sheet.cssRules.length; ++j) {
var rule = sheet.cssRules[j];
var cssText = rule.cssText.slice(rule.cssText.indexOf('{')+1);
var attrs = cssText.split(';');
var ruleSet = {};
for (var k = 0; k < attrs.length; ++k) {
var keyValue = attrs[k].split(':');
if (keyValue.length == 2) {
var key = keyValue[0].trim();
var value = keyValue[1].trim();
ruleSet[key] = value;
}
}
for (var testRule in ruleSet) { // We are going to add the rule iff it is not an empty object
css[rule.selectorText] = ruleSet;
break;
}
}
}
console.log(css);
これはこのような何かを生み出すでしょう: