Browse Source

Add selectorsAdd property to CSS rules for additional selectors

This will allow to contain not class-based rules inside.
From: `.class1 .class2, .class3.class4 { color:red }`
To: `
  {
    selectors: ['class3', 'class4'],
    selectorsAdd: '.class1 .class2',
    style: { color: 'red'}
  }
`
pull/80/head
Artur Arseniev 9 years ago
parent
commit
550b33c49f
  1. 46
      src/parser/model/ParserCss.js
  2. 23
      test/specs/parser/model/ParserCss.js

46
src/parser/model/ParserCss.js

@ -6,16 +6,21 @@ define(function(require) {
/**
* Parse selector string to array.
* Only concatenated classes are valid as CSS rules inside editor.
* Only classe based are valid as CSS rules inside editor, not valid
* selectors will be dropped as additional
* It's ok with the last part of the string as state (:hover, :active)
* @param {string} str Selectors string
* @return {Array<Array>}
* @return {Object}
* @example
* var res = ParserCss.parseSelector('.test1, .test1.test2, .test2.test3');
* var res = ParserCss.parseSelector('.test1, .test1.test2, .test2 .test3');
* console.log(res);
* // [['test1'], ['test1', 'test2'], ['test2', 'test3']]
* // {
* //result: [['test1'], ['test1', 'test2']],
* //add: ['.test2 .test3']
* //}
*/
parseSelector: function(str){
parseSelector: function(str) {
var add = [];
var result = [];
var sels = str.split(',');
for (var i = 0, len = sels.length; i < len; i++) {
@ -25,9 +30,14 @@ define(function(require) {
if (/^(\.{1}[\w\-]+)+(:{1,2}[\w\-()]+)?$/ig.test(sel)) {
var cls = sel.split('.').filter(Boolean);
result.push(cls);
} else {
add.push(sel);
}
}
return result;
return {
result: result,
add: add,
};
},
/**
@ -42,6 +52,7 @@ define(function(require) {
for (var i = 0, len = nodes.length; i < len; i++) {
var node = nodes[i];
var sels = node.selectorText;
var selsAdd = [];
// It's a CSSMediaRule
if(node.cssRules) {
@ -61,15 +72,18 @@ define(function(require) {
if(!sels)
continue;
sels = this.parseSelector(sels);
var selsParsed = this.parseSelector(sels);
sels = selsParsed.result;
selsAdd = selsParsed.add;
// Create style object from the big one
var stl = node.style;
var style = {};
for(var j = 0, len2 = stl.length; j < len2; j++){
for (var j = 0, len2 = stl.length; j < len2; j++) {
style[stl[j]] = stl[stl[j]];
}
var lastRule;
// For each group of selectors
for (var k = 0, len3 = sels.length; k < len3; k++) {
var selArr = sels[k];
@ -85,9 +99,25 @@ define(function(require) {
model.selectors = selArr;
model.style = style;
lastRule = model;
result.push(model);
}
// Need to push somewhere not class-based selectors, if some rule was
// created will push them there, otherwise will create a new rule
if (selsAdd.length) {
var selsAddStr = selsAdd.join(', ');
if (lastRule) {
lastRule.selectorsAdd = selsAddStr;
} else {
result.push({
selectors: [],
selectorsAdd: selsAddStr,
style: style,
});
}
}
}
return result;

23
test/specs/parser/model/ParserCss.js

@ -153,6 +153,29 @@ define([path + 'model/ParserCss',],
obj.parse(str).should.deep.equal(result);
});
it('Parse rules with not class-based selectors', function() {
var str = ' .class1 .class2, div > .class3 { color:red }';
var result = {
selectors: [],
selectorsAdd: '.class1 .class2, div > .class3',
style: { color: 'red'}
};
obj.parse(str).should.deep.equal(result);
});
it.only('Parse rule with mixed selectors', function() {
var str = ' .class1 .class2, .class3, div > .class4, .class5.class6 { color:red }';
var result = [{
selectors: ['class3'],
style: { color: 'red'}
},{
selectors: ['class5', 'class6'],
selectorsAdd: '.class1 .class2, div > .class4',
style: { color: 'red'}
}];
obj.parse(str).should.deep.equal(result);
});
});
}

Loading…
Cancel
Save