@tiptap/suggestion 2.0.0-beta.98 → 2.0.0-rc.2
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/README.md +3 -3
- package/dist/{tiptap-suggestion.cjs.js → index.cjs} +11 -15
- package/dist/index.cjs.map +1 -0
- package/dist/{tiptap-suggestion.esm.js → index.js} +7 -11
- package/dist/index.js.map +1 -0
- package/dist/{tiptap-suggestion.umd.js → index.umd.js} +13 -17
- package/dist/index.umd.js.map +1 -0
- package/dist/packages/suggestion/src/findSuggestionMatch.d.ts +1 -1
- package/dist/packages/suggestion/src/suggestion.d.ts +2 -2
- package/package.json +22 -11
- package/src/findSuggestionMatch.ts +10 -14
- package/src/suggestion.ts +42 -56
- package/LICENSE.md +0 -21
- package/dist/tiptap-suggestion.cjs.js.map +0 -1
- package/dist/tiptap-suggestion.esm.js.map +0 -1
- package/dist/tiptap-suggestion.umd.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
[](https://github.com/sponsors/ueberdosis)
|
|
6
6
|
|
|
7
7
|
## Introduction
|
|
8
|
-
|
|
8
|
+
Tiptap is a headless wrapper around [ProseMirror](https://ProseMirror.net) – a toolkit for building rich text WYSIWYG editors, which is already in use at many well-known companies such as *New York Times*, *The Guardian* or *Atlassian*.
|
|
9
9
|
|
|
10
10
|
## Official Documentation
|
|
11
|
-
Documentation can be found on the [
|
|
11
|
+
Documentation can be found on the [Tiptap website](https://tiptap.dev).
|
|
12
12
|
|
|
13
13
|
## License
|
|
14
|
-
|
|
14
|
+
Tiptap is open sourced software licensed under the [MIT license](https://github.com/ueberdosis/tiptap/blob/main/LICENSE.md).
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
6
|
-
var
|
|
5
|
+
var state = require('@tiptap/pm/state');
|
|
6
|
+
var view = require('@tiptap/pm/view');
|
|
7
7
|
var core = require('@tiptap/core');
|
|
8
8
|
|
|
9
9
|
function findSuggestionMatch(config) {
|
|
@@ -54,11 +54,11 @@ function findSuggestionMatch(config) {
|
|
|
54
54
|
return null;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
const SuggestionPluginKey = new
|
|
57
|
+
const SuggestionPluginKey = new state.PluginKey('suggestion');
|
|
58
58
|
function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allowSpaces = false, allowedPrefixes = [' '], startOfLine = false, decorationTag = 'span', decorationClass = 'suggestion', command = () => null, items = () => [], render = () => ({}), allow = () => true, }) {
|
|
59
59
|
let props;
|
|
60
60
|
const renderer = render === null || render === void 0 ? void 0 : render();
|
|
61
|
-
const plugin = new
|
|
61
|
+
const plugin = new state.Plugin({
|
|
62
62
|
key: pluginKey,
|
|
63
63
|
view() {
|
|
64
64
|
return {
|
|
@@ -78,9 +78,7 @@ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allow
|
|
|
78
78
|
if (!handleStart && !handleChange && !handleExit) {
|
|
79
79
|
return;
|
|
80
80
|
}
|
|
81
|
-
const state = handleExit && !handleStart
|
|
82
|
-
? prev
|
|
83
|
-
: next;
|
|
81
|
+
const state = handleExit && !handleStart ? prev : next;
|
|
84
82
|
const decorationNode = view.dom.querySelector(`[data-decoration-id="${state.decorationId}"]`);
|
|
85
83
|
props = {
|
|
86
84
|
editor,
|
|
@@ -101,7 +99,7 @@ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allow
|
|
|
101
99
|
clientRect: decorationNode
|
|
102
100
|
? () => {
|
|
103
101
|
var _a;
|
|
104
|
-
// because of `items` can be asynchrounous we’ll search for the current
|
|
102
|
+
// because of `items` can be asynchrounous we’ll search for the current decoration node
|
|
105
103
|
const { decorationId } = (_a = this.key) === null || _a === void 0 ? void 0 : _a.getState(editor.state); // eslint-disable-line
|
|
106
104
|
const currentDecorationNode = view.dom.querySelector(`[data-decoration-id="${decorationId}"]`);
|
|
107
105
|
return (currentDecorationNode === null || currentDecorationNode === void 0 ? void 0 : currentDecorationNode.getBoundingClientRect()) || null;
|
|
@@ -167,9 +165,7 @@ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allow
|
|
|
167
165
|
// * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)
|
|
168
166
|
if (isEditable && (empty || editor.view.composing)) {
|
|
169
167
|
// Reset active state if we just left the previous suggestion range
|
|
170
|
-
if ((
|
|
171
|
-
&& !composing
|
|
172
|
-
&& !prev.composing) {
|
|
168
|
+
if ((from < prev.range.from || from > prev.range.to) && !composing && !prev.composing) {
|
|
173
169
|
next.active = false;
|
|
174
170
|
}
|
|
175
171
|
// Try to match against where our cursor currently is
|
|
@@ -180,7 +176,7 @@ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allow
|
|
|
180
176
|
startOfLine,
|
|
181
177
|
$position: selection.$from,
|
|
182
178
|
});
|
|
183
|
-
const decorationId = `id_${Math.floor(Math.random() *
|
|
179
|
+
const decorationId = `id_${Math.floor(Math.random() * 0xffffffff)}`;
|
|
184
180
|
// If we found a match, update the current state to show it
|
|
185
181
|
if (match && allow({ editor, state, range: match.range })) {
|
|
186
182
|
next.active = true;
|
|
@@ -222,8 +218,8 @@ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allow
|
|
|
222
218
|
if (!active) {
|
|
223
219
|
return null;
|
|
224
220
|
}
|
|
225
|
-
return
|
|
226
|
-
|
|
221
|
+
return view.DecorationSet.create(state.doc, [
|
|
222
|
+
view.Decoration.inline(range.from, range.to, {
|
|
227
223
|
nodeName: decorationTag,
|
|
228
224
|
class: decorationClass,
|
|
229
225
|
'data-decoration-id': decorationId,
|
|
@@ -239,4 +235,4 @@ exports.Suggestion = Suggestion;
|
|
|
239
235
|
exports.SuggestionPluginKey = SuggestionPluginKey;
|
|
240
236
|
exports["default"] = Suggestion;
|
|
241
237
|
exports.findSuggestionMatch = findSuggestionMatch;
|
|
242
|
-
//# sourceMappingURL=
|
|
238
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/findSuggestionMatch.ts","../src/suggestion.ts"],"sourcesContent":["import { escapeForRegEx, Range } from '@tiptap/core'\nimport { ResolvedPos } from '@tiptap/pm/model'\n\nexport interface Trigger {\n char: string\n allowSpaces: boolean\n allowedPrefixes: string[] | null\n startOfLine: boolean\n $position: ResolvedPos\n}\n\nexport type SuggestionMatch = {\n range: Range\n query: string\n text: string\n} | null\n\nexport function findSuggestionMatch(config: Trigger): SuggestionMatch {\n const {\n char, allowSpaces, allowedPrefixes, startOfLine, $position,\n } = config\n\n const escapedChar = escapeForRegEx(char)\n const suffix = new RegExp(`\\\\s${escapedChar}$`)\n const prefix = startOfLine ? '^' : ''\n const regexp = allowSpaces\n ? new RegExp(`${prefix}${escapedChar}.*?(?=\\\\s${escapedChar}|$)`, 'gm')\n : new RegExp(`${prefix}(?:^)?${escapedChar}[^\\\\s${escapedChar}]*`, 'gm')\n\n const text = $position.nodeBefore?.isText && $position.nodeBefore.text\n\n if (!text) {\n return null\n }\n\n const textFrom = $position.pos - text.length\n const match = Array.from(text.matchAll(regexp)).pop()\n\n if (!match || match.input === undefined || match.index === undefined) {\n return null\n }\n\n // JavaScript doesn't have lookbehinds. This hacks a check that first character\n // is a space or the start of the line\n const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index)\n const matchPrefixIsAllowed = new RegExp(`^[${allowedPrefixes?.join('')}\\0]?$`).test(matchPrefix)\n\n if (allowedPrefixes !== null && !matchPrefixIsAllowed) {\n return null\n }\n\n // The absolute position of the match in the document\n const from = textFrom + match.index\n let to = from + match[0].length\n\n // Edge case handling; if spaces are allowed and we're directly in between\n // two triggers\n if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) {\n match[0] += ' '\n to += 1\n }\n\n // If the $position is located within the matched substring, return that range\n if (from < $position.pos && to >= $position.pos) {\n return {\n range: {\n from,\n to,\n },\n query: match[0].slice(char.length),\n text: match[0],\n }\n }\n\n return null\n}\n","import { Editor, Range } from '@tiptap/core'\nimport { EditorState, Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet, EditorView } from '@tiptap/pm/view'\n\nimport { findSuggestionMatch } from './findSuggestionMatch'\n\nexport interface SuggestionOptions<I = any> {\n pluginKey?: PluginKey\n editor: Editor\n char?: string\n allowSpaces?: boolean\n allowedPrefixes?: string[] | null\n startOfLine?: boolean\n decorationTag?: string\n decorationClass?: string\n command?: (props: { editor: Editor; range: Range; props: I }) => void\n items?: (props: { query: string; editor: Editor }) => I[] | Promise<I[]>\n render?: () => {\n onBeforeStart?: (props: SuggestionProps<I>) => void\n onStart?: (props: SuggestionProps<I>) => void\n onBeforeUpdate?: (props: SuggestionProps<I>) => void\n onUpdate?: (props: SuggestionProps<I>) => void\n onExit?: (props: SuggestionProps<I>) => void\n onKeyDown?: (props: SuggestionKeyDownProps) => boolean\n }\n allow?: (props: { editor: Editor; state: EditorState; range: Range }) => boolean\n}\n\nexport interface SuggestionProps<I = any> {\n editor: Editor\n range: Range\n query: string\n text: string\n items: I[]\n command: (props: I) => void\n decorationNode: Element | null\n clientRect?: (() => DOMRect | null) | null\n}\n\nexport interface SuggestionKeyDownProps {\n view: EditorView\n event: KeyboardEvent\n range: Range\n}\n\nexport const SuggestionPluginKey = new PluginKey('suggestion')\n\nexport function Suggestion<I = any>({\n pluginKey = SuggestionPluginKey,\n editor,\n char = '@',\n allowSpaces = false,\n allowedPrefixes = [' '],\n startOfLine = false,\n decorationTag = 'span',\n decorationClass = 'suggestion',\n command = () => null,\n items = () => [],\n render = () => ({}),\n allow = () => true,\n}: SuggestionOptions<I>) {\n let props: SuggestionProps<I> | undefined\n const renderer = render?.()\n\n const plugin: Plugin<any> = new Plugin({\n key: pluginKey,\n\n view() {\n return {\n update: async (view, prevState) => {\n const prev = this.key?.getState(prevState)\n const next = this.key?.getState(view.state)\n\n // See how the state changed\n const moved = prev.active && next.active && prev.range.from !== next.range.from\n const started = !prev.active && next.active\n const stopped = prev.active && !next.active\n const changed = !started && !stopped && prev.query !== next.query\n const handleStart = started || moved\n const handleChange = changed && !moved\n const handleExit = stopped || moved\n\n // Cancel when suggestion isn't active\n if (!handleStart && !handleChange && !handleExit) {\n return\n }\n\n const state = handleExit && !handleStart ? prev : next\n const decorationNode = view.dom.querySelector(\n `[data-decoration-id=\"${state.decorationId}\"]`,\n )\n\n props = {\n editor,\n range: state.range,\n query: state.query,\n text: state.text,\n items: [],\n command: commandProps => {\n command({\n editor,\n range: state.range,\n props: commandProps,\n })\n },\n decorationNode,\n // virtual node for popper.js or tippy.js\n // this can be used for building popups without a DOM node\n clientRect: decorationNode\n ? () => {\n // because of `items` can be asynchrounous we’ll search for the current decoration node\n const { decorationId } = this.key?.getState(editor.state) // eslint-disable-line\n const currentDecorationNode = view.dom.querySelector(\n `[data-decoration-id=\"${decorationId}\"]`,\n )\n\n return currentDecorationNode?.getBoundingClientRect() || null\n }\n : null,\n }\n\n if (handleStart) {\n renderer?.onBeforeStart?.(props)\n }\n\n if (handleChange) {\n renderer?.onBeforeUpdate?.(props)\n }\n\n if (handleChange || handleStart) {\n props.items = await items({\n editor,\n query: state.query,\n })\n }\n\n if (handleExit) {\n renderer?.onExit?.(props)\n }\n\n if (handleChange) {\n renderer?.onUpdate?.(props)\n }\n\n if (handleStart) {\n renderer?.onStart?.(props)\n }\n },\n\n destroy: () => {\n if (!props) {\n return\n }\n\n renderer?.onExit?.(props)\n },\n }\n },\n\n state: {\n // Initialize the plugin's internal state.\n init() {\n const state: {\n active: boolean\n range: Range\n query: null | string\n text: null | string\n composing: boolean\n decorationId?: string | null\n } = {\n active: false,\n range: {\n from: 0,\n to: 0,\n },\n query: null,\n text: null,\n composing: false,\n }\n\n return state\n },\n\n // Apply changes to the plugin state from a view transaction.\n apply(transaction, prev, oldState, state) {\n const { isEditable } = editor\n const { composing } = editor.view\n const { selection } = transaction\n const { empty, from } = selection\n const next = { ...prev }\n\n next.composing = composing\n\n // We can only be suggesting if the view is editable, and:\n // * there is no selection, or\n // * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)\n if (isEditable && (empty || editor.view.composing)) {\n // Reset active state if we just left the previous suggestion range\n if ((from < prev.range.from || from > prev.range.to) && !composing && !prev.composing) {\n next.active = false\n }\n\n // Try to match against where our cursor currently is\n const match = findSuggestionMatch({\n char,\n allowSpaces,\n allowedPrefixes,\n startOfLine,\n $position: selection.$from,\n })\n const decorationId = `id_${Math.floor(Math.random() * 0xffffffff)}`\n\n // If we found a match, update the current state to show it\n if (match && allow({ editor, state, range: match.range })) {\n next.active = true\n next.decorationId = prev.decorationId ? prev.decorationId : decorationId\n next.range = match.range\n next.query = match.query\n next.text = match.text\n } else {\n next.active = false\n }\n } else {\n next.active = false\n }\n\n // Make sure to empty the range if suggestion is inactive\n if (!next.active) {\n next.decorationId = null\n next.range = { from: 0, to: 0 }\n next.query = null\n next.text = null\n }\n\n return next\n },\n },\n\n props: {\n // Call the keydown hook if suggestion is active.\n handleKeyDown(view, event) {\n const { active, range } = plugin.getState(view.state)\n\n if (!active) {\n return false\n }\n\n return renderer?.onKeyDown?.({ view, event, range }) || false\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const { active, range, decorationId } = plugin.getState(state)\n\n if (!active) {\n return null\n }\n\n return DecorationSet.create(state.doc, [\n Decoration.inline(range.from, range.to, {\n nodeName: decorationTag,\n class: decorationClass,\n 'data-decoration-id': decorationId,\n }),\n ])\n },\n },\n })\n\n return plugin\n}\n"],"names":["escapeForRegEx","PluginKey","Plugin","DecorationSet","Decoration"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { PluginKey, Plugin } from '
|
|
2
|
-
import { DecorationSet, Decoration } from '
|
|
1
|
+
import { PluginKey, Plugin } from '@tiptap/pm/state';
|
|
2
|
+
import { DecorationSet, Decoration } from '@tiptap/pm/view';
|
|
3
3
|
import { escapeForRegEx } from '@tiptap/core';
|
|
4
4
|
|
|
5
5
|
function findSuggestionMatch(config) {
|
|
@@ -74,9 +74,7 @@ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allow
|
|
|
74
74
|
if (!handleStart && !handleChange && !handleExit) {
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
|
-
const state = handleExit && !handleStart
|
|
78
|
-
? prev
|
|
79
|
-
: next;
|
|
77
|
+
const state = handleExit && !handleStart ? prev : next;
|
|
80
78
|
const decorationNode = view.dom.querySelector(`[data-decoration-id="${state.decorationId}"]`);
|
|
81
79
|
props = {
|
|
82
80
|
editor,
|
|
@@ -97,7 +95,7 @@ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allow
|
|
|
97
95
|
clientRect: decorationNode
|
|
98
96
|
? () => {
|
|
99
97
|
var _a;
|
|
100
|
-
// because of `items` can be asynchrounous we’ll search for the current
|
|
98
|
+
// because of `items` can be asynchrounous we’ll search for the current decoration node
|
|
101
99
|
const { decorationId } = (_a = this.key) === null || _a === void 0 ? void 0 : _a.getState(editor.state); // eslint-disable-line
|
|
102
100
|
const currentDecorationNode = view.dom.querySelector(`[data-decoration-id="${decorationId}"]`);
|
|
103
101
|
return (currentDecorationNode === null || currentDecorationNode === void 0 ? void 0 : currentDecorationNode.getBoundingClientRect()) || null;
|
|
@@ -163,9 +161,7 @@ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allow
|
|
|
163
161
|
// * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)
|
|
164
162
|
if (isEditable && (empty || editor.view.composing)) {
|
|
165
163
|
// Reset active state if we just left the previous suggestion range
|
|
166
|
-
if ((
|
|
167
|
-
&& !composing
|
|
168
|
-
&& !prev.composing) {
|
|
164
|
+
if ((from < prev.range.from || from > prev.range.to) && !composing && !prev.composing) {
|
|
169
165
|
next.active = false;
|
|
170
166
|
}
|
|
171
167
|
// Try to match against where our cursor currently is
|
|
@@ -176,7 +172,7 @@ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allow
|
|
|
176
172
|
startOfLine,
|
|
177
173
|
$position: selection.$from,
|
|
178
174
|
});
|
|
179
|
-
const decorationId = `id_${Math.floor(Math.random() *
|
|
175
|
+
const decorationId = `id_${Math.floor(Math.random() * 0xffffffff)}`;
|
|
180
176
|
// If we found a match, update the current state to show it
|
|
181
177
|
if (match && allow({ editor, state, range: match.range })) {
|
|
182
178
|
next.active = true;
|
|
@@ -232,4 +228,4 @@ function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allow
|
|
|
232
228
|
}
|
|
233
229
|
|
|
234
230
|
export { Suggestion, SuggestionPluginKey, Suggestion as default, findSuggestionMatch };
|
|
235
|
-
//# sourceMappingURL=
|
|
231
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/findSuggestionMatch.ts","../src/suggestion.ts"],"sourcesContent":["import { escapeForRegEx, Range } from '@tiptap/core'\nimport { ResolvedPos } from '@tiptap/pm/model'\n\nexport interface Trigger {\n char: string\n allowSpaces: boolean\n allowedPrefixes: string[] | null\n startOfLine: boolean\n $position: ResolvedPos\n}\n\nexport type SuggestionMatch = {\n range: Range\n query: string\n text: string\n} | null\n\nexport function findSuggestionMatch(config: Trigger): SuggestionMatch {\n const {\n char, allowSpaces, allowedPrefixes, startOfLine, $position,\n } = config\n\n const escapedChar = escapeForRegEx(char)\n const suffix = new RegExp(`\\\\s${escapedChar}$`)\n const prefix = startOfLine ? '^' : ''\n const regexp = allowSpaces\n ? new RegExp(`${prefix}${escapedChar}.*?(?=\\\\s${escapedChar}|$)`, 'gm')\n : new RegExp(`${prefix}(?:^)?${escapedChar}[^\\\\s${escapedChar}]*`, 'gm')\n\n const text = $position.nodeBefore?.isText && $position.nodeBefore.text\n\n if (!text) {\n return null\n }\n\n const textFrom = $position.pos - text.length\n const match = Array.from(text.matchAll(regexp)).pop()\n\n if (!match || match.input === undefined || match.index === undefined) {\n return null\n }\n\n // JavaScript doesn't have lookbehinds. This hacks a check that first character\n // is a space or the start of the line\n const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index)\n const matchPrefixIsAllowed = new RegExp(`^[${allowedPrefixes?.join('')}\\0]?$`).test(matchPrefix)\n\n if (allowedPrefixes !== null && !matchPrefixIsAllowed) {\n return null\n }\n\n // The absolute position of the match in the document\n const from = textFrom + match.index\n let to = from + match[0].length\n\n // Edge case handling; if spaces are allowed and we're directly in between\n // two triggers\n if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) {\n match[0] += ' '\n to += 1\n }\n\n // If the $position is located within the matched substring, return that range\n if (from < $position.pos && to >= $position.pos) {\n return {\n range: {\n from,\n to,\n },\n query: match[0].slice(char.length),\n text: match[0],\n }\n }\n\n return null\n}\n","import { Editor, Range } from '@tiptap/core'\nimport { EditorState, Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet, EditorView } from '@tiptap/pm/view'\n\nimport { findSuggestionMatch } from './findSuggestionMatch'\n\nexport interface SuggestionOptions<I = any> {\n pluginKey?: PluginKey\n editor: Editor\n char?: string\n allowSpaces?: boolean\n allowedPrefixes?: string[] | null\n startOfLine?: boolean\n decorationTag?: string\n decorationClass?: string\n command?: (props: { editor: Editor; range: Range; props: I }) => void\n items?: (props: { query: string; editor: Editor }) => I[] | Promise<I[]>\n render?: () => {\n onBeforeStart?: (props: SuggestionProps<I>) => void\n onStart?: (props: SuggestionProps<I>) => void\n onBeforeUpdate?: (props: SuggestionProps<I>) => void\n onUpdate?: (props: SuggestionProps<I>) => void\n onExit?: (props: SuggestionProps<I>) => void\n onKeyDown?: (props: SuggestionKeyDownProps) => boolean\n }\n allow?: (props: { editor: Editor; state: EditorState; range: Range }) => boolean\n}\n\nexport interface SuggestionProps<I = any> {\n editor: Editor\n range: Range\n query: string\n text: string\n items: I[]\n command: (props: I) => void\n decorationNode: Element | null\n clientRect?: (() => DOMRect | null) | null\n}\n\nexport interface SuggestionKeyDownProps {\n view: EditorView\n event: KeyboardEvent\n range: Range\n}\n\nexport const SuggestionPluginKey = new PluginKey('suggestion')\n\nexport function Suggestion<I = any>({\n pluginKey = SuggestionPluginKey,\n editor,\n char = '@',\n allowSpaces = false,\n allowedPrefixes = [' '],\n startOfLine = false,\n decorationTag = 'span',\n decorationClass = 'suggestion',\n command = () => null,\n items = () => [],\n render = () => ({}),\n allow = () => true,\n}: SuggestionOptions<I>) {\n let props: SuggestionProps<I> | undefined\n const renderer = render?.()\n\n const plugin: Plugin<any> = new Plugin({\n key: pluginKey,\n\n view() {\n return {\n update: async (view, prevState) => {\n const prev = this.key?.getState(prevState)\n const next = this.key?.getState(view.state)\n\n // See how the state changed\n const moved = prev.active && next.active && prev.range.from !== next.range.from\n const started = !prev.active && next.active\n const stopped = prev.active && !next.active\n const changed = !started && !stopped && prev.query !== next.query\n const handleStart = started || moved\n const handleChange = changed && !moved\n const handleExit = stopped || moved\n\n // Cancel when suggestion isn't active\n if (!handleStart && !handleChange && !handleExit) {\n return\n }\n\n const state = handleExit && !handleStart ? prev : next\n const decorationNode = view.dom.querySelector(\n `[data-decoration-id=\"${state.decorationId}\"]`,\n )\n\n props = {\n editor,\n range: state.range,\n query: state.query,\n text: state.text,\n items: [],\n command: commandProps => {\n command({\n editor,\n range: state.range,\n props: commandProps,\n })\n },\n decorationNode,\n // virtual node for popper.js or tippy.js\n // this can be used for building popups without a DOM node\n clientRect: decorationNode\n ? () => {\n // because of `items` can be asynchrounous we’ll search for the current decoration node\n const { decorationId } = this.key?.getState(editor.state) // eslint-disable-line\n const currentDecorationNode = view.dom.querySelector(\n `[data-decoration-id=\"${decorationId}\"]`,\n )\n\n return currentDecorationNode?.getBoundingClientRect() || null\n }\n : null,\n }\n\n if (handleStart) {\n renderer?.onBeforeStart?.(props)\n }\n\n if (handleChange) {\n renderer?.onBeforeUpdate?.(props)\n }\n\n if (handleChange || handleStart) {\n props.items = await items({\n editor,\n query: state.query,\n })\n }\n\n if (handleExit) {\n renderer?.onExit?.(props)\n }\n\n if (handleChange) {\n renderer?.onUpdate?.(props)\n }\n\n if (handleStart) {\n renderer?.onStart?.(props)\n }\n },\n\n destroy: () => {\n if (!props) {\n return\n }\n\n renderer?.onExit?.(props)\n },\n }\n },\n\n state: {\n // Initialize the plugin's internal state.\n init() {\n const state: {\n active: boolean\n range: Range\n query: null | string\n text: null | string\n composing: boolean\n decorationId?: string | null\n } = {\n active: false,\n range: {\n from: 0,\n to: 0,\n },\n query: null,\n text: null,\n composing: false,\n }\n\n return state\n },\n\n // Apply changes to the plugin state from a view transaction.\n apply(transaction, prev, oldState, state) {\n const { isEditable } = editor\n const { composing } = editor.view\n const { selection } = transaction\n const { empty, from } = selection\n const next = { ...prev }\n\n next.composing = composing\n\n // We can only be suggesting if the view is editable, and:\n // * there is no selection, or\n // * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)\n if (isEditable && (empty || editor.view.composing)) {\n // Reset active state if we just left the previous suggestion range\n if ((from < prev.range.from || from > prev.range.to) && !composing && !prev.composing) {\n next.active = false\n }\n\n // Try to match against where our cursor currently is\n const match = findSuggestionMatch({\n char,\n allowSpaces,\n allowedPrefixes,\n startOfLine,\n $position: selection.$from,\n })\n const decorationId = `id_${Math.floor(Math.random() * 0xffffffff)}`\n\n // If we found a match, update the current state to show it\n if (match && allow({ editor, state, range: match.range })) {\n next.active = true\n next.decorationId = prev.decorationId ? prev.decorationId : decorationId\n next.range = match.range\n next.query = match.query\n next.text = match.text\n } else {\n next.active = false\n }\n } else {\n next.active = false\n }\n\n // Make sure to empty the range if suggestion is inactive\n if (!next.active) {\n next.decorationId = null\n next.range = { from: 0, to: 0 }\n next.query = null\n next.text = null\n }\n\n return next\n },\n },\n\n props: {\n // Call the keydown hook if suggestion is active.\n handleKeyDown(view, event) {\n const { active, range } = plugin.getState(view.state)\n\n if (!active) {\n return false\n }\n\n return renderer?.onKeyDown?.({ view, event, range }) || false\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const { active, range, decorationId } = plugin.getState(state)\n\n if (!active) {\n return null\n }\n\n return DecorationSet.create(state.doc, [\n Decoration.inline(range.from, range.to, {\n nodeName: decorationTag,\n class: decorationClass,\n 'data-decoration-id': decorationId,\n }),\n ])\n },\n },\n })\n\n return plugin\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', '
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@tiptap/suggestion"] = {}, global.
|
|
5
|
-
})(this, (function (exports,
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tiptap/pm/state'), require('@tiptap/pm/view'), require('@tiptap/core')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', '@tiptap/pm/state', '@tiptap/pm/view', '@tiptap/core'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@tiptap/suggestion"] = {}, global.state, global.view, global.core));
|
|
5
|
+
})(this, (function (exports, state, view, core) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function findSuggestionMatch(config) {
|
|
8
8
|
var _a;
|
|
@@ -52,11 +52,11 @@
|
|
|
52
52
|
return null;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
const SuggestionPluginKey = new
|
|
55
|
+
const SuggestionPluginKey = new state.PluginKey('suggestion');
|
|
56
56
|
function Suggestion({ pluginKey = SuggestionPluginKey, editor, char = '@', allowSpaces = false, allowedPrefixes = [' '], startOfLine = false, decorationTag = 'span', decorationClass = 'suggestion', command = () => null, items = () => [], render = () => ({}), allow = () => true, }) {
|
|
57
57
|
let props;
|
|
58
58
|
const renderer = render === null || render === void 0 ? void 0 : render();
|
|
59
|
-
const plugin = new
|
|
59
|
+
const plugin = new state.Plugin({
|
|
60
60
|
key: pluginKey,
|
|
61
61
|
view() {
|
|
62
62
|
return {
|
|
@@ -76,9 +76,7 @@
|
|
|
76
76
|
if (!handleStart && !handleChange && !handleExit) {
|
|
77
77
|
return;
|
|
78
78
|
}
|
|
79
|
-
const state = handleExit && !handleStart
|
|
80
|
-
? prev
|
|
81
|
-
: next;
|
|
79
|
+
const state = handleExit && !handleStart ? prev : next;
|
|
82
80
|
const decorationNode = view.dom.querySelector(`[data-decoration-id="${state.decorationId}"]`);
|
|
83
81
|
props = {
|
|
84
82
|
editor,
|
|
@@ -99,7 +97,7 @@
|
|
|
99
97
|
clientRect: decorationNode
|
|
100
98
|
? () => {
|
|
101
99
|
var _a;
|
|
102
|
-
// because of `items` can be asynchrounous we’ll search for the current
|
|
100
|
+
// because of `items` can be asynchrounous we’ll search for the current decoration node
|
|
103
101
|
const { decorationId } = (_a = this.key) === null || _a === void 0 ? void 0 : _a.getState(editor.state); // eslint-disable-line
|
|
104
102
|
const currentDecorationNode = view.dom.querySelector(`[data-decoration-id="${decorationId}"]`);
|
|
105
103
|
return (currentDecorationNode === null || currentDecorationNode === void 0 ? void 0 : currentDecorationNode.getBoundingClientRect()) || null;
|
|
@@ -165,9 +163,7 @@
|
|
|
165
163
|
// * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)
|
|
166
164
|
if (isEditable && (empty || editor.view.composing)) {
|
|
167
165
|
// Reset active state if we just left the previous suggestion range
|
|
168
|
-
if ((
|
|
169
|
-
&& !composing
|
|
170
|
-
&& !prev.composing) {
|
|
166
|
+
if ((from < prev.range.from || from > prev.range.to) && !composing && !prev.composing) {
|
|
171
167
|
next.active = false;
|
|
172
168
|
}
|
|
173
169
|
// Try to match against where our cursor currently is
|
|
@@ -178,7 +174,7 @@
|
|
|
178
174
|
startOfLine,
|
|
179
175
|
$position: selection.$from,
|
|
180
176
|
});
|
|
181
|
-
const decorationId = `id_${Math.floor(Math.random() *
|
|
177
|
+
const decorationId = `id_${Math.floor(Math.random() * 0xffffffff)}`;
|
|
182
178
|
// If we found a match, update the current state to show it
|
|
183
179
|
if (match && allow({ editor, state, range: match.range })) {
|
|
184
180
|
next.active = true;
|
|
@@ -220,8 +216,8 @@
|
|
|
220
216
|
if (!active) {
|
|
221
217
|
return null;
|
|
222
218
|
}
|
|
223
|
-
return
|
|
224
|
-
|
|
219
|
+
return view.DecorationSet.create(state.doc, [
|
|
220
|
+
view.Decoration.inline(range.from, range.to, {
|
|
225
221
|
nodeName: decorationTag,
|
|
226
222
|
class: decorationClass,
|
|
227
223
|
'data-decoration-id': decorationId,
|
|
@@ -241,4 +237,4 @@
|
|
|
241
237
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
242
238
|
|
|
243
239
|
}));
|
|
244
|
-
//# sourceMappingURL=
|
|
240
|
+
//# sourceMappingURL=index.umd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/findSuggestionMatch.ts","../src/suggestion.ts"],"sourcesContent":["import { escapeForRegEx, Range } from '@tiptap/core'\nimport { ResolvedPos } from '@tiptap/pm/model'\n\nexport interface Trigger {\n char: string\n allowSpaces: boolean\n allowedPrefixes: string[] | null\n startOfLine: boolean\n $position: ResolvedPos\n}\n\nexport type SuggestionMatch = {\n range: Range\n query: string\n text: string\n} | null\n\nexport function findSuggestionMatch(config: Trigger): SuggestionMatch {\n const {\n char, allowSpaces, allowedPrefixes, startOfLine, $position,\n } = config\n\n const escapedChar = escapeForRegEx(char)\n const suffix = new RegExp(`\\\\s${escapedChar}$`)\n const prefix = startOfLine ? '^' : ''\n const regexp = allowSpaces\n ? new RegExp(`${prefix}${escapedChar}.*?(?=\\\\s${escapedChar}|$)`, 'gm')\n : new RegExp(`${prefix}(?:^)?${escapedChar}[^\\\\s${escapedChar}]*`, 'gm')\n\n const text = $position.nodeBefore?.isText && $position.nodeBefore.text\n\n if (!text) {\n return null\n }\n\n const textFrom = $position.pos - text.length\n const match = Array.from(text.matchAll(regexp)).pop()\n\n if (!match || match.input === undefined || match.index === undefined) {\n return null\n }\n\n // JavaScript doesn't have lookbehinds. This hacks a check that first character\n // is a space or the start of the line\n const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index)\n const matchPrefixIsAllowed = new RegExp(`^[${allowedPrefixes?.join('')}\\0]?$`).test(matchPrefix)\n\n if (allowedPrefixes !== null && !matchPrefixIsAllowed) {\n return null\n }\n\n // The absolute position of the match in the document\n const from = textFrom + match.index\n let to = from + match[0].length\n\n // Edge case handling; if spaces are allowed and we're directly in between\n // two triggers\n if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) {\n match[0] += ' '\n to += 1\n }\n\n // If the $position is located within the matched substring, return that range\n if (from < $position.pos && to >= $position.pos) {\n return {\n range: {\n from,\n to,\n },\n query: match[0].slice(char.length),\n text: match[0],\n }\n }\n\n return null\n}\n","import { Editor, Range } from '@tiptap/core'\nimport { EditorState, Plugin, PluginKey } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet, EditorView } from '@tiptap/pm/view'\n\nimport { findSuggestionMatch } from './findSuggestionMatch'\n\nexport interface SuggestionOptions<I = any> {\n pluginKey?: PluginKey\n editor: Editor\n char?: string\n allowSpaces?: boolean\n allowedPrefixes?: string[] | null\n startOfLine?: boolean\n decorationTag?: string\n decorationClass?: string\n command?: (props: { editor: Editor; range: Range; props: I }) => void\n items?: (props: { query: string; editor: Editor }) => I[] | Promise<I[]>\n render?: () => {\n onBeforeStart?: (props: SuggestionProps<I>) => void\n onStart?: (props: SuggestionProps<I>) => void\n onBeforeUpdate?: (props: SuggestionProps<I>) => void\n onUpdate?: (props: SuggestionProps<I>) => void\n onExit?: (props: SuggestionProps<I>) => void\n onKeyDown?: (props: SuggestionKeyDownProps) => boolean\n }\n allow?: (props: { editor: Editor; state: EditorState; range: Range }) => boolean\n}\n\nexport interface SuggestionProps<I = any> {\n editor: Editor\n range: Range\n query: string\n text: string\n items: I[]\n command: (props: I) => void\n decorationNode: Element | null\n clientRect?: (() => DOMRect | null) | null\n}\n\nexport interface SuggestionKeyDownProps {\n view: EditorView\n event: KeyboardEvent\n range: Range\n}\n\nexport const SuggestionPluginKey = new PluginKey('suggestion')\n\nexport function Suggestion<I = any>({\n pluginKey = SuggestionPluginKey,\n editor,\n char = '@',\n allowSpaces = false,\n allowedPrefixes = [' '],\n startOfLine = false,\n decorationTag = 'span',\n decorationClass = 'suggestion',\n command = () => null,\n items = () => [],\n render = () => ({}),\n allow = () => true,\n}: SuggestionOptions<I>) {\n let props: SuggestionProps<I> | undefined\n const renderer = render?.()\n\n const plugin: Plugin<any> = new Plugin({\n key: pluginKey,\n\n view() {\n return {\n update: async (view, prevState) => {\n const prev = this.key?.getState(prevState)\n const next = this.key?.getState(view.state)\n\n // See how the state changed\n const moved = prev.active && next.active && prev.range.from !== next.range.from\n const started = !prev.active && next.active\n const stopped = prev.active && !next.active\n const changed = !started && !stopped && prev.query !== next.query\n const handleStart = started || moved\n const handleChange = changed && !moved\n const handleExit = stopped || moved\n\n // Cancel when suggestion isn't active\n if (!handleStart && !handleChange && !handleExit) {\n return\n }\n\n const state = handleExit && !handleStart ? prev : next\n const decorationNode = view.dom.querySelector(\n `[data-decoration-id=\"${state.decorationId}\"]`,\n )\n\n props = {\n editor,\n range: state.range,\n query: state.query,\n text: state.text,\n items: [],\n command: commandProps => {\n command({\n editor,\n range: state.range,\n props: commandProps,\n })\n },\n decorationNode,\n // virtual node for popper.js or tippy.js\n // this can be used for building popups without a DOM node\n clientRect: decorationNode\n ? () => {\n // because of `items` can be asynchrounous we’ll search for the current decoration node\n const { decorationId } = this.key?.getState(editor.state) // eslint-disable-line\n const currentDecorationNode = view.dom.querySelector(\n `[data-decoration-id=\"${decorationId}\"]`,\n )\n\n return currentDecorationNode?.getBoundingClientRect() || null\n }\n : null,\n }\n\n if (handleStart) {\n renderer?.onBeforeStart?.(props)\n }\n\n if (handleChange) {\n renderer?.onBeforeUpdate?.(props)\n }\n\n if (handleChange || handleStart) {\n props.items = await items({\n editor,\n query: state.query,\n })\n }\n\n if (handleExit) {\n renderer?.onExit?.(props)\n }\n\n if (handleChange) {\n renderer?.onUpdate?.(props)\n }\n\n if (handleStart) {\n renderer?.onStart?.(props)\n }\n },\n\n destroy: () => {\n if (!props) {\n return\n }\n\n renderer?.onExit?.(props)\n },\n }\n },\n\n state: {\n // Initialize the plugin's internal state.\n init() {\n const state: {\n active: boolean\n range: Range\n query: null | string\n text: null | string\n composing: boolean\n decorationId?: string | null\n } = {\n active: false,\n range: {\n from: 0,\n to: 0,\n },\n query: null,\n text: null,\n composing: false,\n }\n\n return state\n },\n\n // Apply changes to the plugin state from a view transaction.\n apply(transaction, prev, oldState, state) {\n const { isEditable } = editor\n const { composing } = editor.view\n const { selection } = transaction\n const { empty, from } = selection\n const next = { ...prev }\n\n next.composing = composing\n\n // We can only be suggesting if the view is editable, and:\n // * there is no selection, or\n // * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)\n if (isEditable && (empty || editor.view.composing)) {\n // Reset active state if we just left the previous suggestion range\n if ((from < prev.range.from || from > prev.range.to) && !composing && !prev.composing) {\n next.active = false\n }\n\n // Try to match against where our cursor currently is\n const match = findSuggestionMatch({\n char,\n allowSpaces,\n allowedPrefixes,\n startOfLine,\n $position: selection.$from,\n })\n const decorationId = `id_${Math.floor(Math.random() * 0xffffffff)}`\n\n // If we found a match, update the current state to show it\n if (match && allow({ editor, state, range: match.range })) {\n next.active = true\n next.decorationId = prev.decorationId ? prev.decorationId : decorationId\n next.range = match.range\n next.query = match.query\n next.text = match.text\n } else {\n next.active = false\n }\n } else {\n next.active = false\n }\n\n // Make sure to empty the range if suggestion is inactive\n if (!next.active) {\n next.decorationId = null\n next.range = { from: 0, to: 0 }\n next.query = null\n next.text = null\n }\n\n return next\n },\n },\n\n props: {\n // Call the keydown hook if suggestion is active.\n handleKeyDown(view, event) {\n const { active, range } = plugin.getState(view.state)\n\n if (!active) {\n return false\n }\n\n return renderer?.onKeyDown?.({ view, event, range }) || false\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const { active, range, decorationId } = plugin.getState(state)\n\n if (!active) {\n return null\n }\n\n return DecorationSet.create(state.doc, [\n Decoration.inline(range.from, range.to, {\n nodeName: decorationTag,\n class: decorationClass,\n 'data-decoration-id': decorationId,\n }),\n ])\n },\n },\n })\n\n return plugin\n}\n"],"names":["escapeForRegEx","PluginKey","Plugin","DecorationSet","Decoration"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Editor, Range } from '@tiptap/core';
|
|
2
|
-
import { EditorState, Plugin, PluginKey } from '
|
|
3
|
-
import { EditorView } from '
|
|
2
|
+
import { EditorState, Plugin, PluginKey } from '@tiptap/pm/state';
|
|
3
|
+
import { EditorView } from '@tiptap/pm/view';
|
|
4
4
|
export interface SuggestionOptions<I = any> {
|
|
5
5
|
pluginKey?: PluginKey;
|
|
6
6
|
editor: Editor;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/suggestion",
|
|
3
3
|
"description": "suggestion plugin for tiptap",
|
|
4
|
-
"version": "2.0.0-
|
|
4
|
+
"version": "2.0.0-rc.2",
|
|
5
5
|
"homepage": "https://tiptap.dev",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
@@ -12,26 +12,37 @@
|
|
|
12
12
|
"type": "github",
|
|
13
13
|
"url": "https://github.com/sponsors/ueberdosis"
|
|
14
14
|
},
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/packages/suggestion/src/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js",
|
|
19
|
+
"require": "./dist/index.cjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"main": "dist/index.cjs",
|
|
23
|
+
"module": "dist/index.js",
|
|
24
|
+
"umd": "dist/index.umd.js",
|
|
18
25
|
"types": "dist/packages/suggestion/src/index.d.ts",
|
|
26
|
+
"type": "module",
|
|
19
27
|
"files": [
|
|
20
28
|
"src",
|
|
21
29
|
"dist"
|
|
22
30
|
],
|
|
23
31
|
"peerDependencies": {
|
|
24
|
-
"@tiptap/core": "^2.0.0-
|
|
32
|
+
"@tiptap/core": "^2.0.0-rc.1",
|
|
33
|
+
"@tiptap/pm": "^2.0.0-rc.1"
|
|
25
34
|
},
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"prosemirror-view": "1.26.2"
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@tiptap/core": "^2.0.0-rc.1",
|
|
37
|
+
"@tiptap/pm": "^2.0.0-rc.1"
|
|
30
38
|
},
|
|
31
39
|
"repository": {
|
|
32
40
|
"type": "git",
|
|
33
41
|
"url": "https://github.com/ueberdosis/tiptap",
|
|
34
42
|
"directory": "packages/suggestion"
|
|
35
43
|
},
|
|
36
|
-
"
|
|
37
|
-
|
|
44
|
+
"scripts": {
|
|
45
|
+
"clean": "rm -rf dist",
|
|
46
|
+
"build": "npm run clean && rollup -c"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -1,27 +1,23 @@
|
|
|
1
1
|
import { escapeForRegEx, Range } from '@tiptap/core'
|
|
2
|
-
import { ResolvedPos } from '
|
|
2
|
+
import { ResolvedPos } from '@tiptap/pm/model'
|
|
3
3
|
|
|
4
4
|
export interface Trigger {
|
|
5
|
-
char: string
|
|
6
|
-
allowSpaces: boolean
|
|
7
|
-
allowedPrefixes: string[] | null
|
|
8
|
-
startOfLine: boolean
|
|
9
|
-
$position: ResolvedPos
|
|
5
|
+
char: string
|
|
6
|
+
allowSpaces: boolean
|
|
7
|
+
allowedPrefixes: string[] | null
|
|
8
|
+
startOfLine: boolean
|
|
9
|
+
$position: ResolvedPos
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export type SuggestionMatch = {
|
|
13
|
-
range: Range
|
|
14
|
-
query: string
|
|
15
|
-
text: string
|
|
13
|
+
range: Range
|
|
14
|
+
query: string
|
|
15
|
+
text: string
|
|
16
16
|
} | null
|
|
17
17
|
|
|
18
18
|
export function findSuggestionMatch(config: Trigger): SuggestionMatch {
|
|
19
19
|
const {
|
|
20
|
-
char,
|
|
21
|
-
allowSpaces,
|
|
22
|
-
allowedPrefixes,
|
|
23
|
-
startOfLine,
|
|
24
|
-
$position,
|
|
20
|
+
char, allowSpaces, allowedPrefixes, startOfLine, $position,
|
|
25
21
|
} = config
|
|
26
22
|
|
|
27
23
|
const escapedChar = escapeForRegEx(char)
|
package/src/suggestion.ts
CHANGED
|
@@ -1,57 +1,46 @@
|
|
|
1
1
|
import { Editor, Range } from '@tiptap/core'
|
|
2
|
-
import { EditorState, Plugin, PluginKey } from '
|
|
3
|
-
import { Decoration, DecorationSet, EditorView } from '
|
|
2
|
+
import { EditorState, Plugin, PluginKey } from '@tiptap/pm/state'
|
|
3
|
+
import { Decoration, DecorationSet, EditorView } from '@tiptap/pm/view'
|
|
4
4
|
|
|
5
5
|
import { findSuggestionMatch } from './findSuggestionMatch'
|
|
6
6
|
|
|
7
7
|
export interface SuggestionOptions<I = any> {
|
|
8
|
-
pluginKey?: PluginKey
|
|
9
|
-
editor: Editor
|
|
10
|
-
char?: string
|
|
11
|
-
allowSpaces?: boolean
|
|
12
|
-
allowedPrefixes?: string[] | null
|
|
13
|
-
startOfLine?: boolean
|
|
14
|
-
decorationTag?: string
|
|
15
|
-
decorationClass?: string
|
|
16
|
-
command?: (props: {
|
|
17
|
-
|
|
18
|
-
range: Range,
|
|
19
|
-
props: I,
|
|
20
|
-
}) => void,
|
|
21
|
-
items?: (props: {
|
|
22
|
-
query: string,
|
|
23
|
-
editor: Editor,
|
|
24
|
-
}) => I[] | Promise<I[]>,
|
|
8
|
+
pluginKey?: PluginKey
|
|
9
|
+
editor: Editor
|
|
10
|
+
char?: string
|
|
11
|
+
allowSpaces?: boolean
|
|
12
|
+
allowedPrefixes?: string[] | null
|
|
13
|
+
startOfLine?: boolean
|
|
14
|
+
decorationTag?: string
|
|
15
|
+
decorationClass?: string
|
|
16
|
+
command?: (props: { editor: Editor; range: Range; props: I }) => void
|
|
17
|
+
items?: (props: { query: string; editor: Editor }) => I[] | Promise<I[]>
|
|
25
18
|
render?: () => {
|
|
26
19
|
onBeforeStart?: (props: SuggestionProps<I>) => void
|
|
27
|
-
onStart?: (props: SuggestionProps<I>) => void
|
|
20
|
+
onStart?: (props: SuggestionProps<I>) => void
|
|
28
21
|
onBeforeUpdate?: (props: SuggestionProps<I>) => void
|
|
29
|
-
onUpdate?: (props: SuggestionProps<I>) => void
|
|
30
|
-
onExit?: (props: SuggestionProps<I>) => void
|
|
31
|
-
onKeyDown?: (props: SuggestionKeyDownProps) => boolean
|
|
32
|
-
}
|
|
33
|
-
allow?: (props: {
|
|
34
|
-
editor: Editor,
|
|
35
|
-
state: EditorState,
|
|
36
|
-
range: Range,
|
|
37
|
-
}) => boolean,
|
|
22
|
+
onUpdate?: (props: SuggestionProps<I>) => void
|
|
23
|
+
onExit?: (props: SuggestionProps<I>) => void
|
|
24
|
+
onKeyDown?: (props: SuggestionKeyDownProps) => boolean
|
|
25
|
+
}
|
|
26
|
+
allow?: (props: { editor: Editor; state: EditorState; range: Range }) => boolean
|
|
38
27
|
}
|
|
39
28
|
|
|
40
29
|
export interface SuggestionProps<I = any> {
|
|
41
|
-
editor: Editor
|
|
42
|
-
range: Range
|
|
43
|
-
query: string
|
|
44
|
-
text: string
|
|
45
|
-
items: I[]
|
|
46
|
-
command: (props: I) => void
|
|
47
|
-
decorationNode: Element | null
|
|
48
|
-
clientRect?: (() => DOMRect | null) | null
|
|
30
|
+
editor: Editor
|
|
31
|
+
range: Range
|
|
32
|
+
query: string
|
|
33
|
+
text: string
|
|
34
|
+
items: I[]
|
|
35
|
+
command: (props: I) => void
|
|
36
|
+
decorationNode: Element | null
|
|
37
|
+
clientRect?: (() => DOMRect | null) | null
|
|
49
38
|
}
|
|
50
39
|
|
|
51
40
|
export interface SuggestionKeyDownProps {
|
|
52
|
-
view: EditorView
|
|
53
|
-
event: KeyboardEvent
|
|
54
|
-
range: Range
|
|
41
|
+
view: EditorView
|
|
42
|
+
event: KeyboardEvent
|
|
43
|
+
range: Range
|
|
55
44
|
}
|
|
56
45
|
|
|
57
46
|
export const SuggestionPluginKey = new PluginKey('suggestion')
|
|
@@ -70,7 +59,6 @@ export function Suggestion<I = any>({
|
|
|
70
59
|
render = () => ({}),
|
|
71
60
|
allow = () => true,
|
|
72
61
|
}: SuggestionOptions<I>) {
|
|
73
|
-
|
|
74
62
|
let props: SuggestionProps<I> | undefined
|
|
75
63
|
const renderer = render?.()
|
|
76
64
|
|
|
@@ -97,10 +85,10 @@ export function Suggestion<I = any>({
|
|
|
97
85
|
return
|
|
98
86
|
}
|
|
99
87
|
|
|
100
|
-
const state = handleExit && !handleStart
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
88
|
+
const state = handleExit && !handleStart ? prev : next
|
|
89
|
+
const decorationNode = view.dom.querySelector(
|
|
90
|
+
`[data-decoration-id="${state.decorationId}"]`,
|
|
91
|
+
)
|
|
104
92
|
|
|
105
93
|
props = {
|
|
106
94
|
editor,
|
|
@@ -120,9 +108,11 @@ export function Suggestion<I = any>({
|
|
|
120
108
|
// this can be used for building popups without a DOM node
|
|
121
109
|
clientRect: decorationNode
|
|
122
110
|
? () => {
|
|
123
|
-
// because of `items` can be asynchrounous we’ll search for the current
|
|
124
|
-
|
|
125
|
-
const currentDecorationNode = view.dom.querySelector(
|
|
111
|
+
// because of `items` can be asynchrounous we’ll search for the current decoration node
|
|
112
|
+
const { decorationId } = this.key?.getState(editor.state) // eslint-disable-line
|
|
113
|
+
const currentDecorationNode = view.dom.querySelector(
|
|
114
|
+
`[data-decoration-id="${decorationId}"]`,
|
|
115
|
+
)
|
|
126
116
|
|
|
127
117
|
return currentDecorationNode?.getBoundingClientRect() || null
|
|
128
118
|
}
|
|
@@ -171,8 +161,8 @@ export function Suggestion<I = any>({
|
|
|
171
161
|
// Initialize the plugin's internal state.
|
|
172
162
|
init() {
|
|
173
163
|
const state: {
|
|
174
|
-
active: boolean
|
|
175
|
-
range: Range
|
|
164
|
+
active: boolean
|
|
165
|
+
range: Range
|
|
176
166
|
query: null | string
|
|
177
167
|
text: null | string
|
|
178
168
|
composing: boolean
|
|
@@ -206,11 +196,7 @@ export function Suggestion<I = any>({
|
|
|
206
196
|
// * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)
|
|
207
197
|
if (isEditable && (empty || editor.view.composing)) {
|
|
208
198
|
// Reset active state if we just left the previous suggestion range
|
|
209
|
-
if (
|
|
210
|
-
((from < prev.range.from) || from > prev.range.to)
|
|
211
|
-
&& !composing
|
|
212
|
-
&& !prev.composing
|
|
213
|
-
) {
|
|
199
|
+
if ((from < prev.range.from || from > prev.range.to) && !composing && !prev.composing) {
|
|
214
200
|
next.active = false
|
|
215
201
|
}
|
|
216
202
|
|
|
@@ -222,7 +208,7 @@ export function Suggestion<I = any>({
|
|
|
222
208
|
startOfLine,
|
|
223
209
|
$position: selection.$from,
|
|
224
210
|
})
|
|
225
|
-
const decorationId = `id_${Math.floor(Math.random() *
|
|
211
|
+
const decorationId = `id_${Math.floor(Math.random() * 0xffffffff)}`
|
|
226
212
|
|
|
227
213
|
// If we found a match, update the current state to show it
|
|
228
214
|
if (match && allow({ editor, state, range: match.range })) {
|
package/LICENSE.md
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2021, überdosis GbR
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tiptap-suggestion.cjs.js","sources":["../src/findSuggestionMatch.ts","../src/suggestion.ts"],"sourcesContent":["import { escapeForRegEx, Range } from '@tiptap/core'\nimport { ResolvedPos } from 'prosemirror-model'\n\nexport interface Trigger {\n char: string,\n allowSpaces: boolean,\n allowedPrefixes: string[] | null,\n startOfLine: boolean,\n $position: ResolvedPos,\n}\n\nexport type SuggestionMatch = {\n range: Range,\n query: string,\n text: string,\n} | null\n\nexport function findSuggestionMatch(config: Trigger): SuggestionMatch {\n const {\n char,\n allowSpaces,\n allowedPrefixes,\n startOfLine,\n $position,\n } = config\n\n const escapedChar = escapeForRegEx(char)\n const suffix = new RegExp(`\\\\s${escapedChar}$`)\n const prefix = startOfLine ? '^' : ''\n const regexp = allowSpaces\n ? new RegExp(`${prefix}${escapedChar}.*?(?=\\\\s${escapedChar}|$)`, 'gm')\n : new RegExp(`${prefix}(?:^)?${escapedChar}[^\\\\s${escapedChar}]*`, 'gm')\n\n const text = $position.nodeBefore?.isText && $position.nodeBefore.text\n\n if (!text) {\n return null\n }\n\n const textFrom = $position.pos - text.length\n const match = Array.from(text.matchAll(regexp)).pop()\n\n if (!match || match.input === undefined || match.index === undefined) {\n return null\n }\n\n // JavaScript doesn't have lookbehinds. This hacks a check that first character\n // is a space or the start of the line\n const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index)\n const matchPrefixIsAllowed = new RegExp(`^[${allowedPrefixes?.join('')}\\0]?$`).test(matchPrefix)\n\n if (allowedPrefixes !== null && !matchPrefixIsAllowed) {\n return null\n }\n\n // The absolute position of the match in the document\n const from = textFrom + match.index\n let to = from + match[0].length\n\n // Edge case handling; if spaces are allowed and we're directly in between\n // two triggers\n if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) {\n match[0] += ' '\n to += 1\n }\n\n // If the $position is located within the matched substring, return that range\n if (from < $position.pos && to >= $position.pos) {\n return {\n range: {\n from,\n to,\n },\n query: match[0].slice(char.length),\n text: match[0],\n }\n }\n\n return null\n}\n","import { Editor, Range } from '@tiptap/core'\nimport { EditorState, Plugin, PluginKey } from 'prosemirror-state'\nimport { Decoration, DecorationSet, EditorView } from 'prosemirror-view'\n\nimport { findSuggestionMatch } from './findSuggestionMatch'\n\nexport interface SuggestionOptions<I = any> {\n pluginKey?: PluginKey,\n editor: Editor,\n char?: string,\n allowSpaces?: boolean,\n allowedPrefixes?: string[] | null,\n startOfLine?: boolean,\n decorationTag?: string,\n decorationClass?: string,\n command?: (props: {\n editor: Editor,\n range: Range,\n props: I,\n }) => void,\n items?: (props: {\n query: string,\n editor: Editor,\n }) => I[] | Promise<I[]>,\n render?: () => {\n onBeforeStart?: (props: SuggestionProps<I>) => void\n onStart?: (props: SuggestionProps<I>) => void,\n onBeforeUpdate?: (props: SuggestionProps<I>) => void\n onUpdate?: (props: SuggestionProps<I>) => void,\n onExit?: (props: SuggestionProps<I>) => void,\n onKeyDown?: (props: SuggestionKeyDownProps) => boolean,\n },\n allow?: (props: {\n editor: Editor,\n state: EditorState,\n range: Range,\n }) => boolean,\n}\n\nexport interface SuggestionProps<I = any> {\n editor: Editor,\n range: Range,\n query: string,\n text: string,\n items: I[],\n command: (props: I) => void,\n decorationNode: Element | null,\n clientRect?: (() => DOMRect | null) | null,\n}\n\nexport interface SuggestionKeyDownProps {\n view: EditorView,\n event: KeyboardEvent,\n range: Range,\n}\n\nexport const SuggestionPluginKey = new PluginKey('suggestion')\n\nexport function Suggestion<I = any>({\n pluginKey = SuggestionPluginKey,\n editor,\n char = '@',\n allowSpaces = false,\n allowedPrefixes = [' '],\n startOfLine = false,\n decorationTag = 'span',\n decorationClass = 'suggestion',\n command = () => null,\n items = () => [],\n render = () => ({}),\n allow = () => true,\n}: SuggestionOptions<I>) {\n\n let props: SuggestionProps<I> | undefined\n const renderer = render?.()\n\n const plugin: Plugin<any> = new Plugin({\n key: pluginKey,\n\n view() {\n return {\n update: async (view, prevState) => {\n const prev = this.key?.getState(prevState)\n const next = this.key?.getState(view.state)\n\n // See how the state changed\n const moved = prev.active && next.active && prev.range.from !== next.range.from\n const started = !prev.active && next.active\n const stopped = prev.active && !next.active\n const changed = !started && !stopped && prev.query !== next.query\n const handleStart = started || moved\n const handleChange = changed && !moved\n const handleExit = stopped || moved\n\n // Cancel when suggestion isn't active\n if (!handleStart && !handleChange && !handleExit) {\n return\n }\n\n const state = handleExit && !handleStart\n ? prev\n : next\n const decorationNode = view.dom.querySelector(`[data-decoration-id=\"${state.decorationId}\"]`)\n\n props = {\n editor,\n range: state.range,\n query: state.query,\n text: state.text,\n items: [],\n command: commandProps => {\n command({\n editor,\n range: state.range,\n props: commandProps,\n })\n },\n decorationNode,\n // virtual node for popper.js or tippy.js\n // this can be used for building popups without a DOM node\n clientRect: decorationNode\n ? () => {\n // because of `items` can be asynchrounous we’ll search for the current docoration node\n const { decorationId } = this.key?.getState(editor.state) // eslint-disable-line\n const currentDecorationNode = view.dom.querySelector(`[data-decoration-id=\"${decorationId}\"]`)\n\n return currentDecorationNode?.getBoundingClientRect() || null\n }\n : null,\n }\n\n if (handleStart) {\n renderer?.onBeforeStart?.(props)\n }\n\n if (handleChange) {\n renderer?.onBeforeUpdate?.(props)\n }\n\n if (handleChange || handleStart) {\n props.items = await items({\n editor,\n query: state.query,\n })\n }\n\n if (handleExit) {\n renderer?.onExit?.(props)\n }\n\n if (handleChange) {\n renderer?.onUpdate?.(props)\n }\n\n if (handleStart) {\n renderer?.onStart?.(props)\n }\n },\n\n destroy: () => {\n if (!props) {\n return\n }\n\n renderer?.onExit?.(props)\n },\n }\n },\n\n state: {\n // Initialize the plugin's internal state.\n init() {\n const state: {\n active: boolean,\n range: Range,\n query: null | string\n text: null | string\n composing: boolean\n decorationId?: string | null\n } = {\n active: false,\n range: {\n from: 0,\n to: 0,\n },\n query: null,\n text: null,\n composing: false,\n }\n\n return state\n },\n\n // Apply changes to the plugin state from a view transaction.\n apply(transaction, prev, oldState, state) {\n const { isEditable } = editor\n const { composing } = editor.view\n const { selection } = transaction\n const { empty, from } = selection\n const next = { ...prev }\n\n next.composing = composing\n\n // We can only be suggesting if the view is editable, and:\n // * there is no selection, or\n // * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)\n if (isEditable && (empty || editor.view.composing)) {\n // Reset active state if we just left the previous suggestion range\n if (\n ((from < prev.range.from) || from > prev.range.to)\n && !composing\n && !prev.composing\n ) {\n next.active = false\n }\n\n // Try to match against where our cursor currently is\n const match = findSuggestionMatch({\n char,\n allowSpaces,\n allowedPrefixes,\n startOfLine,\n $position: selection.$from,\n })\n const decorationId = `id_${Math.floor(Math.random() * 0xFFFFFFFF)}`\n\n // If we found a match, update the current state to show it\n if (match && allow({ editor, state, range: match.range })) {\n next.active = true\n next.decorationId = prev.decorationId ? prev.decorationId : decorationId\n next.range = match.range\n next.query = match.query\n next.text = match.text\n } else {\n next.active = false\n }\n } else {\n next.active = false\n }\n\n // Make sure to empty the range if suggestion is inactive\n if (!next.active) {\n next.decorationId = null\n next.range = { from: 0, to: 0 }\n next.query = null\n next.text = null\n }\n\n return next\n },\n },\n\n props: {\n // Call the keydown hook if suggestion is active.\n handleKeyDown(view, event) {\n const { active, range } = plugin.getState(view.state)\n\n if (!active) {\n return false\n }\n\n return renderer?.onKeyDown?.({ view, event, range }) || false\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const { active, range, decorationId } = plugin.getState(state)\n\n if (!active) {\n return null\n }\n\n return DecorationSet.create(state.doc, [\n Decoration.inline(range.from, range.to, {\n nodeName: decorationTag,\n class: decorationClass,\n 'data-decoration-id': decorationId,\n }),\n ])\n },\n },\n })\n\n return plugin\n}\n"],"names":["escapeForRegEx","PluginKey","Plugin","DecorationSet","Decoration"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tiptap-suggestion.esm.js","sources":["../src/findSuggestionMatch.ts","../src/suggestion.ts"],"sourcesContent":["import { escapeForRegEx, Range } from '@tiptap/core'\nimport { ResolvedPos } from 'prosemirror-model'\n\nexport interface Trigger {\n char: string,\n allowSpaces: boolean,\n allowedPrefixes: string[] | null,\n startOfLine: boolean,\n $position: ResolvedPos,\n}\n\nexport type SuggestionMatch = {\n range: Range,\n query: string,\n text: string,\n} | null\n\nexport function findSuggestionMatch(config: Trigger): SuggestionMatch {\n const {\n char,\n allowSpaces,\n allowedPrefixes,\n startOfLine,\n $position,\n } = config\n\n const escapedChar = escapeForRegEx(char)\n const suffix = new RegExp(`\\\\s${escapedChar}$`)\n const prefix = startOfLine ? '^' : ''\n const regexp = allowSpaces\n ? new RegExp(`${prefix}${escapedChar}.*?(?=\\\\s${escapedChar}|$)`, 'gm')\n : new RegExp(`${prefix}(?:^)?${escapedChar}[^\\\\s${escapedChar}]*`, 'gm')\n\n const text = $position.nodeBefore?.isText && $position.nodeBefore.text\n\n if (!text) {\n return null\n }\n\n const textFrom = $position.pos - text.length\n const match = Array.from(text.matchAll(regexp)).pop()\n\n if (!match || match.input === undefined || match.index === undefined) {\n return null\n }\n\n // JavaScript doesn't have lookbehinds. This hacks a check that first character\n // is a space or the start of the line\n const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index)\n const matchPrefixIsAllowed = new RegExp(`^[${allowedPrefixes?.join('')}\\0]?$`).test(matchPrefix)\n\n if (allowedPrefixes !== null && !matchPrefixIsAllowed) {\n return null\n }\n\n // The absolute position of the match in the document\n const from = textFrom + match.index\n let to = from + match[0].length\n\n // Edge case handling; if spaces are allowed and we're directly in between\n // two triggers\n if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) {\n match[0] += ' '\n to += 1\n }\n\n // If the $position is located within the matched substring, return that range\n if (from < $position.pos && to >= $position.pos) {\n return {\n range: {\n from,\n to,\n },\n query: match[0].slice(char.length),\n text: match[0],\n }\n }\n\n return null\n}\n","import { Editor, Range } from '@tiptap/core'\nimport { EditorState, Plugin, PluginKey } from 'prosemirror-state'\nimport { Decoration, DecorationSet, EditorView } from 'prosemirror-view'\n\nimport { findSuggestionMatch } from './findSuggestionMatch'\n\nexport interface SuggestionOptions<I = any> {\n pluginKey?: PluginKey,\n editor: Editor,\n char?: string,\n allowSpaces?: boolean,\n allowedPrefixes?: string[] | null,\n startOfLine?: boolean,\n decorationTag?: string,\n decorationClass?: string,\n command?: (props: {\n editor: Editor,\n range: Range,\n props: I,\n }) => void,\n items?: (props: {\n query: string,\n editor: Editor,\n }) => I[] | Promise<I[]>,\n render?: () => {\n onBeforeStart?: (props: SuggestionProps<I>) => void\n onStart?: (props: SuggestionProps<I>) => void,\n onBeforeUpdate?: (props: SuggestionProps<I>) => void\n onUpdate?: (props: SuggestionProps<I>) => void,\n onExit?: (props: SuggestionProps<I>) => void,\n onKeyDown?: (props: SuggestionKeyDownProps) => boolean,\n },\n allow?: (props: {\n editor: Editor,\n state: EditorState,\n range: Range,\n }) => boolean,\n}\n\nexport interface SuggestionProps<I = any> {\n editor: Editor,\n range: Range,\n query: string,\n text: string,\n items: I[],\n command: (props: I) => void,\n decorationNode: Element | null,\n clientRect?: (() => DOMRect | null) | null,\n}\n\nexport interface SuggestionKeyDownProps {\n view: EditorView,\n event: KeyboardEvent,\n range: Range,\n}\n\nexport const SuggestionPluginKey = new PluginKey('suggestion')\n\nexport function Suggestion<I = any>({\n pluginKey = SuggestionPluginKey,\n editor,\n char = '@',\n allowSpaces = false,\n allowedPrefixes = [' '],\n startOfLine = false,\n decorationTag = 'span',\n decorationClass = 'suggestion',\n command = () => null,\n items = () => [],\n render = () => ({}),\n allow = () => true,\n}: SuggestionOptions<I>) {\n\n let props: SuggestionProps<I> | undefined\n const renderer = render?.()\n\n const plugin: Plugin<any> = new Plugin({\n key: pluginKey,\n\n view() {\n return {\n update: async (view, prevState) => {\n const prev = this.key?.getState(prevState)\n const next = this.key?.getState(view.state)\n\n // See how the state changed\n const moved = prev.active && next.active && prev.range.from !== next.range.from\n const started = !prev.active && next.active\n const stopped = prev.active && !next.active\n const changed = !started && !stopped && prev.query !== next.query\n const handleStart = started || moved\n const handleChange = changed && !moved\n const handleExit = stopped || moved\n\n // Cancel when suggestion isn't active\n if (!handleStart && !handleChange && !handleExit) {\n return\n }\n\n const state = handleExit && !handleStart\n ? prev\n : next\n const decorationNode = view.dom.querySelector(`[data-decoration-id=\"${state.decorationId}\"]`)\n\n props = {\n editor,\n range: state.range,\n query: state.query,\n text: state.text,\n items: [],\n command: commandProps => {\n command({\n editor,\n range: state.range,\n props: commandProps,\n })\n },\n decorationNode,\n // virtual node for popper.js or tippy.js\n // this can be used for building popups without a DOM node\n clientRect: decorationNode\n ? () => {\n // because of `items` can be asynchrounous we’ll search for the current docoration node\n const { decorationId } = this.key?.getState(editor.state) // eslint-disable-line\n const currentDecorationNode = view.dom.querySelector(`[data-decoration-id=\"${decorationId}\"]`)\n\n return currentDecorationNode?.getBoundingClientRect() || null\n }\n : null,\n }\n\n if (handleStart) {\n renderer?.onBeforeStart?.(props)\n }\n\n if (handleChange) {\n renderer?.onBeforeUpdate?.(props)\n }\n\n if (handleChange || handleStart) {\n props.items = await items({\n editor,\n query: state.query,\n })\n }\n\n if (handleExit) {\n renderer?.onExit?.(props)\n }\n\n if (handleChange) {\n renderer?.onUpdate?.(props)\n }\n\n if (handleStart) {\n renderer?.onStart?.(props)\n }\n },\n\n destroy: () => {\n if (!props) {\n return\n }\n\n renderer?.onExit?.(props)\n },\n }\n },\n\n state: {\n // Initialize the plugin's internal state.\n init() {\n const state: {\n active: boolean,\n range: Range,\n query: null | string\n text: null | string\n composing: boolean\n decorationId?: string | null\n } = {\n active: false,\n range: {\n from: 0,\n to: 0,\n },\n query: null,\n text: null,\n composing: false,\n }\n\n return state\n },\n\n // Apply changes to the plugin state from a view transaction.\n apply(transaction, prev, oldState, state) {\n const { isEditable } = editor\n const { composing } = editor.view\n const { selection } = transaction\n const { empty, from } = selection\n const next = { ...prev }\n\n next.composing = composing\n\n // We can only be suggesting if the view is editable, and:\n // * there is no selection, or\n // * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)\n if (isEditable && (empty || editor.view.composing)) {\n // Reset active state if we just left the previous suggestion range\n if (\n ((from < prev.range.from) || from > prev.range.to)\n && !composing\n && !prev.composing\n ) {\n next.active = false\n }\n\n // Try to match against where our cursor currently is\n const match = findSuggestionMatch({\n char,\n allowSpaces,\n allowedPrefixes,\n startOfLine,\n $position: selection.$from,\n })\n const decorationId = `id_${Math.floor(Math.random() * 0xFFFFFFFF)}`\n\n // If we found a match, update the current state to show it\n if (match && allow({ editor, state, range: match.range })) {\n next.active = true\n next.decorationId = prev.decorationId ? prev.decorationId : decorationId\n next.range = match.range\n next.query = match.query\n next.text = match.text\n } else {\n next.active = false\n }\n } else {\n next.active = false\n }\n\n // Make sure to empty the range if suggestion is inactive\n if (!next.active) {\n next.decorationId = null\n next.range = { from: 0, to: 0 }\n next.query = null\n next.text = null\n }\n\n return next\n },\n },\n\n props: {\n // Call the keydown hook if suggestion is active.\n handleKeyDown(view, event) {\n const { active, range } = plugin.getState(view.state)\n\n if (!active) {\n return false\n }\n\n return renderer?.onKeyDown?.({ view, event, range }) || false\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const { active, range, decorationId } = plugin.getState(state)\n\n if (!active) {\n return null\n }\n\n return DecorationSet.create(state.doc, [\n Decoration.inline(range.from, range.to, {\n nodeName: decorationTag,\n class: decorationClass,\n 'data-decoration-id': decorationId,\n }),\n ])\n },\n },\n })\n\n return plugin\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tiptap-suggestion.umd.js","sources":["../src/findSuggestionMatch.ts","../src/suggestion.ts"],"sourcesContent":["import { escapeForRegEx, Range } from '@tiptap/core'\nimport { ResolvedPos } from 'prosemirror-model'\n\nexport interface Trigger {\n char: string,\n allowSpaces: boolean,\n allowedPrefixes: string[] | null,\n startOfLine: boolean,\n $position: ResolvedPos,\n}\n\nexport type SuggestionMatch = {\n range: Range,\n query: string,\n text: string,\n} | null\n\nexport function findSuggestionMatch(config: Trigger): SuggestionMatch {\n const {\n char,\n allowSpaces,\n allowedPrefixes,\n startOfLine,\n $position,\n } = config\n\n const escapedChar = escapeForRegEx(char)\n const suffix = new RegExp(`\\\\s${escapedChar}$`)\n const prefix = startOfLine ? '^' : ''\n const regexp = allowSpaces\n ? new RegExp(`${prefix}${escapedChar}.*?(?=\\\\s${escapedChar}|$)`, 'gm')\n : new RegExp(`${prefix}(?:^)?${escapedChar}[^\\\\s${escapedChar}]*`, 'gm')\n\n const text = $position.nodeBefore?.isText && $position.nodeBefore.text\n\n if (!text) {\n return null\n }\n\n const textFrom = $position.pos - text.length\n const match = Array.from(text.matchAll(regexp)).pop()\n\n if (!match || match.input === undefined || match.index === undefined) {\n return null\n }\n\n // JavaScript doesn't have lookbehinds. This hacks a check that first character\n // is a space or the start of the line\n const matchPrefix = match.input.slice(Math.max(0, match.index - 1), match.index)\n const matchPrefixIsAllowed = new RegExp(`^[${allowedPrefixes?.join('')}\\0]?$`).test(matchPrefix)\n\n if (allowedPrefixes !== null && !matchPrefixIsAllowed) {\n return null\n }\n\n // The absolute position of the match in the document\n const from = textFrom + match.index\n let to = from + match[0].length\n\n // Edge case handling; if spaces are allowed and we're directly in between\n // two triggers\n if (allowSpaces && suffix.test(text.slice(to - 1, to + 1))) {\n match[0] += ' '\n to += 1\n }\n\n // If the $position is located within the matched substring, return that range\n if (from < $position.pos && to >= $position.pos) {\n return {\n range: {\n from,\n to,\n },\n query: match[0].slice(char.length),\n text: match[0],\n }\n }\n\n return null\n}\n","import { Editor, Range } from '@tiptap/core'\nimport { EditorState, Plugin, PluginKey } from 'prosemirror-state'\nimport { Decoration, DecorationSet, EditorView } from 'prosemirror-view'\n\nimport { findSuggestionMatch } from './findSuggestionMatch'\n\nexport interface SuggestionOptions<I = any> {\n pluginKey?: PluginKey,\n editor: Editor,\n char?: string,\n allowSpaces?: boolean,\n allowedPrefixes?: string[] | null,\n startOfLine?: boolean,\n decorationTag?: string,\n decorationClass?: string,\n command?: (props: {\n editor: Editor,\n range: Range,\n props: I,\n }) => void,\n items?: (props: {\n query: string,\n editor: Editor,\n }) => I[] | Promise<I[]>,\n render?: () => {\n onBeforeStart?: (props: SuggestionProps<I>) => void\n onStart?: (props: SuggestionProps<I>) => void,\n onBeforeUpdate?: (props: SuggestionProps<I>) => void\n onUpdate?: (props: SuggestionProps<I>) => void,\n onExit?: (props: SuggestionProps<I>) => void,\n onKeyDown?: (props: SuggestionKeyDownProps) => boolean,\n },\n allow?: (props: {\n editor: Editor,\n state: EditorState,\n range: Range,\n }) => boolean,\n}\n\nexport interface SuggestionProps<I = any> {\n editor: Editor,\n range: Range,\n query: string,\n text: string,\n items: I[],\n command: (props: I) => void,\n decorationNode: Element | null,\n clientRect?: (() => DOMRect | null) | null,\n}\n\nexport interface SuggestionKeyDownProps {\n view: EditorView,\n event: KeyboardEvent,\n range: Range,\n}\n\nexport const SuggestionPluginKey = new PluginKey('suggestion')\n\nexport function Suggestion<I = any>({\n pluginKey = SuggestionPluginKey,\n editor,\n char = '@',\n allowSpaces = false,\n allowedPrefixes = [' '],\n startOfLine = false,\n decorationTag = 'span',\n decorationClass = 'suggestion',\n command = () => null,\n items = () => [],\n render = () => ({}),\n allow = () => true,\n}: SuggestionOptions<I>) {\n\n let props: SuggestionProps<I> | undefined\n const renderer = render?.()\n\n const plugin: Plugin<any> = new Plugin({\n key: pluginKey,\n\n view() {\n return {\n update: async (view, prevState) => {\n const prev = this.key?.getState(prevState)\n const next = this.key?.getState(view.state)\n\n // See how the state changed\n const moved = prev.active && next.active && prev.range.from !== next.range.from\n const started = !prev.active && next.active\n const stopped = prev.active && !next.active\n const changed = !started && !stopped && prev.query !== next.query\n const handleStart = started || moved\n const handleChange = changed && !moved\n const handleExit = stopped || moved\n\n // Cancel when suggestion isn't active\n if (!handleStart && !handleChange && !handleExit) {\n return\n }\n\n const state = handleExit && !handleStart\n ? prev\n : next\n const decorationNode = view.dom.querySelector(`[data-decoration-id=\"${state.decorationId}\"]`)\n\n props = {\n editor,\n range: state.range,\n query: state.query,\n text: state.text,\n items: [],\n command: commandProps => {\n command({\n editor,\n range: state.range,\n props: commandProps,\n })\n },\n decorationNode,\n // virtual node for popper.js or tippy.js\n // this can be used for building popups without a DOM node\n clientRect: decorationNode\n ? () => {\n // because of `items` can be asynchrounous we’ll search for the current docoration node\n const { decorationId } = this.key?.getState(editor.state) // eslint-disable-line\n const currentDecorationNode = view.dom.querySelector(`[data-decoration-id=\"${decorationId}\"]`)\n\n return currentDecorationNode?.getBoundingClientRect() || null\n }\n : null,\n }\n\n if (handleStart) {\n renderer?.onBeforeStart?.(props)\n }\n\n if (handleChange) {\n renderer?.onBeforeUpdate?.(props)\n }\n\n if (handleChange || handleStart) {\n props.items = await items({\n editor,\n query: state.query,\n })\n }\n\n if (handleExit) {\n renderer?.onExit?.(props)\n }\n\n if (handleChange) {\n renderer?.onUpdate?.(props)\n }\n\n if (handleStart) {\n renderer?.onStart?.(props)\n }\n },\n\n destroy: () => {\n if (!props) {\n return\n }\n\n renderer?.onExit?.(props)\n },\n }\n },\n\n state: {\n // Initialize the plugin's internal state.\n init() {\n const state: {\n active: boolean,\n range: Range,\n query: null | string\n text: null | string\n composing: boolean\n decorationId?: string | null\n } = {\n active: false,\n range: {\n from: 0,\n to: 0,\n },\n query: null,\n text: null,\n composing: false,\n }\n\n return state\n },\n\n // Apply changes to the plugin state from a view transaction.\n apply(transaction, prev, oldState, state) {\n const { isEditable } = editor\n const { composing } = editor.view\n const { selection } = transaction\n const { empty, from } = selection\n const next = { ...prev }\n\n next.composing = composing\n\n // We can only be suggesting if the view is editable, and:\n // * there is no selection, or\n // * a composition is active (see: https://github.com/ueberdosis/tiptap/issues/1449)\n if (isEditable && (empty || editor.view.composing)) {\n // Reset active state if we just left the previous suggestion range\n if (\n ((from < prev.range.from) || from > prev.range.to)\n && !composing\n && !prev.composing\n ) {\n next.active = false\n }\n\n // Try to match against where our cursor currently is\n const match = findSuggestionMatch({\n char,\n allowSpaces,\n allowedPrefixes,\n startOfLine,\n $position: selection.$from,\n })\n const decorationId = `id_${Math.floor(Math.random() * 0xFFFFFFFF)}`\n\n // If we found a match, update the current state to show it\n if (match && allow({ editor, state, range: match.range })) {\n next.active = true\n next.decorationId = prev.decorationId ? prev.decorationId : decorationId\n next.range = match.range\n next.query = match.query\n next.text = match.text\n } else {\n next.active = false\n }\n } else {\n next.active = false\n }\n\n // Make sure to empty the range if suggestion is inactive\n if (!next.active) {\n next.decorationId = null\n next.range = { from: 0, to: 0 }\n next.query = null\n next.text = null\n }\n\n return next\n },\n },\n\n props: {\n // Call the keydown hook if suggestion is active.\n handleKeyDown(view, event) {\n const { active, range } = plugin.getState(view.state)\n\n if (!active) {\n return false\n }\n\n return renderer?.onKeyDown?.({ view, event, range }) || false\n },\n\n // Setup decorator on the currently active suggestion.\n decorations(state) {\n const { active, range, decorationId } = plugin.getState(state)\n\n if (!active) {\n return null\n }\n\n return DecorationSet.create(state.doc, [\n Decoration.inline(range.from, range.to, {\n nodeName: decorationTag,\n class: decorationClass,\n 'data-decoration-id': decorationId,\n }),\n ])\n },\n },\n })\n\n return plugin\n}\n"],"names":["escapeForRegEx","PluginKey","Plugin","DecorationSet","Decoration"],"mappings":"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"}
|