import { __INTERNAL_REMIRROR_IDENTIFIER_KEY__, ExtensionPriority, RemirrorIdentifier } from '@remirror/core-constants'; import type { ApplySchemaAttributes, Dispose, EditorState, EditorView, EmptyShape, MarkExtensionSpec, MarkSpecOverride, MarkType, NodeExtensionSpec, NodeSpecOverride, NodeType, Replace, Shape, ValidOptions } from '@remirror/core-types'; import type { AppendLifecycleProps, ApplyStateLifecycleProps, BaseExtensionOptions, ExtensionCommandReturn, ExtensionHelperReturn, StateUpdateLifecycleProps } from '../types'; import { AnyBaseClassOverrides, BaseClass, BaseClassConstructor, ConstructorProps, DefaultOptions } from './base-class'; /** * Auto infers the parameter for the constructor. If there is a required static * option then the TypeScript compiler will error if nothing is passed in. */ export declare type ExtensionConstructorProps = ConstructorProps; /** * Extensions are fundamental to the way that Remirror works by grouping * together the functionality and handling the management of similar concerns. * * @remarks * * Extension can adjust editor functionality in any way. Here are some * examples. * * - How the editor displays certain content, i.e. **bold**, _italic_, * **underline**. * - Which commands should be made available e.g. `commands.toggleBold()` to * toggle the weight of the selected text. * - Check if a command is currently enabled (i.e a successful dry run) e.g. * `commands.toggleBold.isEnabled()`. * - Register Prosemirror `Plugin`s, `keymap`s, `InputRule`s `PasteRule`s, * `Suggestions`, and custom `nodeViews` which affect the behavior of the * editor. * * There are three types of `Extension`. * * - `NodeExtension` - For creating Prosemirror nodes in the editor. See * {@link NodeExtension} * - `MarkExtension` - For creating Prosemirror marks in the editor. See * {@link MarkExtension} * - `PlainExtension` - For behavior which doesn't map to a `ProsemirrorNode` or * `Mark` and as a result doesn't directly affect the Prosemirror `Schema` or * content. See {@link PlainExtension}. * * This `Extension` is an abstract class that should not be used directly but * rather extended to add the intended functionality. * * ```ts * import { PlainExtension, Static } from 'remirror'; * * interface AwesomeExtensionOptions { * isAwesome?: Static; * id?: string; * } * * class AwesomeExtension extends PlainExtension { * static defaultOptions: DefaultExtensionOptions = { * isAwesome: true, * id: '', * } * * get name() { * return 'awesome' as const; * } * } * ``` */ declare abstract class Extension extends BaseClass { /** * The default priority for this family of extensions. */ static readonly defaultPriority: ExtensionPriority; /** * Allows for the `RemirrorManager` or `Preset`'s to override the priority of * an extension. */ private priorityOverride?; /** * The priority level for this instance of the extension. A higher value * corresponds to a higher priority extension */ get priority(): ExtensionPriority; /** * The name that the constructor should have, which doesn't get mangled in * production. */ get constructorName(): string; /** * The store is a shared object that's internal to each extension. It includes * often used items like the `view` and `schema` that are added by the * extension manager and also the lifecycle extension methods. * * **NOTE** - The store is not available until the manager has been created * and received the extension. As a result trying to access the store during * `init` and `constructor` will result in a runtime error. * * Some properties of the store are available at different phases. You should * check the inline documentation to know when a certain property is useable * in your extension. */ protected get store(): Remirror.ExtensionStore; /** * The list of extensions added to the editor by this `Preset`. */ get extensions(): Array; /** * Private list of extension stored within this [[`Preset`]]. */ private _extensions; /** * An extension mapping of the extensions and their constructors. */ private readonly extensionMap; /** * This store is can be modified by the extension manager with and lifecycle * extension methods. * * Different properties are added at different times so it's important to * check the documentation for each property to know what phase is being * added. */ private _store?; constructor(...args: ExtensionConstructorProps); /** * When there are duplicate extensions used within the editor the extension * manager will call this method and make sure all extension holders are using * the same instance of the `ExtensionConstructor`. * * @internal */ replaceChildExtension(constructor: AnyExtensionConstructor, extension: this['~E']): void; /** * Not for usage. This is purely for types to make it easier to infer * available sub extension types. * * @internal */ ['~E']: ReturnType[number]; /** * Create the extensions which will be consumed by the preset. Override this * if you would like to make your extension a parent to other (holder) * extensions which don't make sense existing outside of the context of this * extension. * * @remarks * * Since this method is called in the constructor it should always be created * as an instance method and not a property. Properties aren't available for * the call to the parent class. * * ```ts * class HolderExtension extends PlainExtension { * get name() { * return 'holder' * } * * // GOOD ✅ * createExtensions() { * return []; * } * * // BAD ❌ * createExtensions = () => { * return []; * } * } * ``` */ createExtensions(): AnyExtension[]; /** * Get an extension from this holder extension by providing the desired * `Constructor`. * * @param Constructor - the extension constructor to find in the editor. * * @remarks * * This method will throw an error if the constructor doesn't exist within the * extension created by this extension. * * It can be used to forward options and attach handlers to the children * extensions. It is the spiritual replacement of the `Preset` extension. * * ```ts * import { PlainExtension, OnSetOptionsProps } from 'remirror'; * * interface ParentOptions { weight?: string } * * class ParentExtension extends PlainExtension { * get name() { * return 'parent' as const; * } * * createExtensions() { * return [new BoldExtension()] * } * * onSetOptions(options: OnSetOptionsProps): void { * if (options.changes.weight.changed) { * // Update the value of the provided extension. * this.getExtension(BoldExtension).setOption({ weight: options.changes.weight.value }); * } * } * } * ``` */ getExtension(Constructor: Type): InstanceType; /** * Check if the type of this extension's constructor matches the type of the * provided constructor. */ isOfType(Constructor: Type): this is InstanceType; /** * Pass a reference to the globally shared `ExtensionStore` for this * extension. * * @remarks * * The extension store allows extensions to access important variables without * complicating their creator methods. * * ```ts * import { PlainExtension } from 'remirror'; * * class Awesome extends PlainExtension { * customMethod() { * if (this.store.view.hasFocus()) { * log('dance dance dance'); * } * } * } * ``` * * This should only be called by the `RemirrorManager`. * * @internal * @nonVirtual */ setStore(store: Remirror.ExtensionStore): void; /** * Clone an extension. */ clone(...args: ExtensionConstructorProps): Extension; /** * Set the priority override for this extension. This is used in the * `RemirrorManager` in order to override the priority of an extension. * * If you set the first parameter to `undefined` it will remove the priority * override. * * @internal */ setPriority(priority: undefined | ExtensionPriority): void; /** * This handler is called when the `RemirrorManager` is first created. * * @remarks * * Since it is called as soon as the manager is some methods may not be * available in the extension store. When accessing methods on `this.store` be * shore to check when they become available in the lifecycle. * * You can return a `Dispose` function which will automatically be called when * the extension is destroyed. * * This handler is called before the `onView` handler. * * @category Lifecycle Methods */ onCreate?(): Dispose | void; /** * This event happens when the view is first received from the view layer * (e.g. React). * * Return a dispose function which will be called when the extension is * destroyed. * * This handler is called after the `onCreate` handler. * * @category Lifecycle Methods */ onView?(view: EditorView): Dispose | void; /** * This can be used by the `Extension` to append a transaction to the latest * update. * * This is shorthand for the `ProsemirrorPlugin.spec.appendTransaction`. * * @category Lifecycle Methods */ onAppendTransaction?(props: AppendLifecycleProps): void; /** * This is called when the prosemirror editor state is first attached to the * editor. It can be useful for doing some preparation work. * * This is a shorthand for creating a plugin and adding the * [[`Plugin.spec.state.init`]]. * * @category Lifecycle Methods */ onInitState?(state: EditorState): void; /** * This is called when the state is being applied to the editor. This can be * used as a shorthand for the [[`Plugin.spec.state.apply`]] method. * * For example, when using [[`createDecorations`]] you can respond to editor * updates within this callback. * * @category Lifecycle Methods */ onApplyState?(props: ApplyStateLifecycleProps): void; /** * This handler is called after a transaction successfully updates the editor * state. It is called asynchronously after the [[`onApplyState`]] hook has * been run run. * * @category Lifecycle Methods */ onStateUpdate?(props: StateUpdateLifecycleProps): void; /** * Called when the extension is being destroyed. * * @category Lifecycle Methods */ onDestroy?(): void; } /** * Declaration merging since the constructor property can't be defined on the * actual class. */ interface Extension extends Remirror.BaseExtension { /** * The type of the constructor for the extension. */ constructor: ExtensionConstructor; /** * An extension can declare the extensions it requires. * * @remarks * * When creating the extension manager the extension will be checked for * required extension as well as a quick check to see if the required * extension is already included. If not present a descriptive error will be * thrown. */ requiredExtensions?: AnyExtensionConstructor[]; } /** * Get the expected type signature for the `defaultOptions`. Requires that every * optional setting key (except for keys which are defined on the * `BaseExtensionOptions`) has a value assigned. */ export declare type DefaultExtensionOptions = DefaultOptions; /** * Create a plain extension which doesn't directly map to Prosemirror nodes or * marks. * * Plain extensions are a great way to add custom behavior to your editor. */ export declare abstract class PlainExtension extends Extension { /** @internal */ static get [__INTERNAL_REMIRROR_IDENTIFIER_KEY__](): RemirrorIdentifier.PlainExtensionConstructor; /** @internal */ get [__INTERNAL_REMIRROR_IDENTIFIER_KEY__](): RemirrorIdentifier.PlainExtension; } /** * A mark extension is based on the `Mark` concept from from within prosemirror * {@link https://prosemirror.net/docs/guide/#schema.marks} * * @remarks * * Marks are used to add extra styling or other information to inline content. * Mark types are objects much like node types, used to tag mark objects and * provide additional information about them. */ export declare abstract class MarkExtension extends Extension { /** @internal */ static get [__INTERNAL_REMIRROR_IDENTIFIER_KEY__](): RemirrorIdentifier.MarkExtensionConstructor; /** * Whether to disable extra attributes for this extension. */ static readonly disableExtraAttributes: boolean; /** @internal */ get [__INTERNAL_REMIRROR_IDENTIFIER_KEY__](): RemirrorIdentifier.MarkExtension; /** * Provides access to the mark type from the schema. * * @remarks * * The type is available as soon as the schema is created by the * `SchemaExtension` which has the priority `Highest`. It should be safe to * access in any of the lifecycle methods. */ get type(): MarkType; constructor(...args: ExtensionConstructorProps); /** * Provide a method for creating the schema. This is required in order to * create a `MarkExtension`. * * @remarks * * The main difference between the return value of this method and Prosemirror * `MarkSpec` is that that the `toDOM` method doesn't allow dom manipulation. * You can only return an array or string. * * For more advanced requirements, it may be possible to create a `nodeView` * to manage the dom interactions. */ abstract createMarkSpec(extra: ApplySchemaAttributes, override: MarkSpecOverride): MarkExtensionSpec; } export interface MarkExtension extends Extension, Remirror.MarkExtension { } /** * Defines the abstract class for extensions which can place nodes into the * prosemirror state. * * @remarks * * For more information see {@link https://prosemirror.net/docs/ref/#model.Node} */ export declare abstract class NodeExtension extends Extension { static get [__INTERNAL_REMIRROR_IDENTIFIER_KEY__](): RemirrorIdentifier.NodeExtensionConstructor; /** * Whether to disable extra attributes for this extension. */ static readonly disableExtraAttributes: boolean; /** @internal */ get [__INTERNAL_REMIRROR_IDENTIFIER_KEY__](): RemirrorIdentifier.NodeExtension; /** * Provides access to the node type from the schema. */ get type(): NodeType; constructor(...args: ExtensionConstructorProps); /** * Provide a method for creating the schema. This is required in order to * create a `NodeExtension`. * * @remarks * * A node schema defines the behavior of the content within the editor. This * is very tied to the prosemirror implementation and the best place to learn * more about it is in the * {@link https://prosemirror.net/docs/guide/#schema docs}. * * @params hole - a method that is meant to indicate where extra attributes * should be placed (if they exist). * * The `hole` is a function that augments the passed object adding a special * `secret` key which is used to insert the extra attributes setter. * * ```ts * import { NodeExtension, SpecHole } from 'remirror'; * * class AwesomeExtension extends NodeExtension { * get name() { return 'awesome' as const'; } * * createNodeSpec() { * return { * toDOM: (node) => { * return ['p', hole(), 0] * } * } * } * } * ``` * * The above example will have the `hole()` method call replaced with the * extra attributes. */ abstract createNodeSpec(extra: ApplySchemaAttributes, override: NodeSpecOverride): NodeExtensionSpec; } export interface NodeExtension extends Extension, Remirror.NodeExtension { } /** * The type which is applicable to any extension instance. * * **NOTE** `& object` forces VSCode to use the name `AnyExtension` rather than * print out `Replace, Remirror.AnyExtensionOverrides>` */ export declare type AnyExtension = Replace, Remirror.AnyExtensionOverrides> & object; /** * The type which is applicable to any extension instance. */ export declare type AnyExtensionConstructor = Replace, { new (...args: any[]): AnyExtension; }>; /** * The type for any potential PlainExtension. */ export declare type AnyPlainExtension = Replace, Remirror.AnyExtensionOverrides> & object; /** * The type for any potential NodeExtension. */ export declare type AnyNodeExtension = Replace, Remirror.AnyExtensionOverrides> & object; /** * The type for any potential MarkExtension. */ export declare type AnyMarkExtension = Replace, Remirror.AnyExtensionOverrides> & object; /** * Mutate the default extension options. * * @remarks * * This is a dangerous method since it allows you to mutate the received object. * Don't use it unless you absolutely have to. * * A potential use case is for adding a new default option to all extensions. It * shows an example of how to accomplish this in a typesafe way. * * ```ts * import { mutateDefaultExtensionOptions } from 'remirror'; * * mutateDefaultExtensionOptions((settings) => { * // Set the default value of all extensions to have a property `customSetting` with value `false`. * settings.customSetting = false; * }) * * declare global { * namespace Remirror { * interface BaseExtensionOptions { * customSetting?: boolean; * } * } * } *``` * * The mutation must happen before any extension have been instantiated. */ export declare function mutateDefaultExtensionOptions(mutatorMethod: (defaultOptions: BaseExtensionOptions) => void): void; /** * Determines if the passed value is an extension. * * @param value - the value to test */ export declare function isExtension(value: unknown): value is Type; /** * Determines if the passed value is an extension constructor. * * @param value - the value to test */ export declare function isExtensionConstructor(value: unknown): value is Type; /** * Checks whether the provided value is a plain extension. * * @param value - the extension to check */ export declare function isPlainExtension(value: unknown): value is Type; /** * Determines if the passed in extension is a node extension. Useful as a type * guard where a particular type of extension is needed. * * @param value - the extension to check */ export declare function isNodeExtension(value: unknown): value is Type; /** * Determines if the passed in extension is a mark extension. Useful as a type * guard where a particular type of extension is needed. * * @param value - the extension to check */ export declare function isMarkExtension(value: unknown): value is Type; export interface ExtensionConstructor extends BaseClassConstructor, Partial { new (...args: ExtensionConstructorProps): Extension; /** * The default priority level for all instance of this extension. * * @defaultValue ExtensionPriority.Default */ readonly defaultPriority: ExtensionPriority; } export declare type AnyManagerStore = Remirror.ManagerStore; export declare type ManagerStoreKeys = keyof Remirror.ManagerStore; declare global { /** * This namespace is global and you can use declaration merging to extend and * create new types used by the `remirror` project. * * @remarks * * The following would add `MyCustomType` to the `Remirror` namespace. Please * note that this can only be used for types and interfaces. * * ```ts * declare global { * namespace Remirror { * type MyCustomType = 'look-at-me'; * } * } * ``` */ namespace Remirror { /** * This interface stores all the currently installed extensions. As a result * it can be used to set the default loaded extensions to include all * available within `node_modules`. By extending this extension in the * global `Remirror` namespace the key is ignored but the value is used to * form the union type in the `chain`, `commands`, `helpers` properties on * the `Remirror.ExtensionStore` interface. * * This is useful for extensions being able to reuse the work of other * extension. */ interface AllExtensions { } /** * This is the global interface for adding extra methods and properties to * all [[`Extension`]]s using declaration merging. * * @remarks * * The following will add `newOption` to the expected options. This is the * way that extensions which add new functionality to the editor can request * configuration options. * * ```ts * declare global { * namespace Remirror { * interface ExtensionFactoryProps { * newOption?: string; * } * } * } * ``` */ interface BaseExtension { } interface NodeExtension { } interface MarkExtension { } /** * An override to for the `AnyExtension` type. If you're extension adds a * new property to the `Extension` that is deeply nested or very complex it * can break the `AnyExtension` implementation from being compatible with * all valid extensions. * * The keys you provide on this override replace the default `AnyExtension` * types include unsafe properties that need to be simplified. * * An example is the `constructor` property which makes it impossible to * find a common interface between extensions with different settings and * properties. By setting the `constructor` to a much simpler override all * `Extension`'s are now assignable to the `AnyExtension type again.` */ interface AnyExtensionOverrides extends AnyBaseClassOverrides { constructor: AnyExtensionConstructor; ['~C']: ExtensionCommandReturn; ['~H']: ExtensionHelperReturn; ['~E']: AnyExtension; } } } export type { Extension };