@prosekit/core
Advanced tools
Comparing version 0.0.5 to 0.0.6
@@ -31,2 +31,3 @@ export { toggleMark, type ToggleMarkOptions } from './commands/toggle-mark' | ||
type ExtractNodes, | ||
type SimplifyExtension, | ||
} from './types/extension' | ||
@@ -33,0 +34,0 @@ export { type ExtensionTyping } from './types/extension-typing' |
@@ -133,6 +133,13 @@ import { MarkType, Attrs, NodeType, Schema, ProseMirrorNode, MarkSpec, NodeSpec } from '@prosekit/pm/model'; | ||
interface Slot<Input, Output> { | ||
create: (inputs: Input[]) => Output; | ||
update: (inputs: Input[]) => Output | null; | ||
} | ||
/** @public */ | ||
interface FacetOptions<Input, Output> { | ||
combine: (inputs: Input[]) => Output; | ||
combine?: (inputs: Input[]) => Output; | ||
slot?: () => Slot<Input, Output>; | ||
next: Facet<Output, any>; | ||
single?: boolean; | ||
} | ||
@@ -144,9 +151,11 @@ /** @public */ | ||
/** @internal */ | ||
readonly combine: (inputs: Input[]) => Output; | ||
readonly slot: () => Slot<Input, Output>; | ||
/** @internal */ | ||
readonly next: Facet<Output, any> | null; | ||
/** @internal */ | ||
readonly single: boolean; | ||
private constructor(); | ||
static define<Input, Output>({ combine, next }: FacetOptions<Input, Output>): Facet<Input, Output>; | ||
static define<Input, Output>({ slot, combine, next, single, }: FacetOptions<Input, Output>): Facet<Input, Output>; | ||
/** @internal */ | ||
static defineSlot<Input>({ combine, }: Omit<FacetOptions<Input, Input>, 'next'>): Facet<Input, Input>; | ||
static defineSlot<Input>(options: Omit<FacetOptions<Input, Input>, 'next'>): Facet<Input, Input>; | ||
extension(inputs: Input[]): FacetExtension<Input, Output>; | ||
@@ -299,2 +308,2 @@ } | ||
export { CommandArgs, Editor, EditorOptions, Extension, ExtensionTyping, ExtractCommandCreators, ExtractCommandDispatchers, ExtractMarks, ExtractNodes, Facet, FacetExtension, FacetOptions, Keymap, MarkSpecOptions, NodeSpecOptions, NodeViewOptions, PluginFacetInput, PluginOptions, Priority, ProseKitError, SimplifyUnion, StateConfigCallback, StateConfigContext, ToggleMarkOptions, ToggleNodeOptions, ViewProps, addBaseCommands, addBaseKeymap, addCommands, addDoc, addInputRule, addKeymap, addMarkSpec, addNodeSpec, addNodeView, addParagraph, addPlugin, addText, createEditor, defineExtension, getMarkType, getNodeType, pluginFacet, toggleMark, toggleNode, withPriority }; | ||
export { CommandArgs, Editor, EditorOptions, Extension, ExtensionTyping, ExtractCommandCreators, ExtractCommandDispatchers, ExtractMarks, ExtractNodes, Facet, FacetExtension, FacetOptions, Keymap, MarkSpecOptions, NodeSpecOptions, NodeViewOptions, PluginFacetInput, PluginOptions, Priority, ProseKitError, SimplifyExtension, SimplifyUnion, StateConfigCallback, StateConfigContext, ToggleMarkOptions, ToggleNodeOptions, ViewProps, addBaseCommands, addBaseKeymap, addCommands, addDoc, addInputRule, addKeymap, addMarkSpec, addNodeSpec, addNodeView, addParagraph, addPlugin, addText, createEditor, defineExtension, getMarkType, getNodeType, pluginFacet, toggleMark, toggleNode, withPriority }; |
@@ -117,6 +117,2 @@ // src/commands/toggle-mark.ts | ||
// src/types/void-function.ts | ||
function voidFunction() { | ||
} | ||
// src/utils/is-mark-active.ts | ||
@@ -140,19 +136,53 @@ function isMarkActive(state, type, attrs) { | ||
// src/utils/uniq-array.ts | ||
function uniqPush(prev, next) { | ||
const result = [...prev]; | ||
for (const item of next) { | ||
if (!result.includes(item)) { | ||
result.push(item); | ||
} | ||
} | ||
return result; | ||
} | ||
function uniqRemove(prev, next) { | ||
const result = [...prev]; | ||
for (const item of next) { | ||
const index = result.indexOf(item); | ||
if (index !== -1) { | ||
result.splice(index, 1); | ||
} | ||
} | ||
return result; | ||
} | ||
// src/editor/facet.ts | ||
var nextIndex = 0; | ||
var Facet = class _Facet { | ||
constructor(combine, next) { | ||
constructor(slot, next, single) { | ||
/** @internal */ | ||
this.index = nextIndex++; | ||
this.combine = combine; | ||
this.slot = slot; | ||
this.next = next; | ||
this.single = single; | ||
} | ||
static define({ combine, next }) { | ||
return new _Facet(combine, next); | ||
static define({ | ||
slot, | ||
combine, | ||
next, | ||
single | ||
}) { | ||
const slotFn = slot ? slot : combine ? () => ({ | ||
create: combine, | ||
update: combine | ||
}) : null; | ||
if (!slotFn) { | ||
throw new ProseKitError( | ||
"Facet must have either 'slot' or 'combine' option" | ||
); | ||
} | ||
return new _Facet(slotFn, next, single != null ? single : false); | ||
} | ||
/** @internal */ | ||
static defineSlot({ | ||
combine | ||
}) { | ||
return new _Facet(combine, null); | ||
static defineSlot(options) { | ||
return _Facet.define(options); | ||
} | ||
@@ -220,3 +250,3 @@ extension(inputs) { | ||
// src/editor/slot.ts | ||
// src/editor/slots.ts | ||
import OrderedMap from "orderedmap"; | ||
@@ -240,3 +270,3 @@ var schemaSlot = Facet.defineSlot({ | ||
return (ctx) => { | ||
var _a, _b, _c, _d, _e; | ||
var _a, _b, _c, _d, _e, _f; | ||
const configs = callbacks.map((cb) => cb(ctx)); | ||
@@ -253,3 +283,3 @@ const config = { | ||
config.storedMarks = [...config.storedMarks, ...(_d = c.storedMarks) != null ? _d : []]; | ||
config.plugins = [...config.plugins, ...(_e = c.plugins) != null ? _e : []]; | ||
config.plugins = uniqPush((_e = config.plugins) != null ? _e : [], (_f = c.plugins) != null ? _f : []); | ||
} | ||
@@ -278,3 +308,42 @@ if (!config.doc && !config.schema) { | ||
// src/editor/flatten.ts | ||
function flatten(root) { | ||
function flattenInputTuple(inputTuple) { | ||
return [ | ||
...inputTuple[0], | ||
...inputTuple[1], | ||
...inputTuple[2], | ||
...inputTuple[3], | ||
...inputTuple[4] | ||
]; | ||
} | ||
function mergeInputTuple(tupleA, tupleB) { | ||
if (!tupleA) | ||
return tupleB; | ||
if (!tupleB) | ||
return tupleA; | ||
const [a0, a1, a2, a3, a4] = tupleA; | ||
const [b0, b1, b2, b3, b4] = tupleB; | ||
return [ | ||
uniqPush(a0, b0), | ||
uniqPush(a1, b1), | ||
uniqPush(a2, b2), | ||
uniqPush(a3, b3), | ||
uniqPush(a4, b4) | ||
]; | ||
} | ||
function removeInputTuple(tupleA, tupleB) { | ||
if (!tupleA) | ||
return [[], [], [], [], []]; | ||
if (!tupleB) | ||
return tupleA; | ||
const [a0, a1, a2, a3, a4] = tupleA; | ||
const [b0, b1, b2, b3, b4] = tupleB; | ||
return [ | ||
uniqRemove(a0, b0), | ||
uniqRemove(a1, b1), | ||
uniqRemove(a2, b2), | ||
uniqRemove(a3, b3), | ||
uniqRemove(a4, b4) | ||
]; | ||
} | ||
function extractFacets(root) { | ||
var _a; | ||
@@ -311,2 +380,7 @@ const extensions = [root]; | ||
} | ||
return [facets, inputs]; | ||
} | ||
function updateExtension(prevInputs, prevSlots, extension, mode) { | ||
const modifyInputTuple = mode === "add" ? mergeInputTuple : removeInputTuple; | ||
const [facets, inputs] = extractFacets(extension); | ||
let schemaInput = null; | ||
@@ -316,36 +390,85 @@ let stateInput = null; | ||
let commandInput = null; | ||
const sortedFacets = sortFacets(facets); | ||
for (const facet of sortedFacets) { | ||
const nextFacet = facet.next; | ||
if (nextFacet) { | ||
for (const facet of sortFacets(facets)) { | ||
if (!inputs[facet.index]) { | ||
continue; | ||
} | ||
const inputTuple = modifyInputTuple( | ||
prevInputs[facet.index], | ||
inputs[facet.index] | ||
); | ||
prevInputs[facet.index] = inputTuple; | ||
if (facet.next && !facet.single) { | ||
let hasOutput = false; | ||
const outputTuple = [[], [], [], [], []]; | ||
for (let pri = 0; pri < 5; pri++) { | ||
const input = inputs[facet.index][pri]; | ||
if (input.length > 0) { | ||
const output = facet.combine(input); | ||
if (!inputs[nextFacet.index]) { | ||
inputs[nextFacet.index] = [[], [], [], [], []]; | ||
} | ||
inputs[nextFacet.index][pri].push(output); | ||
const inputArray = inputTuple[pri]; | ||
if (inputArray.length === 0) { | ||
continue; | ||
} | ||
const slotTuple = prevSlots[facet.index] || (prevSlots[facet.index] = [ | ||
void 0, | ||
void 0, | ||
void 0, | ||
void 0, | ||
void 0 | ||
]); | ||
const prevSlot = slotTuple[pri]; | ||
const slot = prevSlot || facet.slot(); | ||
prevSlots[facet.index][pri] = slot; | ||
const output = prevSlot ? slot.update(inputArray) : slot.create(inputArray); | ||
if (!output) { | ||
continue; | ||
} | ||
hasOutput = true; | ||
outputTuple[pri].push(output); | ||
} | ||
} else if (inputs[facet.index]) { | ||
const [i1, i2, i3, i4, i5] = inputs[facet.index]; | ||
const jointInputs = [...i1, ...i2, ...i3, ...i4, ...i5]; | ||
const output = facet.combine(jointInputs); | ||
switch (facet) { | ||
case schemaSlot: | ||
schemaInput = output; | ||
break; | ||
case stateSlot: | ||
stateInput = output; | ||
break; | ||
case viewSlot: | ||
viewInput = output; | ||
break; | ||
case commandSlot: | ||
commandInput = output; | ||
break; | ||
default: | ||
throw new Error("Invalid facet"); | ||
if (!hasOutput) { | ||
continue; | ||
} | ||
inputs[facet.next.index] = modifyInputTuple( | ||
inputs[facet.next.index], | ||
outputTuple | ||
); | ||
continue; | ||
} else { | ||
const inputArray = flattenInputTuple(inputTuple); | ||
const slotTuple = prevSlots[facet.index] || (prevSlots[facet.index] = [ | ||
void 0, | ||
void 0, | ||
void 0, | ||
void 0, | ||
void 0 | ||
]); | ||
const prevSlot = slotTuple[2 /* default */]; | ||
const slot = prevSlot || facet.slot(); | ||
prevSlots[facet.index][2 /* default */] = slot; | ||
const output = prevSlot ? slot.update(inputArray) : slot.create(inputArray); | ||
if (!output) { | ||
continue; | ||
} | ||
const outputTuple = [[], [], [output], [], []]; | ||
if (facet.next) { | ||
inputs[facet.next.index] = modifyInputTuple( | ||
inputs[facet.next.index], | ||
outputTuple | ||
); | ||
continue; | ||
} else { | ||
switch (facet) { | ||
case schemaSlot: | ||
schemaInput = output; | ||
break; | ||
case stateSlot: | ||
stateInput = output; | ||
break; | ||
case viewSlot: | ||
viewInput = output; | ||
break; | ||
case commandSlot: | ||
commandInput = output; | ||
break; | ||
default: | ||
throw new Error("Invalid facet"); | ||
} | ||
} | ||
} | ||
@@ -360,27 +483,55 @@ } | ||
}) { | ||
const { schemaInput, stateInput, viewInput, commandInput } = flatten(extension); | ||
if (!schemaInput) { | ||
throw new Error("Schema must be defined"); | ||
} | ||
const schema = new Schema3(schemaInput); | ||
const stateConfig = stateInput ? stateInput({ schema }) : { schema }; | ||
const state = EditorState.create(stateConfig); | ||
const directEditorProps = { state, ...viewInput }; | ||
const instance = new EditorInstance(directEditorProps); | ||
if (commandInput) { | ||
for (const [name, commandCreator] of Object.entries(commandInput)) { | ||
instance.addCommand(name, commandCreator); | ||
} | ||
} | ||
return Editor.create(instance); | ||
const instance = new EditorInstance(extension); | ||
const editor = Editor.create(instance); | ||
return editor; | ||
} | ||
var EditorInstance = class { | ||
constructor(directEditorProps) { | ||
this.directEditorProps = directEditorProps; | ||
constructor(extension) { | ||
this.view = null; | ||
this.commandDispatchers = {}; | ||
this.inputs = []; | ||
this.slots = []; | ||
this.mount = this.mount.bind(this); | ||
this.unmount = this.unmount.bind(this); | ||
this.schema = directEditorProps.state.schema; | ||
const { schemaInput, stateInput, viewInput, commandInput } = updateExtension(this.inputs, this.slots, extension, "add"); | ||
if (!schemaInput) { | ||
throw new Error("Schema must be defined"); | ||
} | ||
const schema = new Schema3(schemaInput); | ||
const stateConfig = stateInput ? stateInput({ schema }) : { schema }; | ||
const state = EditorState.create(stateConfig); | ||
if (commandInput) { | ||
for (const [name, commandCreator] of Object.entries(commandInput)) { | ||
this.addCommand(name, commandCreator); | ||
} | ||
} | ||
this.directEditorProps = { state, ...viewInput }; | ||
this.schema = this.directEditorProps.state.schema; | ||
} | ||
updateExtension(extension, mode) { | ||
var _a; | ||
const { schemaInput, stateInput, viewInput, commandInput } = updateExtension(this.inputs, this.slots, extension, mode); | ||
if (schemaInput) { | ||
throw new ProseKitError("Schema cannot be changed"); | ||
} | ||
if (viewInput) { | ||
throw new ProseKitError("View cannot be changed"); | ||
} | ||
const plugins = (_a = stateInput == null ? void 0 : stateInput({ schema: this.schema })) == null ? void 0 : _a.plugins; | ||
if (plugins && plugins.length > 0) { | ||
if (!this.view) { | ||
throw new ProseKitError( | ||
"Unexpected inner state: EditorInstance.view is not defined" | ||
); | ||
} | ||
const state = this.view.state.reconfigure({ plugins }); | ||
this.view.updateState(state); | ||
} | ||
if (commandInput) { | ||
const names = Object.keys(commandInput); | ||
for (const name of names) { | ||
this.addCommand(name, commandInput[name]); | ||
} | ||
} | ||
} | ||
mount(place) { | ||
@@ -446,3 +597,3 @@ if (this.view) { | ||
if (!(instance instanceof EditorInstance)) { | ||
throw new TypeError("Editor's instance is not EditorInstance"); | ||
throw new TypeError("Invalid EditorInstance"); | ||
} | ||
@@ -486,29 +637,4 @@ return new _Editor(instance); | ||
} | ||
const { schemaInput, stateInput, viewInput, commandInput } = flatten(extension); | ||
if (schemaInput) { | ||
throw new ProseKitError("Schema cannot be changed"); | ||
} | ||
if (viewInput) { | ||
throw new ProseKitError("View cannot be changed"); | ||
} | ||
if (stateInput) { | ||
const stateConfig = stateInput({ schema: this.schema }); | ||
const plugins = stateConfig.plugins; | ||
if (plugins && plugins.length > 0) { | ||
this.instance.addPlugins(plugins); | ||
return () => this.instance.removePlugins(plugins); | ||
} | ||
} | ||
if (commandInput) { | ||
const names = Object.keys(commandInput); | ||
for (const name of names) { | ||
this.instance.addCommand(name, commandInput[name]); | ||
} | ||
return () => { | ||
for (const name of names) { | ||
this.instance.removeCommand(name); | ||
} | ||
}; | ||
} | ||
return voidFunction; | ||
this.instance.updateExtension(extension, "add"); | ||
return () => this.instance.updateExtension(extension, "remove"); | ||
} | ||
@@ -538,3 +664,3 @@ isNodeActive(nodeType, attrs) { | ||
import "@prosekit/pm/model"; | ||
import { AllSelection, Selection } from "@prosekit/pm/state"; | ||
import { AllSelection } from "@prosekit/pm/state"; | ||
import { findWrapping, insertPoint } from "@prosekit/pm/transform"; | ||
@@ -569,4 +695,2 @@ function addCommands(commands) { | ||
const tr = state.tr.insert(insertPos, node); | ||
const $pos = tr.doc.resolve(insertPos); | ||
tr.setSelection(Selection.near($pos)); | ||
dispatch(tr); | ||
@@ -690,4 +814,4 @@ } | ||
import { baseKeymap, chainCommands } from "@prosekit/pm/commands"; | ||
import { keymap as createKeymapPlugin } from "@prosekit/pm/keymap"; | ||
import "@prosekit/pm/state"; | ||
import { keydownHandler } from "@prosekit/pm/keymap"; | ||
import { Plugin as Plugin3, PluginKey } from "@prosekit/pm/state"; | ||
function addKeymap(keymap) { | ||
@@ -700,8 +824,27 @@ return keymapFacet.extension([keymap]); | ||
var keymapFacet = Facet.define({ | ||
combine: (keymaps) => { | ||
const keymap = mergeKeymaps(keymaps); | ||
const plugin = createKeymapPlugin(keymap); | ||
return () => [plugin]; | ||
slot: () => { | ||
let handler = null; | ||
const handlerWrapper = (view, event) => { | ||
if (handler) | ||
return handler(view, event); | ||
return false; | ||
}; | ||
const plugin = new Plugin3({ | ||
key: keymapPluginKey, | ||
props: { handleKeyDown: handlerWrapper } | ||
}); | ||
const pluginFunc = () => [plugin]; | ||
return { | ||
create: (keymaps) => { | ||
handler = keydownHandler(mergeKeymaps(keymaps)); | ||
return pluginFunc; | ||
}, | ||
update: (keymaps) => { | ||
handler = keydownHandler(mergeKeymaps(keymaps)); | ||
return null; | ||
} | ||
}; | ||
}, | ||
next: pluginFacet | ||
next: pluginFacet, | ||
single: true | ||
}); | ||
@@ -712,5 +855,4 @@ function mergeKeymaps(keymaps) { | ||
for (const [key, command] of Object.entries(keymap)) { | ||
if (!bindings[key]) | ||
bindings[key] = []; | ||
bindings[key].push(command); | ||
const commands = bindings[key] || (bindings[key] = []); | ||
commands.push(command); | ||
} | ||
@@ -725,2 +867,3 @@ } | ||
} | ||
var keymapPluginKey = new PluginKey("prosekit-keymap"); | ||
@@ -727,0 +870,0 @@ // src/extensions/mark-spec.ts |
{ | ||
"name": "@prosekit/core", | ||
"type": "module", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"private": false, | ||
@@ -6,0 +6,0 @@ "author": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
38894
1276