/**
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/
/**
* @module core/plugin
*/
import { type ObservableMixinConstructor } from "@ckeditor/ckeditor5-utils";
import { type Editor } from "./editor/editor.js";
declare const PluginBase: ObservableMixinConstructor;
/**
* The base class for CKEditor plugin classes.
*/
export declare class Plugin extends PluginBase implements PluginInterface {
	/**
	* The editor instance.
	*
	* Note that most editors implement the {@link module:core/editor/editor~Editor#ui} property.
	* However, editors with an external UI (i.e. Bootstrap-based) or a headless editor may not have this property or
	* throw an error when accessing it.
	*
	* Because of above, to make plugins more universal, it is recommended to split features into:
	*  - The "editing" part that uses the {@link module:core/editor/editor~Editor} class without `ui` property.
	*  - The "UI" part that uses the {@link module:core/editor/editor~Editor} class and accesses `ui` property.
	*/
	readonly editor: Editor;
	/**
	* Flag indicating whether a plugin is enabled or disabled.
	* A disabled plugin will not transform text.
	*
	* Plugin can be simply disabled like that:
	*
	* ```ts
	* // Disable the plugin so that no toolbars are visible.
	* editor.plugins.get( 'TextTransformation' ).isEnabled = false;
	* ```
	*
	* You can also use {@link #forceDisabled} method.
	*
	* @observable
	* @readonly
	*/
	isEnabled: boolean;
	/**
	* Holds identifiers for {@link #forceDisabled} mechanism.
	*/
	private _disableStack;
	/**
	* @inheritDoc
	*/
	constructor(editor: Editor);
	/**
	* Disables the plugin.
	*
	* Plugin may be disabled by multiple features or algorithms (at once). When disabling a plugin, unique id should be passed
	* (e.g. feature name). The same identifier should be used when {@link #clearForceDisabled enabling back} the plugin.
	* The plugin becomes enabled only after all features {@link #clearForceDisabled enabled it back}.
	*
	* Disabling and enabling a plugin:
	*
	* ```ts
	* plugin.isEnabled; // -> true
	* plugin.forceDisabled( 'MyFeature' );
	* plugin.isEnabled; // -> false
	* plugin.clearForceDisabled( 'MyFeature' );
	* plugin.isEnabled; // -> true
	* ```
	*
	* Plugin disabled by multiple features:
	*
	* ```ts
	* plugin.forceDisabled( 'MyFeature' );
	* plugin.forceDisabled( 'OtherFeature' );
	* plugin.clearForceDisabled( 'MyFeature' );
	* plugin.isEnabled; // -> false
	* plugin.clearForceDisabled( 'OtherFeature' );
	* plugin.isEnabled; // -> true
	* ```
	*
	* Multiple disabling with the same identifier is redundant:
	*
	* ```ts
	* plugin.forceDisabled( 'MyFeature' );
	* plugin.forceDisabled( 'MyFeature' );
	* plugin.clearForceDisabled( 'MyFeature' );
	* plugin.isEnabled; // -> true
	* ```
	*
	* **Note:** some plugins or algorithms may have more complex logic when it comes to enabling or disabling certain plugins,
	* so the plugin might be still disabled after {@link #clearForceDisabled} was used.
	*
	* @param id Unique identifier for disabling. Use the same id when {@link #clearForceDisabled enabling back} the plugin.
	*/
	forceDisabled(id: string): void;
	/**
	* Clears forced disable previously set through {@link #forceDisabled}. See {@link #forceDisabled}.
	*
	* @param id Unique identifier, equal to the one passed in {@link #forceDisabled} call.
	*/
	clearForceDisabled(id: string): void;
	/**
	* @inheritDoc
	*/
	destroy(): void;
	/**
	* @inheritDoc
	*/
	static get isContextPlugin(): false;
	/**
	* @inheritDoc
	* @internal
	*/
	static get isOfficialPlugin(): boolean;
	/**
	* @inheritDoc
	* @internal
	*/
	static get isPremiumPlugin(): boolean;
}
/**
* The base interface for CKEditor plugins.
*
* In its minimal form a plugin can be a simple function that accepts {@link module:core/editor/editor~Editor the editor}
* as a parameter:
*
* ```ts
* // A simple plugin that enables a data processor.
* function MyPlugin( editor ) {
* 	editor.data.processor = new MyDataProcessor();
* }
* ```
*
* In most cases however, you will want to inherit from the {@link ~Plugin} class which implements the
* {@link module:utils/observablemixin~Observable} and is, therefore, more convenient:
*
* ```ts
* class MyPlugin extends Plugin {
* 	init() {
* 		// `listenTo()` and `editor` are available thanks to `Plugin`.
* 		// By using `listenTo()` you will ensure that the listener is removed when
* 		// the plugin is destroyed.
* 		this.listenTo( this.editor.data, 'ready', () => {
* 			// Do something when the data is ready.
* 		} );
* 	}
* }
* ```
*
* The plugin class can have `pluginName` and `requires` static members. See {@link ~PluginStaticMembers} for more details.
*
* The plugin can also implement methods (e.g. {@link ~PluginInterface#init `init()`} or
* {@link ~PluginInterface#destroy `destroy()`}) which, when present, will be used to properly
* initialize and destroy the plugin.
*
* **Note:** When defined as a plain function, the plugin acts as a constructor and will be
* called in parallel with other plugins' {@link ~PluginConstructor constructors}.
* This means the code of that plugin will be executed **before** {@link ~PluginInterface#init `init()`} and
* {@link ~PluginInterface#afterInit `afterInit()`} methods of other plugins and, for instance,
* you cannot use it to extend other plugins' {@glink framework/architecture/editing-engine#schema schema}
* rules as they are defined later on during the `init()` stage.
*/
export interface PluginInterface {
	/**
	* The second stage (after plugin constructor) of the plugin initialization.
	* Unlike the plugin constructor this method can be asynchronous.
	*
	* A plugin's `init()` method is called after its {@link ~PluginStaticMembers#requires dependencies} are initialized,
	* so in the same order as the constructors of these plugins.
	*
	* **Note:** This method is optional. A plugin instance does not need to have it defined.
	*/
	init?(): Promise<unknown> | null | undefined | void;
	/**
	* The third (and last) stage of the plugin initialization. See also {@link ~PluginConstructor} and {@link ~PluginInterface#init}.
	*
	* **Note:** This method is optional. A plugin instance does not need to have it defined.
	*/
	afterInit?(): Promise<unknown> | null | undefined | void;
	/**
	* Destroys the plugin.
	*
	* **Note:** This method is optional. A plugin instance does not need to have it defined.
	*/
	destroy?(): Promise<unknown> | null | undefined | void;
}
/**
* Creates a new plugin instance. This is the first step of the plugin initialization.
* See also {@link ~PluginInterface#init} and {@link ~PluginInterface#afterInit}.
*
* The plugin static properties should conform to {@link ~PluginStaticMembers `PluginStaticMembers` interface}.
*
* A plugin is always instantiated after its {@link ~PluginStaticMembers#requires dependencies} and the
* {@link ~PluginInterface#init} and {@link ~PluginInterface#afterInit} methods are called in the same order.
*
* Usually, you will want to put your plugin's initialization code in the {@link ~PluginInterface#init} method.
* The constructor can be understood as "before init" and used in special cases, just like
* {@link ~PluginInterface#afterInit} serves the special "after init" scenarios (e.g.the code which depends on other
* plugins, but which does not {@link ~PluginStaticMembers#requires explicitly require} them).
*/
export type PluginConstructor<TContext = Editor> = (PluginClassConstructor<TContext> | PluginFunctionConstructor<TContext>) & PluginStaticMembers<TContext>;
/**
* In most cases, you will want to inherit from the {@link ~Plugin} class which implements the
* {@link module:utils/observablemixin~Observable} and is, therefore, more convenient:
*
* ```ts
* class MyPlugin extends Plugin {
* 	init() {
* 		// `listenTo()` and `editor` are available thanks to `Plugin`.
* 		// By using `listenTo()` you will ensure that the listener is removed when
* 		// the plugin is destroyed.
* 		this.listenTo( this.editor.data, 'ready', () => {
* 			// Do something when the data is ready.
* 		} );
* 	}
* }
* ```
*/
export type PluginClassConstructor<TContext = Editor> = new (editor: TContext) => PluginInterface;
/**
* In its minimal form a plugin can be a simple function that accepts {@link module:core/editor/editor~Editor the editor}
* as a parameter:
*
* ```ts
* // A simple plugin that enables a data processor.
* function MyPlugin( editor ) {
* 	editor.data.processor = new MyDataProcessor();
* }
* ```
*/
export type PluginFunctionConstructor<TContext = Editor> = (editor: TContext) => void;
/**
* Static properties of a plugin.
*/
export interface PluginStaticMembers<TContext = Editor> {
	/**
	* An array of plugins required by this plugin.
	*
	* To keep the plugin class definition tight it is recommended to define this property as a static getter:
	*
	* ```ts
	* import { Image } from './image.js';
	*
	* export class ImageCaption {
	* 	static get requires(): PluginDependenciesOf<[ Image ]> {
	* 		return [ Image ];
	* 	}
	* }
	* ```
	*/
	readonly requires?: PluginDependencies<TContext>;
	/**
	* An optional name of the plugin. If set, the plugin will be available in
	* {@link module:core/plugincollection~PluginCollection#get} by its
	* name and its constructor. If not, then only by its constructor.
	*
	* The name should reflect the constructor name.
	*
	* To keep the plugin class definition tight, it is recommended to define this property as a static getter:
	*
	* ```ts
	* export class ImageCaption {
	* 	static get pluginName() {
	* 		return 'ImageCaption';
	* 	}
	* }
	* ```
	*
	* Note: The native `Function.name` property could not be used to keep the plugin name because
	* it will be mangled during code minification.
	*
	* Naming a plugin is necessary to enable removing it through the
	* {@link module:core/editor/editorconfig~EditorConfig#removePlugins `config.removePlugins`} option.
	*/
	readonly pluginName?: string;
	/**
	* A flag which defines if a plugin is allowed or not allowed to be used directly by a {@link module:core/context~Context}.
	*/
	readonly isContextPlugin?: boolean;
	/**
	* A flag which defines if a plugin is an official CKEditor 5 plugin.
	*
	* @internal
	*/
	readonly isOfficialPlugin?: boolean;
	/**
	* A flag which defines if a plugin is a premium CKEditor 5 plugin.
	*
	* @internal
	*/
	readonly isPremiumPlugin?: boolean;
	/**
	* An unique id of a plugin which belongs to the free plan on commercial license.
	*
	* @internal
	*/
	readonly licenseFeatureCode?: string;
}
export type PluginDependencies<TContext = Editor> = ReadonlyArray<PluginConstructor<TContext> | string>;
/**
* Maps plugin instances and plugin names to plugin dependency constructors and literal plugin names.
*/
export type PluginDependenciesOf<
	TDependencies extends ReadonlyArray<PluginInterface | string>,
	TContext = Editor
> = Readonly<{ [K in keyof TDependencies]: TDependencies[K] extends string ? TDependencies[K] : PluginConstructor<TContext> & (new (context: TContext) => TDependencies[K]) }>;
/**
* An array of loaded plugins.
*/
export type LoadedPlugins = Array<PluginInterface>;
export {};
