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 | import type Editor from './editor/editor.js';
|
6 | declare const Plugin_base: {
|
7 | new (): import("@ckeditor/ckeditor5-utils").Observable;
|
8 | prototype: import("@ckeditor/ckeditor5-utils").Observable;
|
9 | };
|
10 | /**
|
11 | * The base class for CKEditor plugin classes.
|
12 | */
|
13 | export default class Plugin extends /* #__PURE__ */ Plugin_base implements PluginInterface {
|
14 | /**
|
15 | * The editor instance.
|
16 | *
|
17 | * Note that most editors implement the {@link module:core/editor/editor~Editor#ui} property.
|
18 | * However, editors with an external UI (i.e. Bootstrap-based) or a headless editor may not have this property or
|
19 | * throw an error when accessing it.
|
20 | *
|
21 | * Because of above, to make plugins more universal, it is recommended to split features into:
|
22 | * - The "editing" part that uses the {@link module:core/editor/editor~Editor} class without `ui` property.
|
23 | * - The "UI" part that uses the {@link module:core/editor/editor~Editor} class and accesses `ui` property.
|
24 | */
|
25 | readonly editor: Editor;
|
26 | /**
|
27 | * Flag indicating whether a plugin is enabled or disabled.
|
28 | * A disabled plugin will not transform text.
|
29 | *
|
30 | * Plugin can be simply disabled like that:
|
31 | *
|
32 | * ```ts
|
33 | * // Disable the plugin so that no toolbars are visible.
|
34 | * editor.plugins.get( 'TextTransformation' ).isEnabled = false;
|
35 | * ```
|
36 | *
|
37 | * You can also use {@link #forceDisabled} method.
|
38 | *
|
39 | * @observable
|
40 | * @readonly
|
41 | */
|
42 | isEnabled: boolean;
|
43 | /**
|
44 | * Holds identifiers for {@link #forceDisabled} mechanism.
|
45 | */
|
46 | private _disableStack;
|
47 | /**
|
48 | * @inheritDoc
|
49 | */
|
50 | constructor(editor: Editor);
|
51 | /**
|
52 | * Disables the plugin.
|
53 | *
|
54 | * Plugin may be disabled by multiple features or algorithms (at once). When disabling a plugin, unique id should be passed
|
55 | * (e.g. feature name). The same identifier should be used when { #clearForceDisabled enabling back} the plugin.
|
56 | * The plugin becomes enabled only after all features { #clearForceDisabled enabled it back}.
|
57 | *
|
58 | * Disabling and enabling a plugin:
|
59 | *
|
60 | * ```ts
|
61 | * plugin.isEnabled; // -> true
|
62 | * plugin.forceDisabled( 'MyFeature' );
|
63 | * plugin.isEnabled; // -> false
|
64 | * plugin.clearForceDisabled( 'MyFeature' );
|
65 | * plugin.isEnabled; // -> true
|
66 | * ```
|
67 | *
|
68 | * Plugin disabled by multiple features:
|
69 | *
|
70 | * ```ts
|
71 | * plugin.forceDisabled( 'MyFeature' );
|
72 | * plugin.forceDisabled( 'OtherFeature' );
|
73 | * plugin.clearForceDisabled( 'MyFeature' );
|
74 | * plugin.isEnabled; // -> false
|
75 | * plugin.clearForceDisabled( 'OtherFeature' );
|
76 | * plugin.isEnabled; // -> true
|
77 | * ```
|
78 | *
|
79 | * Multiple disabling with the same identifier is redundant:
|
80 | *
|
81 | * ```ts
|
82 | * plugin.forceDisabled( 'MyFeature' );
|
83 | * plugin.forceDisabled( 'MyFeature' );
|
84 | * plugin.clearForceDisabled( 'MyFeature' );
|
85 | * plugin.isEnabled; // -> true
|
86 | * ```
|
87 | *
|
88 | * **Note:** some plugins or algorithms may have more complex logic when it comes to enabling or disabling certain plugins,
|
89 | * so the plugin might be still disabled after { #clearForceDisabled} was used.
|
90 | *
|
91 | * for disabling. Use the same id when { #clearForceDisabled enabling back} the plugin.
id Unique identifier |
92 | */
|
93 | forceDisabled(id: string): void;
|
94 | /**
|
95 | * Clears forced disable previously set through {@link #forceDisabled}. See {@link #forceDisabled}.
|
96 | *
|
97 | * @param id Unique identifier, equal to the one passed in {@link #forceDisabled} call.
|
98 | */
|
99 | clearForceDisabled(id: string): void;
|
100 | /**
|
101 | * @inheritDoc
|
102 | */
|
103 | destroy(): void;
|
104 | /**
|
105 | * @inheritDoc
|
106 | */
|
107 | static get isContextPlugin(): false;
|
108 | }
|
109 | /**
|
110 | * The base interface for CKEditor plugins.
|
111 | *
|
112 | * In its minimal form a plugin can be a simple function that accepts {@link module:core/editor/editor~Editor the editor}
|
113 | * as a parameter:
|
114 | *
|
115 | * ```ts
|
116 | * // A simple plugin that enables a data processor.
|
117 | * function MyPlugin( editor ) {
|
118 | * editor.data.processor = new MyDataProcessor();
|
119 | * }
|
120 | * ```
|
121 | *
|
122 | * In most cases however, you will want to inherit from the {@link ~Plugin} class which implements the
|
123 | * {@link module:utils/observablemixin~Observable} and is, therefore, more convenient:
|
124 | *
|
125 | * ```ts
|
126 | * class MyPlugin extends Plugin {
|
127 | * init() {
|
128 | * // `listenTo()` and `editor` are available thanks to `Plugin`.
|
129 | * // By using `listenTo()` you will ensure that the listener is removed when
|
130 | * // the plugin is destroyed.
|
131 | * this.listenTo( this.editor.data, 'ready', () => {
|
132 | * // Do something when the data is ready.
|
133 | * } );
|
134 | * }
|
135 | * }
|
136 | * ```
|
137 | *
|
138 | * The plugin class can have `pluginName` and `requires` static members. See {@link ~PluginStaticMembers} for more details.
|
139 | *
|
140 | * The plugin can also implement methods (e.g. {@link ~PluginInterface#init `init()`} or
|
141 | * {@link ~PluginInterface#destroy `destroy()`}) which, when present, will be used to properly
|
142 | * initialize and destroy the plugin.
|
143 | *
|
144 | * **Note:** When defined as a plain function, the plugin acts as a constructor and will be
|
145 | * called in parallel with other plugins' {@link ~PluginConstructor constructors}.
|
146 | * This means the code of that plugin will be executed **before** {@link ~PluginInterface#init `init()`} and
|
147 | * {@link ~PluginInterface#afterInit `afterInit()`} methods of other plugins and, for instance,
|
148 | * you cannot use it to extend other plugins' {@glink framework/architecture/editing-engine#schema schema}
|
149 | * rules as they are defined later on during the `init()` stage.
|
150 | */
|
151 | export interface PluginInterface {
|
152 | /**
|
153 | * The second stage (after plugin constructor) of the plugin initialization.
|
154 | * Unlike the plugin constructor this method can be asynchronous.
|
155 | *
|
156 | * A plugin's `init()` method is called after its {@link ~PluginStaticMembers#requires dependencies} are initialized,
|
157 | * so in the same order as the constructors of these plugins.
|
158 | *
|
159 | * **Note:** This method is optional. A plugin instance does not need to have it defined.
|
160 | */
|
161 | init?(): Promise<unknown> | null | undefined | void;
|
162 | /**
|
163 | * The third (and last) stage of the plugin initialization. See also {@link ~PluginConstructor} and {@link ~PluginInterface#init}.
|
164 | *
|
165 | * **Note:** This method is optional. A plugin instance does not need to have it defined.
|
166 | */
|
167 | afterInit?(): Promise<unknown> | null | undefined | void;
|
168 | /**
|
169 | * Destroys the plugin.
|
170 | *
|
171 | * **Note:** This method is optional. A plugin instance does not need to have it defined.
|
172 | */
|
173 | destroy?(): Promise<unknown> | null | undefined | void;
|
174 | }
|
175 | /**
|
176 | * Creates a new plugin instance. This is the first step of the plugin initialization.
|
177 | * See also {@link ~PluginInterface#init} and {@link ~PluginInterface#afterInit}.
|
178 | *
|
179 | * The plugin static properties should conform to {@link ~PluginStaticMembers `PluginStaticMembers` interface}.
|
180 | *
|
181 | * A plugin is always instantiated after its {@link ~PluginStaticMembers#requires dependencies} and the
|
182 | * {@link ~PluginInterface#init} and {@link ~PluginInterface#afterInit} methods are called in the same order.
|
183 | *
|
184 | * Usually, you will want to put your plugin's initialization code in the {@link ~PluginInterface#init} method.
|
185 | * The constructor can be understood as "before init" and used in special cases, just like
|
186 | * {@link ~PluginInterface#afterInit} serves the special "after init" scenarios (e.g.the code which depends on other
|
187 | * plugins, but which does not {@link ~PluginStaticMembers#requires explicitly require} them).
|
188 | */
|
189 | export type PluginConstructor<TContext = Editor> = (PluginClassConstructor<TContext> | PluginFunctionConstructor<TContext>) & PluginStaticMembers<TContext>;
|
190 | /**
|
191 | * In most cases, you will want to inherit from the {@link ~Plugin} class which implements the
|
192 | * {@link module:utils/observablemixin~Observable} and is, therefore, more convenient:
|
193 | *
|
194 | * ```ts
|
195 | * class MyPlugin extends Plugin {
|
196 | * init() {
|
197 | * // `listenTo()` and `editor` are available thanks to `Plugin`.
|
198 | * // By using `listenTo()` you will ensure that the listener is removed when
|
199 | * // the plugin is destroyed.
|
200 | * this.listenTo( this.editor.data, 'ready', () => {
|
201 | * // Do something when the data is ready.
|
202 | * } );
|
203 | * }
|
204 | * }
|
205 | * ```
|
206 | */
|
207 | export type PluginClassConstructor<TContext = Editor> = new (editor: TContext) => PluginInterface;
|
208 | /**
|
209 | * In its minimal form a plugin can be a simple function that accepts {@link module:core/editor/editor~Editor the editor}
|
210 | * as a parameter:
|
211 | *
|
212 | * ```ts
|
213 | * // A simple plugin that enables a data processor.
|
214 | * function MyPlugin( editor ) {
|
215 | * editor.data.processor = new MyDataProcessor();
|
216 | * }
|
217 | * ```
|
218 | */
|
219 | export type PluginFunctionConstructor<TContext = Editor> = (editor: TContext) => void;
|
220 | /**
|
221 | * Static properties of a plugin.
|
222 | */
|
223 | export interface PluginStaticMembers<TContext = Editor> {
|
224 | /**
|
225 | * An array of plugins required by this plugin.
|
226 | *
|
227 | * To keep the plugin class definition tight it is recommended to define this property as a static getter:
|
228 | *
|
229 | * ```ts
|
230 | * import Image from './image.js';
|
231 | *
|
232 | * export default class ImageCaption {
|
233 | * static get requires() {
|
234 | * return [ Image ];
|
235 | * }
|
236 | * }
|
237 | * ```
|
238 | */
|
239 | readonly requires?: PluginDependencies<TContext>;
|
240 | /**
|
241 | * An optional name of the plugin. If set, the plugin will be available in
|
242 | * {@link module:core/plugincollection~PluginCollection#get} by its
|
243 | * name and its constructor. If not, then only by its constructor.
|
244 | *
|
245 | * The name should reflect the constructor name.
|
246 | *
|
247 | * To keep the plugin class definition tight, it is recommended to define this property as a static getter:
|
248 | *
|
249 | * ```ts
|
250 | * export default class ImageCaption {
|
251 | * static get pluginName() {
|
252 | * return 'ImageCaption';
|
253 | * }
|
254 | * }
|
255 | * ```
|
256 | *
|
257 | * Note: The native `Function.name` property could not be used to keep the plugin name because
|
258 | * it will be mangled during code minification.
|
259 | *
|
260 | * Naming a plugin is necessary to enable removing it through the
|
261 | * {@link module:core/editor/editorconfig~EditorConfig#removePlugins `config.removePlugins`} option.
|
262 | */
|
263 | readonly pluginName?: string;
|
264 | /**
|
265 | * A flag which defines if a plugin is allowed or not allowed to be used directly by a {@link module:core/context~Context}.
|
266 | */
|
267 | readonly isContextPlugin?: boolean;
|
268 | }
|
269 | export type PluginDependencies<TContext = Editor> = ReadonlyArray<PluginConstructor<TContext> | string>;
|
270 | /**
|
271 | * An array of loaded plugins.
|
272 | */
|
273 | export type LoadedPlugins = Array<PluginInterface>;
|
274 | export {};
|