我有一个带有以下css的字符串,我需要使用javascript
进行处理h1
{
color: red;
}
.info
{
border: 1px dotted blue;
padding: 10px;
}
#rect
{
background: pink;
}
h2,
h3,
h4
{
font-weight: bold;
}
table td:last td
{
background: gainsboro;
}
如何为每条规则添加前缀.page
,以便css不会中断?
我想要这个结果
.page h1
{
color: red;
}
.page .info
{
border: 1px dotted blue;
padding: 10px;
}
...
现在,我通过寻找缩进来解决它,但代码在这种情况下失败
h1
{
color: red;
}
然后以
结束.page h1
{
.page color: red;
}
我还可以查找只有括号的行,但这种情况会失败
h1 { color: red; }
我不想构建自己的css解析器,我发现它主要处理应用于DOM中元素的css而不是css中的字符串。有没有一个好的解析器,或者这可以实现吗?
答案 0 :(得分:2)
这是一个为所有选择器添加类名前缀的功能。此函数正确处理@规则:
var prefixCssSelectors = function(rules, className) {
var classLen = className.length,
char, nextChar, isAt, isIn;
// makes sure the className will not concatenate the selector
className += ' ';
// removes comments
rules = rules.replace( /\/\*(?:(?!\*\/)[\s\S])*\*\/|[\r\n\t]+/g, '' );
// makes sure nextChar will not target a space
rules = rules.replace( /}(\s*)@/g, '}@' );
rules = rules.replace( /}(\s*)}/g, '}}' );
for (var i = 0; i < rules.length-2; i++) {
char = rules[i];
nextChar = rules[i+1];
if (char === '@') isAt = true;
if (!isAt && char === '{') isIn = true;
if (isIn && char === '}') isIn = false;
if (
!isIn &&
nextChar !== '@' &&
nextChar !== '}' &&
(
char === '}' ||
char === ',' ||
((char === '{' || char === ';') && isAt)
)
) {
rules = rules.slice(0, i+1) + className + rules.slice(i+1);
i += classLen;
isAt = false;
}
};
// prefix the first select if it is not `@media` and if it is not yet prefixed
if (rules.indexOf(className) !== 0 && rules.indexOf('@') !== 0) rules = className+rules;
return rules;
}
// Some examples:
console.log(prefixCssSelectors('div { width: 100%; }', '.page'));
console.log(prefixCssSelectors('@charset "utf-8"; div { width: 100%; }', '.page'));
console.log(prefixCssSelectors('@media only screen { div { width: 100%; } p { size: 1.2rem; } } @media only print { p { size: 1.2rem; } } div { height: 100%; font-family: "Arial", Times; }', '.page'));
如果只想使用html
和body
选择器的类名,请添加以下内容:
rules = rules.replace(/( html| body)/g, '');
答案 1 :(得分:1)
您提出的问题是如何解决您认为实际问题的解决方案,这似乎是,如何将一些CSS仅应用于文档的某个部分?
最终,解决方案将是<style scoped>
。在我们等待的同时,您可以尝试使用https://github.com/PM5544/scoped-polyfill,http://thomaspark.co/2015/07/polyfill-for-scoped-css/,https://github.com/thingsinjars/jQuery-Scoped-CSS-plugin或https://github.com/thomaspark/scoper等填充。
如果您有一串CSS(顺便说一下,从哪里获得?),那么要使用这些polyfill,您只需在<style scoped>
元素下的.page
元素中插入add
元素,包含你在字符串中的CSS。
所有这些polyfill的主要优点是它们基于CSS,正如浏览器正确解析的那样,并且不会在出现问题的第一个迹象时破坏,因为你不可接受地接受的正则表达式解决方案,以及所有其他正则表达式解决方案,不可避免地将
答案 2 :(得分:0)
如果您使用sass,您只需编写类似
的内容即可.page {
h1 {
color: red;
}
h2 {
color: green;
}
}
这将被编译为您想要的。但如果这不是一个选项,你必须编写自己的解析器。
答案 3 :(得分:0)
一个解决方案,它循环遍历CSS规则并动态更新它们。
/* debug purpose */
var j = JSON.stringify;
var el = document.getElementById('el');
var log = function( val ){el.innerHTML+='<div>'+val+'</div>'}
var doIt = function(){
// you have to identify your stylesheet to get it
var ss = document.styleSheets[0];
// we get all the rules from this stylesheets
var rules = ss.cssRules;
// we loop over all rules
for( var i = 0 ; i < rules.length; i++){
var rule = rules[i];
var selector = rule.selectorText;
var def = rule.cssText.replace(selector , '');
// we update the selector
var selector2 = selector.replace(/([^,]+,?)/g , '.page $1 ' );
// we modify the rules on the fly !
var def2 = def.replace('red' , 'green');
def2 = def2.replace('blue' , 'red');
def2 = def2.replace('pink' , 'lime');
log(i);
log( 'def : ' + def);
log( 'modified : ' + def2);
log( 'selector : ' + selector);
log( 'updated : ' + selector2);
log('----------');
ss.deleteRule(i);// we remove the old
ss.insertRule(selector2 + def2 , i);// we add the new
};
// we check the stylecheet !
log( ' checking the results');
for( var i = 0 ; i < rules.length; i++){
var rule = rules[i];
var curRule = rule.cssText;
log( i + ': curRule => ' + curRule);
};
};
h1
{
color: red;
}
.info
{
border: 1px dotted blue;
padding: 10px;
}
#rect
{
background: pink;
}
h2,
h3,
h4
{
font-weight: bold;
}
table td:last td
{
background: gainsboro;
}
<div class='page'>
<div id='rect'> RECT </div>
<div class='info'> INFO </div>
<div>
<button onclick='doIt()'>update it</button>
<div id='el'><div>
答案 4 :(得分:-1)
看一下正则表达式
例如:
/([^]*?)({[^]*?}|,)/g
应捕获第一组中css字符串中的所有选择器,并捕获第二组中的规则。然后你做这样的事情来取代比赛
var str = "your css text here";
re = /([^]*?)({[^]*?}|,)/g;
var new_str = str.replace(re, ".prefix $1 $2"); //prefixed css
console.log(new_str);
如果您不熟悉正则表达式,我建议您阅读Eloquent Javascript
中的相关章节