Merge data overrides with actual block data when inserting a block

This commit is contained in:
Tanya Fomina 2022-06-05 13:01:46 +08:00
parent f2fe90b65c
commit eb0a59cc64
10 changed files with 104 additions and 90 deletions

View file

@ -228,15 +228,15 @@ export default class BlocksAPI extends Module {
* @param {boolean?} needToFocus - flag to focus inserted Block
* @param replace - pass true to replace the Block existed under passed index
*/
public insert = (
public insert = async (
type: string = this.config.defaultBlock,
data: BlockToolData = {},
config: ToolConfig = {},
index?: number,
needToFocus?: boolean,
replace?: boolean
): BlockAPIInterface => {
const insertedBlock = this.Editor.BlockManager.insert({
): Promise<BlockAPIInterface> => {
const insertedBlock = await this.Editor.BlockManager.insert({
tool: type,
data,
index,
@ -267,7 +267,7 @@ export default class BlocksAPI extends Module {
* @param id - id of the block to update
* @param data - the new data
*/
public update = (id: string, data: BlockToolData): void => {
public update = async (id: string, data: BlockToolData): Promise<void> => {
const { BlockManager } = this.Editor;
const block = BlockManager.getBlockById(id);
@ -278,8 +278,7 @@ export default class BlocksAPI extends Module {
}
const blockIndex = BlockManager.getBlockIndex(block);
BlockManager.insert({
await BlockManager.insert({
id: block.id,
tool: block.name,
data,

View file

@ -191,13 +191,13 @@ export default class BlockEvents extends Module {
return;
}
BlockSelection.copySelectedBlocks(event).then(() => {
BlockSelection.copySelectedBlocks(event).then(async () => {
const selectionPositionIndex = BlockManager.removeSelectedBlocks();
/**
* Insert default block in place of removed ones
*/
const insertedBlock = BlockManager.insertDefaultBlockAtIndex(selectionPositionIndex, true);
const insertedBlock = await BlockManager.insertDefaultBlockAtIndex(selectionPositionIndex, true);
Caret.setToBlock(insertedBlock, Caret.positions.START);
@ -211,7 +211,7 @@ export default class BlockEvents extends Module {
*
* @param {KeyboardEvent} event - keydown
*/
private enter(event: KeyboardEvent): void {
private async enter(event: KeyboardEvent): Promise<void> {
const { BlockManager, UI } = this.Editor;
const currentBlock = BlockManager.currentBlock;
@ -250,7 +250,7 @@ export default class BlockEvents extends Module {
* Split the Current Block into two blocks
* Renew local current node after split
*/
newCurrent = this.Editor.BlockManager.split();
newCurrent = await this.Editor.BlockManager.split();
}
this.Editor.Caret.setToBlock(newCurrent);

View file

@ -15,6 +15,7 @@ import { BlockToolData, PasteEvent } from '../../../types';
import { BlockTuneData } from '../../../types/block-tunes/block-tune-data';
import BlockAPI from '../block/api';
import { BlockMutationType } from '../../../types/events/block/mutation-type';
import BlockTool from '../tools/block';
/**
* @typedef {BlockManager} BlockManager
@ -232,23 +233,23 @@ export default class BlockManager extends Module {
*
* @returns {Block}
*/
public composeBlock({
public async composeBlock({
tool: name,
data = {},
id = undefined,
tunes: tunesData = {},
}: {tool: string; id?: string; data?: BlockToolData; tunes?: {[name: string]: BlockTuneData}}): Block {
}: { tool: string; id?: string; data?: BlockToolData; tunes?: { [name: string]: BlockTuneData } }): Promise<Block> {
const readOnly = this.Editor.ReadOnly.isEnabled;
const tool = this.Editor.Tools.blockTools.get(name);
const actialData = await this.composeBlockData(tool, data);
const block = new Block({
id,
data,
data: actialData,
tool,
api: this.Editor.API,
readOnly,
tunesData,
});
if (!readOnly) {
this.bindBlockEvents(block);
}
@ -269,7 +270,7 @@ export default class BlockManager extends Module {
*
* @returns {Block}
*/
public insert({
public async insert({
id = undefined,
tool = this.config.defaultBlock,
data = {},
@ -284,15 +285,14 @@ export default class BlockManager extends Module {
index?: number;
needToFocus?: boolean;
replace?: boolean;
tunes?: {[name: string]: BlockTuneData};
} = {}): Block {
tunes?: { [name: string]: BlockTuneData };
} = {}): Promise<Block> {
let newIndex = index;
if (newIndex === undefined) {
newIndex = this.currentBlockIndex + (replace ? 0 : 1);
}
const block = this.composeBlock({
const block = await this.composeBlock({
id,
tool,
data,
@ -339,7 +339,7 @@ export default class BlockManager extends Module {
public replace({
tool = this.config.defaultBlock,
data = {},
}): Block {
}): Promise<Block> {
return this.insert({
tool,
data,
@ -355,12 +355,12 @@ export default class BlockManager extends Module {
* @param {PasteEvent} pasteEvent - pasted data
* @param {boolean} replace - should replace current block
*/
public paste(
public async paste(
toolName: string,
pasteEvent: PasteEvent,
replace = false
): Block {
const block = this.insert({
): Promise<Block> {
const block = await this.insert({
tool: toolName,
replace,
});
@ -384,8 +384,8 @@ export default class BlockManager extends Module {
*
* @returns {Block} inserted Block
*/
public insertDefaultBlockAtIndex(index: number, needToFocus = false): Block {
const block = this.composeBlock({ tool: this.config.defaultBlock });
public async insertDefaultBlockAtIndex(index: number, needToFocus = false): Promise<Block> {
const block = await this.composeBlock({ tool: this.config.defaultBlock });
this._blocks[index] = block;
@ -410,7 +410,7 @@ export default class BlockManager extends Module {
*
* @returns {Block}
*/
public insertAtEnd(): Block {
public insertAtEnd(): Promise<Block> {
/**
* Define new value for current block index
*/
@ -534,7 +534,7 @@ export default class BlockManager extends Module {
*
* @returns {Block}
*/
public split(): Block {
public split(): Promise<Block> {
const extractedFragment = this.Editor.Caret.extractFragmentFromCaretPosition();
const wrapper = $.make('div');
@ -881,4 +881,24 @@ export default class BlockManager extends Module {
return block;
}
/**
* Retrieves default block data by creating fake block.
* Merges retrieved data with specified data object.
*
* @param tool - block's tool
* @param dataOverrides - object containing overrides for default block data
*/
private async composeBlockData(tool: BlockTool, dataOverrides = {}): Promise<BlockToolData> {
const block = new Block({
tool,
api: this.Editor.API,
readOnly: true,
data: {},
tunesData: {},
});
const blockData = await block.data;
return Object.assign(blockData, dataOverrides);
}
}

View file

@ -336,9 +336,9 @@ export default class Caret extends Module {
if (lastBlock.tool.isDefault && lastBlock.isEmpty) {
this.setToBlock(lastBlock);
} else {
const newBlock = this.Editor.BlockManager.insertAtEnd();
this.setToBlock(newBlock);
this.Editor.BlockManager.insertAtEnd().then(newBlock => {
this.setToBlock(newBlock);
});
}
}
@ -390,7 +390,7 @@ export default class Caret extends Module {
*
* @returns {boolean}
*/
public navigateNext(): boolean {
public async navigateNext(): Promise<boolean> {
const { BlockManager } = this.Editor;
const { currentBlock, nextContentfulBlock } = BlockManager;
const { nextInput } = currentBlock;
@ -417,7 +417,7 @@ export default class Caret extends Module {
* If there is no nextBlock, but currentBlock is not default,
* insert new default block at the end and navigate to it
*/
nextBlock = BlockManager.insertAtEnd();
nextBlock = await BlockManager.insertAtEnd();
}
if (isAtEnd) {

View file

@ -6,7 +6,6 @@ import {
PasteEvent,
PasteEventDetail
} from '../../../types';
import Block from '../block';
import { SavedData } from '../../../types/data-formats';
import { clean, sanitizeBlocks } from '../utils/sanitizer';
import BlockTool from '../tools/block';
@ -112,12 +111,12 @@ export default class Paste extends Module {
/**
* Tags` substitutions parameters
*/
private toolsTags: {[tag: string]: TagSubstitute} = {};
private toolsTags: { [tag: string]: TagSubstitute } = {};
/**
* Store tags to substitute by tool name
*/
private tagsByTool: {[tools: string]: string[]} = {};
private tagsByTool: { [tools: string]: string[] } = {};
/** Patterns` substitutions parameters */
private toolsPatterns: PatternSubstitute[] = [];
@ -186,7 +185,7 @@ export default class Paste extends Module {
this.insertEditorJSData(JSON.parse(editorJSData));
return;
} catch (e) {} // Do nothing and continue execution as usual if error appears
} catch (e) { } // Do nothing and continue execution as usual if error appears
}
/**
@ -449,7 +448,7 @@ export default class Paste extends Module {
private async processFiles(items: FileList): Promise<void> {
const { BlockManager } = this.Editor;
let dataToInsert: {type: string; event: PasteEvent}[];
let dataToInsert: { type: string; event: PasteEvent }[];
dataToInsert = await Promise.all(
Array
@ -473,7 +472,7 @@ export default class Paste extends Module {
*
* @param {File} file - file to process
*/
private async processFile(file: File): Promise<{event: PasteEvent; type: string}> {
private async processFile(file: File): Promise<{ event: PasteEvent; type: string }> {
const extension = _.getFileExtension(file);
const foundConfig = Object
@ -576,7 +575,7 @@ export default class Paste extends Module {
* @returns {PasteData[]}
*/
private processPlain(plain: string): PasteData[] {
const { defaultBlock } = this.config as {defaultBlock: string};
const { defaultBlock } = this.config as { defaultBlock: string };
if (!plain) {
return [];
@ -652,9 +651,9 @@ export default class Paste extends Module {
BlockManager.currentBlock.tool.isDefault &&
BlockManager.currentBlock.isEmpty;
const insertedBlock = BlockManager.paste(blockData.tool, blockData.event, needToReplaceCurrentBlock);
Caret.setToBlock(insertedBlock, Caret.positions.END);
BlockManager.paste(blockData.tool, blockData.event, needToReplaceCurrentBlock).then(insertedBlock => {
Caret.setToBlock(insertedBlock, Caret.positions.END);
});
return;
}
@ -681,7 +680,7 @@ export default class Paste extends Module {
*
* @returns {Promise<{event: PasteEvent, tool: string}>}
*/
private async processPattern(text: string): Promise<{event: PasteEvent; tool: string}> {
private async processPattern(text: string): Promise<{ event: PasteEvent; tool: string }> {
const pattern = this.toolsPatterns.find((substitute) => {
const execResult = substitute.pattern.exec(text);
@ -718,18 +717,16 @@ export default class Paste extends Module {
private insertBlock(data: PasteData, canReplaceCurrentBlock = false): void {
const { BlockManager, Caret } = this.Editor;
const { currentBlock } = BlockManager;
let block: Block;
if (canReplaceCurrentBlock && currentBlock && currentBlock.isEmpty) {
block = BlockManager.paste(data.tool, data.event, true);
Caret.setToBlock(block, Caret.positions.END);
return;
BlockManager.paste(data.tool, data.event, true).then(block => {
Caret.setToBlock(block, Caret.positions.END);
});
} else {
BlockManager.paste(data.tool, data.event).then(block => {
Caret.setToBlock(block, Caret.positions.END);
});
}
block = BlockManager.paste(data.tool, data.event);
Caret.setToBlock(block, Caret.positions.END);
}
/**
@ -754,13 +751,13 @@ export default class Paste extends Module {
needToReplaceCurrentBlock = isCurrentBlockDefault && BlockManager.currentBlock.isEmpty;
}
const block = BlockManager.insert({
BlockManager.insert({
tool,
data,
replace: needToReplaceCurrentBlock,
}).then(block => {
Caret.setToBlock(block, Caret.positions.END);
});
Caret.setToBlock(block, Caret.positions.END);
});
}

View file

@ -77,7 +77,7 @@ export default class Renderer extends Module {
if (Tools.available.has(tool)) {
try {
BlockManager.insert({
await BlockManager.insert({
id,
tool,
data,
@ -105,12 +105,11 @@ export default class Renderer extends Module {
stubData.title = toolboxTitle || stubData.title;
}
const stub = BlockManager.insert({
const stub = await BlockManager.insert({
id,
tool: Tools.stubTool,
data: stubData,
});
})
stub.stretched = true;
_.log(`Tool «${tool}» is not found. Check 'tools' property at your initial Editor.js config.`, 'warn');

View file

@ -514,19 +514,21 @@ export default class UI extends Module<UINodes> {
if (BlockSelection.anyBlockSelected && !Selection.isSelectionExists) {
const selectionPositionIndex = BlockManager.removeSelectedBlocks();
Caret.setToBlock(BlockManager.insertDefaultBlockAtIndex(selectionPositionIndex, true), Caret.positions.START);
BlockManager.insertDefaultBlockAtIndex(selectionPositionIndex, true).then(block => {
Caret.setToBlock(block, Caret.positions.START);
/** Clear selection */
BlockSelection.clearSelection(event);
/** Clear selection */
BlockSelection.clearSelection(event);
/**
* Stop propagations
* Manipulation with BlockSelections is handled in global backspacePress because they may occur
* with CMD+A or RectangleSelection and they can be handled on document event
*/
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
/**
* Stop propagations
* Manipulation with BlockSelections is handled in global backspacePress because they may occur
* with CMD+A or RectangleSelection and they can be handled on document event
*/
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
});
}
}
@ -596,19 +598,19 @@ export default class UI extends Module<UINodes> {
/**
* Insert the default typed Block
*/
const newBlock = this.Editor.BlockManager.insert();
this.Editor.BlockManager.insert().then(newBlock => {
this.Editor.Caret.setToBlock(newBlock);
this.Editor.Caret.setToBlock(newBlock);
/**
* And highlight
*/
this.Editor.BlockManager.highlightCurrentNode();
/**
* And highlight
*/
this.Editor.BlockManager.highlightCurrentNode();
/**
* Move toolbar and show plus button because new Block is empty
*/
this.Editor.Toolbar.moveAndOpen(newBlock);
/**
* Move toolbar and show plus button because new Block is empty
*/
this.Editor.Toolbar.moveAndOpen(newBlock);
});
}
this.Editor.BlockSelection.clearSelection(event);

View file

@ -379,7 +379,7 @@ export default class Toolbox extends EventsDispatcher<ToolboxEvent> {
* @param {string} toolName - Tool name
* @param blockDataOverrides - predefined Block data
*/
private insertNewBlock(toolName: string, blockDataOverrides?: BlockToolData): void {
private async insertNewBlock(toolName: string, blockDataOverrides?: BlockToolData): Promise<void> {
const currentBlockIndex = this.api.blocks.getCurrentBlockIndex();
const currentBlock = this.api.blocks.getBlockByIndex(currentBlockIndex);
@ -393,7 +393,7 @@ export default class Toolbox extends EventsDispatcher<ToolboxEvent> {
*/
const index = currentBlock.isEmpty ? currentBlockIndex : currentBlockIndex + 1;
const newBlock = this.api.blocks.insert(
const newBlock = await this.api.blocks.insert(
toolName,
blockDataOverrides,
undefined,

View file

@ -65,8 +65,7 @@ describe('api.blocks', () => {
const newBlockData = {
text: 'Updated text',
};
editor.blocks.update(idToUpdate, newBlockData);
await editor.blocks.update(idToUpdate, newBlockData);
cy.get('[data-cy=editorjs]')
.get('div.ce-block')
@ -86,12 +85,10 @@ describe('api.blocks', () => {
const newBlockData = {
text: 'Updated text',
};
editor.blocks.update(idToUpdate, newBlockData);
await editor.blocks.update(idToUpdate, newBlockData);
const output = await (editor as any).save();
const text = output.blocks[0].data.text;
expect(text).to.be.eq(newBlockData.text);
});
});

View file

@ -110,7 +110,7 @@ export interface Blocks {
index?: number,
needToFocus?: boolean,
replace?: boolean,
): BlockAPI;
): Promise<BlockAPI>;
/**
@ -119,5 +119,5 @@ export interface Blocks {
* @param id - id of the block to update
* @param data - the new data
*/
update(id: string, data: BlockToolData): void;
update(id: string, data: BlockToolData): Promise<void>;
}