mirror of
https://github.com/codex-team/editor.js
synced 2024-05-10 10:26:46 +02:00
Merge data overrides with actual block data when inserting a block
This commit is contained in:
parent
f2fe90b65c
commit
eb0a59cc64
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
|
4
types/api/blocks.d.ts
vendored
4
types/api/blocks.d.ts
vendored
|
@ -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>;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue