diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml new file mode 100644 index 00000000..61aa925e --- /dev/null +++ b/.github/workflows/core.yml @@ -0,0 +1,22 @@ +name: Core check +on: + pull_request: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run ESLint check + uses: ./.github/actions/lint + with: + package-name: '@editorjs/core' + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build the package + uses: ./.github/actions/build + with: + package-name: '@editorjs/core' \ No newline at end of file diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml new file mode 100644 index 00000000..9985de18 --- /dev/null +++ b/.github/workflows/sdk.yml @@ -0,0 +1,22 @@ +name: SDK check +on: + pull_request: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run ESLint check + uses: ./.github/actions/lint + with: + package-name: '@editorjs/sdk' + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build the package + uses: ./.github/actions/build + with: + package-name: '@editorjs/sdk' \ No newline at end of file diff --git a/packages/core/eslint.config.mjs b/packages/core/eslint.config.mjs index 99a05ca5..817f054f 100644 --- a/packages/core/eslint.config.mjs +++ b/packages/core/eslint.config.mjs @@ -21,6 +21,14 @@ export default [ ], ignoreTypeImport: true, }], + // @todo: remove when we setup eslint to correctly handle the types + 'n/no-missing-import': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + '@typescript-eslint/no-missing-import': 'off', + '@typescript-eslint/no-unsafe-return': 'off', }, }, ]; diff --git a/packages/core/package.json b/packages/core/package.json index 61663469..b6dea246 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -8,7 +8,7 @@ "build": "yarn clear && tsc --build tsconfig.build.json", "dev": "yarn build --watch", "lint": "eslint ./src", - "lint:ci": "yarn lint --max-warnings 0", + "lint:ci": "eslint --config ./eslint.config.mjs ./src --max-warnings 0", "lint:fix": "yarn lint --fix", "clear": "rm -rf ./dist && rm -rf ./tsconfig.build.tsbuildinfo" }, diff --git a/packages/core/src/api/BlocksAPI.ts b/packages/core/src/api/BlocksAPI.ts index 8fbced92..4813fcef 100644 --- a/packages/core/src/api/BlocksAPI.ts +++ b/packages/core/src/api/BlocksAPI.ts @@ -2,14 +2,15 @@ import 'reflect-metadata'; import { Inject, Service } from 'typedi'; import { BlocksManager } from '../components/BlockManager.js'; import { BlockToolData, ToolConfig } from '@editorjs/editorjs'; -import { CoreConfigValidated } from '../entities/index.js'; +import { CoreConfigValidated } from '@editorjs/sdk'; +import { BlocksAPI as BlocksApiInterface } from '@editorjs/sdk'; /** * Blocks API * - provides methods to work with blocks */ @Service() -export class BlocksAPI { +export class BlocksAPI implements BlocksApiInterface { /** * BlocksManager instance to work with blocks */ @@ -58,7 +59,6 @@ export class BlocksAPI { ): void { this.#blocksManager.insert({ type, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment data, index, replace, diff --git a/packages/core/src/api/SelectionAPI.ts b/packages/core/src/api/SelectionAPI.ts index 7985ab75..b50eae25 100644 --- a/packages/core/src/api/SelectionAPI.ts +++ b/packages/core/src/api/SelectionAPI.ts @@ -4,13 +4,14 @@ import { Service } from 'typedi'; import { SelectionManager } from '../components/SelectionManager.js'; import { createInlineToolName } from '@editorjs/model'; import { InlineToolFormatData } from '@editorjs/sdk'; +import { SelectionAPI as SelectionApiInterface } from '@editorjs/sdk'; /** * Selection API class * - provides methods to work with selection */ @Service() -export class SelectionAPI { +export class SelectionAPI implements SelectionApiInterface { #selectionManager: SelectionManager; /** diff --git a/packages/core/src/api/index.ts b/packages/core/src/api/index.ts index de454453..d8dcc517 100644 --- a/packages/core/src/api/index.ts +++ b/packages/core/src/api/index.ts @@ -1,5 +1,6 @@ import 'reflect-metadata'; import { Inject, Service } from 'typedi'; +import { EditorAPI as EditorApiInterface } from '@editorjs/sdk'; import { BlocksAPI } from './BlocksAPI.js'; import { SelectionAPI } from './SelectionAPI.js'; @@ -7,7 +8,7 @@ import { SelectionAPI } from './SelectionAPI.js'; * Class gathers all Editor's APIs */ @Service() -export class EditorAPI { +export class EditorAPI implements EditorApiInterface { /** * Blocks API instance to work with blocks */ diff --git a/packages/core/src/components/BlockManager.ts b/packages/core/src/components/BlockManager.ts index c44207e7..81320fff 100644 --- a/packages/core/src/components/BlockManager.ts +++ b/packages/core/src/components/BlockManager.ts @@ -4,9 +4,7 @@ import { Inject, Service } from 'typedi'; import { BlockToolAdapter, CaretAdapter, FormattingAdapter } from '@editorjs/dom-adapters'; import ToolsManager from '../tools/ToolsManager.js'; import { BlockAPI, BlockToolData } from '@editorjs/editorjs'; -import { CoreConfigValidated } from '../entities/Config.js'; -import { BlockAddedCoreEvent, BlockRemovedCoreEvent } from './EventBus/index.js'; -import { EventBus } from '@editorjs/sdk'; +import { CoreConfigValidated, EventBus, BlockAddedCoreEvent, BlockRemovedCoreEvent } from '@editorjs/sdk'; /** * Parameters for the BlocksManager.insert() method */ @@ -121,7 +119,6 @@ export class BlocksManager { newIndex = this.#model.length + (replace ? 0 : 1); } - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this.#model.addBlock(this.#config.userId, { ...data, name: type, diff --git a/packages/core/src/components/EventBus/index.ts b/packages/core/src/components/EventBus/index.ts deleted file mode 100644 index de6b54e0..00000000 --- a/packages/core/src/components/EventBus/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { Event } from '@editorjs/sdk'; - -export type CoreEvent = Event<'core', Name>; - -export * from './core-events/index.js'; -export * from './ui-events/index.js'; diff --git a/packages/core/src/components/EventBus/ui-events/index.ts b/packages/core/src/components/EventBus/ui-events/index.ts deleted file mode 100644 index c56c0551..00000000 --- a/packages/core/src/components/EventBus/ui-events/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './UIEventBase.js'; diff --git a/packages/core/src/components/SelectionManager.ts b/packages/core/src/components/SelectionManager.ts index 0f928f94..b708abc8 100644 --- a/packages/core/src/components/SelectionManager.ts +++ b/packages/core/src/components/SelectionManager.ts @@ -3,10 +3,8 @@ import { FormattingAdapter } from '@editorjs/dom-adapters'; import type { CaretManagerEvents, InlineFragment, InlineToolName } from '@editorjs/model'; import { CaretManagerCaretUpdatedEvent, Index, EditorJSModel, createInlineToolData, createInlineToolName } from '@editorjs/model'; import { EventType } from '@editorjs/model'; -import { CoreEventType, ToolLoadedCoreEvent } from './EventBus/index.js'; -import { EventBus } from '@editorjs/sdk'; +import { CoreEventType, ToolLoadedCoreEvent, EventBus, SelectionChangedCoreEvent } from '@editorjs/sdk'; import { Inject, Service } from 'typedi'; -import { SelectionChangedCoreEvent } from './EventBus/core-events/SelectionChangedCoreEvent.js'; import { type CoreConfig, InlineTool, InlineToolFormatData } from '@editorjs/sdk'; /** @@ -61,7 +59,7 @@ export class SelectionManager { this.#eventBus.addEventListener(`core:${CoreEventType.ToolLoaded}`, (event: ToolLoadedCoreEvent) => { const { tool } = event.detail; - if (!tool.isInline()) { + if ('isInline' in tool && tool.isInline() === false) { return; } diff --git a/packages/core/src/entities/Config.ts b/packages/core/src/entities/Config.ts deleted file mode 100644 index c04ccf07..00000000 --- a/packages/core/src/entities/Config.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { CoreConfig } from '@editorjs/sdk'; - -/** - * After validation we can be sure that all required fields are set - */ -export type CoreConfigValidated = Required; diff --git a/packages/core/src/entities/index.ts b/packages/core/src/entities/index.ts deleted file mode 100644 index 45f04ac4..00000000 --- a/packages/core/src/entities/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './Config.js'; -export * from './UnifiedToolConfig.js'; -export * from './EditorjsPlugin.js'; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 2e555cda..af8ad288 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -2,16 +2,13 @@ import { CollaborationManager } from '@editorjs/collaboration-manager'; import { type DocumentId, EditorJSModel, EventType } from '@editorjs/model'; import type { ContainerInstance } from 'typedi'; import { Container } from 'typedi'; -import { CoreEventType } from './components/EventBus/index.js'; -import { EventBus, UiComponentType } from '@editorjs/sdk'; +import { CoreEventType, EventBus, UiComponentType } from '@editorjs/sdk'; import { composeDataFromVersion2 } from './utils/composeDataFromVersion2.js'; import ToolsManager from './tools/ToolsManager.js'; import { CaretAdapter, FormattingAdapter } from '@editorjs/dom-adapters'; -import type { CoreConfigValidated } from './entities/Config.js'; -import type { CoreConfig } from '@editorjs/sdk'; +import type { CoreConfigValidated, CoreConfig, EditorjsPluginConstructor } from '@editorjs/sdk'; import { BlocksManager } from './components/BlockManager.js'; import { SelectionManager } from './components/SelectionManager.js'; -import type { EditorjsPluginConstructor } from './entities/EditorjsPlugin.js'; import { EditorAPI } from './api/index.js'; import { generateId } from './utils/uid.js'; @@ -163,7 +160,7 @@ export default class Core { /** * Get all registered plugin types from the container */ - const pluginTypes = Object.values(UiComponentType) as string[]; + const pluginTypes = Object.values(UiComponentType); for (const pluginType of pluginTypes) { const plugin = this.#iocContainer.get(pluginType); @@ -204,7 +201,7 @@ export default class Core { } } - if (config.data) { + if (config.data !== undefined) { if (config.data.blocks === undefined) { throw new Error('Editor configuration should contain blocks'); } @@ -219,11 +216,3 @@ export default class Core { } } } - -/** - * @todo move to "sdk" package - */ -export type * from './entities/index.js'; -export * from './components/EventBus/index.js'; -export * from './api/index.js'; -export * from './tools/facades/index.js'; diff --git a/packages/core/src/tools/facades/ToolsFactory.ts b/packages/core/src/tools/ToolsFactory.ts similarity index 77% rename from packages/core/src/tools/facades/ToolsFactory.ts rename to packages/core/src/tools/ToolsFactory.ts index 8dd38a1f..e6db40f2 100644 --- a/packages/core/src/tools/facades/ToolsFactory.ts +++ b/packages/core/src/tools/ToolsFactory.ts @@ -1,18 +1,20 @@ /* eslint-disable jsdoc/informative-docs */ -import type { BlockToolConstructor, InlineToolConstructor } from '@editorjs/sdk'; -import { InternalInlineToolSettings, InternalTuneSettings } from './BaseToolFacade.js'; -import { InlineToolFacade } from './InlineToolFacade.js'; -import { BlockTuneFacade } from './BlockTuneFacade.js'; -import { BlockToolFacade } from './BlockToolFacade.js'; -// import type ApiModule from '../modules/api'; +import type { BlockToolConstructor, EditorAPI, InlineToolConstructor, UnifiedToolConfig } from '@editorjs/sdk'; +import { + InternalInlineToolSettings, + InternalTuneSettings, + InlineToolFacade, + BlockTuneFacade, + BlockToolFacade +} from '@editorjs/sdk'; ; import type { ToolConstructable, EditorConfig, InlineToolConstructable, BlockTuneConstructable } from '@editorjs/editorjs'; -import type { UnifiedToolConfig } from '../../entities/UnifiedToolConfig.js'; +// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents type ToolConstructor = typeof InlineToolFacade | typeof BlockToolFacade | typeof BlockTuneFacade; /** @@ -27,8 +29,8 @@ export class ToolsFactory { /** * EditorJS API Module */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - private api: any; + + private api: EditorAPI; /** * EditorJS configuration @@ -47,7 +49,6 @@ export class ToolsFactory { // eslint-disable-next-line @typescript-eslint/no-explicit-any api: any ) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this.api = api; this.config = config; this.editorConfig = editorConfig; @@ -57,13 +58,13 @@ export class ToolsFactory { * Returns Tool object based on it's type * @param name - tool name */ + // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents public get(name: string): InlineToolFacade | BlockToolFacade | BlockTuneFacade { const { class: constructable, isInternal = false, ...config } = this.config[name]; const Constructor = this.getConstructor(constructable); // const isTune = constructable[InternalTuneSettings.IsTune]; - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument return new Constructor({ name, constructable, @@ -84,6 +85,7 @@ export class ToolsFactory { * Find appropriate Tool object constructor for Tool constructable * @param constructable - Tools constructable */ + // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents private getConstructor(constructable: ToolConstructable | BlockToolConstructor | InlineToolConstructor): ToolConstructor { switch (true) { case (constructable as InlineToolConstructable)[InternalInlineToolSettings.IsInline]: diff --git a/packages/core/src/tools/ToolsManager.ts b/packages/core/src/tools/ToolsManager.ts index 7644e313..bc4b5a06 100644 --- a/packages/core/src/tools/ToolsManager.ts +++ b/packages/core/src/tools/ToolsManager.ts @@ -1,27 +1,30 @@ -import type { BlockToolConstructor } from '@editorjs/sdk'; +import type { + BlockToolConstructor, + UnifiedToolConfig +} from '@editorjs/sdk'; import 'reflect-metadata'; import { deepMerge, isFunction, isObject, PromiseQueue } from '@editorjs/helpers'; import { Inject, Service } from 'typedi'; -import { - BlockToolFacade, BlockTuneFacade, - InlineToolFacade, - ToolFacadeClass, - ToolsCollection, - ToolsFactory -} from './facades/index.js'; +import { ToolsFactory } from './ToolsFactory.js'; import { Paragraph } from './internal/block-tools/paragraph/index.js'; import type { EditorConfig, ToolConstructable, ToolSettings } from '@editorjs/editorjs'; -import { InlineTool, InlineToolConstructor } from '@editorjs/sdk'; -import type { UnifiedToolConfig } from '../entities/index.js'; +import { + InlineTool, + InlineToolConstructor, + ToolLoadedCoreEvent, + BlockToolFacade, BlockTuneFacade, + InlineToolFacade, + ToolFacadeClass, + ToolsCollection, + EventBus +} from '@editorjs/sdk'; import BoldInlineTool from './internal/inline-tools/bold/index.js'; import ItalicInlineTool from './internal/inline-tools/italic/index.js'; import LinkInlineTool from './internal/inline-tools/link/index.js'; -import { ToolLoadedCoreEvent } from '../components/EventBus/index.js'; -import { EventBus } from '@editorjs/sdk'; /** * Works with tools @@ -146,14 +149,14 @@ export default class ToolsManager { const tool = this.#factory.get(toolName); - if (tool.isInline()) { + if ('isInline' in tool && tool.isInline() === true) { /** * Some Tools validation */ const inlineToolRequiredMethods = ['render']; const notImplementedMethods = inlineToolRequiredMethods.filter(method => tool.create()[method as keyof InlineTool] !== undefined); - if (notImplementedMethods.length) { + if (notImplementedMethods.length > 0) { /** * @todo implement logger */ diff --git a/packages/core/src/tools/facades/index.ts b/packages/core/src/tools/facades/index.ts deleted file mode 100644 index cd655e06..00000000 --- a/packages/core/src/tools/facades/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './BlockToolFacade.js'; -export * from './BlockTuneFacade.js'; -export * from './InlineToolFacade.js'; -export * from './ToolsFactory.js'; -export * from './ToolsCollection.js'; -export * from './ToolType.js'; diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index b86ffbb4..31b8fe22 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -25,6 +25,15 @@ "references": [ { "path": "../model/tsconfig.build.json" + }, + { + "path": "../sdk/tsconfig.build.json" + }, + { + "path": "../dom-adapters/tsconfig.build.json" + }, + { + "path": "../collaboration-manager/tsconfig.build.json" } ] } diff --git a/packages/dom-adapters/.eslintrc.yml b/packages/dom-adapters/.eslintrc.yml index 5ad199a0..1825e41e 100644 --- a/packages/dom-adapters/.eslintrc.yml +++ b/packages/dom-adapters/.eslintrc.yml @@ -18,6 +18,15 @@ rules: - always '@typescript-eslint/no-unsafe-declaration-merging': - 0 + # @todo: remove when we setup eslint to correctly handle the types + '@typescript-eslint/no-unsafe-call': + - 0 + '@typescript-eslint/no-unsafe-member-access': + - 0 + '@typescript-eslint/no-unsafe-assignment': + - 0 + '@typescript-eslint/no-unsafe-argument': + - 0 env: browser: true diff --git a/packages/dom-adapters/src/BlockToolAdapter/index.ts b/packages/dom-adapters/src/BlockToolAdapter/index.ts index 88d8b427..bed1da9d 100644 --- a/packages/dom-adapters/src/BlockToolAdapter/index.ts +++ b/packages/dom-adapters/src/BlockToolAdapter/index.ts @@ -20,7 +20,7 @@ import { isNonTextInput } from '../utils/index.js'; import { InputType } from './types/InputType.js'; -import type { BlockToolAdapter as BlockToolAdapterInterface, CoreConfig } from '@editorjs/sdk'; +import { type BlockToolAdapter as BlockToolAdapterInterface, type CoreConfig } from '@editorjs/sdk'; import type { FormattingAdapter } from '../FormattingAdapter/index.js'; import type { EventBus } from '@editorjs/sdk'; @@ -86,6 +86,10 @@ export class BlockToolAdapter implements BlockToolAdapterInterface { this.#caretAdapter = caretAdapter; this.#formattingAdapter = formattingAdapter; this.#toolName = toolName; + + // eventBus.addEventListener(BeforeInputUIEventName, (event: BeforeInputUIEvent) => { + // console.log('BeforeInputUIEventName', event); + // }); } /** diff --git a/packages/sdk/eslint.config.mjs b/packages/sdk/eslint.config.mjs index 99a05ca5..64a70977 100644 --- a/packages/sdk/eslint.config.mjs +++ b/packages/sdk/eslint.config.mjs @@ -21,6 +21,7 @@ export default [ ], ignoreTypeImport: true, }], + 'n/no-missing-import': 'off', }, }, ]; diff --git a/packages/sdk/package.json b/packages/sdk/package.json index a397ed50..94d58a91 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,21 +1,22 @@ { "name": "@editorjs/sdk", - "version": "0.0.0", + "version": "0.1.0", "packageManager": "yarn@4.0.1", "main": "dist/index.js", "types": "dist/index.d.ts", "type": "module", "scripts": { - "build": "tsc", + "build": "yarn clear && tsc --build tsconfig.build.json", "lint": "eslint", "lint:ci": "yarn lint --max-warnings 0", - "lint:fix": "yarn lint --fix" + "lint:fix": "yarn lint --fix", + "clear": "rm -rf dist && rm -f tsconfig.build.tsbuildinfo && rm -f tsconfig.tsbuildinfo" }, "devDependencies": { - "@types/eslint": "^8", - "eslint": "^8.38.0", - "eslint-config-codex": "^1.7.2", - "eslint-plugin-import": "^2.29.0", + "@types/eslint": "^9.6.1", + "eslint": "^9.24.0", + "eslint-config-codex": "^2.0.3", + "eslint-plugin-import": "^2.31.0", "ts-node": "^10.9.2", "typescript": "^5.5.4" }, diff --git a/packages/sdk/src/api/BlocksAPI.ts b/packages/sdk/src/api/BlocksAPI.ts new file mode 100644 index 00000000..5aa0bff7 --- /dev/null +++ b/packages/sdk/src/api/BlocksAPI.ts @@ -0,0 +1,27 @@ +import type { BlockToolData, ToolConfig } from '@editorjs/editorjs'; + +/** + * Blocks API interface + * Provides methods to work with blocks + */ +export interface BlocksAPI { + /** + * Inserts a new block to the editor + * @param type - Block tool name to insert + * @param data - Block's initial data + * @param _config - not used but left for compatibility + * @param index - index to insert block at + * @param needToFocus - flag indicates if new block should be focused @todo implement + * @param replace - flag indicates if block at index should be replaced @todo implement + * @param id - id of the inserted block @todo implement + */ + insert( + type?: string, + data?: BlockToolData, + _config?: ToolConfig, + index?: number, + needToFocus?: boolean, + replace?: boolean, + id?: string + ): void; +} diff --git a/packages/sdk/src/api/EditorAPI.ts b/packages/sdk/src/api/EditorAPI.ts new file mode 100644 index 00000000..5f918ded --- /dev/null +++ b/packages/sdk/src/api/EditorAPI.ts @@ -0,0 +1,18 @@ +import type { BlocksAPI } from './BlocksAPI.js'; +import type { SelectionAPI } from './SelectionAPI.js'; + +/** + * Editor API interface + * Gathers all Editor's APIs + */ +export interface EditorAPI { + /** + * Blocks API instance to work with blocks + */ + blocks: BlocksAPI; + + /** + * Selection API instance to work with selection and inline formatting + */ + selection: SelectionAPI; +} diff --git a/packages/sdk/src/api/SelectionAPI.ts b/packages/sdk/src/api/SelectionAPI.ts new file mode 100644 index 00000000..6e12990e --- /dev/null +++ b/packages/sdk/src/api/SelectionAPI.ts @@ -0,0 +1,14 @@ +import type { InlineToolName } from '@editorjs/model'; + +/** + * Selection API interface + * Provides methods to work with text selection and inline tools + */ +export interface SelectionAPI { + /** + * Applies inline tool for the current selection + * @param tool - name of the inline tool to apply + * @param data - optional data for the inline tool + */ + applyInlineToolForCurrentSelection(tool: InlineToolName, data?: Record): void; +} diff --git a/packages/sdk/src/api/index.ts b/packages/sdk/src/api/index.ts new file mode 100644 index 00000000..70429d30 --- /dev/null +++ b/packages/sdk/src/api/index.ts @@ -0,0 +1,3 @@ +export type * from './EditorAPI.js'; +export type * from './BlocksAPI.js'; +export type * from './SelectionAPI.js'; diff --git a/packages/sdk/src/entities/BlockTool.ts b/packages/sdk/src/entities/BlockTool.ts index 0c58c453..7fb8499c 100644 --- a/packages/sdk/src/entities/BlockTool.ts +++ b/packages/sdk/src/entities/BlockTool.ts @@ -1,7 +1,7 @@ import type { BlockTool as BlockToolVersion2, BlockToolConstructable as BlockToolConstructableV2, ToolConfig } from '@editorjs/editorjs'; import type { BlockToolConstructorOptions as BlockToolConstructorOptionsVersion2 } from '@editorjs/editorjs'; import type { ValueSerialized } from '@editorjs/model'; -import { BlockToolAdapter } from './BlockToolAdapter'; +import type { BlockToolAdapter } from './BlockToolAdapter.js'; /** * Extended BlockToolConstructorOptions interface for version 3. @@ -39,18 +39,20 @@ export interface BlockToolConstructorOptions< * In version 3, the save method is removed since all data is stored in the model */ export type BlockTool< - /** + /** * Data structure describing the tool's input/output data - * + * * any is used as a placeholder to allow using BlockToolData without generic */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any Data extends BlockToolData = any, /** * User-end configuration for the tool - * + * * any is used as a placeholder to allow using BlockToolData without generic */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any Config extends ToolConfig = any > = Omit; @@ -61,7 +63,8 @@ export type BlockToolConstructor = BlockToolConstructableV2 & (new (options: Blo /** * Data structure describing the tool's input/output data - * + * * any is used as a placeholder to allow using BlockToolData without generic */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type BlockToolData = any> = T; diff --git a/packages/sdk/src/entities/BlockToolAdapter.ts b/packages/sdk/src/entities/BlockToolAdapter.ts index e0c1a71f..cddf1fba 100644 --- a/packages/sdk/src/entities/BlockToolAdapter.ts +++ b/packages/sdk/src/entities/BlockToolAdapter.ts @@ -5,7 +5,6 @@ export interface BlockToolAdapter { /** * Attaches input to the model using key * It handles beforeinput events and updates model data - * * @param keyRaw - tools data key to attach input to * @param input - input element */ diff --git a/packages/sdk/src/entities/Config.ts b/packages/sdk/src/entities/Config.ts index 63bcd7b4..bb84fb76 100644 --- a/packages/sdk/src/entities/Config.ts +++ b/packages/sdk/src/entities/Config.ts @@ -12,7 +12,7 @@ export interface CoreConfig extends EditorConfig { /** * DEV MODE ONLY - * + * * Allows to subscribe to model updates. Used in playground for visualizing model changes * @param model - EditorJSModel instance */ @@ -37,3 +37,8 @@ export interface CoreConfig extends EditorConfig { */ collaborationServer?: string; } + +/** + * After validation we can be sure that all required fields are set + */ +export type CoreConfigValidated = Required; diff --git a/packages/core/src/entities/EditorjsPlugin.ts b/packages/sdk/src/entities/EditorjsPlugin.ts similarity index 78% rename from packages/core/src/entities/EditorjsPlugin.ts rename to packages/sdk/src/entities/EditorjsPlugin.ts index 5f3a68a6..2b1e077d 100644 --- a/packages/core/src/entities/EditorjsPlugin.ts +++ b/packages/sdk/src/entities/EditorjsPlugin.ts @@ -1,6 +1,6 @@ -import { EventBus } from '@editorjs/sdk'; -import type { CoreConfigValidated } from './Config.js'; -import type { EditorAPI } from '../api/index.js'; +import type { EventBus } from '@/entities/EventBus/EventBus.js'; +import type { CoreConfigValidated } from '@/entities/Config.js'; +import type { EditorAPI } from '@/api/EditorAPI.js'; /** * Parameters for EditorjsPlugin constructor diff --git a/packages/sdk/src/entities/EventBus/EventBus.ts b/packages/sdk/src/entities/EventBus/EventBus.ts new file mode 100644 index 00000000..20793624 --- /dev/null +++ b/packages/sdk/src/entities/EventBus/EventBus.ts @@ -0,0 +1,34 @@ +import type { Event } from './Event.js'; + +/** + * Extension for the EventTarget interface to allow for custom events. + */ +declare global { + /** + * EventTarget interface extension + */ + interface EventTarget { + /** + * Adds an event listener for the specified event type + * @param type - a string representing the event type to listen for + * @param callback - the function to call when the event is triggered + * @param options - an options object that specifies characteristics about the event listener + */ + // eslint-disable-next-line n/no-unsupported-features/node-builtins + addEventListener(type: Event, callback: ((event: CustomEvent) => void) | null, options?: AddEventListenerOptions | boolean): void; + /** + * Removes an event listener for the specified event type + * @param type - a string representing the event type to stop listening for + * @param callback - the event callback to remove + * @param options - an options object that specifies characteristics about the event listener + */ + // eslint-disable-next-line n/no-unsupported-features/node-builtins + removeEventListener(type: Event, callback: ((event: CustomEvent) => void) | null, options?: EventListenerOptions | boolean): void; + } +} + +/** + * EventBus class to handle events between components + * Extends native EventTarget class + */ +export class EventBus extends EventTarget {} diff --git a/packages/core/src/components/EventBus/core-events/BlockAddedCoreEvent.ts b/packages/sdk/src/entities/EventBus/events/core/BlockAddedCoreEvent.ts similarity index 100% rename from packages/core/src/components/EventBus/core-events/BlockAddedCoreEvent.ts rename to packages/sdk/src/entities/EventBus/events/core/BlockAddedCoreEvent.ts diff --git a/packages/core/src/components/EventBus/core-events/BlockRemovedCoreEvent.ts b/packages/sdk/src/entities/EventBus/events/core/BlockRemovedCoreEvent.ts similarity index 100% rename from packages/core/src/components/EventBus/core-events/BlockRemovedCoreEvent.ts rename to packages/sdk/src/entities/EventBus/events/core/BlockRemovedCoreEvent.ts diff --git a/packages/core/src/components/EventBus/core-events/CoreEventBase.ts b/packages/sdk/src/entities/EventBus/events/core/CoreEventBase.ts similarity index 100% rename from packages/core/src/components/EventBus/core-events/CoreEventBase.ts rename to packages/sdk/src/entities/EventBus/events/core/CoreEventBase.ts diff --git a/packages/core/src/components/EventBus/core-events/CoreEventType.ts b/packages/sdk/src/entities/EventBus/events/core/CoreEventType.ts similarity index 100% rename from packages/core/src/components/EventBus/core-events/CoreEventType.ts rename to packages/sdk/src/entities/EventBus/events/core/CoreEventType.ts diff --git a/packages/core/src/components/EventBus/core-events/RedoCoreEvent.ts b/packages/sdk/src/entities/EventBus/events/core/RedoCoreEvent.ts similarity index 100% rename from packages/core/src/components/EventBus/core-events/RedoCoreEvent.ts rename to packages/sdk/src/entities/EventBus/events/core/RedoCoreEvent.ts diff --git a/packages/core/src/components/EventBus/core-events/SelectionChangedCoreEvent.ts b/packages/sdk/src/entities/EventBus/events/core/SelectionChangedCoreEvent.ts similarity index 88% rename from packages/core/src/components/EventBus/core-events/SelectionChangedCoreEvent.ts rename to packages/sdk/src/entities/EventBus/events/core/SelectionChangedCoreEvent.ts index cd29d849..e2595b07 100644 --- a/packages/core/src/components/EventBus/core-events/SelectionChangedCoreEvent.ts +++ b/packages/sdk/src/entities/EventBus/events/core/SelectionChangedCoreEvent.ts @@ -1,4 +1,4 @@ -import type { InlineTool } from '@editorjs/sdk'; +import type { InlineTool } from '@/entities/InlineTool.js'; import { CoreEventBase } from './CoreEventBase.js'; import { CoreEventType } from './CoreEventType.js'; import type { Index, InlineFragment, InlineToolName } from '@editorjs/model'; @@ -11,6 +11,7 @@ export interface SelectionChangedCoreEventPayload { /** * Updated caret index */ + // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents readonly index: Index | null; /** diff --git a/packages/core/src/components/EventBus/core-events/ToolLoadedCoreEvent.ts b/packages/sdk/src/entities/EventBus/events/core/ToolLoadedCoreEvent.ts similarity index 91% rename from packages/core/src/components/EventBus/core-events/ToolLoadedCoreEvent.ts rename to packages/sdk/src/entities/EventBus/events/core/ToolLoadedCoreEvent.ts index 0a410d09..4640f403 100644 --- a/packages/core/src/components/EventBus/core-events/ToolLoadedCoreEvent.ts +++ b/packages/sdk/src/entities/EventBus/events/core/ToolLoadedCoreEvent.ts @@ -1,4 +1,4 @@ -import type { ToolFacadeClass } from '../../../tools/facades/index.js'; +import type { ToolFacadeClass } from '@/tools/facades/index.js'; import { CoreEventBase } from './CoreEventBase.js'; import { CoreEventType } from './CoreEventType.js'; diff --git a/packages/core/src/components/EventBus/core-events/UndoCoreEvent.ts b/packages/sdk/src/entities/EventBus/events/core/UndoCoreEvent.ts similarity index 100% rename from packages/core/src/components/EventBus/core-events/UndoCoreEvent.ts rename to packages/sdk/src/entities/EventBus/events/core/UndoCoreEvent.ts diff --git a/packages/core/src/components/EventBus/core-events/index.ts b/packages/sdk/src/entities/EventBus/events/core/index.ts similarity index 66% rename from packages/core/src/components/EventBus/core-events/index.ts rename to packages/sdk/src/entities/EventBus/events/core/index.ts index 24c6900f..0dfaae58 100644 --- a/packages/core/src/components/EventBus/core-events/index.ts +++ b/packages/sdk/src/entities/EventBus/events/core/index.ts @@ -3,3 +3,6 @@ export * from './BlockRemovedCoreEvent.js'; export * from './ToolLoadedCoreEvent.js'; export * from './CoreEventType.js'; export * from './SelectionChangedCoreEvent.js'; +export * from './RedoCoreEvent.js'; +export * from './UndoCoreEvent.js'; +export * from './CoreEventBase.js'; diff --git a/packages/sdk/src/entities/EventBus/events/index.ts b/packages/sdk/src/entities/EventBus/events/index.ts new file mode 100644 index 00000000..f1a3049c --- /dev/null +++ b/packages/sdk/src/entities/EventBus/events/index.ts @@ -0,0 +1,2 @@ +export * from './core/index.js'; +export * from './ui/index.js'; diff --git a/packages/ui/src/Blocks/BeforeInputUIEvent.ts b/packages/sdk/src/entities/EventBus/events/ui/BeforeInputUIEvent.ts similarity index 89% rename from packages/ui/src/Blocks/BeforeInputUIEvent.ts rename to packages/sdk/src/entities/EventBus/events/ui/BeforeInputUIEvent.ts index 0de1a1af..c2539e1e 100644 --- a/packages/ui/src/Blocks/BeforeInputUIEvent.ts +++ b/packages/sdk/src/entities/EventBus/events/ui/BeforeInputUIEvent.ts @@ -1,9 +1,9 @@ -import { UIEventBase } from '@editorjs/core'; +import { UIEventBase } from './UIEventBase.js'; /** * Name of the event */ -export const BeforeInputUIEventName = 'ui:before-input'; +export const BeforeInputUIEventName = 'before-input'; /** * Payload of the BeforeInputUIEvent diff --git a/packages/core/src/components/EventBus/ui-events/UIEventBase.ts b/packages/sdk/src/entities/EventBus/events/ui/UIEventBase.ts similarity index 100% rename from packages/core/src/components/EventBus/ui-events/UIEventBase.ts rename to packages/sdk/src/entities/EventBus/events/ui/UIEventBase.ts diff --git a/packages/sdk/src/entities/EventBus/events/ui/index.ts b/packages/sdk/src/entities/EventBus/events/ui/index.ts new file mode 100644 index 00000000..b7feaf5a --- /dev/null +++ b/packages/sdk/src/entities/EventBus/events/ui/index.ts @@ -0,0 +1,2 @@ +export * from './UIEventBase.js'; +export * from './BeforeInputUIEvent.js'; diff --git a/packages/sdk/src/entities/EventBus/index.ts b/packages/sdk/src/entities/EventBus/index.ts index 3978bad5..f08fa317 100644 --- a/packages/sdk/src/entities/EventBus/index.ts +++ b/packages/sdk/src/entities/EventBus/index.ts @@ -1,36 +1,3 @@ -import type { Event } from './Event.js'; - -/** - * Extension for the EventTarget interface to allow for custom events. - */ -declare global { - /** - * EventTarget interface extension - */ - interface EventTarget { - /** - * Adds an event listener for the specified event type - * @param type - a string representing the event type to listen for - * @param callback - the function to call when the event is triggered - * @param options - an options object that specifies characteristics about the event listener - */ - // eslint-disable-next-line n/no-unsupported-features/node-builtins - addEventListener(type: Event, callback: ((event: CustomEvent) => void) | null, options?: AddEventListenerOptions | boolean): void; - /** - * Removes an event listener for the specified event type - * @param type - a string representing the event type to stop listening for - * @param callback - the event callback to remove - * @param options - an options object that specifies characteristics about the event listener - */ - // eslint-disable-next-line n/no-unsupported-features/node-builtins - removeEventListener(type: Event, callback: ((event: CustomEvent) => void) | null, options?: EventListenerOptions | boolean): void; - } -} - -/** - * EventBus class to handle events between components - * Extends native EventTarget class - */ -export class EventBus extends EventTarget {} - -export * from './Event.js'; +export * from './EventBus.js'; +export type * from './Event.js'; +export * from './events/index.js'; diff --git a/packages/sdk/src/entities/InlineTool.ts b/packages/sdk/src/entities/InlineTool.ts index 5dfb1add..6e8dd3f8 100644 --- a/packages/sdk/src/entities/InlineTool.ts +++ b/packages/sdk/src/entities/InlineTool.ts @@ -29,7 +29,11 @@ export interface ToolFormattingOptions { * Interface that represents options handled by toolbar element */ export interface ToolbarOptions { - fakeSelectionRequired: boolean + /** + * Some tools require fake selection to be applied when 'actions' is open + * Example: Link tool + */ + fakeSelectionRequired: boolean; } /** @@ -40,7 +44,7 @@ export interface ActionsElementWithOptions { /** * HTML element rendered by tool for data forming */ - element: HTMLElement, + element: HTMLElement; /** * Oprions of custom toolbar behaviour @@ -70,7 +74,7 @@ export interface InlineTool extends Omit { this.#api.selection.applyInlineToolForCurrentSelection(name, data); }) ?? { element: null }; diff --git a/packages/ui/src/InlineToolbar/InlineToolbarRenderedUIEvent.ts b/packages/ui/src/InlineToolbar/InlineToolbarRenderedUIEvent.ts index 6993bf48..dda03c4c 100644 --- a/packages/ui/src/InlineToolbar/InlineToolbarRenderedUIEvent.ts +++ b/packages/ui/src/InlineToolbar/InlineToolbarRenderedUIEvent.ts @@ -1,4 +1,4 @@ -import { UIEventBase } from '@editorjs/core'; +import { UIEventBase } from '@editorjs/sdk'; /** * Payload of the InlineToolbarRenderedUIEvent diff --git a/packages/ui/src/Toolbox/Toolbox.ts b/packages/ui/src/Toolbox/Toolbox.ts index b6812c12..786cde67 100644 --- a/packages/ui/src/Toolbox/Toolbox.ts +++ b/packages/ui/src/Toolbox/Toolbox.ts @@ -1,15 +1,17 @@ import { make } from '@editorjs/dom'; -import type { ToolLoadedCoreEvent, +import type { BlockToolFacade, EditorjsPlugin, - EditorjsPluginParams } from '@editorjs/core'; + EditorjsPluginParams, + EventBus, + EditorAPI, + ToolLoadedCoreEvent +} from '@editorjs/sdk'; import { - CoreEventType -} from '@editorjs/core'; + CoreEventType, + UiComponentType +} from '@editorjs/sdk'; import { ToolboxRenderedUIEvent } from './ToolboxRenderedUIEvent.js'; -import type { EditorAPI } from '@editorjs/core'; -import type { EventBus } from '@editorjs/sdk'; -import { UiComponentType } from '@editorjs/sdk'; /** * UI module responsible for rendering the toolbox @@ -53,7 +55,7 @@ export class ToolboxUI implements EditorjsPlugin { this.#eventBus.addEventListener(`core:${CoreEventType.ToolLoaded}`, (event: ToolLoadedCoreEvent) => { const { tool } = event.detail; - if (tool.isBlock()) { + if ('isBlock' in tool && tool.isBlock()) { this.addTool(tool); } }); diff --git a/packages/ui/src/Toolbox/ToolboxRenderedUIEvent.ts b/packages/ui/src/Toolbox/ToolboxRenderedUIEvent.ts index b35c0e9f..5e7a0aa0 100644 --- a/packages/ui/src/Toolbox/ToolboxRenderedUIEvent.ts +++ b/packages/ui/src/Toolbox/ToolboxRenderedUIEvent.ts @@ -1,4 +1,4 @@ -import { UIEventBase } from '@editorjs/core'; +import { UIEventBase } from '@editorjs/sdk'; /** * Payload of the ToolboxRenderedUIEvent diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index f31f1b7f..90171e7b 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -1,7 +1,7 @@ -import type { CoreConfigValidated, +import type { EventBus, + CoreConfigValidated, EditorjsPlugin, - EditorjsPluginParams } from '@editorjs/core'; -import type { EventBus } from '@editorjs/sdk'; + EditorjsPluginParams } from '@editorjs/sdk'; import { UiComponentType } from '@editorjs/sdk'; @@ -79,4 +79,3 @@ export class EditorjsUI implements EditorjsPlugin { export * from './InlineToolbar/InlineToolbar.js'; export * from './Blocks/Blocks.js'; export * from './Toolbox/Toolbox.js'; -export * from './Blocks/BeforeInputUIEvent.js'; diff --git a/yarn.lock b/yarn.lock index 8ee927c7..1d11d287 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1233,10 +1233,10 @@ __metadata: dependencies: "@editorjs/editorjs": "npm:^2.30.5" "@editorjs/model": "workspace:^" - "@types/eslint": "npm:^8" - eslint: "npm:^8.38.0" - eslint-config-codex: "npm:^1.7.2" - eslint-plugin-import: "npm:^2.29.0" + "@types/eslint": "npm:^9.6.1" + eslint: "npm:^9.24.0" + eslint-config-codex: "npm:^2.0.3" + eslint-plugin-import: "npm:^2.31.0" ts-node: "npm:^10.9.2" typescript: "npm:^5.5.4" languageName: unknown