@milkdown/plugin-slash 7.20.0 → 7.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -29,7 +29,7 @@ function slashFactory(id) {
29
29
  //#endregion
30
30
  //#region src/slash-provider.ts
31
31
  var SlashProvider = class {
32
- #initialized = false;
32
+ #initialized;
33
33
  #middleware;
34
34
  #floatingUIOptions;
35
35
  #root;
@@ -39,8 +39,48 @@ var SlashProvider = class {
39
39
  #updater;
40
40
  #offset;
41
41
  constructor(options) {
42
+ this.#initialized = false;
42
43
  this.onShow = () => {};
43
44
  this.onHide = () => {};
45
+ this.#onUpdate = (view, prevState) => {
46
+ const { state, composing } = view;
47
+ const { selection, doc } = state;
48
+ const { ranges } = selection;
49
+ const from = Math.min(...ranges.map((range) => range.$from.pos));
50
+ const to = Math.max(...ranges.map((range) => range.$to.pos));
51
+ const isSame = prevState && prevState.doc.eq(doc) && prevState.selection.eq(selection);
52
+ if (!this.#initialized) {
53
+ (this.#root ?? view.dom.parentElement ?? document.body).appendChild(this.element);
54
+ this.#initialized = true;
55
+ }
56
+ if (composing || isSame) return;
57
+ if (!this.#shouldShow(view, prevState)) {
58
+ this.hide();
59
+ return;
60
+ }
61
+ computePosition({ getBoundingClientRect: () => posToDOMRect(view, from, to) }, this.element, {
62
+ placement: "bottom-start",
63
+ middleware: [
64
+ flip(),
65
+ offset(this.#offset),
66
+ ...this.#middleware
67
+ ],
68
+ ...this.#floatingUIOptions
69
+ }).then(({ x, y }) => {
70
+ Object.assign(this.element.style, {
71
+ left: `${x}px`,
72
+ top: `${y}px`
73
+ });
74
+ }).catch(console.error);
75
+ this.show();
76
+ };
77
+ this.#_shouldShow = (view) => {
78
+ const currentTextBlockContent = this.getContent(view);
79
+ if (!currentTextBlockContent) return false;
80
+ const target = currentTextBlockContent.at(-1);
81
+ if (!target) return false;
82
+ return Array.isArray(this.#trigger) ? this.#trigger.includes(target) : this.#trigger === target;
83
+ };
44
84
  this.update = (view, prevState) => {
45
85
  this.#updater(view, prevState);
46
86
  };
@@ -77,45 +117,8 @@ var SlashProvider = class {
77
117
  this.#root = options.root;
78
118
  this.#updater = debounce(this.#onUpdate, this.#debounce);
79
119
  }
80
- #onUpdate = (view, prevState) => {
81
- const { state, composing } = view;
82
- const { selection, doc } = state;
83
- const { ranges } = selection;
84
- const from = Math.min(...ranges.map((range) => range.$from.pos));
85
- const to = Math.max(...ranges.map((range) => range.$to.pos));
86
- const isSame = prevState && prevState.doc.eq(doc) && prevState.selection.eq(selection);
87
- if (!this.#initialized) {
88
- (this.#root ?? view.dom.parentElement ?? document.body).appendChild(this.element);
89
- this.#initialized = true;
90
- }
91
- if (composing || isSame) return;
92
- if (!this.#shouldShow(view, prevState)) {
93
- this.hide();
94
- return;
95
- }
96
- computePosition({ getBoundingClientRect: () => posToDOMRect(view, from, to) }, this.element, {
97
- placement: "bottom-start",
98
- middleware: [
99
- flip(),
100
- offset(this.#offset),
101
- ...this.#middleware
102
- ],
103
- ...this.#floatingUIOptions
104
- }).then(({ x, y }) => {
105
- Object.assign(this.element.style, {
106
- left: `${x}px`,
107
- top: `${y}px`
108
- });
109
- }).catch(console.error);
110
- this.show();
111
- };
112
- #_shouldShow = (view) => {
113
- const currentTextBlockContent = this.getContent(view);
114
- if (!currentTextBlockContent) return false;
115
- const target = currentTextBlockContent.at(-1);
116
- if (!target) return false;
117
- return Array.isArray(this.#trigger) ? this.#trigger.includes(target) : this.#trigger === target;
118
- };
120
+ #onUpdate;
121
+ #_shouldShow;
119
122
  };
120
123
  //#endregion
121
124
  export { SlashProvider, slashFactory };
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["#middleware","#floatingUIOptions","#root","#debounce","#trigger","#shouldShow","#updater","#offset","#_shouldShow","#onUpdate","#initialized"],"sources":["../src/slash-plugin.ts","../src/slash-provider.ts"],"sourcesContent":["import type { SliceType } from '@milkdown/ctx'\nimport type { PluginSpec } from '@milkdown/prose/state'\nimport type { $Ctx, $Prose } from '@milkdown/utils'\n\nimport { Plugin, PluginKey } from '@milkdown/prose/state'\nimport { $ctx, $prose } from '@milkdown/utils'\n\n/// @internal\nexport type SlashPluginSpecId<Id extends string> = `${Id}_SLASH_SPEC`\n\n/// @internal\nexport type SlashPlugin<Id extends string, State = any> = [\n $Ctx<PluginSpec<State>, SlashPluginSpecId<Id>>,\n $Prose,\n] & {\n key: SliceType<PluginSpec<State>, SlashPluginSpecId<Id>>\n pluginKey: $Prose['key']\n}\n\n/// Create a slash plugin with a unique id.\nexport function slashFactory<Id extends string, State = any>(id: Id) {\n const slashSpec = $ctx<PluginSpec<State>, SlashPluginSpecId<Id>>(\n {},\n `${id}_SLASH_SPEC`\n )\n const slashPlugin = $prose((ctx) => {\n const spec = ctx.get(slashSpec.key)\n return new Plugin({\n key: new PluginKey(`${id}_SLASH`),\n ...spec,\n })\n })\n const result = [slashSpec, slashPlugin] as SlashPlugin<Id>\n result.key = slashSpec.key\n result.pluginKey = slashPlugin.key\n slashSpec.meta = {\n package: '@milkdown/plugin-slash',\n displayName: `Ctx<slashSpec>|${id}`,\n }\n slashPlugin.meta = {\n package: '@milkdown/plugin-slash',\n displayName: `Prose<slash>|${id}`,\n }\n\n return result\n}\n","import type {\n ComputePositionConfig,\n Middleware,\n OffsetOptions,\n VirtualElement,\n} from '@floating-ui/dom'\nimport type { Node } from '@milkdown/prose/model'\nimport type { EditorState } from '@milkdown/prose/state'\nimport type { EditorView } from '@milkdown/prose/view'\n\nimport { computePosition, flip, offset } from '@floating-ui/dom'\nimport { findParentNode, posToDOMRect } from '@milkdown/prose'\nimport { TextSelection } from '@milkdown/prose/state'\nimport { debounce } from 'lodash-es'\n\n/// Options for slash provider.\nexport interface SlashProviderOptions {\n /// The slash content.\n content: HTMLElement\n /// The debounce time for updating slash, 200ms by default.\n debounce?: number\n /// The function to determine whether the tooltip should be shown.\n shouldShow?: (view: EditorView, prevState?: EditorState) => boolean\n /// The key trigger for shouldShow, '/' by default.\n trigger?: string | string[]\n /// The offset to get the block. Default is 0.\n offset?: OffsetOptions\n /// Other middlewares for floating ui. This will be added after the internal middlewares.\n middleware?: Middleware[]\n /// Options for floating ui. If you pass `middleware` or `placement`, it will override the internal settings.\n floatingUIOptions?: Partial<ComputePositionConfig>\n /// The root element that the slash will be appended to.\n root?: HTMLElement\n}\n\n/// A provider for creating slash.\nexport class SlashProvider {\n /// The root element of the slash.\n element: HTMLElement\n\n /// @internal\n #initialized = false\n\n /// @internal\n readonly #middleware: Middleware[]\n\n /// @internal\n readonly #floatingUIOptions: Partial<ComputePositionConfig>\n\n /// @internal\n readonly #root?: HTMLElement\n\n /// @internal\n readonly #debounce: number\n\n /// @internal\n readonly #trigger: string | string[]\n\n /// @internal\n readonly #shouldShow: (view: EditorView, prevState?: EditorState) => boolean\n\n /// @internal\n readonly #updater: {\n (view: EditorView, prevState?: EditorState): void\n cancel: () => void\n }\n\n /// The offset to get the block. Default is 0.\n readonly #offset?: OffsetOptions\n\n /// On show callback.\n onShow = () => {}\n\n /// On hide callback.\n onHide = () => {}\n\n constructor(options: SlashProviderOptions) {\n this.element = options.content\n this.#debounce = options.debounce ?? 200\n this.#shouldShow = options.shouldShow ?? this.#_shouldShow\n this.#trigger = options.trigger ?? '/'\n this.#offset = options.offset\n this.#middleware = options.middleware ?? []\n this.#floatingUIOptions = options.floatingUIOptions ?? {}\n this.#root = options.root\n this.#updater = debounce(this.#onUpdate, this.#debounce)\n }\n\n /// @internal\n #onUpdate = (view: EditorView, prevState?: EditorState): void => {\n const { state, composing } = view\n const { selection, doc } = state\n const { ranges } = selection\n const from = Math.min(...ranges.map((range) => range.$from.pos))\n const to = Math.max(...ranges.map((range) => range.$to.pos))\n const isSame =\n prevState && prevState.doc.eq(doc) && prevState.selection.eq(selection)\n\n if (!this.#initialized) {\n const root = this.#root ?? view.dom.parentElement ?? document.body\n root.appendChild(this.element)\n this.#initialized = true\n }\n\n if (composing || isSame) return\n\n if (!this.#shouldShow(view, prevState)) {\n this.hide()\n return\n }\n\n const virtualEl: VirtualElement = {\n getBoundingClientRect: () => posToDOMRect(view, from, to),\n }\n computePosition(virtualEl, this.element, {\n placement: 'bottom-start',\n middleware: [flip(), offset(this.#offset), ...this.#middleware],\n ...this.#floatingUIOptions,\n })\n .then(({ x, y }) => {\n Object.assign(this.element.style, {\n left: `${x}px`,\n top: `${y}px`,\n })\n })\n .catch(console.error)\n\n this.show()\n }\n\n /// @internal\n #_shouldShow = (view: EditorView): boolean => {\n const currentTextBlockContent = this.getContent(view)\n\n if (!currentTextBlockContent) return false\n\n const target = currentTextBlockContent.at(-1)\n\n if (!target) return false\n\n return Array.isArray(this.#trigger)\n ? this.#trigger.includes(target)\n : this.#trigger === target\n }\n\n /// Update provider state by editor view.\n update = (view: EditorView, prevState?: EditorState): void => {\n this.#updater(view, prevState)\n }\n\n /// Get the content of the current text block.\n /// Pass the `matchNode` function to determine whether the current node should be matched, by default, it will match the paragraph node.\n getContent = (\n view: EditorView,\n matchNode: (node: Node) => boolean = (node) =>\n node.type.name === 'paragraph'\n ): string | undefined => {\n const { selection } = view.state\n const { empty, $from } = selection\n const isTextBlock = view.state.selection instanceof TextSelection\n\n if (typeof document === 'undefined') return\n\n const isSlashChildren = this.element.contains(document.activeElement)\n\n const notHasFocus = !view.hasFocus() && !isSlashChildren\n\n const isReadonly = !view.editable\n\n const paragraph = findParentNode(matchNode)(view.state.selection)\n\n const isNotInParagraph = !paragraph\n\n if (notHasFocus || isReadonly || !empty || !isTextBlock || isNotInParagraph)\n return\n\n return $from.parent.textBetween(\n Math.max(0, $from.parentOffset - 500),\n $from.parentOffset,\n undefined,\n '\\uFFFC'\n )\n }\n\n /// Destroy the slash.\n destroy = () => {\n this.#updater.cancel()\n }\n\n /// Show the slash.\n show = () => {\n this.element.dataset.show = 'true'\n this.onShow()\n }\n\n /// Hide the slash.\n hide = () => {\n this.element.dataset.show = 'false'\n this.onHide()\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["#middleware","#floatingUIOptions","#root","#debounce","#trigger","#shouldShow","#updater","#offset","#initialized","#_shouldShow","#onUpdate"],"sources":["../src/slash-plugin.ts","../src/slash-provider.ts"],"sourcesContent":["import type { SliceType } from '@milkdown/ctx'\nimport type { PluginSpec } from '@milkdown/prose/state'\nimport type { $Ctx, $Prose } from '@milkdown/utils'\n\nimport { Plugin, PluginKey } from '@milkdown/prose/state'\nimport { $ctx, $prose } from '@milkdown/utils'\n\n/// @internal\nexport type SlashPluginSpecId<Id extends string> = `${Id}_SLASH_SPEC`\n\n/// @internal\nexport type SlashPlugin<Id extends string, State = any> = [\n $Ctx<PluginSpec<State>, SlashPluginSpecId<Id>>,\n $Prose,\n] & {\n key: SliceType<PluginSpec<State>, SlashPluginSpecId<Id>>\n pluginKey: $Prose['key']\n}\n\n/// Create a slash plugin with a unique id.\nexport function slashFactory<Id extends string, State = any>(id: Id) {\n const slashSpec = $ctx<PluginSpec<State>, SlashPluginSpecId<Id>>(\n {},\n `${id}_SLASH_SPEC`\n )\n const slashPlugin = $prose((ctx) => {\n const spec = ctx.get(slashSpec.key)\n return new Plugin({\n key: new PluginKey(`${id}_SLASH`),\n ...spec,\n })\n })\n const result = [slashSpec, slashPlugin] as SlashPlugin<Id>\n result.key = slashSpec.key\n result.pluginKey = slashPlugin.key\n slashSpec.meta = {\n package: '@milkdown/plugin-slash',\n displayName: `Ctx<slashSpec>|${id}`,\n }\n slashPlugin.meta = {\n package: '@milkdown/plugin-slash',\n displayName: `Prose<slash>|${id}`,\n }\n\n return result\n}\n","import type {\n ComputePositionConfig,\n Middleware,\n OffsetOptions,\n VirtualElement,\n} from '@floating-ui/dom'\nimport type { Node } from '@milkdown/prose/model'\nimport type { EditorState } from '@milkdown/prose/state'\nimport type { EditorView } from '@milkdown/prose/view'\n\nimport { computePosition, flip, offset } from '@floating-ui/dom'\nimport { findParentNode, posToDOMRect } from '@milkdown/prose'\nimport { TextSelection } from '@milkdown/prose/state'\nimport { debounce } from 'lodash-es'\n\n/// Options for slash provider.\nexport interface SlashProviderOptions {\n /// The slash content.\n content: HTMLElement\n /// The debounce time for updating slash, 200ms by default.\n debounce?: number\n /// The function to determine whether the tooltip should be shown.\n shouldShow?: (view: EditorView, prevState?: EditorState) => boolean\n /// The key trigger for shouldShow, '/' by default.\n trigger?: string | string[]\n /// The offset to get the block. Default is 0.\n offset?: OffsetOptions\n /// Other middlewares for floating ui. This will be added after the internal middlewares.\n middleware?: Middleware[]\n /// Options for floating ui. If you pass `middleware` or `placement`, it will override the internal settings.\n floatingUIOptions?: Partial<ComputePositionConfig>\n /// The root element that the slash will be appended to.\n root?: HTMLElement\n}\n\n/// A provider for creating slash.\nexport class SlashProvider {\n /// The root element of the slash.\n element: HTMLElement\n\n /// @internal\n #initialized = false\n\n /// @internal\n readonly #middleware: Middleware[]\n\n /// @internal\n readonly #floatingUIOptions: Partial<ComputePositionConfig>\n\n /// @internal\n readonly #root?: HTMLElement\n\n /// @internal\n readonly #debounce: number\n\n /// @internal\n readonly #trigger: string | string[]\n\n /// @internal\n readonly #shouldShow: (view: EditorView, prevState?: EditorState) => boolean\n\n /// @internal\n readonly #updater: {\n (view: EditorView, prevState?: EditorState): void\n cancel: () => void\n }\n\n /// The offset to get the block. Default is 0.\n readonly #offset?: OffsetOptions\n\n /// On show callback.\n onShow = () => {}\n\n /// On hide callback.\n onHide = () => {}\n\n constructor(options: SlashProviderOptions) {\n this.element = options.content\n this.#debounce = options.debounce ?? 200\n this.#shouldShow = options.shouldShow ?? this.#_shouldShow\n this.#trigger = options.trigger ?? '/'\n this.#offset = options.offset\n this.#middleware = options.middleware ?? []\n this.#floatingUIOptions = options.floatingUIOptions ?? {}\n this.#root = options.root\n this.#updater = debounce(this.#onUpdate, this.#debounce)\n }\n\n /// @internal\n #onUpdate = (view: EditorView, prevState?: EditorState): void => {\n const { state, composing } = view\n const { selection, doc } = state\n const { ranges } = selection\n const from = Math.min(...ranges.map((range) => range.$from.pos))\n const to = Math.max(...ranges.map((range) => range.$to.pos))\n const isSame =\n prevState && prevState.doc.eq(doc) && prevState.selection.eq(selection)\n\n if (!this.#initialized) {\n const root = this.#root ?? view.dom.parentElement ?? document.body\n root.appendChild(this.element)\n this.#initialized = true\n }\n\n if (composing || isSame) return\n\n if (!this.#shouldShow(view, prevState)) {\n this.hide()\n return\n }\n\n const virtualEl: VirtualElement = {\n getBoundingClientRect: () => posToDOMRect(view, from, to),\n }\n computePosition(virtualEl, this.element, {\n placement: 'bottom-start',\n middleware: [flip(), offset(this.#offset), ...this.#middleware],\n ...this.#floatingUIOptions,\n })\n .then(({ x, y }) => {\n Object.assign(this.element.style, {\n left: `${x}px`,\n top: `${y}px`,\n })\n })\n .catch(console.error)\n\n this.show()\n }\n\n /// @internal\n #_shouldShow = (view: EditorView): boolean => {\n const currentTextBlockContent = this.getContent(view)\n\n if (!currentTextBlockContent) return false\n\n const target = currentTextBlockContent.at(-1)\n\n if (!target) return false\n\n return Array.isArray(this.#trigger)\n ? this.#trigger.includes(target)\n : this.#trigger === target\n }\n\n /// Update provider state by editor view.\n update = (view: EditorView, prevState?: EditorState): void => {\n this.#updater(view, prevState)\n }\n\n /// Get the content of the current text block.\n /// Pass the `matchNode` function to determine whether the current node should be matched, by default, it will match the paragraph node.\n getContent = (\n view: EditorView,\n matchNode: (node: Node) => boolean = (node) =>\n node.type.name === 'paragraph'\n ): string | undefined => {\n const { selection } = view.state\n const { empty, $from } = selection\n const isTextBlock = view.state.selection instanceof TextSelection\n\n if (typeof document === 'undefined') return\n\n const isSlashChildren = this.element.contains(document.activeElement)\n\n const notHasFocus = !view.hasFocus() && !isSlashChildren\n\n const isReadonly = !view.editable\n\n const paragraph = findParentNode(matchNode)(view.state.selection)\n\n const isNotInParagraph = !paragraph\n\n if (notHasFocus || isReadonly || !empty || !isTextBlock || isNotInParagraph)\n return\n\n return $from.parent.textBetween(\n Math.max(0, $from.parentOffset - 500),\n $from.parentOffset,\n undefined,\n '\\uFFFC'\n )\n }\n\n /// Destroy the slash.\n destroy = () => {\n this.#updater.cancel()\n }\n\n /// Show the slash.\n show = () => {\n this.element.dataset.show = 'true'\n this.onShow()\n }\n\n /// Hide the slash.\n hide = () => {\n this.element.dataset.show = 'false'\n this.onHide()\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milkdown/plugin-slash",
3
- "version": "7.20.0",
3
+ "version": "7.21.0",
4
4
  "keywords": [
5
5
  "milkdown",
6
6
  "milkdown plugin"
@@ -28,9 +28,9 @@
28
28
  "@floating-ui/dom": "^1.5.1",
29
29
  "@types/lodash-es": "^4.17.12",
30
30
  "lodash-es": "^4.17.21",
31
- "@milkdown/ctx": "7.20.0",
32
- "@milkdown/utils": "7.20.0",
33
- "@milkdown/prose": "7.20.0"
31
+ "@milkdown/ctx": "7.21.0",
32
+ "@milkdown/prose": "7.21.0",
33
+ "@milkdown/utils": "7.21.0"
34
34
  },
35
35
  "scripts": {
36
36
  "build": "vite build"