diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 978c58ac..2e2d81a8 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -8,7 +8,7 @@ - `Fix` — Resolve compiler error from importing the BlockToolData type. - `Fix` — Resolved a problem when document was being scrolled to the beginning after moving up a Block above the viewport. - `Improvement` — Package size reduced by removing redundant files -- `Fix`- Entire block being deleted on backspace key press when the browser has 3rd party grammer checker extension +- `Fix`- Several bugs caused by random browser extensions ### 2.26.5 diff --git a/package.json b/package.json index 30ba45d0..7c4a26bf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@editorjs/editorjs", - "version": "2.27.0-rc.3", + "version": "2.27.0-rc.4", "description": "Editor.js — Native JS, based on API and Open Source", "main": "dist/editor.js", "types": "./types/index.d.ts", diff --git a/src/components/block/index.ts b/src/components/block/index.ts index f7632936..642ed483 100644 --- a/src/components/block/index.ts +++ b/src/components/block/index.ts @@ -153,6 +153,11 @@ export default class Block extends EventsDispatcher { */ private cachedInputs: HTMLElement[] = []; + /** + * We'll store a reference to the tool's rendered element to access it later + */ + private toolRenderedElement: HTMLElement | null = null; + /** * Tool class instance */ @@ -553,23 +558,7 @@ export default class Block extends EventsDispatcher { * @returns {HTMLElement} */ public get pluginsContent(): HTMLElement { - const blockContentNodes = this.holder.querySelector(`.${Block.CSS.content}`); - - if (blockContentNodes && blockContentNodes.childNodes.length) { - /** - * Editors Block content can contain different Nodes from extensions - * We use DOM isExtensionNode to ignore such Nodes and return first Block that does not match filtering list - */ - for (let child = blockContentNodes.childNodes.length - 1; child >= 0; child--) { - const contentNode = blockContentNodes.childNodes[child]; - - if (!$.isExtensionNode(contentNode)) { - return contentNode as HTMLElement; - } - } - } - - return null; + return this.toolRenderedElement; } /** @@ -825,7 +814,12 @@ export default class Block extends EventsDispatcher { contentNode = $.make('div', Block.CSS.content), pluginsContent = this.toolInstance.render(); - contentNode.appendChild(pluginsContent); + /** + * Saving a reference to plugin's content element for guaranteed accessing it later + */ + this.toolRenderedElement = pluginsContent; + + contentNode.appendChild(this.toolRenderedElement); /** * Block Tunes might wrap Block's content node to provide any UI changes diff --git a/src/components/dom.ts b/src/components/dom.ts index 62405423..52aff5ba 100644 --- a/src/components/dom.ts +++ b/src/components/dom.ts @@ -550,26 +550,6 @@ export default class Dom { return element; } - /** - * Method checks passed Node if it is some extension Node - * - * @param {Node} node - any node - * @returns {boolean} - */ - public static isExtensionNode(node: Node): boolean { - const extensions = [ - 'grammarly-extension', - 'mci-extension', - 'gdiv', - 'pwa-container-wrapper', - 'pwa-editor-bar-cnt', - 'editor-squiggler', - 'quillbot-extension', - ]; - - return node && extensions.includes(node.nodeName.toLowerCase()); - } - /** * Returns true if element is anchor (is A tag) * diff --git a/test/cypress/tests/modules/Saver.spec.ts b/test/cypress/tests/modules/Saver.spec.ts new file mode 100644 index 00000000..7a28037d --- /dev/null +++ b/test/cypress/tests/modules/Saver.spec.ts @@ -0,0 +1,37 @@ +import type EditorJS from '../../../../types/index'; + +describe('Saver module', function () { + describe('save()', function () { + it('should correctly save block if there are some 3rd party (eg. browser extensions) nodes inserted into the layout', function () { + cy.createEditor({ + data: { + blocks: [ + { + type: 'paragraph', + data: { + text: 'The block with some text', + }, + }, + ], + }, + }).then((editor: EditorJS) => { + /** + * Add some node just like browser extensions doing + */ + const extensionNode = document.createElement('extension-node'); + + cy.get('[data-cy=editorjs]') + .find('.ce-block__content') + .then((blockContent) => { + blockContent.append(extensionNode); + }) + .then(async () => { + const savedData = await editor.save(); + + expect(savedData.blocks.length).to.equal(1); + expect(savedData.blocks[0].data.text).to.equal('The block with some text'); + }); + }); + }); + }); +});