add type to this context in extensions

This commit is contained in:
Philipp Kühn
2020-10-22 23:21:52 +02:00
parent 6746163dda
commit d8d33c7429
8 changed files with 258 additions and 64 deletions

View File

@@ -8,7 +8,7 @@ import markIsActive from './utils/markIsActive'
import getNodeAttrs from './utils/getNodeAttrs' import getNodeAttrs from './utils/getNodeAttrs'
import getMarkAttrs from './utils/getMarkAttrs' import getMarkAttrs from './utils/getMarkAttrs'
import removeElement from './utils/removeElement' import removeElement from './utils/removeElement'
import getSchemaTypeByName from './utils/getSchemaTypeByName' import getSchemaTypeNameByName from './utils/getSchemaTypeNameByName'
import getHtmlFromFragment from './utils/getHtmlFromFragment' import getHtmlFromFragment from './utils/getHtmlFromFragment'
import createStyleTag from './utils/createStyleTag' import createStyleTag from './utils/createStyleTag'
import CommandManager from './CommandManager' import CommandManager from './CommandManager'
@@ -109,7 +109,6 @@ export class Editor extends EventEmitter {
this.createCommandManager() this.createCommandManager()
this.createExtensionManager() this.createExtensionManager()
this.createSchema() this.createSchema()
// this.extensionManager.resolveConfigs()
this.createView() this.createView()
this.registerCommands(coreCommands) this.registerCommands(coreCommands)
this.injectCSS() this.injectCSS()
@@ -338,7 +337,7 @@ export class Editor extends EventEmitter {
* @param attrs Attributes of the node or mark * @param attrs Attributes of the node or mark
*/ */
public isActive(name: string, attrs = {}) { public isActive(name: string, attrs = {}) {
const schemaType = getSchemaTypeByName(name, this.schema) const schemaType = getSchemaTypeNameByName(name, this.schema)
if (schemaType === 'node') { if (schemaType === 'node') {
return nodeIsActive(this.state, this.schema.nodes[name], attrs) return nodeIsActive(this.state, this.schema.nodes[name], attrs)

View File

@@ -1,3 +1,4 @@
import { MarkType, NodeType } from 'prosemirror-model'
import { Plugin } from 'prosemirror-state' import { Plugin } from 'prosemirror-state'
import { Editor } from './Editor' import { Editor } from './Editor'
import { GlobalAttributes } from './types' import { GlobalAttributes } from './types'
@@ -16,11 +17,9 @@ export interface ExtensionSpec<Options = {}, Commands = {}> {
/** /**
* Global attributes * Global attributes
*/ */
addGlobalAttributes?: ( addGlobalAttributes?: (this: {
this: { options: Options,
options: Options, }) => GlobalAttributes,
},
) => GlobalAttributes,
/** /**
* Commands * Commands
@@ -28,6 +27,7 @@ export interface ExtensionSpec<Options = {}, Commands = {}> {
addCommands?: (this: { addCommands?: (this: {
options: Options, options: Options,
editor: Editor, editor: Editor,
type: NodeType | MarkType,
}) => Commands, }) => Commands,
/** /**
@@ -36,6 +36,7 @@ export interface ExtensionSpec<Options = {}, Commands = {}> {
addKeyboardShortcuts?: (this: { addKeyboardShortcuts?: (this: {
options: Options, options: Options,
editor: Editor, editor: Editor,
type: NodeType | MarkType,
}) => { }) => {
[key: string]: any [key: string]: any
}, },
@@ -46,6 +47,7 @@ export interface ExtensionSpec<Options = {}, Commands = {}> {
addInputRules?: (this: { addInputRules?: (this: {
options: Options, options: Options,
editor: Editor, editor: Editor,
// type: NodeType | MarkType,
}) => any[], }) => any[],
/** /**
@@ -54,6 +56,7 @@ export interface ExtensionSpec<Options = {}, Commands = {}> {
addPasteRules?: (this: { addPasteRules?: (this: {
options: Options, options: Options,
editor: Editor, editor: Editor,
type: NodeType | MarkType,
}) => any[], }) => any[],
/** /**
@@ -62,6 +65,7 @@ export interface ExtensionSpec<Options = {}, Commands = {}> {
addProseMirrorPlugins?: (this: { addProseMirrorPlugins?: (this: {
options: Options, options: Options,
editor: Editor, editor: Editor,
type: NodeType | MarkType,
}) => Plugin[], }) => Plugin[],
} }

View File

@@ -3,11 +3,11 @@ import { keymap } from 'prosemirror-keymap'
// import { Schema, Node as ProsemirrorNode } from 'prosemirror-model' // import { Schema, Node as ProsemirrorNode } from 'prosemirror-model'
import { inputRules } from 'prosemirror-inputrules' import { inputRules } from 'prosemirror-inputrules'
// import { EditorView, Decoration } from 'prosemirror-view' // import { EditorView, Decoration } from 'prosemirror-view'
import { Editor } from './Editor' import { Editor } from './Editor'
// import capitalize from './utils/capitalize' // import capitalize from './utils/capitalize'
import { Extensions } from './types' import { Extensions } from './types'
import getSchema from './utils/getSchema' import getSchema from './utils/getSchema'
import getSchemaTypeByName from './utils/getSchemaTypeByName'
export default class ExtensionManager { export default class ExtensionManager {
@@ -18,54 +18,39 @@ export default class ExtensionManager {
constructor(extensions: Extensions, editor: Editor) { constructor(extensions: Extensions, editor: Editor) {
this.editor = editor this.editor = editor
this.extensions = extensions this.extensions = extensions
this.extensions.forEach(extension => {
const context = {
options: extension.options,
editor: this.editor,
type: getSchemaTypeByName(extension.name, this.schema),
}
const commands = extension.addCommands.bind(context)()
editor.registerCommands(commands)
})
} }
// resolveConfigs() {
// this.extensions.forEach(extension => {
// const { editor } = this
// const { name } = extension.config
// const options = {
// ...extension.config.defaults,
// ...extension.options,
// }
// const type = extension.type === 'node'
// ? editor.schema.nodes[name]
// : editor.schema.marks[name]
// resolveExtensionConfig(extension, 'commands', {
// name, options, editor, type,
// })
// resolveExtensionConfig(extension, 'inputRules', {
// name, options, editor, type,
// })
// resolveExtensionConfig(extension, 'pasteRules', {
// name, options, editor, type,
// })
// resolveExtensionConfig(extension, 'keys', {
// name, options, editor, type,
// })
// resolveExtensionConfig(extension, 'plugins', {
// name, options, editor, type,
// })
// if (extension.config.commands) {
// editor.registerCommands(extension.config.commands)
// }
// })
// }
get schema() { get schema() {
return getSchema(this.extensions) return getSchema(this.extensions)
} }
get plugins(): Plugin[] { get plugins(): Plugin[] {
// const plugins = collect(this.extensions) const plugins = this.extensions
// .flatMap(extension => extension.config.plugins) .map(extension => {
// .filter(plugin => plugin) const context = {
// .toArray() options: extension.options,
editor: this.editor,
type: getSchemaTypeByName(extension.name, this.schema),
}
return extension.addProseMirrorPlugins.bind(context)()
})
.flat()
return [ return [
// ...plugins, ...plugins,
...this.keymaps, ...this.keymaps,
...this.pasteRules, ...this.pasteRules,
inputRules({ rules: this.inputRules }), inputRules({ rules: this.inputRules }),
@@ -73,19 +58,31 @@ export default class ExtensionManager {
} }
get inputRules(): any { get inputRules(): any {
return [] return this.extensions
// return collect(this.extensions) .map(extension => {
// .flatMap(extension => extension.config.inputRules) const context = {
// .filter(plugin => plugin) options: extension.options,
// .toArray() editor: this.editor,
type: getSchemaTypeByName(extension.name, this.schema),
}
return extension.addInputRules.bind(context)()
})
.flat()
} }
get pasteRules(): any { get pasteRules(): any {
return [] return this.extensions
// return collect(this.extensions) .map(extension => {
// .flatMap(extension => extension.config.pasteRules) const context = {
// .filter(plugin => plugin) options: extension.options,
// .toArray() editor: this.editor,
type: getSchemaTypeByName(extension.name, this.schema),
}
return extension.addPasteRules.bind(context)()
})
.flat()
} }
get keymaps() { get keymaps() {
@@ -93,6 +90,7 @@ export default class ExtensionManager {
const context = { const context = {
options: extension.options, options: extension.options,
editor: this.editor, editor: this.editor,
type: getSchemaTypeByName(extension.name, this.schema),
} }
return keymap(extension.addKeyboardShortcuts.bind(context)()) return keymap(extension.addKeyboardShortcuts.bind(context)())

View File

@@ -1,17 +1,44 @@
import { DOMOutputSpec, MarkSpec, Mark } from 'prosemirror-model' import {
DOMOutputSpec, MarkSpec, Mark, MarkType,
} from 'prosemirror-model'
import { Plugin } from 'prosemirror-state'
import { ExtensionSpec, defaultExtension } from './Extension' import { ExtensionSpec, defaultExtension } from './Extension'
import { Attributes } from './types' import { Attributes } from './types'
import { Editor } from './Editor'
export interface MarkExtensionSpec<Options = {}, Commands = {}> extends ExtensionSpec<Options, Commands> { export interface MarkExtensionSpec<Options = {}, Commands = {}> extends ExtensionSpec<Options, Commands> {
/**
* Inclusive
*/
inclusive?: MarkSpec['inclusive'], inclusive?: MarkSpec['inclusive'],
/**
* Excludes
*/
excludes?: MarkSpec['excludes'], excludes?: MarkSpec['excludes'],
/**
* Group
*/
group?: MarkSpec['group'], group?: MarkSpec['group'],
/**
* Spanning
*/
spanning?: MarkSpec['spanning'], spanning?: MarkSpec['spanning'],
/**
* Parse HTML
*/
parseHTML?: ( parseHTML?: (
this: { this: {
options: Options, options: Options,
}, },
) => MarkSpec['parseDOM'], ) => MarkSpec['parseDOM'],
/**
* Render HTML
*/
renderHTML?: ( renderHTML?: (
this: { this: {
options: Options, options: Options,
@@ -21,11 +48,62 @@ export interface MarkExtensionSpec<Options = {}, Commands = {}> extends Extensio
attributes: { [key: string]: any }, attributes: { [key: string]: any },
} }
) => DOMOutputSpec, ) => DOMOutputSpec,
/**
* Attributes
*/
addAttributes?: ( addAttributes?: (
this: { this: {
options: Options, options: Options,
}, },
) => Attributes, ) => Attributes,
/**
* Commands
*/
addCommands?: (this: {
options: Options,
editor: Editor,
type: MarkType,
}) => Commands,
/**
* Keyboard shortcuts
*/
addKeyboardShortcuts?: (this: {
options: Options,
editor: Editor,
type: MarkType,
}) => {
[key: string]: any
},
/**
* Input rules
*/
addInputRules?: (this: {
options: Options,
editor: Editor,
type: MarkType,
}) => any[],
/**
* Paste rules
*/
addPasteRules?: (this: {
options: Options,
editor: Editor,
type: MarkType,
}) => any[],
/**
* ProseMirror plugins
*/
addProseMirrorPlugins?: (this: {
options: Options,
editor: Editor,
type: MarkType,
}) => Plugin[],
} }
export type MarkExtension = Required<Omit<MarkExtensionSpec, 'defaultOptions'> & { export type MarkExtension = Required<Omit<MarkExtensionSpec, 'defaultOptions'> & {

View File

@@ -1,28 +1,79 @@
import { DOMOutputSpec, NodeSpec, Node } from 'prosemirror-model' import {
DOMOutputSpec, NodeSpec, Node, NodeType,
} from 'prosemirror-model'
import { Plugin } from 'prosemirror-state'
import { ExtensionSpec, defaultExtension } from './Extension' import { ExtensionSpec, defaultExtension } from './Extension'
import { Attributes } from './types' import { Attributes } from './types'
import { Editor } from './Editor'
export interface NodeExtensionSpec<Options = {}, Commands = {}> extends ExtensionSpec<Options, Commands> { export interface NodeExtensionSpec<Options = {}, Commands = {}> extends ExtensionSpec<Options, Commands> {
/**
* TopNode
*/
topNode?: boolean, topNode?: boolean,
/** /**
* content * Content
*/ */
content?: NodeSpec['content'], content?: NodeSpec['content'],
/**
* Marks
*/
marks?: NodeSpec['marks'], marks?: NodeSpec['marks'],
/**
* Group
*/
group?: NodeSpec['group'], group?: NodeSpec['group'],
/**
* Inline
*/
inline?: NodeSpec['inline'], inline?: NodeSpec['inline'],
/**
* Atom
*/
atom?: NodeSpec['atom'], atom?: NodeSpec['atom'],
/**
* Selectable
*/
selectable?: NodeSpec['selectable'], selectable?: NodeSpec['selectable'],
/**
* Draggable
*/
draggable?: NodeSpec['draggable'], draggable?: NodeSpec['draggable'],
/**
* Code
*/
code?: NodeSpec['code'], code?: NodeSpec['code'],
/**
* Defining
*/
defining?: NodeSpec['defining'], defining?: NodeSpec['defining'],
/**
* Isolating
*/
isolating?: NodeSpec['isolating'], isolating?: NodeSpec['isolating'],
/**
* Parse HTML
*/
parseHTML?: ( parseHTML?: (
this: { this: {
options: Options, options: Options,
}, },
) => NodeSpec['parseDOM'], ) => NodeSpec['parseDOM'],
/**
* Render HTML
*/
renderHTML?: ( renderHTML?: (
this: { this: {
options: Options, options: Options,
@@ -32,11 +83,62 @@ export interface NodeExtensionSpec<Options = {}, Commands = {}> extends Extensio
attributes: { [key: string]: any }, attributes: { [key: string]: any },
} }
) => DOMOutputSpec, ) => DOMOutputSpec,
/**
* Add Attributes
*/
addAttributes?: ( addAttributes?: (
this: { this: {
options: Options, options: Options,
}, },
) => Attributes, ) => Attributes,
/**
* Commands
*/
addCommands?: (this: {
options: Options,
editor: Editor,
type: NodeType,
}) => Commands,
/**
* Keyboard shortcuts
*/
addKeyboardShortcuts?: (this: {
options: Options,
editor: Editor,
type: NodeType,
}) => {
[key: string]: any
},
/**
* Input rules
*/
addInputRules?: (this: {
options: Options,
editor: Editor,
type: NodeType,
}) => any[],
/**
* Paste rules
*/
addPasteRules?: (this: {
options: Options,
editor: Editor,
type: NodeType,
}) => any[],
/**
* ProseMirror plugins
*/
addProseMirrorPlugins?: (this: {
options: Options,
editor: Editor,
type: NodeType,
}) => Plugin[],
} }
export type NodeExtension = Required<Omit<NodeExtensionSpec, 'defaultOptions'> & { export type NodeExtension = Required<Omit<NodeExtensionSpec, 'defaultOptions'> & {

View File

@@ -2,11 +2,11 @@ import { Schema } from 'prosemirror-model'
export default function getSchemaTypeByName(name: string, schema: Schema) { export default function getSchemaTypeByName(name: string, schema: Schema) {
if (schema.nodes[name]) { if (schema.nodes[name]) {
return 'node' return schema.nodes[name]
} }
if (schema.marks[name]) { if (schema.marks[name]) {
return 'mark' return schema.marks[name]
} }
return null return null

View File

@@ -0,0 +1,13 @@
import { Schema } from 'prosemirror-model'
export default function getSchemaTypeNameByName(name: string, schema: Schema) {
if (schema.nodes[name]) {
return 'node'
}
if (schema.marks[name]) {
return 'mark'
}
return null
}

View File

@@ -17,7 +17,7 @@ const Code = createMark({
}, },
renderHTML({ attributes }) { renderHTML({ attributes }) {
return ['strong', attributes, 0] return ['code', attributes, 0]
}, },
addCommands() { addCommands() {