From a63a4d07a82e2f6c43c19eeea3b40c4d8fc9cd8b Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Mon, 10 Aug 2026 12:37:51 +0400 Subject: [PATCH] Fixes frame (#6809) * Fix isStyleInFlow * Fix save restore * Format --- packages/core/src/canvas/model/Frame.ts | 4 ++++ packages/core/src/editor/model/Editor.ts | 13 +++++++---- .../src/style_manager/model/PropertySelect.ts | 4 ++-- packages/core/src/utils/sorter/SorterUtils.ts | 2 +- packages/core/test/specs/grapesjs/index.ts | 23 +++++++++++++++++++ 5 files changed, 38 insertions(+), 8 deletions(-) diff --git a/packages/core/src/canvas/model/Frame.ts b/packages/core/src/canvas/model/Frame.ts index 125039c67..61a9ba45f 100644 --- a/packages/core/src/canvas/model/Frame.ts +++ b/packages/core/src/canvas/model/Frame.ts @@ -200,6 +200,10 @@ export default class Frame extends ModuleModel { return this.get('component'); } + getMainComponent(): Component { + return this.refComponent || this.root; + } + getStyles() { return this.get('styles'); } diff --git a/packages/core/src/editor/model/Editor.ts b/packages/core/src/editor/model/Editor.ts index 2c6474e1a..b7bdbbec1 100644 --- a/packages/core/src/editor/model/Editor.ts +++ b/packages/core/src/editor/model/Editor.ts @@ -909,11 +909,14 @@ export default class EditorModel extends Model { this.clearDirtyCount(); }, 1); const data = this.storeData(); - await this.Storage.store(data, options); - setTimeout(() => { - this._isStoring = false; - }, 1); - return data; + try { + await this.Storage.store(data, options); + return data; + } finally { + setTimeout(() => { + this._isStoring = false; + }, 1); + } } /** diff --git a/packages/core/src/style_manager/model/PropertySelect.ts b/packages/core/src/style_manager/model/PropertySelect.ts index 72e156f1b..428ea2dcb 100644 --- a/packages/core/src/style_manager/model/PropertySelect.ts +++ b/packages/core/src/style_manager/model/PropertySelect.ts @@ -3,7 +3,7 @@ import { ObjectAny } from '../../common'; import { isDef } from '../../utils/mixins'; import Property, { PropertyProps } from './Property'; -type SelectOption = { +interface SelectOption { id: string; value?: string; label?: string; @@ -12,7 +12,7 @@ type SelectOption = { title?: string; style?: string; propValue?: ObjectAny; -}; +} /** @private */ export interface PropertySelectProps extends PropertyProps { diff --git a/packages/core/src/utils/sorter/SorterUtils.ts b/packages/core/src/utils/sorter/SorterUtils.ts index 8cc05f690..de794ba06 100644 --- a/packages/core/src/utils/sorter/SorterUtils.ts +++ b/packages/core/src/utils/sorter/SorterUtils.ts @@ -144,7 +144,7 @@ export function closest(el: HTMLElement, selector: string): HTMLElement | undefi * @private */ export function isStyleInFlow(el: HTMLElement, parent: HTMLElement): boolean { - if (isTextNode(el)) return false; + if (!el || isTextNode(el)) return false; const elementStyles = el.style || {}; const $el = $(el); diff --git a/packages/core/test/specs/grapesjs/index.ts b/packages/core/test/specs/grapesjs/index.ts index d04c2a82a..ada107f7c 100644 --- a/packages/core/test/specs/grapesjs/index.ts +++ b/packages/core/test/specs/grapesjs/index.ts @@ -4,6 +4,7 @@ import ComponentWrapper from '../../../src/dom_components/model/ComponentWrapper import { EditorConfig } from '../../../src/editor/config/config'; import PluginsEvents, { Plugin } from '../../../src/plugin_manager/types'; import { StorageManagerConfig } from '../../../src/storage_manager/config/config'; +import { wait } from '../../../src/utils/mixins'; import { fixJsDom, fixJsDomIframe, waitEditorEvent } from '../../common'; type TestPlugin = Plugin<{ cVal: string }>; @@ -517,6 +518,28 @@ describe('GrapesJS', () => { expect(data).toEqual(projectData); }); + test('Allows retrying store after a storage failure', async () => { + const store = jest.fn().mockRejectedValueOnce(new Error('store failed')).mockResolvedValueOnce(undefined); + + (config.storageManager as StorageManagerConfig).type = storageId; + config.plugins = [ + (e) => + e.StorageManager.add(storageId, { + store, + async load() { + return {}; + }, + }), + ]; + const editor = initTestEditor(config); + + await expect(editor.store()).rejects.toThrow('store failed'); + await wait(2); + await editor.store(); + + expect(store).toHaveBeenCalledTimes(2); + }); + test('Adds a new storage and fetch correctly data from it', async () => { fixture.innerHTML = documentEl; const styleResult = { color: 'white', display: 'block' };