Browse Source

Avoid default strict name escaping for Selector names #5994

pull/6013/head
Artur Arseniev 2 years ago
parent
commit
99dfa6b6a1
  1. 18
      src/css_composer/model/CssRule.ts
  2. 20
      src/selector_manager/model/Selector.ts
  3. 6
      test/specs/selector_manager/model/SelectorModels.ts

18
src/css_composer/model/CssRule.ts

@ -128,14 +128,14 @@ export default class CssRule extends StyleableModel<CssRuleProperties> {
clone(): CssRule { clone(): CssRule {
const opts = { ...this.opt }; const opts = { ...this.opt };
const attr = { ...this.attributes }; const attr = { ...this.attributes };
attr.selectors = this.get('selectors')!.map(s => s.clone()) as Selector[]; attr.selectors = this.get('selectors')!.map(s => s.clone() as Selector);
// @ts-ignore // @ts-ignore
return new this.constructor(attr, opts); return new this.constructor(attr, opts);
} }
ensureSelectors(m: any, c: any, opts: any) { ensureSelectors(m: any, c: any, opts: any) {
const { em } = this; const { em } = this;
const sm = em?.get('SelectorManager'); const sm = em?.Selectors;
const toListen = [this, 'change:selectors', this.ensureSelectors]; const toListen = [this, 'change:selectors', this.ensureSelectors];
let sels = this.getSelectors() as any; let sels = this.getSelectors() as any;
this.stopListening(...toListen); this.stopListening(...toListen);
@ -193,7 +193,7 @@ export default class CssRule extends StyleableModel<CssRuleProperties> {
escape: (str: string) => (CSS && CSS.escape ? CSS.escape(str) : str), escape: (str: string) => (CSS && CSS.escape ? CSS.escape(str) : str),
}; };
// @ts-ignore // @ts-ignore
const selectors = this.get('selectors').getFullString(0, selOpts); const selectors = this.getSelectors().getFullString(0, selOpts);
const stateStr = state && !opts.skipState ? `:${state}` : ''; const stateStr = state && !opts.skipState ? `:${state}` : '';
selectors && result.push(`${selectors}${stateStr}`); selectors && result.push(`${selectors}${stateStr}`);
addSelector && !opts.skipAdd && result.push(addSelector); addSelector && !opts.skipAdd && result.push(addSelector);
@ -235,12 +235,12 @@ export default class CssRule extends StyleableModel<CssRuleProperties> {
getDevice() { getDevice() {
const { em } = this; const { em } = this;
const { atRuleType, mediaText } = this.attributes; const { atRuleType, mediaText } = this.attributes;
const devices = em?.get('DeviceManager').getDevices() || []; const devices = em?.Devices.getDevices() || [];
const deviceDefault = devices.filter((d: any) => d.getWidthMedia() === '')[0]; const deviceDefault = devices.filter(d => d.getWidthMedia() === '')[0];
if (atRuleType !== 'media' || !mediaText) { if (atRuleType !== 'media' || !mediaText) {
return deviceDefault || null; return deviceDefault || null;
} }
return devices.filter((d: any) => d.getWidthMedia() === getMediaLength(mediaText))[0] || null; return devices.filter(d => d.getWidthMedia() === getMediaLength(mediaText))[0] || null;
} }
/** /**
@ -253,8 +253,8 @@ export default class CssRule extends StyleableModel<CssRuleProperties> {
getState() { getState() {
const { em } = this; const { em } = this;
const stateValue = this.get('state'); const stateValue = this.get('state');
const states = em?.get('SelectorManager').getStates() || []; const states = em?.Selectors.getStates() || [];
return states.filter((s: any) => s.getName() === stateValue)[0] || null; return states.filter(s => s.getName() === stateValue)[0] || null;
} }
/** /**
@ -265,7 +265,7 @@ export default class CssRule extends StyleableModel<CssRuleProperties> {
* console.log(cmp?.toHTML()); * console.log(cmp?.toHTML());
*/ */
getComponent() { getComponent() {
const sel = this.getSelectors() as any; const sel = this.getSelectors();
const sngl = sel.length == 1 && sel.at(0); const sngl = sel.length == 1 && sel.at(0);
const cmpId = sngl && sngl.isId() && sngl.get('name'); const cmpId = sngl && sngl.isId() && sngl.get('name');
return (cmpId && this.em?.Components.getById(cmpId)) || null; return (cmpId && this.em?.Components.getById(cmpId)) || null;

20
src/selector_manager/model/Selector.ts

@ -1,6 +1,7 @@
import { result, forEach, keys } from 'underscore'; import { result, forEach, keys } from 'underscore';
import { Model } from '../../common'; import { Model } from '../../common';
import EditorModel from '../../editor/model/Editor'; import EditorModel from '../../editor/model/Editor';
import { SelectorManagerConfig } from '../config/config';
const TYPE_CLASS = 1; const TYPE_CLASS = 1;
const TYPE_ID = 2; const TYPE_ID = 2;
@ -14,6 +15,15 @@ export interface SelectorProps {
protected?: boolean; protected?: boolean;
} }
export interface SelectorPropsCustom extends SelectorProps {
[key: string]: unknown;
}
export interface SelectorOptions {
config?: SelectorManagerConfig;
em?: EditorModel;
}
/** /**
* @typedef Selector * @typedef Selector
* @property {String} name Selector name, eg. `my-class` * @property {String} name Selector name, eg. `my-class`
@ -23,7 +33,7 @@ export interface SelectorProps {
* @property {Boolean} [private=false] If true, it can't be seen by the Style Manager, but it will be rendered in the canvas and in export code. * @property {Boolean} [private=false] If true, it can't be seen by the Style Manager, but it will be rendered in the canvas and in export code.
* @property {Boolean} [protected=false] If true, it can't be removed from the attached component. * @property {Boolean} [protected=false] If true, it can't be removed from the attached component.
*/ */
export default class Selector extends Model<SelectorProps & { [key: string]: unknown }> { export default class Selector extends Model<SelectorPropsCustom> {
defaults() { defaults() {
return { return {
name: '', name: '',
@ -40,12 +50,12 @@ export default class Selector extends Model<SelectorProps & { [key: string]: unk
static readonly TYPE_CLASS = TYPE_CLASS; static readonly TYPE_CLASS = TYPE_CLASS;
static readonly TYPE_ID = TYPE_ID; static readonly TYPE_ID = TYPE_ID;
em: EditorModel; em?: EditorModel;
/** /**
* @hideconstructor * @hideconstructor
*/ */
constructor(props: any, opts: any = {}) { constructor(props: SelectorPropsCustom, opts: SelectorOptions = {}) {
super(props, opts); super(props, opts);
const { config = {} } = opts; const { config = {} } = opts;
const name = this.get('name'); const name = this.get('name');
@ -159,7 +169,7 @@ export default class Selector extends Model<SelectorProps & { [key: string]: unk
let obj = Model.prototype.toJSON.call(this, [opts]); let obj = Model.prototype.toJSON.call(this, [opts]);
const defaults = result(this, 'defaults'); const defaults = result(this, 'defaults');
if (em && em.getConfig().avoidDefaults) { if (em?.getConfig().avoidDefaults) {
forEach(defaults, (value, key) => { forEach(defaults, (value, key) => {
if (obj[key] === value) { if (obj[key] === value) {
delete obj[key]; delete obj[key];
@ -191,7 +201,7 @@ export default class Selector extends Model<SelectorProps & { [key: string]: unk
* @private * @private
*/ */
static escapeName(name: string) { static escapeName(name: string) {
return `${name}`.trim().replace(/([^a-z0-9\w\-\\:@\\/#()\.%\+\[\]]+)/gi, '-'); return `${name}`.trim().replace(/\s+/g, '-');
} }
} }

6
test/specs/selector_manager/model/SelectorModels.ts

@ -3,11 +3,11 @@ import Selectors from '../../../../src/selector_manager/model/Selectors';
describe('Selector', () => { describe('Selector', () => {
let obj: Selector; let obj: Selector;
const nameToEscape = '@Te sT:*[]().%/+#'; const nameToEscape = ' @Te sT:*[]!"£$%&/()=?^{}(). %/+#';
const nameEscaped = '@Te-sT:-[]().%/+#'; const nameEscaped = '@Te-sT:*[]!"£$%&/()=?^{}().-%/+#';
beforeEach(() => { beforeEach(() => {
obj = new Selector({}); obj = new Selector({ name: '' });
}); });
test('Has name property', () => { test('Has name property', () => {

Loading…
Cancel
Save