1 | /**
|
2 | * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
|
3 | * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4 | */
|
5 | /**
|
6 | * @module core/context
|
7 | */
|
8 | import { Config, Collection, Locale, type LocaleTranslate } from '@ckeditor/ckeditor5-utils';
|
9 | import PluginCollection from './plugincollection.js';
|
10 | import type Editor from './editor/editor.js';
|
11 | import type { LoadedPlugins, PluginConstructor } from './plugin.js';
|
12 | import type { EditorConfig } from './editor/editorconfig.js';
|
13 | /**
|
14 | * Provides a common, higher-level environment for solutions that use multiple {@link module:core/editor/editor~Editor editors}
|
15 | * or plugins that work outside the editor. Use it instead of {@link module:core/editor/editor~Editor.create `Editor.create()`}
|
16 | * in advanced application integrations.
|
17 | *
|
18 | * All configuration options passed to a context will be used as default options for the editor instances initialized in that context.
|
19 | *
|
20 | * {@link module:core/contextplugin~ContextPlugin Context plugins} passed to a context instance will be shared among all
|
21 | * editor instances initialized in this context. These will be the same plugin instances for all the editors.
|
22 | *
|
23 | * **Note:** The context can only be initialized with {@link module:core/contextplugin~ContextPlugin context plugins}
|
24 | * (e.g. [comments](https://ckeditor.com/collaboration/comments/)). Regular {@link module:core/plugin~Plugin plugins} require an
|
25 | * editor instance to work and cannot be added to a context.
|
26 | *
|
27 | * **Note:** You can add a context plugin to an editor instance, though.
|
28 | *
|
29 | * If you are using multiple editor instances on one page and use any context plugins, create a context to share the configuration and
|
30 | * plugins among these editors. Some plugins will use the information about all existing editors to better integrate between them.
|
31 | *
|
32 | * If you are using plugins that do not require an editor to work (e.g. [comments](https://ckeditor.com/collaboration/comments/)),
|
33 | * enable and configure them using the context.
|
34 | *
|
35 | * If you are using only a single editor on each page, use {@link module:core/editor/editor~Editor.create `Editor.create()`} instead.
|
36 | * In such a case, a context instance will be created by the editor instance in a transparent way.
|
37 | *
|
38 | * See {@link ~Context.create `Context.create()`} for usage examples.
|
39 | */
|
40 | export default class Context {
|
41 | /**
|
42 | * Stores all the configurations specific to this context instance.
|
43 | */
|
44 | readonly config: Config<ContextConfig>;
|
45 | /**
|
46 | * The plugins loaded and in use by this context instance.
|
47 | */
|
48 | readonly plugins: PluginCollection<Context | Editor>;
|
49 | readonly locale: Locale;
|
50 | /**
|
51 | * Shorthand for {@link module:utils/locale~Locale#t}.
|
52 | */
|
53 | readonly t: LocaleTranslate;
|
54 | /**
|
55 | * A list of editors that this context instance is injected to.
|
56 | */
|
57 | readonly editors: Collection<Editor>;
|
58 | /**
|
59 | * The default configuration which is built into the `Context` class.
|
60 | *
|
61 | * It is used in CKEditor 5 builds featuring `Context` to provide the default configuration options which are later used during the
|
62 | * context initialization.
|
63 | *
|
64 | * ```ts
|
65 | * Context.defaultConfig = {
|
66 | * foo: 1,
|
67 | * bar: 2
|
68 | * };
|
69 | *
|
70 | * Context
|
71 | * .create()
|
72 | * .then( context => {
|
73 | * context.config.get( 'foo' ); // -> 1
|
74 | * context.config.get( 'bar' ); // -> 2
|
75 | * } );
|
76 | *
|
77 | * // The default options can be overridden by the configuration passed to create().
|
78 | * Context
|
79 | * .create( { bar: 3 } )
|
80 | * .then( context => {
|
81 | * context.config.get( 'foo' ); // -> 1
|
82 | * context.config.get( 'bar' ); // -> 3
|
83 | * } );
|
84 | * ```
|
85 | *
|
86 | * See also {@link module:core/context~Context.builtinPlugins `Context.builtinPlugins`}
|
87 | * and {@link module:core/editor/editor~Editor.defaultConfig `Editor.defaultConfig`}.
|
88 | */
|
89 | static defaultConfig: ContextConfig;
|
90 | /**
|
91 | * An array of plugins built into the `Context` class.
|
92 | *
|
93 | * It is used in CKEditor 5 builds featuring `Context` to provide a list of context plugins which are later automatically initialized
|
94 | * during the context initialization.
|
95 | *
|
96 | * They will be automatically initialized by `Context` unless `config.plugins` is passed.
|
97 | *
|
98 | * ```ts
|
99 | * // Build some context plugins into the Context class first.
|
100 | * Context.builtinPlugins = [ FooPlugin, BarPlugin ];
|
101 | *
|
102 | * // Normally, you need to define config.plugins, but since Context.builtinPlugins was
|
103 | * // defined, now you can call create() without any configuration.
|
104 | * Context
|
105 | * .create()
|
106 | * .then( context => {
|
107 | * context.plugins.get( FooPlugin ); // -> An instance of the Foo plugin.
|
108 | * context.plugins.get( BarPlugin ); // -> An instance of the Bar plugin.
|
109 | * } );
|
110 | * ```
|
111 | *
|
112 | * See also {@link module:core/context~Context.defaultConfig `Context.defaultConfig`}
|
113 | * and {@link module:core/editor/editor~Editor.builtinPlugins `Editor.builtinPlugins`}.
|
114 | */
|
115 | static builtinPlugins: Array<PluginConstructor<Context | Editor>>;
|
116 | /**
|
117 | * Reference to the editor which created the context.
|
118 | * Null when the context was created outside of the editor.
|
119 | *
|
120 | * It is used to destroy the context when removing the editor that has created the context.
|
121 | */
|
122 | private _contextOwner;
|
123 | /**
|
124 | * Creates a context instance with a given configuration.
|
125 | *
|
126 | * Usually not to be used directly. See the static {@link module:core/context~Context.create `create()`} method.
|
127 | *
|
128 | * @param config The context configuration.
|
129 | */
|
130 | constructor(config?: ContextConfig);
|
131 | /**
|
132 | * Loads and initializes plugins specified in the configuration.
|
133 | *
|
134 | * @returns A promise which resolves once the initialization is completed, providing an array of loaded plugins.
|
135 | */
|
136 | initPlugins(): Promise<LoadedPlugins>;
|
137 | /**
|
138 | * Destroys the context instance and all editors used with the context,
|
139 | * releasing all resources used by the context.
|
140 | *
|
141 | * @returns A promise that resolves once the context instance is fully destroyed.
|
142 | */
|
143 | destroy(): Promise<unknown>;
|
144 | /**
|
145 | * Adds a reference to the editor which is used with this context.
|
146 | *
|
147 | * When the given editor has created the context, the reference to this editor will be stored
|
148 | * as a { ~Context#_contextOwner}.
|
149 | *
|
150 | * This method should only be used by the editor.
|
151 | *
|
152 | *
|
153 | * as a context owner.
isContextOwner Stores the given editor |
154 | */
|
155 | _addEditor(editor: Editor, isContextOwner: boolean): void;
|
156 | /**
|
157 | * Removes a reference to the editor which was used with this context.
|
158 | * When the context was created by the given editor, the context will be destroyed.
|
159 | *
|
160 | * This method should only be used by the editor.
|
161 | *
|
162 | * @internal
|
163 | * @return A promise that resolves once the editor is removed from the context or when the context was destroyed.
|
164 | */
|
165 | _removeEditor(editor: Editor): Promise<unknown>;
|
166 | /**
|
167 | * Returns the context configuration which will be copied to the editors created using this context.
|
168 | *
|
169 | * The configuration returned by this method has the plugins configuration removed – plugins are shared with all editors
|
170 | * through another mechanism.
|
171 | *
|
172 | * This method should only be used by the editor.
|
173 | *
|
174 | * @internal
|
175 | * @returns Configuration as a plain object.
|
176 | */
|
177 | _getEditorConfig(): Partial<EditorConfig>;
|
178 | /**
|
179 | * Creates and initializes a new context instance.
|
180 | *
|
181 | * ```ts
|
182 | * const commonConfig = { ... }; // Configuration for all the plugins and editors.
|
183 | * const editorPlugins = [ ... ]; // Regular plugins here.
|
184 | *
|
185 | * Context
|
186 | * .create( {
|
187 | * // Only context plugins here.
|
188 | * plugins: [ ... ],
|
189 | *
|
190 | * // Configure the language for all the editors (it cannot be overwritten).
|
191 | * language: { ... },
|
192 | *
|
193 | * // Configuration for context plugins.
|
194 | * comments: { ... },
|
195 | * ...
|
196 | *
|
197 | * // Default configuration for editor plugins.
|
198 | * toolbar: { ... },
|
199 | * image: { ... },
|
200 | * ...
|
201 | * } )
|
202 | * .then( context => {
|
203 | * const promises = [];
|
204 | *
|
205 | * promises.push( ClassicEditor.create(
|
206 | * document.getElementById( 'editor1' ),
|
207 | * {
|
208 | * editorPlugins,
|
209 | * context
|
210 | * }
|
211 | * ) );
|
212 | *
|
213 | * promises.push( ClassicEditor.create(
|
214 | * document.getElementById( 'editor2' ),
|
215 | * {
|
216 | * editorPlugins,
|
217 | * context,
|
218 | * toolbar: { ... } // You can overwrite the configuration of the context.
|
219 | * }
|
220 | * ) );
|
221 | *
|
222 | * return Promise.all( promises );
|
223 | * } );
|
224 | * ```
|
225 | *
|
226 | * @param config The context configuration.
|
227 | * @returns A promise resolved once the context is ready. The promise resolves with the created context instance.
|
228 | */
|
229 | static create(config?: ContextConfig): Promise<Context>;
|
230 | }
|
231 | /**
|
232 | * The context configuration.
|
233 | */
|
234 | export type ContextConfig = {
|
235 | plugins?: Array<PluginConstructor<Context | Editor>>;
|
236 | substitutePlugins?: Array<PluginConstructor<Context | Editor>>;
|
237 | } & Omit<EditorConfig, 'plugins' | 'substitutePlugins' | 'removePlugins' | 'extraPlugins'>;
|