From 5b4963e4a592d9d57a810eb47d6ea18976c75604 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Sun, 8 Nov 2020 22:18:48 +0100 Subject: [PATCH] Clone properly the component with its related styles. FIxes #3093 --- src/commands/view/CopyComponent.js | 5 +---- src/css_composer/index.js | 18 ++++++++++++++++++ src/css_composer/model/CssRule.js | 8 ++++++++ src/dom_components/model/Component.js | 16 +++++++++++----- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/commands/view/CopyComponent.js b/src/commands/view/CopyComponent.js index e5900a304..49e98be60 100644 --- a/src/commands/view/CopyComponent.js +++ b/src/commands/view/CopyComponent.js @@ -2,9 +2,6 @@ export default { run(ed) { const em = ed.getModel(); const models = [...ed.getSelectedAll()]; - - if (models.length) { - em.set('clipboard', models); - } + models.length && em.set('clipboard', models); } }; diff --git a/src/css_composer/index.js b/src/css_composer/index.js index 252034955..a07c2fc8d 100644 --- a/src/css_composer/index.js +++ b/src/css_composer/index.js @@ -373,6 +373,24 @@ export default () => { ); }, + /** + * Find rules, in different states (eg. like `:hover`) and media queries, matching the selector. + * @param {string} selector Selector, eg. '.myclass' + * @returns {Array} + * @example + * // Common scenario, take all the component specific rules + * const id = someComponent.getId(); + * const rules = cc.getRules(`#${id}`); + * console.log(rules.map(rule => rule.toCSS())) + */ + getRules(selector) { + const rules = this.getAll(); + const result = rules.filter( + r => r.getSelectors().getFullString() === selector + ); + return result; + }, + /** * Add/update the CSS rule with id selector * @param {string} name Id selector name, eg. 'my-id' diff --git a/src/css_composer/model/CssRule.js b/src/css_composer/model/CssRule.js index 0f1646a0b..973902de6 100644 --- a/src/css_composer/model/CssRule.js +++ b/src/css_composer/model/CssRule.js @@ -41,10 +41,18 @@ export default Backbone.Model.extend(Styleable).extend({ initialize(c, opt = {}) { this.config = c || {}; + this.opt = opt; this.em = opt.em; this.ensureSelectors(); }, + clone() { + const opts = { ...this.opt }; + const attr = { ...this.attributes }; + attr.selectors = this.get('selectors').map(s => s.clone()); + return new this.constructor(attr, opts); + }, + ensureSelectors() { const { em } = this; const result = []; diff --git a/src/dom_components/model/Component.js b/src/dom_components/model/Component.js index ff5172442..23f50e345 100644 --- a/src/dom_components/model/Component.js +++ b/src/dom_components/model/Component.js @@ -861,9 +861,10 @@ const Component = Backbone.Model.extend(Styleable).extend( */ clone() { const em = this.em; - const style = this.getStyle(); const attr = { ...this.attributes }; const opts = { ...this.opt }; + const id = this.getId(); + const cssc = em && em.get('CssComposer'); attr.attributes = { ...attr.attributes }; delete attr.attributes.id; attr.components = []; @@ -884,15 +885,20 @@ const Component = Backbone.Model.extend(Styleable).extend( attr.view = ''; opts.collection = null; - if (em && em.getConfig('avoidInlineStyle') && !isEmpty(style)) { - attr.style = style; - } - const cloned = new this.constructor(attr, opts); const event = 'component:clone'; em && em.trigger(event, cloned); this.trigger(event, cloned); + // Clone component specific rules + const newId = `#${cloned.getId()}`; + const rulesToClone = cssc ? cssc.getRules(`#${id}`) : []; + rulesToClone.forEach(rule => { + const newRule = rule.clone(); + newRule.set('selectors', [newId]); + cssc.getAll().add(newRule); + }); + return cloned; },