Browse Source

Feature detect document + fixes on configs (#6189)

* Add frame and page getters to Component

* Allow to skip dom reset in components

* Add detectDocument option to parser config

* Add __attrToString

* Update all configs in modules to avoid objects by reference

* Add tests to detectDocument

* Unskip some tests
pull/6193/head
Artur Arseniev 1 year ago
committed by GitHub
parent
commit
336f4b81e6
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      packages/core/src/asset_manager/config/config.ts
  2. 4
      packages/core/src/asset_manager/index.ts
  3. 4
      packages/core/src/block_manager/config/config.ts
  4. 4
      packages/core/src/block_manager/index.ts
  5. 4
      packages/core/src/canvas/config/config.ts
  6. 4
      packages/core/src/canvas/index.ts
  7. 4
      packages/core/src/code_manager/config/config.ts
  8. 4
      packages/core/src/code_manager/index.ts
  9. 4
      packages/core/src/commands/config/config.ts
  10. 4
      packages/core/src/commands/index.ts
  11. 4
      packages/core/src/css_composer/config/config.ts
  12. 4
      packages/core/src/css_composer/index.ts
  13. 4
      packages/core/src/device_manager/config/config.ts
  14. 4
      packages/core/src/device_manager/index.ts
  15. 6
      packages/core/src/dom_components/config/config.ts
  16. 11
      packages/core/src/dom_components/index.ts
  17. 75
      packages/core/src/dom_components/model/Component.ts
  18. 13
      packages/core/src/dom_components/model/ComponentWrapper.ts
  19. 5
      packages/core/src/dom_components/model/Components.ts
  20. 6
      packages/core/src/dom_components/model/types.ts
  21. 10
      packages/core/src/dom_components/view/ComponentsView.ts
  22. 4
      packages/core/src/editor/config/config.ts
  23. 3
      packages/core/src/editor/index.ts
  24. 1
      packages/core/src/editor/model/Editor.ts
  25. 4
      packages/core/src/i18n/config.ts
  26. 4
      packages/core/src/i18n/index.ts
  27. 4
      packages/core/src/keymaps/config.ts
  28. 4
      packages/core/src/keymaps/index.ts
  29. 4
      packages/core/src/modal_dialog/config/config.ts
  30. 4
      packages/core/src/modal_dialog/index.ts
  31. 4
      packages/core/src/navigator/config/config.ts
  32. 4
      packages/core/src/navigator/index.ts
  33. 4
      packages/core/src/panels/config/config.ts
  34. 9
      packages/core/src/panels/index.ts
  35. 9
      packages/core/src/parser/config/config.ts
  36. 4
      packages/core/src/parser/index.ts
  37. 19
      packages/core/src/parser/model/ParserHtml.ts
  38. 4
      packages/core/src/rich_text_editor/config/config.ts
  39. 4
      packages/core/src/rich_text_editor/index.ts
  40. 4
      packages/core/src/selector_manager/config/config.ts
  41. 5
      packages/core/src/selector_manager/index.ts
  42. 4
      packages/core/src/storage_manager/config/config.ts
  43. 4
      packages/core/src/storage_manager/index.ts
  44. 6
      packages/core/src/style_manager/config/config.ts
  45. 4
      packages/core/src/style_manager/index.ts
  46. 4
      packages/core/src/trait_manager/config/config.ts
  47. 4
      packages/core/src/trait_manager/index.ts
  48. 4
      packages/core/src/undo_manager/config.ts
  49. 4
      packages/core/src/undo_manager/index.ts
  50. 11
      packages/core/test/common.ts
  51. 49
      packages/core/test/specs/dom_components/index.ts
  52. 73
      packages/core/test/specs/grapesjs/index.ts
  53. 14
      packages/core/test/specs/navigator/view/ItemView.ts

4
packages/core/src/asset_manager/config/config.ts

@ -141,7 +141,7 @@ export interface AssetManagerConfig {
dropzoneContent?: string;
}
const config: AssetManagerConfig = {
const config: () => AssetManagerConfig = () => ({
assets: [],
noAssets: '',
stylePrefix: 'am-',
@ -163,6 +163,6 @@ const config: AssetManagerConfig = {
dropzone: false,
openAssetsOnDrop: true,
dropzoneContent: '',
};
});
export default config;

4
packages/core/src/asset_manager/index.ts

@ -37,7 +37,7 @@ import { ItemManagerModule } from '../abstract/Module';
import { AddOptions, RemoveOptions } from '../common';
import EditorModel from '../editor/model/Editor';
import { ProjectData } from '../storage_manager';
import defaults, { AssetManagerConfig } from './config/config';
import defConfig, { AssetManagerConfig } from './config/config';
import Asset from './model/Asset';
import Assets from './model/Assets';
import AssetsEvents, { AssetOpenOptions } from './types';
@ -66,7 +66,7 @@ export default class AssetManager extends ItemManagerModule<AssetManagerConfig,
*/
constructor(em: EditorModel) {
// @ts-ignore
super(em, 'AssetManager', new Assets([], em), AssetsEvents, defaults);
super(em, 'AssetManager', new Assets([], em), AssetsEvents, defConfig());
const { all, config } = this;
// @ts-ignore
this.assetsVis = new Assets([]);

4
packages/core/src/block_manager/config/config.ts

@ -38,11 +38,11 @@ export interface BlockManagerConfig {
custom?: boolean;
}
const config: BlockManagerConfig = {
const config: () => BlockManagerConfig = () => ({
appendTo: '',
blocks: [],
appendOnClick: false,
custom: false,
};
});
export default config;

4
packages/core/src/block_manager/index.ts

@ -31,7 +31,7 @@ import { ItemManagerModule } from '../abstract/Module';
import FrameView from '../canvas/view/FrameView';
import Component from '../dom_components/model/Component';
import EditorModel from '../editor/model/Editor';
import defaults, { BlockManagerConfig } from './config/config';
import defConfig, { BlockManagerConfig } from './config/config';
import Block, { BlockProperties } from './model/Block';
import Blocks from './model/Blocks';
import Categories from '../abstract/ModuleCategories';
@ -61,7 +61,7 @@ export default class BlockManager extends ItemManagerModule<BlockManagerConfig,
storageKey = '';
constructor(em: EditorModel) {
super(em, 'BlockManager', new Blocks(em.config.blockManager?.blocks || [], { em }), BlocksEvents, defaults);
super(em, 'BlockManager', new Blocks(em.config.blockManager?.blocks || [], { em }), BlocksEvents, defConfig());
// Global blocks collection
this.blocks = this.all;

4
packages/core/src/canvas/config/config.ts

@ -91,7 +91,7 @@ export interface CanvasConfig {
infiniteCanvas?: boolean;
}
const config: CanvasConfig = {
const config: () => CanvasConfig = () => ({
stylePrefix: 'cv-',
scripts: [],
styles: [],
@ -107,6 +107,6 @@ const config: CanvasConfig = {
`,
notTextable: ['button', 'a', 'input[type=checkbox]', 'input[type=radio]'],
allowExternalDrop: true,
};
});
export default config;

4
packages/core/src/canvas/index.ts

@ -35,7 +35,7 @@ import Component from '../dom_components/model/Component';
import ComponentView from '../dom_components/view/ComponentView';
import EditorModel from '../editor/model/Editor';
import { getElement, getViewEl } from '../utils/mixins';
import defaults, { CanvasConfig } from './config/config';
import defConfig, { CanvasConfig } from './config/config';
import Canvas from './model/Canvas';
import CanvasSpot, { CanvasSpotBuiltInTypes, CanvasSpotProps } from './model/CanvasSpot';
import CanvasSpots from './model/CanvasSpots';
@ -76,7 +76,7 @@ export default class CanvasModule extends Module<CanvasConfig> {
* @private
*/
constructor(em: EditorModel) {
super(em, 'Canvas', defaults);
super(em, 'Canvas', defConfig());
this.canvas = new Canvas(this);
this.spots = new CanvasSpots(this);

4
packages/core/src/code_manager/config/config.ts

@ -12,9 +12,9 @@ export interface CodeManagerConfig {
optsCodeViewer?: Record<string, any>;
}
const config: CodeManagerConfig = {
const config: () => CodeManagerConfig = () => ({
stylePrefix: 'cm-',
optsCodeViewer: {},
};
});
export default config;

4
packages/core/src/code_manager/index.ts

@ -18,7 +18,7 @@
* @module CodeManager
*/
import { isUndefined } from 'underscore';
import defaults, { CodeManagerConfig } from './config/config';
import defConfig, { CodeManagerConfig } from './config/config';
import gHtml from './model/HtmlGenerator';
import gCss from './model/CssGenerator';
import gJson from './model/JsonGenerator';
@ -39,7 +39,7 @@ export default class CodeManagerModule extends Module<CodeManagerConfig & { pSty
EditorView = CodeEditorView;
constructor(em: EditorModel) {
super(em, 'CodeManager', defaults);
super(em, 'CodeManager', defConfig());
const { config } = this;
const ppfx = config.pStylePrefix;
if (ppfx) config.stylePrefix = ppfx + config.stylePrefix;

4
packages/core/src/commands/config/config.ts

@ -21,10 +21,10 @@ export interface CommandsConfig {
strict?: boolean;
}
const config: CommandsConfig = {
const config: () => CommandsConfig = () => ({
stylePrefix: 'com-',
defaults: {},
strict: true,
};
});
export default config;

4
packages/core/src/commands/index.ts

@ -37,7 +37,7 @@
import { isFunction, includes } from 'underscore';
import CommandAbstract, { Command, CommandOptions, CommandObject, CommandFunction } from './view/CommandAbstract';
import defaults, { CommandsConfig } from './config/config';
import defConfig, { CommandsConfig } from './config/config';
import { Module } from '../abstract';
import Component, { eventDrag } from '../dom_components/model/Component';
import Editor from '../editor/model/Editor';
@ -107,7 +107,7 @@ export default class CommandsModule extends Module<CommandsConfig & { pStylePref
* @private
*/
constructor(em: Editor) {
super(em, 'Commands', defaults);
super(em, 'Commands', defConfig());
const { config } = this;
const ppfx = config.pStylePrefix;
const { defaultCommands } = this;

4
packages/core/src/css_composer/config/config.ts

@ -11,9 +11,9 @@ export interface CssComposerConfig {
rules?: Array<string>; // TODO
}
const config: CssComposerConfig = {
const config: () => CssComposerConfig = () => ({
stylePrefix: 'css-',
rules: [],
};
});
export default config;

4
packages/core/src/css_composer/index.ts

@ -31,7 +31,7 @@ import { isArray, isString, isUndefined } from 'underscore';
import { isObject } from '../utils/mixins';
import Selectors from '../selector_manager/model/Selectors';
import Selector from '../selector_manager/model/Selector';
import defaults, { CssComposerConfig } from './config/config';
import defConfig, { CssComposerConfig } from './config/config';
import CssRule, { CssRuleJSON, CssRuleProperties } from './model/CssRule';
import CssRules from './model/CssRules';
import CssRulesView from './view/CssRulesView';
@ -85,7 +85,7 @@ export default class CssComposer extends ItemManagerModule<CssComposerConfig & {
* @private
*/
constructor(em: EditorModel) {
super(em, 'CssComposer', null, {}, defaults);
super(em, 'CssComposer', null, {}, defConfig());
const { config } = this;
const ppfx = config.pStylePrefix;

4
packages/core/src/device_manager/config/config.ts

@ -25,7 +25,7 @@ export interface DeviceManagerConfig {
devices?: DeviceProperties[];
}
const config: DeviceManagerConfig = {
const config: () => DeviceManagerConfig = () => ({
default: '',
devices: [
{
@ -52,6 +52,6 @@ const config: DeviceManagerConfig = {
widthMedia: '480px',
},
],
};
});
export default config;

4
packages/core/src/device_manager/index.ts

@ -35,7 +35,7 @@
import { isString } from 'underscore';
import { ItemManagerModule } from '../abstract/Module';
import EditorModel from '../editor/model/Editor';
import defaults, { DeviceManagerConfig } from './config/config';
import defConfig, { DeviceManagerConfig } from './config/config';
import Device, { DeviceProperties } from './model/Device';
import Devices from './model/Devices';
import DevicesView from './view/DevicesView';
@ -74,7 +74,7 @@ export default class DeviceManager extends ItemManagerModule<
storageKey = '';
constructor(em: EditorModel) {
super(em, 'DeviceManager', new Devices(), deviceEvents, defaults);
super(em, 'DeviceManager', new Devices(), deviceEvents, defConfig());
this.devices = this.all;
this.config.devices?.forEach((device) => this.add(device, { silent: true }));
this.select(this.config.default || this.devices.at(0));

6
packages/core/src/dom_components/config/config.ts

@ -62,7 +62,7 @@ export interface DomComponentsConfig {
useFrameDoc?: boolean;
}
export default {
const config: () => DomComponentsConfig = () => ({
stylePrefix: 'comp-',
components: [],
draggableComponents: true,
@ -87,4 +87,6 @@ export default {
'track',
'wbr',
],
} as DomComponentsConfig;
});
export default config;

11
packages/core/src/dom_components/index.ts

@ -55,10 +55,10 @@
*/
import { debounce, isArray, isBoolean, isEmpty, isFunction, isString, isSymbol, result } from 'underscore';
import { ItemManagerModule } from '../abstract/Module';
import { AddOptions, ObjectAny } from '../common';
import { ObjectAny } from '../common';
import EditorModel from '../editor/model/Editor';
import { isComponent } from '../utils/mixins';
import defaults, { DomComponentsConfig } from './config/config';
import defConfig, { DomComponentsConfig } from './config/config';
import Component, { IComponent, keyUpdate, keyUpdateInside } from './model/Component';
import ComponentComment from './model/ComponentComment';
import ComponentFrame from './model/ComponentFrame';
@ -334,7 +334,7 @@ export default class ComponentManager extends ItemManagerModule<DomComponentsCon
* @private
*/
constructor(em: EditorModel) {
super(em, 'DomComponents', new Components(undefined, { em }));
super(em, 'DomComponents', new Components(undefined, { em }), ComponentsEvents, defConfig());
const { config } = this;
this.symbols = new Symbols([], { em, config, domc: this });
@ -343,11 +343,6 @@ export default class ComponentManager extends ItemManagerModule<DomComponentsCon
this.config.components = em.config.components || this.config.components;
}
for (let name in defaults) {
//@ts-ignore
if (!(name in this.config)) this.config[name] = defaults[name];
}
const ppfx = this.config.pStylePrefix;
if (ppfx) this.config.stylePrefix = ppfx + this.config.stylePrefix;

75
packages/core/src/dom_components/model/Component.ts

@ -20,13 +20,13 @@ import Selectors from '../../selector_manager/model/Selectors';
import Traits from '../../trait_manager/model/Traits';
import EditorModel from '../../editor/model/Editor';
import {
AddComponentsOption,
ComponentAdd,
ComponentDefinition,
ComponentDefinitionDefined,
ComponentOptions,
ComponentProperties,
DragMode,
ResetComponentsOptions,
SymbolToUpOptions,
ToHTMLOptions,
} from './types';
@ -213,6 +213,16 @@ export default class Component extends StyleableModel<ComponentProperties> {
return this.get('locked');
}
get frame() {
return this.opt.frame;
}
get page() {
return this.frame?.getPage();
}
preInit() {}
/**
* Hook method, called once the model is created
*/
@ -238,7 +248,6 @@ export default class Component extends StyleableModel<ComponentProperties> {
views!: ComponentView[];
view?: ComponentView;
viewLayer?: ItemView;
frame?: Frame;
rule?: CssRule;
prevColl?: Components;
__hasUm?: boolean;
@ -275,13 +284,13 @@ export default class Component extends StyleableModel<ComponentProperties> {
opt.em = em;
this.opt = opt;
this.em = em!;
this.frame = opt.frame;
this.config = opt.config || {};
this.set('attributes', {
...(result(this, 'defaults').attributes || {}),
...(this.get('attributes') || {}),
});
this.ccid = Component.createId(this, opt);
this.preInit();
this.initClasses();
this.initComponents();
this.initTraits();
@ -999,7 +1008,7 @@ export default class Component extends StyleableModel<ComponentProperties> {
*/
components<T extends ComponentAdd | undefined>(
components?: T,
opts: AddComponentsOption = {},
opts: ResetComponentsOptions = {},
): undefined extends T ? Components : Component[] {
const coll = this.get('components')!;
@ -1428,19 +1437,43 @@ export default class Component extends StyleableModel<ComponentProperties> {
* // -> <span title="Custom attribute"></span>
*/
toHTML(opts: ToHTMLOptions = {}): string {
const model = this;
const attrs = [];
const customTag = opts.tag;
const tag = customTag || model.get('tagName');
const sTag = model.get('void');
const tag = customTag || this.get('tagName');
delete opts.tag;
const attr = this.__attrToString(opts);
const attrString = attr ? ` ${attr}` : '';
const inner = this.getInnerHTML(opts);
const skipEndTag = !inner && this.get('void');
let code = `<${tag}${attrString}${skipEndTag ? '/' : ''}>${inner}`;
!skipEndTag && (code += `</${tag}>`);
return code;
}
/**
* Get inner HTML of the component
* @param {Object} [opts={}] Same options of `toHTML`
* @returns {String} HTML string
*/
getInnerHTML(opts?: ToHTMLOptions) {
return this.__innerHTML(opts);
}
__innerHTML(opts: ToHTMLOptions = {}) {
const cmps = this.components();
return !cmps.length ? this.content : cmps.map((c) => c.toHTML(opts)).join('');
}
__attrToString(opts: ToHTMLOptions = {}) {
const attrs = [];
const customAttr = opts.attributes;
let attributes = this.getAttrToHTML(opts);
delete opts.tag;
// Get custom attributes if requested
if (customAttr) {
if (isFunction(customAttr)) {
attributes = customAttr(model, attributes) || {};
attributes = customAttr(this, attributes) || {};
} else if (isObject(customAttr)) {
attributes = customAttr;
}
@ -1448,7 +1481,6 @@ export default class Component extends StyleableModel<ComponentProperties> {
if (opts.withProps) {
const props = this.toJSON();
forEach(props, (value, key) => {
const skipProps = ['classes', 'attributes', 'components'];
if (key[0] !== '_' && skipProps.indexOf(key) < 0) {
@ -1478,26 +1510,7 @@ export default class Component extends StyleableModel<ComponentProperties> {
}
}
const attrString = attrs.length ? ` ${attrs.join(' ')}` : '';
const inner = model.getInnerHTML(opts);
let code = `<${tag}${attrString}${sTag ? '/' : ''}>${inner}`;
!sTag && (code += `</${tag}>`);
return code;
}
/**
* Get inner HTML of the component
* @param {Object} [opts={}] Same options of `toHTML`
* @returns {String} HTML string
*/
getInnerHTML(opts?: ToHTMLOptions) {
return this.__innerHTML(opts);
}
__innerHTML(opts: ToHTMLOptions = {}) {
const cmps = this.components();
return !cmps.length ? this.content : cmps.map((c) => c.toHTML(opts)).join('');
return attrs.join(' ');
}
/**

13
packages/core/src/dom_components/model/ComponentWrapper.ts

@ -30,19 +30,16 @@ export default class ComponentWrapper extends Component {
};
}
constructor(...args: ConstructorParameters<typeof Component>) {
super(...args);
const props = args[0] || {};
const opts = args[1];
const cmp = opts?.em?.Components;
preInit() {
const { opt, attributes: props } = this;
const cmp = this.em?.Components;
const CmpHead = cmp?.getType(typeHead)?.model;
const CmpDef = cmp?.getType('default').model;
if (CmpHead) {
this.set(
{
head: new CmpHead({ ...props.head }, opts),
docEl: new CmpDef({ tagName: 'html', ...props.docEl }, opts),
head: new CmpHead({ ...props.head }, opt),
docEl: new CmpDef({ tagName: 'html', ...props.docEl }, opt),
},
{ silent: true },
);

5
packages/core/src/dom_components/model/Components.ts

@ -254,12 +254,13 @@ Component> {
parseString(value: string, opt: ParseStringOptions = {}) {
const { em, domc, parent } = this;
const asDocument = opt.asDocument && parent?.is('wrapper');
const isWrapper = parent?.is('wrapper');
const asDocument = opt.asDocument && isWrapper;
const cssc = em.Css;
const parsed = em.Parser.parseHtml(value, { asDocument, ...opt.parserOptions });
let components = parsed.html;
if (asDocument) {
if (isWrapper && parsed.doctype) {
const root = parent as ComponentWrapper;
const { components: bodyCmps, ...restBody } = (parsed.html as ComponentDefinitionDefined) || {};
const { components: headCmps, ...restHead } = parsed.head || {};

6
packages/core/src/dom_components/model/types.ts

@ -19,6 +19,12 @@ export type DraggableDroppableFn = (source: Component, target: Component, index?
export interface AddComponentsOption extends AddOptions, OptionAsDocument {}
export interface ResetComponentsOptions extends AddComponentsOption {
previousModels?: Component[];
keepIds?: string[];
skipDomReset?: boolean;
}
interface ComponentWithCheck<C extends Component> {
new (props: any, opt: ComponentOptions): C;
isComponent(node: HTMLElement, opts?: ParseNodeOptions): ComponentDefinitionDefined | undefined | boolean;

10
packages/core/src/dom_components/view/ComponentsView.ts

@ -7,6 +7,7 @@ import Component from '../model/Component';
import ComponentView from './ComponentView';
import FrameView from '../../canvas/view/FrameView';
import Components from '../model/Components';
import { ResetComponentsOptions } from '../model/types';
export default class ComponentsView extends View {
opts!: any;
@ -124,9 +125,12 @@ export default class ComponentsView extends View {
return rendered;
}
resetChildren(models: Components, { previousModels = [] } = {}) {
this.parentEl!.innerHTML = '';
previousModels.forEach((md) => this.removeChildren(md, this.collection));
resetChildren(models: Components, opts: ResetComponentsOptions = {}) {
const { previousModels } = opts;
if (!opts.skipDomReset) {
this.parentEl!.innerHTML = '';
}
previousModels?.forEach((md) => this.removeChildren(md, this.collection));
models.each((model) => this.addToCollection(model));
}

4
packages/core/src/editor/config/config.ts

@ -432,7 +432,7 @@ export interface EditorConfig {
export type EditorConfigKeys = keyof EditorConfig;
const config: EditorConfig = {
const config: () => EditorConfig = () => ({
stylePrefix: 'gjs-',
components: '',
style: '',
@ -506,6 +506,6 @@ const config: EditorConfig = {
textViewCode: 'Code',
keepUnusedStyles: false,
customUI: false,
};
});
export default config;

3
packages/core/src/editor/index.ts

@ -89,7 +89,7 @@ import TraitManager from '../trait_manager';
import UndoManagerModule from '../undo_manager';
import UtilsModule from '../utils';
import html from '../utils/html';
import defaults, { EditorConfig, EditorConfigKeys } from './config/config';
import defConfig, { EditorConfig, EditorConfigKeys } from './config/config';
import EditorModel, { EditorLoadOptions } from './model/Editor';
import EditorView from './view/EditorView';
@ -132,6 +132,7 @@ export default class Editor implements IBaseModule<EditorConfig> {
config: EditorConfigType;
constructor(config: EditorConfig = {}, opts: any = {}) {
const defaults = defConfig();
this.config = {
...defaults,
...config,

1
packages/core/src/editor/model/Editor.ts

@ -365,6 +365,7 @@ export default class EditorModel extends Model {
storageManager: false,
undoManager: false,
});
shallow.set({ isShallow: true });
// We only need to load a few modules
shallow.Pages.onLoad();
shallow.Canvas.postLoad();

4
packages/core/src/i18n/config.ts

@ -37,13 +37,13 @@ export interface I18nConfig {
messagesAdd?: Record<string, any>;
}
const config: I18nConfig = {
const config: () => I18nConfig = () => ({
locale: 'en',
localeFallback: 'en',
detectLocale: true,
debug: false,
messages: { en },
messagesAdd: undefined,
};
});
export default config;

4
packages/core/src/i18n/index.ts

@ -27,7 +27,7 @@ import { isUndefined, isString } from 'underscore';
import { Module } from '../abstract';
import EditorModel from '../editor/model/Editor';
import { hasWin, deepMerge } from '../utils/mixins';
import defaults, { I18nConfig } from './config';
import defConfig, { I18nConfig } from './config';
import I18nEvents, { Messages } from './types';
export default class I18nModule extends Module<I18nConfig & { stylePrefix?: string }> {
@ -39,7 +39,7 @@ export default class I18nModule extends Module<I18nConfig & { stylePrefix?: stri
* @private
*/
constructor(em: EditorModel) {
super(em, 'I18n', defaults);
super(em, 'I18n', defConfig());
const add = this.config.messagesAdd;
add && this.addMessages(add);

4
packages/core/src/keymaps/config.ts

@ -24,7 +24,7 @@ export interface KeymapsConfig {
defaults?: Record<string, Omit<Keymap, 'id'> & { opts?: KeymapOptions }>;
}
const config: KeymapsConfig = {
const config: () => KeymapsConfig = () => ({
defaults: {
'core:undo': {
keys: '⌘+z, ctrl+z',
@ -66,6 +66,6 @@ const config: KeymapsConfig = {
opts: { prevent: true },
},
},
};
});
export default config;

4
packages/core/src/keymaps/index.ts

@ -48,7 +48,7 @@ import { hasWin } from '../utils/mixins';
import keymaster from '../utils/keymaster';
import { Module } from '../abstract';
import EditorModel from '../editor/model/Editor';
import defaults, { Keymap, KeymapOptions, KeymapsConfig } from './config';
import defConfig, { Keymap, KeymapOptions, KeymapsConfig } from './config';
export type KeymapEvent = 'keymap:add' | 'keymap:remove' | 'keymap:emit' | `keymap:emit:${string}`;
@ -59,7 +59,7 @@ export default class KeymapsModule extends Module<KeymapsConfig & { name?: strin
keymaps: Record<string, Keymap>;
constructor(em: EditorModel) {
super(em, 'Keymaps', defaults);
super(em, 'Keymaps', defConfig());
this.keymaps = {};
}

4
packages/core/src/modal_dialog/config/config.ts

@ -26,13 +26,13 @@ export interface ModalConfig {
extend?: Record<string, any>;
}
const config: ModalConfig = {
const config: () => ModalConfig = () => ({
stylePrefix: 'mdl-',
title: '',
content: '',
backdrop: true,
custom: false,
extend: {},
};
});
export default config;

4
packages/core/src/modal_dialog/index.ts

@ -38,7 +38,7 @@ import { Module } from '../abstract';
import EditorView from '../editor/view/EditorView';
import EditorModel from '../editor/model/Editor';
import { createText } from '../utils/dom';
import defaults, { ModalConfig } from './config/config';
import defConfig, { ModalConfig } from './config/config';
import ModalM from './model/Modal';
import ModalView from './view/ModalView';
import { EventHandler } from '../common';
@ -54,7 +54,7 @@ export default class ModalModule extends Module<ModalConfig> {
* @private
*/
constructor(em: EditorModel) {
super(em, 'Modal', defaults);
super(em, 'Modal', defConfig());
this.model = new ModalM(this);
this.model.on('change:open', (m: ModalM, enable: boolean) => {

4
packages/core/src/navigator/config/config.ts

@ -108,7 +108,7 @@ export interface LayerManagerConfig {
extend?: Record<string, any>;
}
const config: LayerManagerConfig = {
const config: () => LayerManagerConfig = () => ({
stylePrefix: '',
appendTo: '',
sortable: true,
@ -124,6 +124,6 @@ const config: LayerManagerConfig = {
onInit: () => {},
onRender: () => {},
extend: {},
};
});
export default config;

4
packages/core/src/navigator/index.ts

@ -45,7 +45,7 @@ import Module from '../abstract/Module';
import Component from '../dom_components/model/Component';
import EditorModel from '../editor/model/Editor';
import { hasWin, isComponent, isDef } from '../utils/mixins';
import defaults, { LayerManagerConfig } from './config/config';
import defConfig, { LayerManagerConfig } from './config/config';
import View from './view/ItemView';
import { ComponentsEvents } from '../dom_components/types';
@ -91,7 +91,7 @@ export default class LayerManager extends Module<LayerManagerConfig> {
events = events;
constructor(em: EditorModel) {
super(em, 'LayerManager', defaults);
super(em, 'LayerManager', defConfig());
bindAll(this, 'componentChanged', '__onRootChange', '__onComponent');
this.model = new ModuleModel(this, { opened: {} });
// @ts-ignore

4
packages/core/src/panels/config/config.ts

@ -34,7 +34,7 @@ export interface PanelsConfig {
defaults?: PanelProps[];
}
const config: PanelsConfig = {
const config: () => PanelsConfig = () => ({
stylePrefix: 'pn-',
defaults: [
{
@ -109,6 +109,6 @@ const config: PanelsConfig = {
],
},
],
};
});
export default config;

9
packages/core/src/panels/index.ts

@ -27,7 +27,7 @@
*/
import { Module } from '../abstract';
import EditorModel from '../editor/model/Editor';
import defaults, { PanelsConfig } from './config/config';
import defConfig, { PanelsConfig } from './config/config';
import Panel, { PanelProperties } from './model/Panel';
import Panels from './model/Panels';
import PanelsView from './view/PanelsView';
@ -42,13 +42,8 @@ export default class PanelManager extends Module<PanelsConfig> {
* @private
*/
constructor(em: EditorModel) {
super(em, 'Panels', defaults);
super(em, 'Panels', defConfig());
this.panels = new Panels(this, this.config.defaults!);
for (var name in defaults) {
//@ts-ignore
if (!(name in this.config)) this.config[name] = defaults[name];
}
return this;
}
/**

9
packages/core/src/parser/config/config.ts

@ -60,6 +60,11 @@ export interface HTMLParserOptions extends OptionAsDocument {
*/
keepEmptyTextNodes?: boolean;
/**
* Indicate if or how to detect if the passed HTML string should be parsed as a document.
*/
detectDocument?: boolean | ((html: string) => boolean);
/**
* Custom transformer to run before passing the input HTML to the parser.
* A common use case might be to sanitize the input string.
@ -105,7 +110,7 @@ export interface ParserConfig {
optionsHtml?: HTMLParserOptions;
}
const config: ParserConfig = {
const config: () => ParserConfig = () => ({
textTags: ['br', 'b', 'i', 'u', 'a', 'ul', 'ol'],
textTypes: ['text', 'textnode', 'comment'],
parserCss: undefined,
@ -117,6 +122,6 @@ const config: ParserConfig = {
allowUnsafeAttrValue: false,
keepEmptyTextNodes: false,
},
};
});
export default config;

4
packages/core/src/parser/index.ts

@ -26,7 +26,7 @@
*/
import { Module } from '../abstract';
import EditorModel from '../editor/model/Editor';
import defaults, { HTMLParserOptions, ParserConfig } from './config/config';
import defConfig, { HTMLParserOptions, ParserConfig } from './config/config';
import ParserCss from './model/ParserCss';
import ParserHtml from './model/ParserHtml';
@ -35,7 +35,7 @@ export default class ParserModule extends Module<ParserConfig & { name?: string
parserCss: ReturnType<typeof ParserCss>;
constructor(em: EditorModel) {
super(em, 'Parser', defaults);
super(em, 'Parser', defConfig());
const { config } = this;
this.parserCss = ParserCss(em, config);
this.parserHtml = ParserHtml(em, config);

19
packages/core/src/parser/model/ParserHtml.ts

@ -5,6 +5,7 @@ import EditorModel from '../../editor/model/Editor';
import { HTMLParseResult, HTMLParserOptions, ParseNodeOptions, ParserConfig } from '../config/config';
import BrowserParserHtml from './BrowserParserHtml';
import { doctypeToString } from '../../utils/dom';
import { isDef } from '../../utils/mixins';
const modelAttrStart = 'data-gjs-';
const event = 'parse:html';
@ -313,12 +314,16 @@ const ParserHtml = (em?: EditorModel, config: ParserConfig & { returnArray?: boo
const conf = em?.get('Config') || {};
const res: HTMLParseResult = { html: [] };
const cf = { ...config, ...opts };
const options = {
const preOptions = {
...config.optionsHtml,
// @ts-ignore Support previous `configParser.htmlType` option
htmlType: config.optionsHtml?.htmlType || config.htmlType,
...opts,
};
const options = {
...preOptions,
asDocument: this.__checkAsDocument(str, preOptions),
};
const { preParser, asDocument } = options;
const input = isFunction(preParser) ? preParser(str, { editor: em?.getEditor()! }) : str;
const parseRes = isFunction(cf.parserHtml) ? cf.parserHtml(input, options) : BrowserParserHtml(input, options);
@ -374,7 +379,7 @@ const ParserHtml = (em?: EditorModel, config: ParserConfig & { returnArray?: boo
}
res.html = resHtml;
em?.trigger(event, { input, output: res });
em?.trigger(event, { input, output: res, options });
return res;
},
@ -392,6 +397,16 @@ const ParserHtml = (em?: EditorModel, config: ParserConfig & { returnArray?: boo
toRemove.map((name) => node.removeAttribute(name));
each(nodes, (node) => this.__sanitizeNode(node as HTMLElement, opts));
},
__checkAsDocument(str: string, opts: HTMLParserOptions) {
if (isDef(opts.asDocument)) {
return opts.asDocument;
} else if (isFunction(opts.detectDocument)) {
return !!opts.detectDocument(str);
} else if (opts.detectDocument) {
return str.toLowerCase().trim().startsWith('<!doctype');
}
},
};
};

4
packages/core/src/rich_text_editor/config/config.ts

@ -80,11 +80,11 @@ export interface RichTextEditorConfig {
custom?: boolean;
}
const config: RichTextEditorConfig = {
const config: () => RichTextEditorConfig = () => ({
stylePrefix: 'rte-',
adjustToolbar: true,
actions: ['bold', 'italic', 'underline', 'strikethrough', 'link', 'wrap'],
custom: false,
};
});
export default config;

4
packages/core/src/rich_text_editor/index.ts

@ -44,7 +44,7 @@ import ComponentView from '../dom_components/view/ComponentView';
import EditorModel from '../editor/model/Editor';
import { createEl, cx, on, removeEl } from '../utils/dom';
import { hasWin, isDef } from '../utils/mixins';
import defaults, { CustomRTE, RichTextEditorConfig } from './config/config';
import defConfig, { CustomRTE, RichTextEditorConfig } from './config/config';
import RichTextEditor, { RichTextEditorAction } from './model/RichTextEditor';
import CanvasEvents from '../canvas/types';
import { ComponentsEvents } from '../dom_components/types';
@ -87,7 +87,7 @@ export default class RichTextEditorModule extends Module<RichTextEditorConfig &
*/
constructor(em: EditorModel) {
super(em, 'RichTextEditor', defaults);
super(em, 'RichTextEditor', defConfig());
const { config } = this;
const ppfx = config.pStylePrefix;

4
packages/core/src/selector_manager/config/config.ts

@ -132,7 +132,7 @@ export interface SelectorManagerConfig {
custom?: boolean;
}
const config: SelectorManagerConfig = {
const config: () => SelectorManagerConfig = () => ({
stylePrefix: 'clm-',
appendTo: '',
selectors: [],
@ -148,6 +148,6 @@ const config: SelectorManagerConfig = {
'<svg viewBox="0 0 24 24"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"></path></svg>',
componentFirst: false,
custom: false,
};
});
export default config;

5
packages/core/src/selector_manager/index.ts

@ -76,7 +76,7 @@
import { isString, debounce, isObject, isArray, bindAll } from 'underscore';
import { isComponent, isRule } from '../utils/mixins';
import { Model, Collection, RemoveOptions, SetOptions, Debounced } from '../common';
import defaults, { SelectorManagerConfig } from './config/config';
import defConfig, { SelectorManagerConfig } from './config/config';
import Selector from './model/Selector';
import Selectors from './model/Selectors';
import State from './model/State';
@ -86,7 +86,6 @@ import Component from '../dom_components/model/Component';
import { ItemManagerModule } from '../abstract/Module';
import { StyleModuleParam } from '../style_manager';
import StyleableModel from '../domain_abstract/model/StyleableModel';
import CssRule from '../css_composer/model/CssRule';
import { ComponentsEvents } from '../dom_components/types';
export type SelectorEvent = 'selector:add' | 'selector:remove' | 'selector:update' | 'selector:state' | 'selector';
@ -138,7 +137,7 @@ export default class SelectorManager extends ItemManagerModule<SelectorManagerCo
*/
constructor(em: EditorModel) {
super(em, 'SelectorManager', new Selectors([]), selectorEvents, defaults, { skipListen: true });
super(em, 'SelectorManager', new Selectors([]), selectorEvents, defConfig(), { skipListen: true });
bindAll(this, '__updateSelectedByComponents');
const { config } = this;
const ppfx = config.pStylePrefix;

4
packages/core/src/storage_manager/config/config.ts

@ -78,7 +78,7 @@ export interface StorageManagerConfig {
};
}
const config: StorageManagerConfig = {
const config: () => StorageManagerConfig = () => ({
id: 'gjs-',
type: 'local',
autosave: true,
@ -103,6 +103,6 @@ const config: StorageManagerConfig = {
onLoad: (result) => result,
},
},
};
});
export default config;

4
packages/core/src/storage_manager/index.ts

@ -42,7 +42,7 @@
import { isEmpty, isFunction } from 'underscore';
import { Module } from '../abstract';
import defaults, { StorageManagerConfig } from './config/config';
import defConfig, { StorageManagerConfig } from './config/config';
import LocalStorage from './model/LocalStorage';
import RemoteStorage from './model/RemoteStorage';
import EditorModel from '../editor/model/Editor';
@ -65,7 +65,7 @@ export default class StorageManager extends Module<
events = StorageEvents;
constructor(em: EditorModel) {
super(em, 'StorageManager', defaults);
super(em, 'StorageManager', defConfig());
const { config } = this;
if (config._disable) config.type = undefined;
this.storages = {};

6
packages/core/src/style_manager/config/config.ts

@ -66,7 +66,7 @@ export interface StyleManagerConfig {
pStylePrefix?: string;
}
export default {
const config: () => StyleManagerConfig = () => ({
sectors: [
{
name: 'General',
@ -128,4 +128,6 @@ export default {
showComputed: true,
clearProperties: true,
avoidComputed: ['width', 'height'],
} as StyleManagerConfig;
});
export default config;

4
packages/core/src/style_manager/index.ts

@ -66,7 +66,7 @@
import { isUndefined, isArray, isString, debounce, bindAll } from 'underscore';
import { isComponent } from '../utils/mixins';
import { AddOptions, Debounced, Model } from '../common';
import defaults, { StyleManagerConfig } from './config/config';
import defConfig, { StyleManagerConfig } from './config/config';
import Sector, { SectorProperties } from './model/Sector';
import Sectors from './model/Sectors';
import Properties from './model/Properties';
@ -157,7 +157,7 @@ export default class StyleManager extends ItemManagerModule<
* @private
*/
constructor(em: EditorModel) {
super(em, 'StyleManager', new Sectors([], { em }), stylesEvents, defaults);
super(em, 'StyleManager', new Sectors([], { em }), stylesEvents, defConfig());
bindAll(this, '__clearStateTarget');
const c = this.config;
const ppfx = c.pStylePrefix;

4
packages/core/src/trait_manager/config/config.ts

@ -22,11 +22,11 @@ export interface TraitManagerConfig {
optionsTarget?: Record<string, any>[];
}
const config: TraitManagerConfig = {
const config: () => TraitManagerConfig = () => ({
stylePrefix: 'trt-',
appendTo: '',
optionsTarget: [{ value: false }, { value: '_blank' }],
custom: false,
};
});
export default config;

4
packages/core/src/trait_manager/index.ts

@ -33,7 +33,7 @@ import { Module } from '../abstract';
import { Model } from '../common';
import Component from '../dom_components/model/Component';
import EditorModel from '../editor/model/Editor';
import defaults from './config/config';
import defConfig from './config/config';
import {
CustomTrait,
TraitCustomData,
@ -81,7 +81,7 @@ export default class TraitManager extends Module<TraitManagerConfigModule> {
* @private
*/
constructor(em: EditorModel) {
super(em, 'TraitManager', defaults as any);
super(em, 'TraitManager', defConfig() as any);
const { state, config, events } = this;
const ppfx = config.pStylePrefix;
ppfx && (config.stylePrefix = `${ppfx}${config.stylePrefix}`);

4
packages/core/src/undo_manager/config.ts

@ -11,9 +11,9 @@ export interface UndoManagerConfig {
trackSelection?: boolean;
}
const config: UndoManagerConfig = {
const config: () => UndoManagerConfig = () => ({
maximumStackLength: 500,
trackSelection: true,
};
});
export default config;

4
packages/core/src/undo_manager/index.ts

@ -28,7 +28,7 @@ import UndoManager from 'backbone-undo';
import { isArray, isBoolean, isEmpty, unique, times } from 'underscore';
import { Module } from '../abstract';
import EditorModel from '../editor/model/Editor';
import defaults, { UndoManagerConfig } from './config';
import defConfig, { UndoManagerConfig } from './config';
export interface UndoGroup {
index: number;
@ -47,7 +47,7 @@ export default class UndoManagerModule extends Module<UndoManagerConfig & { name
um: any;
constructor(em: EditorModel) {
super(em, 'UndoManager', defaults);
super(em, 'UndoManager', defConfig());
if (this.config._disable) {
this.config.maximumStackLength = 0;

11
packages/core/test/common.ts

@ -47,6 +47,17 @@ export function setupTestEditor(opts?: { withCanvas?: boolean; config?: Partial<
return { editor, em, dsm, cmpRoot, fixtures: fixtures as HTMLElement };
}
export function fixJsDom(editor: Editor) {
fixJsDomIframe(editor);
}
export const fixJsDomIframe = (em: EditorModel | Editor) => {
em.on(CanvasEvents.frameLoad, ({ el, view }) => {
// this seems to fix the issue of the loop
el.onload = null;
});
};
export function waitEditorEvent(em: Editor | EditorModel, event: string) {
return new Promise((resolve) => em.once(event, resolve));
}

49
packages/core/test/specs/dom_components/index.ts

@ -319,21 +319,21 @@ describe('DOM Components', () => {
describe('Custom components with styles', () => {
test('canMove returns false if source is not provided', () => {
const target = obj.addComponent({ type: 'div' }) as Component;
const target = obj.addComponent({ tagName: 'div' }) as Component;
const result = obj.canMove(target);
expect(result.result).toBe(false);
expect(result.reason).toBe(CanMoveReason.InvalidSource);
});
test('canMove returns false if target is not provided', () => {
const source = obj.addComponent({ type: 'div' }) as Component;
const source = obj.addComponent({ tagName: 'div' }) as Component;
const result = obj.canMove(undefined as any, source);
expect(result.result).toBe(false);
expect(result.reason).toBe(CanMoveReason.InvalidSource);
});
test('canMove returns false when source and target have the same main symbol', () => {
const component = obj.addComponent({ type: 'div' }) as Component;
const component = obj.addComponent({ tagName: 'div' }) as Component;
const mainSymbol = obj.addSymbol(component) as Component;
const target = obj.addSymbol(mainSymbol) as Component;
const source = obj.addSymbol(mainSymbol) as Component;
@ -356,31 +356,31 @@ describe('DOM Components', () => {
});
test('canMove returns false when source is not draggable in the target', () => {
const target = obj.addComponent({ type: 'div', droppable: true }) as Component;
const source = obj.addComponent({ type: 'span', draggable: false }) as Component;
const target = obj.addComponent({ tagName: 'div', droppable: true }) as Component;
const source = obj.addComponent({ tagName: 'span', draggable: false }) as Component;
const result = obj.canMove(target, source);
expect(result.result).toBe(false);
expect(result.reason).toBe(CanMoveReason.SourceReject);
});
test('canMove returns false when target does not accept the source', () => {
const target = obj.addComponent({ type: 'div', droppable: false }) as Component;
const source = obj.addComponent({ type: 'span', draggable: true }) as Component;
const target = obj.addComponent({ tagName: 'div', droppable: false }) as Component;
const source = obj.addComponent({ tagName: 'span', draggable: true }) as Component;
const result = obj.canMove(target, source);
expect(result.result).toBe(false);
expect(result.reason).toBe(CanMoveReason.TargetReject);
});
test('canMove returns true when source is draggable and target is droppable', () => {
const target = obj.addComponent({ type: 'div', droppable: true }) as Component;
const source = obj.addComponent({ type: 'span', draggable: true }) as Component;
const target = obj.addComponent({ tagName: 'div', droppable: true }) as Component;
const source = obj.addComponent({ tagName: 'span', draggable: true }) as Component;
const result = obj.canMove(target, source);
expect(result.result).toBe(true);
});
test('canMove returns false when target is inside the source', () => {
const source = obj.addComponent({ type: 'div' }) as Component;
const target = source.append({ type: 'span' })[0];
const source = obj.addComponent({ tagName: 'div' }) as Component;
const target = source.append({ tagName: 'span' })[0];
const result = obj.canMove(target, source);
expect(result.result).toBe(false);
expect(result.reason).toBe(CanMoveReason.TargetReject);
@ -491,6 +491,33 @@ describe('DOM Components', () => {
expect(newRoot.toHTML()).toBe(flattenHTML(docHtml));
});
test('load projectData containing HTML document, without document detect', () => {
editor.loadProjectData({
pages: [{ component: docHtml }],
});
const newRoot = editor.getWrapper()!;
const { head, doctype } = newRoot;
// Components from the head are moved inside the body
expect(head.components().length).toBe(0);
expect(doctype).toBe('');
expect(newRoot.components().length).toBe(2);
});
test('load projectData containing HTML document, with document detect', () => {
editor.Parser.getConfig().optionsHtml!.detectDocument = true;
editor.loadProjectData({
pages: [{ component: docHtml }],
});
const newRoot = editor.getWrapper()!;
const { head, doctype } = newRoot;
expect(head.components().length).toBe(1);
expect(doctype).toBe('<!DOCTYPE html>');
expect(newRoot.toHTML()).toBe(flattenHTML(docHtml));
});
});
});
});

73
packages/core/test/specs/grapesjs/index.ts

@ -1,6 +1,8 @@
import grapesjs, { Component, Editor, usePlugin } from '../../../src';
import ComponentWrapper from '../../../src/dom_components/model/ComponentWrapper';
import { EditorConfig } from '../../../src/editor/config/config';
import type { Plugin } from '../../../src/plugin_manager';
import { fixJsDom, fixJsDomIframe } from '../../common';
type TestPlugin = Plugin<{ cVal: string }>;
@ -24,6 +26,16 @@ describe('GrapesJS', () => {
},
};
const initTestEditor = (config: Partial<EditorConfig>) => {
const editor = grapesjs.init({
...config,
plugins: [fixJsDom, ...(config.plugins || [])],
});
fixJsDomIframe(editor.getModel().shallow);
return editor;
};
beforeAll(() => {
editorName = 'editor-fixture';
});
@ -86,23 +98,33 @@ describe('GrapesJS', () => {
expect(editor.getStyle().length).toEqual(0);
});
test.skip('Editor canvas baseCSS can be overwritten', () => {
test('Editor canvas baseCSS can be overwritten', (done) => {
config.components = htmlString;
config.baseCss = '#wrapper { background-color: #eee; }';
config.protectedCss = '';
const editor = grapesjs.init(config);
const body = editor.Canvas.getBody();
expect(body.outerHTML).toContain(config.baseCss);
expect(body.outerHTML.replace(/\s+/g, ' ')).not.toContain('body { margin: 0;');
const editor = initTestEditor({
...config,
components: htmlString,
baseCss: '#wrapper { background-color: #eee; }',
protectedCss: '',
});
editor.onReady(() => {
const body = editor.Canvas.getBody();
expect(body.outerHTML).toContain(config.baseCss);
expect(body.outerHTML.replace(/\s+/g, ' ')).not.toContain('body { margin: 0;');
done();
});
});
test.skip('Editor canvas baseCSS defaults to sensible values if not defined', () => {
test('Editor canvas baseCSS defaults to sensible values if not defined', (done) => {
config.components = htmlString;
config.protectedCss = '';
grapesjs.init(config);
expect(window.frames[0].document.documentElement.outerHTML.replace(/\s+/g, ' ')).toContain(
'body { background-color: #fff',
);
const editor = initTestEditor(config);
editor.onReady(() => {
const htmlEl = editor.Canvas.getDocument().documentElement;
expect(htmlEl.outerHTML.replace(/\s+/g, ' ')).toContain('body { background-color: #fff');
done();
});
});
test('Init editor with html', () => {
@ -459,25 +481,32 @@ describe('GrapesJS', () => {
});
});
describe.skip('Component selection', () => {
describe('Component selection', () => {
let editor: Editor;
let wrapper: ComponentWrapper;
let el1: Component;
let el2: Component;
let el3: Component;
beforeEach(() => {
config.storageManager = { type: 0 };
config.components = `<div>
<div id="el1"></div>
<div id="el2"></div>
<div id="el3"></div>
</div>`;
editor = grapesjs.init(config);
beforeEach((done) => {
editor = grapesjs.init({
container: `#${editorName}`,
storageManager: false,
plugins: [fixJsDom],
components: `<div>
<div id="el1"></div>
<div id="el2"></div>
<div id="el3"></div>
</div>`,
});
fixJsDomIframe(editor.getModel().shallow);
wrapper = editor.DomComponents.getWrapper()!;
el1 = wrapper.find('#el1')[0];
el2 = wrapper.find('#el2')[0];
el3 = wrapper.find('#el3')[0];
editor.onReady(() => {
el1 = wrapper.find('#el1')[0];
el2 = wrapper.find('#el2')[0];
el3 = wrapper.find('#el3')[0];
done();
});
});
test('Select a single component', () => {

14
packages/core/test/specs/navigator/view/ItemView.js → packages/core/test/specs/navigator/view/ItemView.ts

@ -1,11 +1,11 @@
import ItemView from 'navigator/view/ItemView';
import config from 'navigator/config/config';
import EditorModel from 'editor/model/Editor';
import defConfig from '../../../../src/navigator/config/config';
import EditorModel from '../../../../src/editor/model/Editor';
import ItemView from '../../../../src/navigator/view/ItemView';
describe('ItemView', () => {
let itemView;
let itemView: ItemView;
const isVisible = (itemView) => {
const isVisible = (itemView: ItemView) => {
return itemView.module.isVisible(itemView.model);
};
@ -16,8 +16,8 @@ describe('ItemView', () => {
itemView = new ItemView({
model: new defCmp({}, { em }),
module: em.get('LayerManager'),
config: { ...config, em },
});
config: { ...defConfig(), em },
} as any);
});
describe('.isVisible', () => {
Loading…
Cancel
Save