From 4e0c1187c03dd650cef69b7e33f347fbef2a5a70 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Sat, 8 Apr 2017 15:53:43 +0200 Subject: [PATCH] Add the possibility to import also not class based selectors. Those selectors won't be selectable but this will avoid a lot of pitfalls --- src/code_manager/model/CssGenerator.js | 290 ++++++++++---------- test/specs/code_manager/model/CodeModels.js | 23 +- 2 files changed, 169 insertions(+), 144 deletions(-) diff --git a/src/code_manager/model/CssGenerator.js b/src/code_manager/model/CssGenerator.js index b7166a08c..c8cdb2006 100644 --- a/src/code_manager/model/CssGenerator.js +++ b/src/code_manager/model/CssGenerator.js @@ -1,145 +1,149 @@ define(['backbone'], - function (Backbone) { - /** - * @class CssGenerator - * */ - return Backbone.Model.extend({ - - initialize: function() { - this.compCls = []; - }, - - /** - * Get CSS from component - * @param {Model} model - * @return {String} - */ - buildFromModel: function (model) { - var code = ''; - var style = model.get('style'); - var classes = model.get('classes'); - - // Let's know what classes I've found - if(classes) { - classes.each(function(model){ - this.compCls.push(model.get('name')); - }, this); - } - - if(style && Object.keys(style).length !== 0) { - code += '#' + model.cid + '{'; - for(var prop in style){ - if(style.hasOwnProperty(prop)) - code += prop + ':' + style[prop] + ';'; - } - code += '}'; - } - - return code; - }, - - /** - * Get CSS from components - * @param {Model} model - * @return {String} - */ - buildFromComp: function(model) { - var coll = model.get('components') || model, - code = ''; - - coll.each(function(m) { - var cln = m.get('components'); - code += this.buildFromModel(m); - - if(cln.length){ - code += this.buildFromComp(cln); - } - - }, this); - - return code; - }, - - /** @inheritdoc */ - build: function(model, cssc) { - this.compCls = []; - var code = this.buildFromModel(model); - code += this.buildFromComp(model); - var compCls = this.compCls; - - if(cssc){ - var rules = cssc.getAll(); - var mediaRules = {}; - rules.each(function(rule){ - var width = rule.get('maxWidth'); - - // If width setted will render it later - if(width){ - var mRule = mediaRules[width]; - if(mRule) - mRule.push(rule); - else - mediaRules[width] = [rule]; - return; - } - - code += this.buildFromRule(rule); - }, this); - - // Get media rules - for (var ruleW in mediaRules) { - var meRules = mediaRules[ruleW]; - var ruleC = ''; - for(var i = 0, len = meRules.length; i < len; i++){ - ruleC += this.buildFromRule(meRules[i]); - } - if(ruleC) - code += '@media (max-width: ' + ruleW + '){' + ruleC + '}'; - } - - } - return code; - }, - - /** - * Get CSS from the rule model - * @param {Model} rule - * @return {string} CSS string - */ - buildFromRule: function(rule) { - var result = ''; - var selectors = rule.get('selectors'); - var ruleStyle = rule.get('style'); - var state = rule.get('state'); - var strSel = ''; - var found = 0; - var compCls = this.compCls; - - // Get string of selectors - selectors.each(function(selector){ - strSel += '.' + selector.get('name'); - if(compCls.indexOf(selector.get('name')) > -1) - found = 1; - }); - - if(strSel && found){ - strSel += state ? ':' + state : ''; - var strStyle = ''; - - // Get string of style properties - if(ruleStyle && Object.keys(ruleStyle).length !== 0){ - for(var prop2 in ruleStyle){ - if(ruleStyle.hasOwnProperty(prop2)) - strStyle += prop2 + ':' + ruleStyle[prop2] + ';'; - } - } - - if(strStyle) - result += strSel + '{' + strStyle + '}'; - } - - return result; - }, - - }); + function (Backbone) { + /** + * @class CssGenerator + * */ + return Backbone.Model.extend({ + + initialize: function() { + this.compCls = []; + }, + + /** + * Get CSS from component + * @param {Model} model + * @return {String} + */ + buildFromModel: function (model) { + var code = ''; + var style = model.get('style'); + var classes = model.get('classes'); + + // Let's know what classes I've found + if(classes) { + classes.each(function(model){ + this.compCls.push(model.get('name')); + }, this); + } + + if(style && Object.keys(style).length !== 0) { + code += '#' + model.cid + '{'; + for(var prop in style){ + if(style.hasOwnProperty(prop)) + code += prop + ':' + style[prop] + ';'; + } + code += '}'; + } + + return code; + }, + + /** + * Get CSS from components + * @param {Model} model + * @return {String} + */ + buildFromComp: function(model) { + var coll = model.get('components') || model, + code = ''; + + coll.each(function(m) { + var cln = m.get('components'); + code += this.buildFromModel(m); + + if(cln.length){ + code += this.buildFromComp(cln); + } + + }, this); + + return code; + }, + + /** @inheritdoc */ + build: function(model, cssc) { + this.compCls = []; + var code = this.buildFromModel(model); + code += this.buildFromComp(model); + var compCls = this.compCls; + + if(cssc){ + var rules = cssc.getAll(); + var mediaRules = {}; + rules.each(function(rule){ + var width = rule.get('maxWidth'); + + // If width setted will render it later + if(width){ + var mRule = mediaRules[width]; + if(mRule) + mRule.push(rule); + else + mediaRules[width] = [rule]; + return; + } + + code += this.buildFromRule(rule); + }, this); + + // Get media rules + for (var ruleW in mediaRules) { + var meRules = mediaRules[ruleW]; + var ruleC = ''; + for(var i = 0, len = meRules.length; i < len; i++){ + ruleC += this.buildFromRule(meRules[i]); + } + if(ruleC) + code += '@media (max-width: ' + ruleW + '){' + ruleC + '}'; + } + + } + return code; + }, + + /** + * Get CSS from the rule model + * @param {Model} rule + * @return {string} CSS string + */ + buildFromRule: function(rule) { + var result = ''; + var selectorsAdd = rule.get('selectorsAdd'); + var selectors = rule.get('selectors'); + var ruleStyle = rule.get('style'); + var state = rule.get('state'); + var strSel = ''; + var found = 0; + var compCls = this.compCls; + + // Get string of selectors + selectors.each(function(selector){ + strSel += '.' + selector.get('name'); + if(compCls.indexOf(selector.get('name')) > -1) + found = 1; + }); + + // With 'found' will skip rules which selectors are not found in + // canvas components. + if ((strSel && found) || selectorsAdd) { + strSel += state ? ':' + state : ''; + strSel += selectorsAdd ? (strSel ? ', ' : '') + selectorsAdd : ''; + var strStyle = ''; + + // Get string of style properties + if(ruleStyle && Object.keys(ruleStyle).length !== 0){ + for(var prop2 in ruleStyle){ + if(ruleStyle.hasOwnProperty(prop2)) + strStyle += prop2 + ':' + ruleStyle[prop2] + ';'; + } + } + + if(strStyle) + result += strSel + '{' + strStyle + '}'; + } + + return result; + }, + + }); }); diff --git a/test/specs/code_manager/model/CodeModels.js b/test/specs/code_manager/model/CodeModels.js index 9ce02e874..36e17071e 100644 --- a/test/specs/code_manager/model/CodeModels.js +++ b/test/specs/code_manager/model/CodeModels.js @@ -128,7 +128,28 @@ define([path + 'HtmlGenerator', rule.set('style',{'prop1':'value1', 'prop2':'value2'}); this.obj.build(comp, cssc).should.equal('.class1.class2{prop1:value1;prop2:value2;}'); - this.obj.build(comp, cssc).should.equal('.class1.class2{prop1:value1;prop2:value2;}'); + }); + + it('Build rules with mixed classes', function() { + var m1 = comp.get('components').add({tagName: 'article'}); + var cls1 = m1.get('classes').add({name: 'class1'}); + var cls2 = m1.get('classes').add({name: 'class2'}); + + var cssc = newCssComp(); + var rule = cssc.add([cls1, cls2]); + rule.set('style',{'prop1':'value1', 'prop2':'value2'}); + rule.set('selectorsAdd', '.class1 .class2, div > .class4'); + + this.obj.build(comp, cssc).should.equal('.class1.class2, .class1 .class2, div > .class4{prop1:value1;prop2:value2;}'); + }); + + it('Build rules with only not class based selectors', function() { + var cssc = newCssComp(); + var rule = cssc.add([]); + rule.set('style',{'prop1':'value1', 'prop2':'value2'}); + rule.set('selectorsAdd', '.class1 .class2, div > .class4'); + + this.obj.build(comp, cssc).should.equal('.class1 .class2, div > .class4{prop1:value1;prop2:value2;}'); }); it('Build correctly with class styled out', function() {