diff --git a/src/code_manager/main.js b/src/code_manager/main.js index e88de7755..a7a9c4d4f 100644 --- a/src/code_manager/main.js +++ b/src/code_manager/main.js @@ -2,7 +2,7 @@ define(function(require) { /** * @class CodeManager * @param {Object} Configurations - * + * * @return {Object} * */ function CodeManager(config) @@ -21,38 +21,38 @@ define(function(require) { if (!(name in c)) c[name] = defaults[name]; } - + this.gi = new gInterface(); this.generators = {}; this.defaultGenerators = {}; this.currentGenerator = null; - + this.ei = new eInterface(); this.editors = {}; this.defaultEditors = {}; this.currentEditor = null; - + var geHtml = new gHtml(), geCss = new gCss(), geJson = new gJson(), edCM = new eCM(); - + this.defaultGenerators[geHtml.getId()] = geHtml; this.defaultGenerators[geCss.getId()] = geCss; this.defaultGenerators[geJson.getId()] = geJson; - + this.defaultEditors[edCM.getId()] = edCM; - + this.EditorView = editorView; this.config = c; } - + CodeManager.prototype = { - + /** * Add new code generator * @param {GeneratorInterface} generator - * + * * @return this * */ addGenerator : function(generator) @@ -63,43 +63,43 @@ define(function(require) { console.warn("addGenerator: method '"+ method +"' was not found"); return; } - + var id = generator.getId(); this.generators[id] = generator; - + if(!this.currentGenerator) this.currentGenerator = id; - + return this; }, - + /** * Returns generator * @param {String}|{Integer} id Generator ID - * + * * @return {GeneratorInterface}|null * */ getGenerator : function(id) { if(id && this.generators[id]) generator = this.generators[id]; - + return generator ? generator : null; }, - + /** * Returns generators - * + * * @return {Array} * */ getGenerators : function() { return this.generators; }, - + /** * Get current generator - * + * * @return {GeneratorInterface} * */ getCurrentGenerator : function() @@ -108,11 +108,11 @@ define(function(require) { this.loadDefaultGenerators(); return this.getGenerator(this.currentGenerator); }, - + /** * Set current generator * @param {Integer} id Generator ID - * + * * @return this * */ setCurrentGenerator : function(id) @@ -120,10 +120,10 @@ define(function(require) { this.currentGenerator = id; return this; }, - + /** * Load default generators - * + * * @return this * */ loadDefaultGenerators : function() @@ -131,14 +131,14 @@ define(function(require) { for (var id in this.defaultGenerators) { this.addGenerator(this.defaultGenerators[id]); } - + return this; }, - + /** * Add new editor * @param {EditorInterface} editor - * + * * @return this * */ addEditor : function(editor) @@ -149,43 +149,43 @@ define(function(require) { console.warn("addEditor: method '"+ method +"' was not found"); return; } - + var id = editor.getId(); this.editors[id] = editor; - + if(!this.currentEditor) this.currentEditor = id; - + return this; }, - + /** * Returns editor * @param {String}|{Integer} id Editor ID - * + * * @return {EditorInterface}|null * */ getEditor : function(id) { if(id && this.editors[id]) editor = this.editors[id]; - + return editor ? editor : null; }, - + /** * Returns editors - * + * * @return {Array} * */ getEditors : function() { return this.editors; }, - + /** * Get current editor - * + * * @return {EditorInterface} * */ getCurrentEditor : function() @@ -194,11 +194,11 @@ define(function(require) { this.loadDefaultEditors(); return this.getEditor(this.currentEditor); }, - + /** * Set current editor * @param {Integer} id Editor ID - * + * * @return this * */ setCurrentEditor : function(id) @@ -206,10 +206,10 @@ define(function(require) { this.currentEditor = id; return this; }, - + /** * Load default editors - * + * * @return this * */ loadDefaultEditors : function() @@ -217,38 +217,38 @@ define(function(require) { for (var id in this.defaultEditors) { this.addEditor(this.defaultEditors[id]); } - + return this; }, - + /** * Get code by name * @param {Backbone.Model} model Model * @param {String}|{Integer} v Id of code generator - * + * * @return {String}|null * */ - getCode : function(model, v) + getCode : function(model, v, em) { var id = v || this.currentGenerator, generator = this.generators[id]; - return generator ? generator.build(model) : null; + return generator ? generator.build(model, em) : null; }, - + /** * Update editor content * @param {EditorInteface} editor Editor * @param {String} code Code value - * + * * @return void * */ updateEditor : function(editor, code) { editor.setContent(code); }, - - + + }; - + return CodeManager; }); \ No newline at end of file diff --git a/src/code_manager/model/CssGenerator.js b/src/code_manager/model/CssGenerator.js index 60162cffb..b7419f0ab 100644 --- a/src/code_manager/model/CssGenerator.js +++ b/src/code_manager/model/CssGenerator.js @@ -1,44 +1,71 @@ -define(['backbone'], +define(['backbone'], function (Backbone) { /** * @class CssGenerator * */ return Backbone.Model.extend({ - + + initialize: function(){ + this.printed = []; + }, + /** @inheritdoc */ getId : function() { - return 'css'; + return 'css'; }, - + /** @inheritdoc */ - build: function(model) + build: function(model, cssc) { - var coll = model.get('components') || model, code = ''; - + coll.each(function(m){ - var css = m.get('style'), - cln = m.get('components'); // Children - + var css = m.get('style'), + cls = m.get('classes'), + cln = m.get('components'); + + // Get id-relative style if(css && Object.keys(css).length !== 0){ code += '#' + m.cid + '{'; - + for(var prop in css) if(css.hasOwnProperty(prop)) - code += prop + ': ' + css[prop] + ';'; - + code += prop + ':' + css[prop] + ';'; + code += '}'; } - + + if(cssc && cls.length){ + var rule = cssc.getRule(cls.models); + if(rule){ + var selectors = rule.get('selectors'); + var ruleStyle = rule.get('style'); + var strSel = ''; + selectors.each(function(selector){ + strSel += '.' + selector.get('name'); + }); + if(this.printed.indexOf(strSel) < 0){ + this.printed.push(strSel); + code += strSel + '{'; + if(ruleStyle && Object.keys(ruleStyle).length !== 0){ + for(var prop2 in ruleStyle) + if(ruleStyle.hasOwnProperty(prop2)) + code += prop2 + ':' + ruleStyle[prop2] + ';'; + } + code += '}'; + } + } + } + if(cln.length) - code += this.build(cln); - + code += this.build(cln, cssc); + }, this); - + return code; }, - + }); }); diff --git a/src/code_manager/model/HtmlGenerator.js b/src/code_manager/model/HtmlGenerator.js index a1ea8450a..acd1c89b2 100644 --- a/src/code_manager/model/HtmlGenerator.js +++ b/src/code_manager/model/HtmlGenerator.js @@ -16,15 +16,18 @@ define(['backbone'], code = ''; coll.each(function(m){ - var tag = m.get('tagName'), // Tag name - sTag = 0, // Single tag - attr = '', // Attributes string - cln = m.get('components'); // Children - - _.each(m.get('attributes'),function(value, prop){ + var tag = m.get('tagName'), // Tag name + sTag = 0, // Single tag + attr = '', // Attributes string + attrId = '', + strCls = '', + cln = m.get('components'), // Children + attrs = m.get('attributes'), + classes = m.get('classes'); + _.each(attrs,function(value, prop){ if(prop == 'onmousedown') return; - attr += value && prop!='style' ? ' ' + prop + '="' + value + '" ' : ''; + attr += value && prop!='style' ? ' ' + prop + '="' + value + '"' : ''; }); if(m.get('type') == 'image'){ @@ -33,7 +36,15 @@ define(['backbone'], attr += 'src="' + m.get('src') + '"'; } - code += '<'+tag+' id="'+m.cid+'"' + attr + (sTag ? '/' : '') + '>' + m.get('content'); + if(!_.isEmpty(m.get('style'))) + attrId = ' id="' + m.cid + '" '; + + classes.each(function(m){ + strCls += ' ' + m.get('name'); + }); + + strCls = strCls !== '' ? ' class="' + strCls.trim() + '"' : ''; + code += '<' + tag + strCls + attrId + attr + (sTag ? '/' : '') + '>' + m.get('content'); if(cln.length) code += this.build(cln); diff --git a/src/commands/view/ExportTemplate.js b/src/commands/view/ExportTemplate.js index 1da11c0cf..b972cc0a8 100644 --- a/src/commands/view/ExportTemplate.js +++ b/src/commands/view/ExportTemplate.js @@ -9,6 +9,7 @@ define(function() { this.components = em.get('Canvas').getWrapper().get('components'); this.modal = em.get('Modal') || null; this.cm = em.get('CodeManager') || null; + this.cssc = em.get('CssComposer') || null; this.enable(); }, @@ -62,7 +63,8 @@ define(function() { } this.htmlEditor.setContent( this.cm.getCode(this.components, 'html') ); - this.cssEditor.setContent( this.cm.getCode(this.components, 'css') ); + this.cm.getGenerator('css').printed = []; + this.cssEditor.setContent( this.cm.getCode(this.components, 'css', this.cssc)); if(this.sender) this.sender.set('active',false); diff --git a/test/runner/main.js b/test/runner/main.js index 45ac312fe..b7ed5ace2 100644 --- a/test/runner/main.js +++ b/test/runner/main.js @@ -14,6 +14,7 @@ require(['../src/config/require-config.js', 'config/config.js'], function() { 'specs/dom_components/main.js', 'specs/class_manager/main.js', 'specs/css_composer/main.js', + 'specs/code_manager/main.js', ], function(chai) { var should = chai.should(), diff --git a/test/specs/code_manager/main.js b/test/specs/code_manager/main.js new file mode 100644 index 000000000..d8af9d133 --- /dev/null +++ b/test/specs/code_manager/main.js @@ -0,0 +1,39 @@ +var modulePath = './../../../test/specs/code_manager'; + +define([ + 'CodeManager', + modulePath + '/model/CodeModels', + //modulePath + '/view/ClassTagView', + //modulePath + '/view/ClassTagsView', + //modulePath + '/e2e/ClassManager' + ], + function( + CodeManager, + Models + ) { + + describe('Code Manager', function() { + + describe('Main', function() { + + beforeEach(function () { + this.obj = new CodeManager(); + }); + + afterEach(function () { + delete this.obj; + }); + + it('Object exists', function() { + CodeManager.should.be.exist; + }); + + }); + + Models.run(); + //ClassTagView.run(); + //ClassTagsView.run(); + //e2e.run(); + + }); +}); \ No newline at end of file diff --git a/test/specs/code_manager/model/CodeModels.js b/test/specs/code_manager/model/CodeModels.js new file mode 100644 index 000000000..95370ac23 --- /dev/null +++ b/test/specs/code_manager/model/CodeModels.js @@ -0,0 +1,106 @@ +var path = 'CodeManager/model/'; +define([path + 'HtmlGenerator', + path + 'CssGenerator', + 'DomComponents/model/Component', + 'CssComposer'], + function(HtmlGenerator, CssGenerator, Component, CssComposer) { + + return { + run : function(){ + describe('HtmlGenerator', function() { + beforeEach(function () { + this.obj = new HtmlGenerator(); + }); + + afterEach(function () { + delete this.obj; + }); + + it('Build correctly one component', function() { + var comp = new Component(); + this.obj.build(comp).should.equal(''); + }); + + it('Build correctly empty component inside', function() { + var comp = new Component(); + var m1 = comp.get('components').add({}); + this.obj.build(comp).should.equal('
'); + }); + + it('Build correctly not empty component inside', function() { + var comp = new Component(); + var m1 = comp.get('components').add({ + tagName: 'article', + attributes: { + 'data-test1': 'value1', + 'data-test2': 'value2' + } + }); + this.obj.build(comp).should.equal('
'); + }); + + it('Build correctly component with classes', function() { + var comp = new Component(); + var m1 = comp.get('components').add({ + tagName: 'article', + attributes: { + 'data-test1': 'value1', + 'data-test2': 'value2' + } + }); + ['class1', 'class2'].forEach(function(item){ + m1.get('classes').add({name: item}); + }); + this.obj.build(comp).should.equal('
'); + }); + }); + + describe('CssGenerator', function() { + beforeEach(function () { + this.obj = new CssGenerator(); + }); + + afterEach(function () { + delete this.obj; + }); + + it('Build correctly one component', function() { + var comp = new Component(); + this.obj.build(comp).should.equal(''); + }); + + it('Build correctly empty component inside', function() { + var comp = new Component(); + var m1 = comp.get('components').add({tagName: 'article'}); + this.obj.build(comp).should.equal(''); + }); + + it('Build correctly component with style inside', function() { + var comp = new Component(); + var m1 = comp.get('components').add({ + tagName: 'article', + style: { + 'prop1': 'value1', + 'prop2': 'value2' + } + }); + this.obj.build(comp).should.equal('#' + m1.cid +'{prop1:value1;prop2:value2;}'); + }); + + it('Build correctly component with class styled', function() { + var comp = new Component(); + var m1 = comp.get('components').add({tagName: 'article'}); + var cls1 = m1.get('classes').add({name: 'class1'}); + + var cssc = new CssComposer(); + var rule = cssc.newRule(cls1); + rule.set('style',{'prop1':'value1', 'prop2':'value2'}); + cssc.addRule(rule); + + this.obj.build(comp, cssc).should.equal('.class1{prop1:value1;prop2:value2;}'); + }); + }) + } + }; + +}); \ No newline at end of file