Skip to content

Commit 4fa0cd4

Browse files
committed
Implement some BlocksAPI method
1 parent 6fbd035 commit 4fa0cd4

File tree

5 files changed

+259
-42
lines changed

5 files changed

+259
-42
lines changed

packages/core/src/api/BlocksAPI.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { BlocksManager } from '../components/BlockManager.js';
44
import { BlockToolData, ToolConfig } from '@editorjs/editorjs';
55
import { CoreConfigValidated } from '@editorjs/sdk';
66
import { BlocksAPI as BlocksApiInterface } from '@editorjs/sdk';
7+
import { type BlockNodeSerialized, EditorDocumentSerialized } from '@editorjs/model';
78

89
/**
910
* Blocks API
@@ -28,12 +29,60 @@ export class BlocksAPI implements BlocksApiInterface {
2829
*/
2930
constructor(
3031
blocksManager: BlocksManager,
31-
@Inject('EditorConfig') config: CoreConfigValidated
32+
@Inject('EditorConfig') config: CoreConfigValidated
3233
) {
3334
this.#blocksManager = blocksManager;
3435
this.#config = config;
3536
}
3637

38+
/**
39+
* Remove all blocks from Document
40+
*/
41+
public clear(): void {
42+
return this.#blocksManager.clear();
43+
}
44+
45+
/**
46+
* Render passed data
47+
* @param document - serialized document data to render
48+
*/
49+
public render(document: EditorDocumentSerialized): void {
50+
return this.#blocksManager.render(document);
51+
}
52+
53+
/**
54+
* Removes Block by index, or current block if index is not passed
55+
* @param index - index of a block to delete
56+
*/
57+
public delete(index?: number): void {
58+
return this.#blocksManager.deleteBlock(index);
59+
}
60+
61+
/**
62+
* Moves a block to a new index
63+
* @param toIndex - index where the block is moved to
64+
* @param [fromIndex] - block to move. Current block if not passed
65+
*/
66+
public move(toIndex: number, fromIndex?: number): void {
67+
return this.#blocksManager.move(toIndex, fromIndex);
68+
}
69+
70+
/**
71+
* Returns Blocks count
72+
*/
73+
public getBlocksCount(): number {
74+
return this.#blocksManager.blocksCount;
75+
}
76+
77+
/**
78+
* Inserts several Blocks to specified index
79+
* @param blocks - array of blocks to insert
80+
* @param [index] - index to insert blocks at. If undefined, inserts at the end
81+
*/
82+
public insertMany(blocks: BlockNodeSerialized[], index?: number): void {
83+
return this.#blocksManager.insertMany(blocks, index);
84+
}
85+
3786
/**
3887
* Inserts a new block to the editor
3988
* @param type - Block tool name to insert
@@ -62,6 +111,7 @@ export class BlocksAPI implements BlocksApiInterface {
62111
data,
63112
index,
64113
replace,
114+
// needToFocus,
65115
});
66116
}
67117
}

packages/core/src/components/BlockManager.ts

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { BlockAddedEvent, BlockRemovedEvent, EditorJSModel, EventType, ModelEvents } from '@editorjs/model';
1+
import {
2+
BlockAddedEvent, type BlockNodeSerialized,
3+
BlockRemovedEvent,
4+
type EditorDocumentSerialized,
5+
EditorJSModel,
6+
EventType,
7+
ModelEvents
8+
} from '@editorjs/model';
29
import 'reflect-metadata';
310
import { Inject, Service } from 'typedi';
411
import { BlockToolAdapter, CaretAdapter, FormattingAdapter } from '@editorjs/dom-adapters';
@@ -68,6 +75,13 @@ export class BlocksManager {
6875
*/
6976
#formattingAdapter: FormattingAdapter;
7077

78+
/**
79+
* Returns Blocks count
80+
*/
81+
public get blocksCount(): number {
82+
return this.#model.length;
83+
}
84+
7185
/**
7286
* BlocksManager constructor
7387
* All parameters are injected thorugh the IoC container
@@ -102,6 +116,7 @@ export class BlocksManager {
102116
* @param parameters.type - block tool name to insert
103117
* @param parameters.data - block's initial data
104118
* @param parameters.index - index to insert block at
119+
// * @param parameters.needToFocus - flag indicates if caret should be set to block after insert
105120
* @param parameters.replace - flag indicates if block at index should be replaced
106121
*/
107122
public insert({
@@ -119,10 +134,78 @@ export class BlocksManager {
119134
newIndex = this.#model.length + (replace ? 0 : 1);
120135
}
121136

137+
if (replace) {
138+
this.#model.removeBlock(this.#config.userId, newIndex);
139+
}
140+
122141
this.#model.addBlock(this.#config.userId, {
123142
...data,
124143
name: type,
125-
}, index);
144+
}, newIndex);
145+
}
146+
147+
/**
148+
* Inserts several Blocks to specified index
149+
* @param blocks - array of blocks to insert
150+
* @param [index] - index to insert blocks at. If undefined, inserts at the end
151+
*/
152+
public insertMany(blocks: BlockNodeSerialized[], index: number = this.#model.length + 1): void {
153+
blocks.forEach((block, i) => this.#model.addBlock(this.#config.userId, block, index + i));
154+
}
155+
156+
/**
157+
* Re-initialize document
158+
* @param document - serialized document data
159+
*/
160+
public render(document: EditorDocumentSerialized): void {
161+
this.#model.initializeDocument(document);
162+
}
163+
164+
/**
165+
* Remove all blocks from Document
166+
*/
167+
public clear(): void {
168+
this.#model.clearBlocks();
169+
}
170+
171+
/**
172+
* Removes Block by index, or current block if index is not passed
173+
* @param index - index of a block to delete
174+
*/
175+
public deleteBlock(index: number | undefined = this.#getCurrentBlockIndex()): void {
176+
if (index === undefined) {
177+
/**
178+
* @todo see what happens in legacy
179+
*/
180+
throw new Error('No block selected to delete');
181+
}
182+
183+
this.#model.removeBlock(this.#config.userId, index);
184+
}
185+
186+
/**
187+
* Moves a block to a new index
188+
* @param toIndex - index where the block is moved to
189+
* @param [fromIndex] - block to move. Current block if not passed
190+
*/
191+
public move(toIndex: number, fromIndex: number | undefined = this.#getCurrentBlockIndex()): void {
192+
if (fromIndex === undefined) {
193+
throw new Error('No block selected to move');
194+
}
195+
196+
const block = this.#model.serialized.blocks[fromIndex];
197+
198+
this.#model.removeBlock(this.#config.userId, fromIndex);
199+
this.#model.addBlock(this.#config.userId, block, toIndex + (fromIndex <= toIndex ? 1 : 0));
200+
}
201+
202+
/**
203+
* Returns block index where user caret is placed
204+
*/
205+
#getCurrentBlockIndex(): number | undefined {
206+
const caretIndex = this.#caretAdapter.userCaretIndex;
207+
208+
return caretIndex?.blockIndex;
126209
}
127210

128211
/**

packages/model/src/EditorJSModel.ts

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Stryker disable all -- we don't count mutation test coverage fot this file as it just proxy calls to EditorDocument
22
/* istanbul ignore file -- we don't count test coverage fot this file as it just proxy calls to EditorDocument */
3-
import { type Index, IndexBuilder } from './entities/index.js';
3+
import { type EditorDocumentSerialized, type Index, IndexBuilder } from './entities/index.js';
44
import { type BlockNodeSerialized, EditorDocument } from './entities/index.js';
55
import {
66
BlockAddedEvent,
@@ -108,11 +108,17 @@ export class EditorJSModel extends EventBus {
108108
/**
109109
* Fills the EditorDocument with the provided blocks.
110110
*
111-
* @param doc - document options
112-
* @param doc.blocks - The blocks to fill the EditorDocument with.
111+
* @param document - document data to initialize
113112
*/
114-
public initializeDocument({ blocks }: { blocks: BlockNodeSerialized[] }): void {
115-
this.#document.initialize(blocks);
113+
public initializeDocument(document: Partial<EditorDocumentSerialized> & Pick<EditorDocumentSerialized, 'blocks'>): void {
114+
this.#document.initialize(document);
115+
}
116+
117+
/**
118+
* Clear all blocks
119+
*/
120+
public clearBlocks(): void {
121+
this.#document.clear();
116122
}
117123

118124
/**
@@ -193,21 +199,6 @@ export class EditorJSModel extends EventBus {
193199
return this.#document.addBlock(...parameters);
194200
}
195201

196-
/**
197-
* Moves a BlockNode from one index to another
198-
*
199-
* @param _userId - user identifier which is being set to the context
200-
* @param parameters = moveBlock method parameters
201-
* @param parameters.from - The index of the BlockNode to move
202-
* @param parameters.to - The index to move the BlockNode to
203-
* @throws Error if the index is out of bounds
204-
*/
205-
@WithContext
206-
public moveBlock(_userId: string | number, ...parameters: Parameters<EditorDocument['moveBlock']>): ReturnType<EditorDocument['moveBlock']> {
207-
return this.#document.moveBlock(...parameters);
208-
}
209-
210-
211202
/**
212203
* Removes a BlockNode from the EditorDocument at the specified index.
213204
*

packages/model/src/entities/EditorDocument/index.ts

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,23 @@ export class EditorDocument extends EventBus {
7979
/**
8080
* Initializes EditorDocument with passed blocks
8181
*
82-
* @param blocks - document serialized blocks
82+
* @param document - document serialized data
8383
*/
84-
public initialize(blocks: BlockNodeSerialized[]): void {
84+
public initialize(document: Partial<EditorDocumentSerialized> & Pick<EditorDocumentSerialized, 'blocks'>): void {
8585
this.clear();
8686

87-
blocks.forEach((block) => {
87+
if (document.identifier !== undefined) {
88+
this.identifier = document.identifier as DocumentId;
89+
}
90+
91+
document.blocks.forEach((block) => {
8892
this.addBlock(block);
8993
});
94+
95+
if (document.properties) {
96+
Object.entries(document.properties)
97+
.forEach(([name, value]) => this.setProperty(name, value));
98+
}
9099
}
91100

92101
/**
@@ -137,22 +146,6 @@ export class EditorDocument extends EventBus {
137146
this.dispatchEvent(new BlockAddedEvent(builder.build(), blockNode.serialized, getContext<string | number>()!));
138147
}
139148

140-
/**
141-
* Moves a BlockNode from one index to another
142-
*
143-
* @param from - The index of the BlockNode to move
144-
* @param to - The index to move the BlockNode to
145-
* @throws Error if the index is out of bounds
146-
*/
147-
public moveBlock(from: number, to: number): void {
148-
this.#checkIndexOutOfBounds(from);
149-
this.#checkIndexOutOfBounds(to);
150-
151-
const blockToMove = this.#children.splice(from, 1)[0];
152-
153-
this.#children.splice(to, 0, blockToMove);
154-
}
155-
156149
/**
157150
* Removes a BlockNode from the EditorDocument at the specified index.
158151
*

0 commit comments

Comments
 (0)