Browse Source

Move CssComposer to TS

pull/4695/head
Artur Arseniev 4 years ago
parent
commit
91022e4267
  1. 132
      src/css_composer/index.ts
  2. 2
      src/css_composer/model/CssRule.ts
  3. 3
      src/domain_abstract/model/StyleableModel.ts

132
src/css_composer/index.js → src/css_composer/index.ts

@ -1,6 +1,6 @@
/** /**
* This module manages CSS rules in the canvas. * This module manages CSS rules in the canvas.
* You can customize the initial state of the module from the editor initialization, by passing the following [Configuration Object](https://github.com/artf/grapesjs/blob/master/src/css_composer/config/config.js) * You can customize the initial state of the module from the editor initialization, by passing the following [Configuration Object](https://github.com/artf/grapesjs/blob/master/src/css_composer/config/config.ts)
* ```js * ```js
* const editor = grapesjs.init({ * const editor = grapesjs.init({
* cssComposer: { * cssComposer: {
@ -29,50 +29,47 @@
import { isArray, isString, isUndefined } from 'underscore'; import { isArray, isString, isUndefined } from 'underscore';
import { isObject } from '../utils/mixins'; import { isObject } from '../utils/mixins';
import Module from '../abstract/moduleLegacy';
import Selectors from '../selector_manager/model/Selectors'; import Selectors from '../selector_manager/model/Selectors';
import Selector from '../selector_manager/model/Selector'; import Selector from '../selector_manager/model/Selector';
import defaults from './config/config'; import defaults, { CssComposerConfig } from './config/config';
import CssRule from './model/CssRule'; import CssRule, { CssRuleProperties } from './model/CssRule';
import CssRules from './model/CssRules'; import CssRules from './model/CssRules';
import CssRulesView from './view/CssRulesView'; import CssRulesView from './view/CssRulesView';
import { ItemManagerModule } from '../abstract/Module';
import EditorModel from '../editor/model/Editor';
import Component from '../dom_components/model/Component';
export default class CssComposer extends Module { type RuleOptions = {
Selectors = Selectors; atRuleType?: string;
atRuleParams?: string;
};
/** type CssRuleStyle = Required<CssRuleProperties>['style'];
* Name of the module type AnyObject = Record<string, any>;
* @type {String}
* @private
*/
name = 'CssComposer';
storageKey = 'styles'; export default class CssComposer extends ItemManagerModule<CssComposerConfig & { pStylePrefix?: string }> {
rules: CssRules;
rulesView?: CssRulesView;
getConfig() { Selectors = Selectors;
return this.c;
} storageKey = 'styles';
/** /**
* Initializes module. Automatically called with a new instance of the editor * Initializes module. Automatically called with a new instance of the editor
* @param {Object} config Configurations * @param {Object} config Configurations
* @private * @private
*/ */
init(config) { constructor(em: EditorModel) {
this.c = config || {}; super(em, 'CssComposer', null, {}, defaults);
for (var name in defaults) { const { config } = this;
if (!(name in this.c)) this.c[name] = defaults[name];
}
var ppfx = this.c.pStylePrefix; const ppfx = config.pStylePrefix;
if (ppfx) this.c.stylePrefix = ppfx + this.c.stylePrefix; if (ppfx) config.stylePrefix = ppfx + config.stylePrefix;
var elStyle = (this.c.em && this.c.em.config.style) || ''; config.rules = this.em.config.style || config.rules || '';
this.c.rules = elStyle || this.c.rules;
this.em = this.c.em; this.rules = new CssRules([], config);
this.rules = new CssRules([], this.c);
return this;
} }
/** /**
@ -80,7 +77,7 @@ export default class CssComposer extends Module {
* @private * @private
*/ */
onLoad() { onLoad() {
this.rules.add(this.c.rules, { silent: 1 }); this.rules.add(this.config.rules, { silent: true });
} }
/** /**
@ -97,7 +94,7 @@ export default class CssComposer extends Module {
return this.getProjectData(); return this.getProjectData();
} }
load(data) { load(data: any) {
return this.loadProjectData(data); return this.loadProjectData(data);
} }
@ -120,11 +117,11 @@ export default class CssComposer extends Module {
* color: '#fff', * color: '#fff',
* }); * });
* */ * */
add(selectors, state, width, opts = {}, addOpts = {}) { add(selectors: any, state?: string, width?: string, opts = {}, addOpts = {}) {
var s = state || ''; const s = state || '';
var w = width || ''; const w = width || '';
var opt = { ...opts }; const opt = { ...opts } as CssRuleProperties;
var rule = this.get(selectors, s, w, opt); let rule = this.get(selectors, s, w, opt);
// do not create rules that were found before // do not create rules that were found before
// unless this is a single at-rule, for which multiple declarations // unless this is a single at-rule, for which multiple declarations
@ -136,7 +133,8 @@ export default class CssComposer extends Module {
opt.mediaText = w; opt.mediaText = w;
opt.selectors = []; opt.selectors = [];
w && (opt.atRuleType = 'media'); w && (opt.atRuleType = 'media');
rule = new CssRule(opt, this.c); rule = new CssRule(opt, this.config);
// @ts-ignore
rule.get('selectors').add(selectors, addOpts); rule.get('selectors').add(selectors, addOpts);
this.rules.add(rule, addOpts); this.rules.add(rule, addOpts);
return rule; return rule;
@ -162,7 +160,7 @@ export default class CssComposer extends Module {
* color: '#000', * color: '#000',
* }); * });
* */ * */
get(selectors, state, width, ruleProps) { get(selectors: any, state?: string, width?: string, ruleProps?: Omit<CssRuleProperties, 'selectors'>) {
let slc = selectors; let slc = selectors;
if (isString(selectors)) { if (isString(selectors)) {
const sm = this.em.get('SelectorManager'); const sm = this.em.get('SelectorManager');
@ -173,6 +171,7 @@ export default class CssComposer extends Module {
return this.rules.find(rule => rule.compare(slc, state, width, ruleProps)) || null; return this.rules.find(rule => rule.compare(slc, state, width, ruleProps)) || null;
} }
// @ts-ignore
getAll() { getAll() {
return this.rules; return this.rules;
} }
@ -186,8 +185,8 @@ export default class CssComposer extends Module {
* @return {Array<Model>} * @return {Array<Model>}
* @private * @private
*/ */
addCollection(data, opts = {}, props = {}) { addCollection(data: string | CssRuleProperties[], opts: Record<string, any> = {}, props = {}) {
const result = []; const result: CssRule[] = [];
if (isString(data)) { if (isString(data)) {
data = this.em.get('Parser').parseCss(data); data = this.em.get('Parser').parseCss(data);
@ -196,28 +195,29 @@ export default class CssComposer extends Module {
const d = data instanceof Array ? data : [data]; const d = data instanceof Array ? data : [data];
for (var i = 0, l = d.length; i < l; i++) { for (var i = 0, l = d.length; i < l; i++) {
var rule = d[i] || {}; const rule = (d[i] || {}) as CssRuleProperties;
if (!rule.selectors) continue; if (!rule.selectors) continue;
var sm = this.em?.get('SelectorManager');
const sm = this.em?.get('SelectorManager');
if (!sm) console.warn('Selector Manager not found'); if (!sm) console.warn('Selector Manager not found');
var sl = rule.selectors; const sl = rule.selectors;
var sels = sl instanceof Array ? sl : [sl]; const sels = sl instanceof Array ? sl : [sl];
var newSels = []; const newSels = [];
for (var j = 0, le = sels.length; j < le; j++) { for (let j = 0, le = sels.length; j < le; j++) {
var selec = sm.add(sels[j]); const selec = sm.add(sels[j]);
newSels.push(selec); newSels.push(selec);
} }
var modelExists = this.get(newSels, rule.state, rule.mediaText, rule); const modelExists = this.get(newSels, rule.state, rule.mediaText, rule);
var model = this.add(newSels, rule.state, rule.mediaText, rule, opts); const model = this.add(newSels, rule.state, rule.mediaText, rule, opts);
var updateStyle = !modelExists || !opts.avoidUpdateStyle; const updateStyle = !modelExists || !opts.avoidUpdateStyle;
const style = rule.style || {}; const style = rule.style || {};
isObject(props) && model.set(props, opts); isObject(props) && model.set(props, opts);
if (updateStyle) { if (updateStyle) {
let styleUpdate = opts.extend ? { ...model.get('style'), ...style } : style; const styleUpdate = opts.extend ? { ...model.get('style'), ...style } : style;
model.set('style', styleUpdate, opts); model.set('style', styleUpdate, opts);
} }
@ -236,7 +236,7 @@ export default class CssComposer extends Module {
* // Check rules * // Check rules
* console.log(addedRules.map(rule => rule.toCSS())); * console.log(addedRules.map(rule => rule.toCSS()));
*/ */
addRules(css) { addRules(css: string) {
return this.addCollection(css); return this.addCollection(css);
} }
@ -262,7 +262,7 @@ export default class CssComposer extends Module {
* }); * });
* // output: @media (min-width: 500px) { .class1:hover { color: red } } * // output: @media (min-width: 500px) { .class1:hover { color: red } }
*/ */
setRule(selectors, style, opts = {}) { setRule(selectors: any, style: CssRuleProperties['style'], opts: RuleOptions = {}) {
const { atRuleType, atRuleParams } = opts; const { atRuleType, atRuleParams } = opts;
const node = this.em.get('Parser').parserCss.checkNode({ const node = this.em.get('Parser').parserCss.checkNode({
selectors, selectors,
@ -294,7 +294,7 @@ export default class CssComposer extends Module {
* atRuleParams: '(min-width: 500px)', * atRuleParams: '(min-width: 500px)',
* }); * });
*/ */
getRule(selectors, opts = {}) { getRule(selectors: any, opts: RuleOptions = {}) {
const sm = this.em.get('SelectorManager'); const sm = this.em.get('SelectorManager');
const node = this.em.get('Parser').parserCss.checkNode({ selectors })[0]; const node = this.em.get('Parser').parserCss.checkNode({ selectors })[0];
const selector = sm.get(node.selectors); const selector = sm.get(node.selectors);
@ -304,7 +304,7 @@ export default class CssComposer extends Module {
selector && selector &&
this.get(selector, state, atRuleParams, { this.get(selector, state, atRuleParams, {
selectorsAdd, selectorsAdd,
atRule: atRuleType, atRuleType,
}) })
); );
} }
@ -321,7 +321,7 @@ export default class CssComposer extends Module {
* // All rules in the project * // All rules in the project
* console.log(css.getRules()) * console.log(css.getRules())
*/ */
getRules(selector) { getRules(selector: string) {
const rules = this.getAll(); const rules = this.getAll();
if (!selector) return [...rules.models]; if (!selector) return [...rules.models];
const optRuleSel = { sort: true }; const optRuleSel = { sort: true };
@ -344,7 +344,7 @@ export default class CssComposer extends Module {
* // #myid { color: red } * // #myid { color: red }
* // #myid:hover { color: blue } * // #myid:hover { color: blue }
*/ */
setIdRule(name, style = {}, opts = {}) { setIdRule(name: string, style: CssRuleStyle = {}, opts: AnyObject = {}) {
const { addOpts = {}, mediaText } = opts; const { addOpts = {}, mediaText } = opts;
const state = opts.state || ''; const state = opts.state || '';
const media = !isUndefined(mediaText) ? mediaText : this.em.getCurrentMedia(); const media = !isUndefined(mediaText) ? mediaText : this.em.getCurrentMedia();
@ -365,7 +365,7 @@ export default class CssComposer extends Module {
* const rule = css.getIdRule('myid'); * const rule = css.getIdRule('myid');
* const ruleHover = css.setIdRule('myid', { state: 'hover' }); * const ruleHover = css.setIdRule('myid', { state: 'hover' });
*/ */
getIdRule(name, opts = {}) { getIdRule(name: string, opts: AnyObject = {}) {
const { mediaText } = opts; const { mediaText } = opts;
const state = opts.state || ''; const state = opts.state || '';
const media = !isUndefined(mediaText) ? mediaText : this.em.getCurrentMedia(); const media = !isUndefined(mediaText) ? mediaText : this.em.getCurrentMedia();
@ -387,7 +387,7 @@ export default class CssComposer extends Module {
* // .myclass { color: red } * // .myclass { color: red }
* // .myclass:hover { color: blue } * // .myclass:hover { color: blue }
*/ */
setClassRule(name, style = {}, opts = {}) { setClassRule(name: string, style: CssRuleStyle = {}, opts: AnyObject = {}) {
const state = opts.state || ''; const state = opts.state || '';
const media = opts.mediaText || this.em.getCurrentMedia(); const media = opts.mediaText || this.em.getCurrentMedia();
const sm = this.em.get('SelectorManager'); const sm = this.em.get('SelectorManager');
@ -407,7 +407,7 @@ export default class CssComposer extends Module {
* const rule = css.getClassRule('myclass'); * const rule = css.getClassRule('myclass');
* const ruleHover = css.getClassRule('myclass', { state: 'hover' }); * const ruleHover = css.getClassRule('myclass', { state: 'hover' });
*/ */
getClassRule(name, opts = {}) { getClassRule(name: string, opts: AnyObject = {}) {
const state = opts.state || ''; const state = opts.state || '';
const media = opts.mediaText || this.em.getCurrentMedia(); const media = opts.mediaText || this.em.getCurrentMedia();
const selector = this.em.get('SelectorManager').get(name, Selector.TYPE_CLASS); const selector = this.em.get('SelectorManager').get(name, Selector.TYPE_CLASS);
@ -425,7 +425,7 @@ export default class CssComposer extends Module {
* // Remove by selector * // Remove by selector
* css.remove('.my-cls-2'); * css.remove('.my-cls-2');
*/ */
remove(rule, opts) { remove(rule: string | CSSRule, opts?: any) {
const toRemove = isString(rule) ? this.getRules(rule) : rule; const toRemove = isString(rule) ? this.getRules(rule) : rule;
const result = this.getAll().remove(toRemove, opts); const result = this.getAll().remove(toRemove, opts);
return isArray(result) ? result : [result]; return isArray(result) ? result : [result];
@ -436,11 +436,11 @@ export default class CssComposer extends Module {
* @return {this} * @return {this}
*/ */
clear(opts = {}) { clear(opts = {}) {
this.getAll().reset(null, opts); this.getAll().reset([], opts);
return this; return this;
} }
getComponentRules(cmp, opts = {}) { getComponentRules(cmp: Component, opts: AnyObject = {}) {
let { state, mediaText, current } = opts; let { state, mediaText, current } = opts;
if (current) { if (current) {
state = this.em.get('state') || ''; state = this.em.get('state') || '';
@ -448,8 +448,8 @@ export default class CssComposer extends Module {
} }
const id = cmp.getId(); const id = cmp.getId();
const rules = this.getAll().filter(r => { const rules = this.getAll().filter(r => {
if (!isUndefined(state) && r.get('state') !== state) return; if (!isUndefined(state) && r.get('state') !== state) return false;
if (!isUndefined(mediaText) && r.get('mediaText') !== mediaText) return; if (!isUndefined(mediaText) && r.get('mediaText') !== mediaText) return false;
return r.getSelectorsString() === `#${id}`; return r.getSelectorsString() === `#${id}`;
}); });
return rules; return rules;
@ -464,7 +464,7 @@ export default class CssComposer extends Module {
this.rulesView?.remove(); this.rulesView?.remove();
this.rulesView = new CssRulesView({ this.rulesView = new CssRulesView({
collection: this.rules, collection: this.rules,
config: this.c, config: this.config,
}); });
return this.rulesView.render().el; return this.rulesView.render().el;
} }
@ -473,7 +473,5 @@ export default class CssComposer extends Module {
this.rules.reset(); this.rules.reset();
this.rules.stopListening(); this.rules.stopListening();
this.rulesView?.remove(); this.rulesView?.remove();
[this.em, this.rules, this.rulesView].forEach(i => (i = null));
this.c = {};
} }
} }

2
src/css_composer/model/CssRule.ts

@ -326,7 +326,7 @@ export default class CssRule extends StyleableModel<CssRuleProperties> {
* @returns {Boolean} * @returns {Boolean}
* @private * @private
*/ */
compare(selectors: any, state: string, width: string, ruleProps: Partial<CssRuleProperties> = {}) { compare(selectors: any, state?: string, width?: string, ruleProps: Partial<CssRuleProperties> = {}) {
const st = state || ''; const st = state || '';
const wd = width || ''; const wd = width || '';
const selAdd = ruleProps.selectorsAdd || ''; const selAdd = ruleProps.selectorsAdd || '';

3
src/domain_abstract/model/StyleableModel.ts

@ -3,6 +3,7 @@ import { shallowDiff } from '../../utils/mixins';
import ParserHtml from '../../parser/model/ParserHtml'; import ParserHtml from '../../parser/model/ParserHtml';
import { Model } from '../../common'; import { Model } from '../../common';
import { ObjectHash } from 'backbone'; import { ObjectHash } from 'backbone';
import Selectors from '../../selector_manager/model/Selectors';
type AnyObject = Record<string, any>; type AnyObject = Record<string, any>;
@ -128,7 +129,7 @@ export default class StyleableModel<T extends ObjectHash = any> extends Model<T>
} }
getSelectors() { getSelectors() {
return this.get('selectors') || this.get('classes'); return (this.get('selectors') || this.get('classes')) as Selectors;
} }
getSelectorsString(opts?: AnyObject) { getSelectorsString(opts?: AnyObject) {

Loading…
Cancel
Save