import { Node as ProseNode , NodeSpec , MarkSpec } from "prosemirror-model" ; import { InputRule } from "prosemirror-inputrules" ; import { Keymap } from "prosemirror-commands" ; import { NodeView } from "prosemirror-view" ; import { ProseSchema , ProseNodeType , ProseMarkType } from "@common/types" ; import * as Uni from "unist" ; import { ProseMarkMap , ProseNodeMap } from "./editor-config" ; export interface ExtensionStore < S extends ProseSchema > { schema : S ; } export abstract class NwtExtension < S extends ProseSchema = ProseSchema , N extends string = string > { abstract get name ( ) : N ; /**
     * Throw an error if the extension's `_store` field hasn't yet been populated.
     * (useful as a type guard to avoid null-checking boilerplate in syntax extensions.)
     */ ensureInitialized ( ) { if ( this . _store === null || this . _store === undefined ) { throw new Error ( `Attempted to access NwtExtension (${ this . name }) before initialization.` ) ; } return true ; } _store : ExtensionStore < S > | null = null ; get store ( ) : ExtensionStore < S > { if ( ! this . ensureInitialized ( ) ) { throw new Error ( "not iniialized" ) ; } return this . _store ; } createInputRules ( ) { return [ ] ; } createKeymap ( ) { return { } ; } } export abstract class NodeExtension < T extends Uni . Node , N extends string = string > extends NwtExtension < ProseSchema < N , string > , N > { /**
     * Returns the ProseMirror NodeType defined by this extension.
     * (not available until the extension has been used to create a schema)
     */ get nodeType ( ) : ProseNodeType < ProseSchema < N , string > , N > { let type = this . store . schema . nodes [ this . name ] ; if ( type === undefined ) { throw new Error ( `error retrieving node type for extension ${ this . name }` ) ; } return type ; } abstract createNodeSpec ( ) ; createNodeView ( ) { return null ; } abstract get mdastNodeType ( ) : T [ "type" ] ; abstract createMdastMap ( ) ; /**
     * Extensions can override this method to impose additional
     * conditions on the Mdast node type, beyond `node.type = T`.
     */ mdastNodeTest ( node ) { return true ; } abstract prose2mdast ( ) ; } export abstract class MarkExtension < T extends Uni . Node , M extends string = string > extends NwtExtension < ProseSchema < string , M > , M > { /**
     * Returns the ProseMirror MarkType defined by this extension.
     * (not available until the extension has been used to create a schema)
     */ get markType ( ) : ProseMarkType < ProseSchema < string , M > , M > { let type = this . store . schema . marks [ this . name ] ; if ( type === undefined ) { throw new Error ( `error retrieving mark type for extension ${ this . name }` ) ; } return type ; } abstract createMarkSpec ( ) ; abstract get mdastNodeType ( ) : T [ "type" ] ; /**
     * Extensions can override this method to impose additional
     * conditions on the Mdast node type, beyond `node.type = T`.
     */ mdastNodeTest ( node ) { return true ; } /**
     * Extensions can override this method to impose additional
     * conditions on the Mdast node type, beyond `node.type = T`.
     *
     * TODO MarkExtension and NodeExtension should inherit from a common parent,
     *   or they should both include an optional `mapper` field
     */ abstract createMdastMap ( ) ; abstract prose2mdast ( ) ; } /** Get the attributes of the ProseMirror Node defined by the `NE` extension. */ export type ExtensionNodeAttrs < NE extends NodeExtension < any > , RT = ReturnType < NE [ "createNodeSpec" ] > [ "attrs" ] > = { [ K in keyof RT ] : RT [ K ] extends { default : infer D ; } ? D : unknown ; } ; export type MdNodeMap_Custom < N extends Uni . Node = Uni . Node , S extends ProseSchema = ProseSchema > = { mapType : "node_custom" ; mapNode : ( node : N , children : ProseNode < S > [ ] , ctx : unknown , state : unknown ) => ProseNode < S > [ ] ; } ; export type MdMarkMap_Custom < N extends Uni . Node = Uni . Node , S extends ProseSchema = ProseSchema > = { mapType : "mark_custom" ; mapMark : ( node : N , children : ProseNode < S > [ ] ) => ProseNode < S > [ ] ; } ; export enum MdastNodeMapType { NODE_DEFAULT = "node_default" , NODE_EMPTY = "node_empty" , NODE_LITERAL = "node_literal" } export enum MdastMarkMapType { MARK_DEFAULT = "mark_default" , MARK_LITERAL = "mark_literal" } export type MdastNodeMap < N extends Uni . Node > = MdNodeMap_Custom < N > | MdastNodeMapType ; export type MdastMarkMap < N extends Uni . Node > = MdMarkMap_Custom < N > | MdastMarkMapType ; export enum Prose2Mdast_NodeMap_Presets { NODE_DEFAULT = "p2m_node_default" , NODE_EMPTY = "p2m_node_empty" , NODE_LIFT_LITERAL = "p2m_node_literal" } export type Prose2Mdast_NodeMap < Ctx = unknown , St = unknown > = Prose2Mdast_NodeMap_Presets | { create : ProseNodeMap < Ctx , St > ; } ; export enum Prose2Mdast_MarkMap_Presets { MARK_DEFAULT = "p2m_mark_default" , MARK_LITERAL = "p2m_mark_literal" } export type Prose2Mdast_MarkMap = Prose2Mdast_MarkMap_Presets | { create : ProseMarkMap ; } ;