Skip to content

Commit febde03

Browse files
authored
Tools options (#134)
* Fix inputs and values attachments to be data-first * Load adapters as plugin * Fix tests * Review comments * (try to) fix test run for core package * Run base branch coverage manually * Fix unit-tests action: use ArtiomTr with pre-generated coverage files * Try just PR branch tests * Try clear before build * Try no cache * Use latest node * Review comments resolved * Resolve review comments * Add destoryBlockToolAdapter method to Adapter plugin * Block ID implementation * Fix lint * Fix tests * Fix build * Remove userId from getBlockSerialized method * Fix call in the block manager * Move all tool's static configuration properties to the single options property * review comments * Review comments
1 parent 82aed33 commit febde03

14 files changed

Lines changed: 284 additions & 175 deletions

File tree

packages/core/src/index.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import {
77
EventBus,
88
type InlineToolConstructor,
99
PluginType,
10-
ToolType
10+
ToolType,
11+
type ToolStaticOptions
1112
} from '@editorjs/sdk';
12-
import type { ToolSettings } from './tools/ToolsFactory';
1313
import { composeDataFromVersion2 } from './utils/composeDataFromVersion2.js';
1414
import ToolsManager from './tools/ToolsManager.js';
1515
import type { CoreConfigValidated, CoreConfig, EditorjsPluginConstructor, BlockTuneConstructor, ToolConstructable, EditorjsAdapterPluginConstructor } from '@editorjs/sdk';
@@ -126,9 +126,9 @@ export default class Core {
126126
/**
127127
* Injects Tool constructor and options into the container
128128
* @param tool - Tool constructor class (static `options` defines defaults merged with the second argument)
129-
* @param options - feature flags, `config` for the tool plugin, etc.
129+
* @param options - Overrides for the tool's static `options` (toolbox, title, config, shortcuts, etc.)
130130
*/
131-
public use(tool: ToolConstructable, options?: Omit<ToolSettings, 'class'>): Core;
131+
public use(tool: ToolConstructable, options?: ToolStaticOptions): Core;
132132
/**
133133
* Injects Plugin into the container to initialize on Editor's init
134134
* @param plugin - allows to pass any implementation of editor plugins
@@ -141,15 +141,15 @@ export default class Core {
141141
*/
142142
public use(
143143
pluginOrTool: ToolConstructable | EditorjsPluginConstructor | EditorjsAdapterPluginConstructor,
144-
options?: Omit<ToolSettings, 'class'>
144+
options?: ToolStaticOptions
145145
): Core {
146146
const pluginType = pluginOrTool.type;
147147

148148
switch (pluginType) {
149149
case ToolType.Block:
150150
case ToolType.Inline:
151151
case ToolType.Tune:
152-
this.#plugins.bind<[ToolConstructable, ToolSettings | undefined]>(pluginType).toConstantValue([pluginOrTool as ToolConstructable, options as ToolSettings | undefined]);
152+
this.#plugins.bind<[ToolConstructable, ToolStaticOptions | undefined]>(pluginType).toConstantValue([pluginOrTool as ToolConstructable, options]);
153153
break;
154154
case PluginType.Adapter:
155155
if (this.#plugins.isBound(PluginType.Adapter)) {
@@ -193,9 +193,9 @@ export default class Core {
193193
* Initalizes loaded tools
194194
*/
195195
async #initializeTools(): Promise<void> {
196-
const blockTools = this.#plugins.getAll<[BlockToolConstructor, ToolSettings]>(ToolType.Block);
197-
const inlineTools = this.#plugins.getAll<[InlineToolConstructor, ToolSettings]>(ToolType.Inline);
198-
const blockTunes = this.#plugins.getAll<[BlockTuneConstructor, ToolSettings]>(ToolType.Tune);
196+
const blockTools = this.#plugins.getAll<[BlockToolConstructor, ToolStaticOptions | undefined]>(ToolType.Block);
197+
const inlineTools = this.#plugins.getAll<[InlineToolConstructor, ToolStaticOptions | undefined]>(ToolType.Inline);
198+
const blockTunes = this.#plugins.getAll<[BlockTuneConstructor, ToolStaticOptions | undefined]>(ToolType.Tune);
199199

200200
return this.#toolsManager.prepareTools([...blockTools, ...inlineTools, ...blockTunes]);
201201
}

packages/core/src/tools/ToolsFactory.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
11
/* eslint-disable jsdoc/informative-docs */
22
import type { EditorAPI } from '@editorjs/sdk';
33
import { ToolType } from '@editorjs/sdk';
4-
import type { ToolConstructable } from '@editorjs/sdk';
4+
import type { ToolConstructable, ToolStaticOptions } from '@editorjs/sdk';
55
import {
66
InlineToolFacade,
77
BlockTuneFacade,
88
BlockToolFacade
99
} from '@editorjs/sdk';
1010
import type {
11-
EditorConfig,
12-
ToolSettings as ToolSettingsV2
11+
EditorConfig
1312
} from '@editorjs/editorjs';
1413

1514
type ToolConstructor = typeof InlineToolFacade | typeof BlockToolFacade | typeof BlockTuneFacade;
1615

1716
/**
18-
* Need this utility type to override some V2 options
17+
* Full tool registration entry: the constructor class plus its options.
1918
*/
20-
export type ToolSettings = Omit<ToolSettingsV2, 'constructable' | 'class'> & {
19+
export type ToolSettings = ToolStaticOptions & {
2120
/**
22-
* Redefine constructable to match V3
21+
* Tool's constructor
2322
*/
2423
class: ToolConstructable;
2524
};
@@ -70,10 +69,10 @@ export class ToolsFactory {
7069
* Register tools in the factory
7170
* @param tools - tools to register in the factory
7271
*/
73-
public setTools(tools: [ToolConstructable, ToolSettings][]): void {
72+
public setTools(tools: [ToolConstructable, ToolStaticOptions | undefined][]): void {
7473
tools.forEach(([tool, settings]) => {
7574
this.#toolsSettings.set(tool.name, {
76-
...settings,
75+
...(settings ?? {}),
7776
class: tool,
7877
});
7978
});

packages/core/src/tools/ToolsManager.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
ToolFacadeClass,
1515
ToolsCollection,
1616
EventBus,
17-
ToolConstructable
17+
type ToolConstructable,
18+
type ToolStaticOptions
1819
} from '@editorjs/sdk';
1920

2021
/**
@@ -105,7 +106,7 @@ export default class ToolsManager {
105106
* Calls tools prepare method if it exists and adds tools to relevant collection (available or unavailable tools)
106107
* @param tools - tools to prepare and their settings
107108
*/
108-
public async prepareTools(tools: [ToolConstructable, ToolSettings][]): Promise<void> {
109+
public async prepareTools(tools: [ToolConstructable, ToolStaticOptions | undefined][]): Promise<void> {
109110
const promiseQueue = new PromiseQueue();
110111

111112
const setToAvailableToolsCollection = (toolName: string, tool: ToolFacadeClass): void => {

packages/core/src/tools/internal/inline-tools/bold/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,19 @@ export class BoldInlineTool implements InlineTool {
1919
*/
2020
public static type = ToolType.Inline as const;
2121

22-
public static title = 'Bold';
22+
/**
23+
* Tool name used to identify the tool across the editor.
24+
*/
25+
public static name = 'bold';
2326

2427
/**
2528
* Predefined options (can be overriden on connection)
2629
*/
2730
public static readonly options = {
31+
/**
32+
* Tool title shown in the inline toolbar
33+
*/
34+
title: 'Bold',
2835
/**
2936
* Shortcuts plugin options
3037
*/

packages/core/src/tools/internal/inline-tools/italic/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,19 @@ export class ItalicInlineTool implements InlineTool {
1919
*/
2020
public static type = ToolType.Inline as const;
2121

22-
public static title = 'Italic';
22+
/**
23+
* Tool name used to identify the tool across the editor.
24+
*/
25+
public static name = 'italic';
2326

2427
/**
2528
* Default options (merged with second argument of `use(ItalicInlineTool, options)`).
2629
*/
2730
public static readonly options = {
31+
/**
32+
* Tool title shown in the inline toolbar
33+
*/
34+
title: 'Italic',
2835
/**
2936
* Shortcuts plugin options
3037
*/

packages/core/src/tools/internal/inline-tools/link/index.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,20 @@ export class LinkInlineTool implements InlineTool {
2626
*/
2727
public static type = ToolType.Inline as const;
2828

29-
public static title = 'Link';
29+
/**
30+
* Tool name used to identify the tool across the editor.
31+
*/
32+
public static name = 'link';
33+
34+
/**
35+
* Default options (merged with second argument of `use(LinkInlineTool, options)`).
36+
*/
37+
public static readonly options = {
38+
/**
39+
* Tool title shown in the inline toolbar
40+
*/
41+
title: 'Link',
42+
};
3043

3144
/**
3245
* Type of behaviour of the tool if new selection range intersect with existing fragment
Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,96 @@
11
import type { ToolConfig } from '@editorjs/editorjs';
2+
import type { BlockToolOptions } from './BlockTool.js';
3+
import type { InlineToolOptions } from './InlineTool.js';
4+
import type { BlockTuneOptions } from './BlockTune.js';
5+
import type { ToolType } from './EntityType.js';
26

37
/**
4-
* Common interface for Tools static properties
8+
* Canonical keys shared by every tool options interface.
59
*/
6-
export interface BaseToolConstructor<Config extends ToolConfig = ToolConfig> {
10+
export enum BaseToolOptionKey {
711
/**
8-
* Default tool options (`static get options()`) provided by the tool developer.
12+
* Plugin-specific configuration object passed to the tool instance.
913
*/
10-
options?: {
11-
/**
12-
* Internal tool configuration
13-
*/
14-
config?: Record<string, unknown>;
14+
Config = 'config'
15+
}
16+
17+
/**
18+
* Options common to every tool type.
19+
* @template Config - Shape of the plugin-specific {@link BaseToolOptionKey.Config} object.
20+
*/
21+
export interface BaseToolOptions<Config extends ToolConfig = ToolConfig> {
22+
/**
23+
* Plugin-specific configuration passed to the tool instance.
24+
* Defaults set here are merged with (and overridden by) the `config` key
25+
* in the second argument of `core.use(Tool, options)`.
26+
*/
27+
[BaseToolOptionKey.Config]?: Config;
28+
}
1529

16-
/**
17-
* Other tool options
18-
*/
19-
[key: string]: unknown;
20-
};
30+
// Re-export so consumers can import all option types from this file
31+
export type { BlockToolOptions, InlineToolOptions, BlockTuneOptions };
32+
33+
/**
34+
* Union of all per-tool option shapes.
35+
* Used as the type of the second argument of `core.use(Tool, options)`.
36+
*/
37+
export type ToolStaticOptions = BlockToolOptions | InlineToolOptions | BlockTuneOptions;
38+
39+
/**
40+
* Maps a {@link ToolType} value to its corresponding tool options interface.
41+
* @example
42+
* function getTitle<T extends ToolType>(type: T, options: ToolTypeToOptions[T]) { ... }
43+
*/
44+
export type ToolTypeToOptions = {
45+
/**
46+
* BlockTool Options
47+
*/
48+
[ToolType.Block]: BlockToolOptions;
49+
/**
50+
* InlineTool Options
51+
*/
52+
[ToolType.Inline]: InlineToolOptions;
53+
/**
54+
* BlockTune Options
55+
*/
56+
[ToolType.Tune]: BlockTuneOptions;
57+
};
58+
59+
/**
60+
* Common interface for Tool constructor (static) side.
61+
* @template Config - Shape of the plugin-specific config object. Passed to
62+
* {@link prepare} and used to type {@link options.config}.
63+
* @template Options - The concrete options interface for this tool type
64+
* (defaults to the generic {@link BaseToolOptions}).
65+
*/
66+
export interface BaseToolConstructor<
67+
Config extends ToolConfig = ToolConfig,
68+
Options extends BaseToolOptions<Config> = BaseToolOptions<Config>
69+
> {
70+
/**
71+
* Tool name used to identify the tool across the editor.
72+
* Falls back to the JavaScript class name if not explicitly set.
73+
*/
74+
name: string;
75+
76+
/**
77+
* All static configuration for the tool.
78+
* Values here are defaults; they can be overridden via the second argument
79+
* of `core.use(Tool, options)`.
80+
*/
81+
options?: Options;
2182

2283
/**
23-
* Tool's prepare method. Can be async
84+
* Tool's prepare method. Can be async.
2485
* @param data - Object with toolName and config properties
2586
* @param data.toolName - Tool's own name
26-
* @param data.config - Tool's configuration
87+
* @param data.config - Merged plugin configuration
2788
*/
2889
// eslint-disable-next-line -- ESLint doesn't understand it's a type
2990
prepare?(data: { toolName: string, config: Config }): void | Promise<void>;
3091

3192
/**
32-
* Tool's reset method to clean up anything set by prepare. Can be async
93+
* Tool's reset method to clean up anything set by prepare. Can be async.
3394
*/
3495
reset?(): void | Promise<void>;
3596
}

0 commit comments

Comments
 (0)