@tiptap/extension-node-range 2.22.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.
@@ -0,0 +1,320 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tiptap/core'), require('@tiptap/pm/state'), require('@tiptap/pm/view'), require('@tiptap/pm/model')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@tiptap/core', '@tiptap/pm/state', '@tiptap/pm/view', '@tiptap/pm/model'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@tiptap/extension-node-range"] = {}, global.core, global.state, global.view, global.model));
5
+ })(this, (function (exports, core, state, view, model) { 'use strict';
6
+
7
+ function getNodeRangeDecorations(ranges) {
8
+ if (!ranges.length) {
9
+ return view.DecorationSet.empty;
10
+ }
11
+ const decorations = [];
12
+ const doc = ranges[0].$from.node(0);
13
+ ranges.forEach(range => {
14
+ const pos = range.$from.pos;
15
+ const node = range.$from.nodeAfter;
16
+ if (!node) {
17
+ return;
18
+ }
19
+ decorations.push(view.Decoration.node(pos, pos + node.nodeSize, {
20
+ class: 'ProseMirror-selectednoderange',
21
+ }));
22
+ });
23
+ return view.DecorationSet.create(doc, decorations);
24
+ }
25
+
26
+ function getSelectionRanges($from, $to, depth) {
27
+ const ranges = [];
28
+ const doc = $from.node(0);
29
+ // eslint-disable-next-line
30
+ depth = (typeof depth === 'number' && depth >= 0)
31
+ ? depth
32
+ : $from.sameParent($to)
33
+ ? Math.max(0, $from.sharedDepth($to.pos) - 1)
34
+ : $from.sharedDepth($to.pos);
35
+ const nodeRange = new model.NodeRange($from, $to, depth);
36
+ const offset = nodeRange.depth === 0
37
+ ? 0
38
+ : doc.resolve(nodeRange.start).posAtIndex(0);
39
+ nodeRange.parent.forEach((node, pos) => {
40
+ const from = offset + pos;
41
+ const to = from + node.nodeSize;
42
+ if (from < nodeRange.start || from >= nodeRange.end) {
43
+ return;
44
+ }
45
+ const selectionRange = new state.SelectionRange(doc.resolve(from), doc.resolve(to));
46
+ ranges.push(selectionRange);
47
+ });
48
+ return ranges;
49
+ }
50
+
51
+ class NodeRangeBookmark {
52
+ constructor(anchor, head) {
53
+ this.anchor = anchor;
54
+ this.head = head;
55
+ }
56
+ map(mapping) {
57
+ return new NodeRangeBookmark(mapping.map(this.anchor), mapping.map(this.head));
58
+ }
59
+ resolve(doc) {
60
+ const $anchor = doc.resolve(this.anchor);
61
+ const $head = doc.resolve(this.head);
62
+ return new NodeRangeSelection($anchor, $head);
63
+ }
64
+ }
65
+
66
+ class NodeRangeSelection extends state.Selection {
67
+ constructor($anchor, $head, depth, bias = 1) {
68
+ // if there is only a cursor we can’t calculate a direction of the selection
69
+ // that’s why we adjust the head position by 1 in the desired direction
70
+ const { doc } = $anchor;
71
+ const isCursor = $anchor === $head;
72
+ const isCursorAtEnd = $anchor.pos === doc.content.size && $head.pos === doc.content.size;
73
+ const $correctedHead = isCursor && !isCursorAtEnd
74
+ ? doc.resolve($head.pos + (bias > 0 ? 1 : -1))
75
+ : $head;
76
+ const $correctedAnchor = isCursor && isCursorAtEnd
77
+ ? doc.resolve($anchor.pos - (bias > 0 ? 1 : -1))
78
+ : $anchor;
79
+ const ranges = getSelectionRanges($correctedAnchor.min($correctedHead), $correctedAnchor.max($correctedHead), depth);
80
+ // get the smallest range start position
81
+ // this will become the $anchor
82
+ const $rangeFrom = ($correctedHead.pos >= $anchor.pos)
83
+ ? ranges[0].$from
84
+ : ranges[ranges.length - 1].$to;
85
+ // get the biggest range end position
86
+ // this will become the $head
87
+ const $rangeTo = ($correctedHead.pos >= $anchor.pos)
88
+ ? ranges[ranges.length - 1].$to
89
+ : ranges[0].$from;
90
+ super($rangeFrom, $rangeTo, ranges);
91
+ this.depth = depth;
92
+ }
93
+ // we can safely ignore this TypeScript error: https://github.com/Microsoft/TypeScript/issues/338
94
+ // @ts-ignore
95
+ get $to() {
96
+ return this.ranges[this.ranges.length - 1].$to;
97
+ }
98
+ eq(other) {
99
+ return other instanceof NodeRangeSelection
100
+ && other.$from.pos === this.$from.pos
101
+ && other.$to.pos === this.$to.pos;
102
+ }
103
+ map(doc, mapping) {
104
+ const $anchor = doc.resolve(mapping.map(this.anchor));
105
+ const $head = doc.resolve(mapping.map(this.head));
106
+ return new NodeRangeSelection($anchor, $head);
107
+ }
108
+ toJSON() {
109
+ return {
110
+ type: 'nodeRange',
111
+ anchor: this.anchor,
112
+ head: this.head,
113
+ };
114
+ }
115
+ get isForwards() {
116
+ return this.head >= this.anchor;
117
+ }
118
+ get isBackwards() {
119
+ return !this.isForwards;
120
+ }
121
+ extendBackwards() {
122
+ const { doc } = this.$from;
123
+ if (this.isForwards && this.ranges.length > 1) {
124
+ const ranges = this.ranges.slice(0, -1);
125
+ const $from = ranges[0].$from;
126
+ const $to = ranges[ranges.length - 1].$to;
127
+ return new NodeRangeSelection($from, $to, this.depth);
128
+ }
129
+ const firstRange = this.ranges[0];
130
+ const $from = doc.resolve(Math.max(0, firstRange.$from.pos - 1));
131
+ return new NodeRangeSelection(this.$anchor, $from, this.depth);
132
+ }
133
+ extendForwards() {
134
+ const { doc } = this.$from;
135
+ if (this.isBackwards && this.ranges.length > 1) {
136
+ const ranges = this.ranges.slice(1);
137
+ const $from = ranges[0].$from;
138
+ const $to = ranges[ranges.length - 1].$to;
139
+ return new NodeRangeSelection($to, $from, this.depth);
140
+ }
141
+ const lastRange = this.ranges[this.ranges.length - 1];
142
+ const $to = doc.resolve(Math.min(doc.content.size, lastRange.$to.pos + 1));
143
+ return new NodeRangeSelection(this.$anchor, $to, this.depth);
144
+ }
145
+ static fromJSON(doc, json) {
146
+ return new NodeRangeSelection(doc.resolve(json.anchor), doc.resolve(json.head));
147
+ }
148
+ static create(doc, anchor, head, depth, bias = 1) {
149
+ return new this(doc.resolve(anchor), doc.resolve(head), depth, bias);
150
+ }
151
+ getBookmark() {
152
+ return new NodeRangeBookmark(this.anchor, this.head);
153
+ }
154
+ }
155
+ NodeRangeSelection.prototype.visible = false;
156
+
157
+ function isNodeRangeSelection(value) {
158
+ return value instanceof NodeRangeSelection;
159
+ }
160
+
161
+ const NodeRange = core.Extension.create({
162
+ name: 'nodeRange',
163
+ addOptions() {
164
+ return {
165
+ depth: undefined,
166
+ key: 'Mod',
167
+ };
168
+ },
169
+ addKeyboardShortcuts() {
170
+ return {
171
+ // extend NodeRangeSelection upwards
172
+ 'Shift-ArrowUp': ({ editor }) => {
173
+ const { depth } = this.options;
174
+ const { view, state } = editor;
175
+ const { doc, selection, tr } = state;
176
+ const { anchor, head } = selection;
177
+ if (!isNodeRangeSelection(selection)) {
178
+ const nodeRangeSelection = NodeRangeSelection.create(doc, anchor, head, depth, -1);
179
+ tr.setSelection(nodeRangeSelection);
180
+ view.dispatch(tr);
181
+ return true;
182
+ }
183
+ const nodeRangeSelection = selection.extendBackwards();
184
+ tr.setSelection(nodeRangeSelection);
185
+ view.dispatch(tr);
186
+ return true;
187
+ },
188
+ // extend NodeRangeSelection downwards
189
+ 'Shift-ArrowDown': ({ editor }) => {
190
+ const { depth } = this.options;
191
+ const { view, state } = editor;
192
+ const { doc, selection, tr } = state;
193
+ const { anchor, head } = selection;
194
+ if (!isNodeRangeSelection(selection)) {
195
+ const nodeRangeSelection = NodeRangeSelection.create(doc, anchor, head, depth);
196
+ tr.setSelection(nodeRangeSelection);
197
+ view.dispatch(tr);
198
+ return true;
199
+ }
200
+ const nodeRangeSelection = selection.extendForwards();
201
+ tr.setSelection(nodeRangeSelection);
202
+ view.dispatch(tr);
203
+ return true;
204
+ },
205
+ // add `NodeRangeSelection` to all nodes
206
+ 'Mod-a': ({ editor }) => {
207
+ const { depth } = this.options;
208
+ const { view, state } = editor;
209
+ const { doc, tr } = state;
210
+ const nodeRangeSelection = NodeRangeSelection.create(doc, 0, doc.content.size, depth);
211
+ tr.setSelection(nodeRangeSelection);
212
+ view.dispatch(tr);
213
+ return true;
214
+ },
215
+ };
216
+ },
217
+ onSelectionUpdate() {
218
+ const { selection } = this.editor.state;
219
+ if (isNodeRangeSelection(selection)) {
220
+ this.editor.view.dom.classList.add('ProseMirror-noderangeselection');
221
+ }
222
+ },
223
+ addProseMirrorPlugins() {
224
+ let hideTextSelection = false;
225
+ let activeMouseSelection = false;
226
+ return [
227
+ new state.Plugin({
228
+ key: new state.PluginKey('nodeRange'),
229
+ props: {
230
+ attributes: () => {
231
+ if (hideTextSelection) {
232
+ return {
233
+ class: 'ProseMirror-noderangeselection',
234
+ };
235
+ }
236
+ return { class: '' };
237
+ },
238
+ handleDOMEvents: {
239
+ mousedown: (view, event) => {
240
+ const { key } = this.options;
241
+ const isMac = /Mac/.test(navigator.platform);
242
+ const isShift = !!event.shiftKey;
243
+ const isControl = !!event.ctrlKey;
244
+ const isAlt = !!event.altKey;
245
+ const isMeta = !!event.metaKey;
246
+ const isMod = isMac
247
+ ? isMeta
248
+ : isControl;
249
+ if (key === null
250
+ || key === undefined
251
+ || (key === 'Shift' && isShift)
252
+ || (key === 'Control' && isControl)
253
+ || (key === 'Alt' && isAlt)
254
+ || (key === 'Meta' && isMeta)
255
+ || (key === 'Mod' && isMod)) {
256
+ activeMouseSelection = true;
257
+ }
258
+ if (!activeMouseSelection) {
259
+ return false;
260
+ }
261
+ document.addEventListener('mouseup', () => {
262
+ activeMouseSelection = false;
263
+ const { state } = view;
264
+ const { doc, selection, tr } = state;
265
+ const { $anchor, $head } = selection;
266
+ if ($anchor.sameParent($head)) {
267
+ return;
268
+ }
269
+ const nodeRangeSelection = NodeRangeSelection.create(doc, $anchor.pos, $head.pos, this.options.depth);
270
+ tr.setSelection(nodeRangeSelection);
271
+ view.dispatch(tr);
272
+ }, { once: true });
273
+ return false;
274
+ },
275
+ },
276
+ // when selecting some text we want to render some decorations
277
+ // to preview a `NodeRangeSelection`
278
+ decorations: state => {
279
+ const { selection } = state;
280
+ const isNodeRange = isNodeRangeSelection(selection);
281
+ hideTextSelection = false;
282
+ if (!activeMouseSelection) {
283
+ if (!isNodeRange) {
284
+ return null;
285
+ }
286
+ hideTextSelection = true;
287
+ return getNodeRangeDecorations(selection.ranges);
288
+ }
289
+ const { $from, $to } = selection;
290
+ // selection is probably in the same node like a paragraph
291
+ // so we don’t render decorations and show
292
+ // a simple text selection instead
293
+ if (!isNodeRange && $from.sameParent($to)) {
294
+ return null;
295
+ }
296
+ // try to calculate some node ranges
297
+ const nodeRanges = getSelectionRanges($from, $to, this.options.depth);
298
+ if (!nodeRanges.length) {
299
+ return null;
300
+ }
301
+ hideTextSelection = true;
302
+ return getNodeRangeDecorations(nodeRanges);
303
+ },
304
+ },
305
+ }),
306
+ ];
307
+ },
308
+ });
309
+
310
+ exports.NodeRange = NodeRange;
311
+ exports.NodeRangeSelection = NodeRangeSelection;
312
+ exports.default = NodeRange;
313
+ exports.getNodeRangeDecorations = getNodeRangeDecorations;
314
+ exports.getSelectionRanges = getSelectionRanges;
315
+ exports.isNodeRangeSelection = isNodeRangeSelection;
316
+
317
+ Object.defineProperty(exports, '__esModule', { value: true });
318
+
319
+ }));
320
+ //# sourceMappingURL=index.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.js","sources":["../src/helpers/getNodeRangeDecorations.ts","../src/helpers/getSelectionRanges.ts","../src/helpers/NodeRangeBookmark.ts","../src/helpers/NodeRangeSelection.ts","../src/helpers/isNodeRangeSelection.ts","../src/node-range.ts"],"sourcesContent":["import { SelectionRange } from '@tiptap/pm/state'\nimport { Decoration, DecorationSet } from '@tiptap/pm/view'\n\nexport function getNodeRangeDecorations(ranges: SelectionRange[]): DecorationSet {\n if (!ranges.length) {\n return DecorationSet.empty\n }\n\n const decorations: Decoration[] = []\n const doc = ranges[0].$from.node(0)\n\n ranges.forEach(range => {\n const pos = range.$from.pos\n const node = range.$from.nodeAfter\n\n if (!node) {\n return\n }\n\n decorations.push(\n Decoration.node(pos, pos + node.nodeSize, {\n class: 'ProseMirror-selectednoderange',\n }),\n )\n })\n\n return DecorationSet.create(doc, decorations)\n}\n","import { NodeRange, ResolvedPos } from '@tiptap/pm/model'\nimport { SelectionRange } from '@tiptap/pm/state'\n\nexport function getSelectionRanges(\n $from: ResolvedPos,\n $to: ResolvedPos,\n depth?: number,\n): SelectionRange[] {\n const ranges: SelectionRange[] = []\n const doc = $from.node(0)\n\n // eslint-disable-next-line\n depth = (typeof depth === 'number' && depth >= 0)\n ? depth\n : $from.sameParent($to)\n ? Math.max(0, $from.sharedDepth($to.pos) - 1)\n : $from.sharedDepth($to.pos)\n\n const nodeRange = new NodeRange($from, $to, depth)\n const offset = nodeRange.depth === 0\n ? 0\n : doc.resolve(nodeRange.start).posAtIndex(0)\n\n nodeRange.parent.forEach((node, pos) => {\n const from = offset + pos\n const to = from + node.nodeSize\n\n if (from < nodeRange.start || from >= nodeRange.end) {\n return\n }\n\n const selectionRange = new SelectionRange(doc.resolve(from), doc.resolve(to))\n\n ranges.push(selectionRange)\n })\n\n return ranges\n}\n","import { Node as ProseMirrorNode } from '@tiptap/pm/model'\nimport { Mappable } from '@tiptap/pm/transform'\n\nimport { NodeRangeSelection } from './NodeRangeSelection.js'\n\nexport class NodeRangeBookmark {\n\n anchor!: number\n\n head!: number\n\n constructor(anchor: number, head: number) {\n this.anchor = anchor\n this.head = head\n }\n\n map(mapping: Mappable) {\n return new NodeRangeBookmark(mapping.map(this.anchor), mapping.map(this.head))\n }\n\n resolve(doc: ProseMirrorNode) {\n const $anchor = doc.resolve(this.anchor)\n const $head = doc.resolve(this.head)\n\n return new NodeRangeSelection($anchor, $head)\n }\n\n}\n","import { Node as ProseMirrorNode, ResolvedPos } from '@tiptap/pm/model'\nimport { Selection } from '@tiptap/pm/state'\nimport { Mapping } from '@tiptap/pm/transform'\n\nimport { getSelectionRanges } from './getSelectionRanges.js'\nimport { NodeRangeBookmark } from './NodeRangeBookmark.js'\n\nexport class NodeRangeSelection extends Selection {\n\n depth: number | undefined\n\n constructor($anchor: ResolvedPos, $head: ResolvedPos, depth?: number, bias = 1) {\n // if there is only a cursor we can’t calculate a direction of the selection\n // that’s why we adjust the head position by 1 in the desired direction\n const { doc } = $anchor\n const isCursor = $anchor === $head\n const isCursorAtEnd = $anchor.pos === doc.content.size && $head.pos === doc.content.size\n const $correctedHead = isCursor && !isCursorAtEnd\n ? doc.resolve($head.pos + (bias > 0 ? 1 : -1))\n : $head\n const $correctedAnchor = isCursor && isCursorAtEnd\n ? doc.resolve($anchor.pos - (bias > 0 ? 1 : -1))\n : $anchor\n\n const ranges = getSelectionRanges(\n $correctedAnchor.min($correctedHead),\n $correctedAnchor.max($correctedHead),\n depth,\n )\n\n // get the smallest range start position\n // this will become the $anchor\n const $rangeFrom = ($correctedHead.pos >= $anchor.pos)\n ? ranges[0].$from\n : ranges[ranges.length - 1].$to\n\n // get the biggest range end position\n // this will become the $head\n const $rangeTo = ($correctedHead.pos >= $anchor.pos)\n ? ranges[ranges.length - 1].$to\n : ranges[0].$from\n\n super($rangeFrom, $rangeTo, ranges)\n\n this.depth = depth\n }\n\n // we can safely ignore this TypeScript error: https://github.com/Microsoft/TypeScript/issues/338\n // @ts-ignore\n get $to() {\n return this.ranges[this.ranges.length - 1].$to\n }\n\n eq(other: Selection): boolean {\n return other instanceof NodeRangeSelection\n && other.$from.pos === this.$from.pos\n && other.$to.pos === this.$to.pos\n }\n\n map(doc: ProseMirrorNode, mapping: Mapping): NodeRangeSelection {\n const $anchor = doc.resolve(mapping.map(this.anchor))\n const $head = doc.resolve(mapping.map(this.head))\n\n return new NodeRangeSelection($anchor, $head)\n }\n\n toJSON() {\n return {\n type: 'nodeRange',\n anchor: this.anchor,\n head: this.head,\n }\n }\n\n get isForwards(): boolean {\n return this.head >= this.anchor\n }\n\n get isBackwards(): boolean {\n return !this.isForwards\n }\n\n extendBackwards(): NodeRangeSelection {\n const { doc } = this.$from\n\n if (this.isForwards && this.ranges.length > 1) {\n const ranges = this.ranges.slice(0, -1)\n const $from = ranges[0].$from\n const $to = ranges[ranges.length - 1].$to\n\n return new NodeRangeSelection($from, $to, this.depth)\n }\n\n const firstRange = this.ranges[0]\n const $from = doc.resolve(Math.max(0, firstRange.$from.pos - 1))\n\n return new NodeRangeSelection(this.$anchor, $from, this.depth)\n }\n\n extendForwards(): NodeRangeSelection {\n const { doc } = this.$from\n\n if (this.isBackwards && this.ranges.length > 1) {\n const ranges = this.ranges.slice(1)\n const $from = ranges[0].$from\n const $to = ranges[ranges.length - 1].$to\n\n return new NodeRangeSelection($to, $from, this.depth)\n }\n\n const lastRange = this.ranges[this.ranges.length - 1]\n const $to = doc.resolve(Math.min(doc.content.size, lastRange.$to.pos + 1))\n\n return new NodeRangeSelection(this.$anchor, $to, this.depth)\n }\n\n static fromJSON(doc: ProseMirrorNode, json: any): NodeRangeSelection {\n return new NodeRangeSelection(doc.resolve(json.anchor), doc.resolve(json.head))\n }\n\n static create(doc: ProseMirrorNode, anchor: number, head: number, depth?: number, bias = 1): NodeRangeSelection {\n return new this(doc.resolve(anchor), doc.resolve(head), depth, bias)\n }\n\n getBookmark(): NodeRangeBookmark {\n return new NodeRangeBookmark(this.anchor, this.head)\n }\n\n}\n\nNodeRangeSelection.prototype.visible = false\n","import { NodeRangeSelection } from './NodeRangeSelection.js'\n\nexport function isNodeRangeSelection(value: unknown): value is NodeRangeSelection {\n return value instanceof NodeRangeSelection\n}\n","import { Extension } from '@tiptap/core'\nimport { Plugin, PluginKey, SelectionRange } from '@tiptap/pm/state'\n\nimport { getNodeRangeDecorations } from './helpers/getNodeRangeDecorations.js'\nimport { getSelectionRanges } from './helpers/getSelectionRanges.js'\nimport { isNodeRangeSelection } from './helpers/isNodeRangeSelection.js'\nimport { NodeRangeSelection } from './helpers/NodeRangeSelection.js'\n\nexport interface NodeRangeOptions {\n depth: number | undefined,\n key: 'Shift' | 'Control' | 'Alt' | 'Meta' | 'Mod' | null | undefined,\n}\n\nexport const NodeRange = Extension.create<NodeRangeOptions>({\n name: 'nodeRange',\n\n addOptions() {\n return {\n depth: undefined,\n key: 'Mod',\n }\n },\n\n addKeyboardShortcuts() {\n return {\n // extend NodeRangeSelection upwards\n 'Shift-ArrowUp': ({ editor }) => {\n const { depth } = this.options\n const { view, state } = editor\n const { doc, selection, tr } = state\n const { anchor, head } = selection\n\n if (!isNodeRangeSelection(selection)) {\n const nodeRangeSelection = NodeRangeSelection.create(doc, anchor, head, depth, -1)\n\n tr.setSelection(nodeRangeSelection)\n view.dispatch(tr)\n\n return true\n }\n\n const nodeRangeSelection = selection.extendBackwards()\n\n tr.setSelection(nodeRangeSelection)\n view.dispatch(tr)\n\n return true\n },\n\n // extend NodeRangeSelection downwards\n 'Shift-ArrowDown': ({ editor }) => {\n const { depth } = this.options\n const { view, state } = editor\n const { doc, selection, tr } = state\n const { anchor, head } = selection\n\n if (!isNodeRangeSelection(selection)) {\n const nodeRangeSelection = NodeRangeSelection.create(doc, anchor, head, depth)\n\n tr.setSelection(nodeRangeSelection)\n view.dispatch(tr)\n\n return true\n }\n\n const nodeRangeSelection = selection.extendForwards()\n\n tr.setSelection(nodeRangeSelection)\n view.dispatch(tr)\n\n return true\n },\n\n // add `NodeRangeSelection` to all nodes\n 'Mod-a': ({ editor }) => {\n const { depth } = this.options\n const { view, state } = editor\n const { doc, tr } = state\n const nodeRangeSelection = NodeRangeSelection.create(doc, 0, doc.content.size, depth)\n\n tr.setSelection(nodeRangeSelection)\n view.dispatch(tr)\n\n return true\n },\n }\n },\n\n onSelectionUpdate() {\n const { selection } = this.editor.state\n\n if (isNodeRangeSelection(selection)) {\n this.editor.view.dom.classList.add('ProseMirror-noderangeselection')\n }\n },\n\n addProseMirrorPlugins() {\n let hideTextSelection = false\n let activeMouseSelection = false\n\n return [\n new Plugin({\n key: new PluginKey('nodeRange'),\n\n props: {\n attributes: () => {\n if (hideTextSelection) {\n return {\n class: 'ProseMirror-noderangeselection',\n }\n }\n\n return { class: '' }\n },\n\n handleDOMEvents: {\n mousedown: (view, event) => {\n const { key } = this.options\n const isMac = /Mac/.test(navigator.platform)\n const isShift = !!event.shiftKey\n const isControl = !!event.ctrlKey\n const isAlt = !!event.altKey\n const isMeta = !!event.metaKey\n const isMod = isMac\n ? isMeta\n : isControl\n\n if (\n key === null\n || key === undefined\n || (key === 'Shift' && isShift)\n || (key === 'Control' && isControl)\n || (key === 'Alt' && isAlt)\n || (key === 'Meta' && isMeta)\n || (key === 'Mod' && isMod)\n ) {\n activeMouseSelection = true\n }\n\n if (!activeMouseSelection) {\n return false\n }\n\n document.addEventListener('mouseup', () => {\n activeMouseSelection = false\n\n const { state } = view\n const { doc, selection, tr } = state\n const { $anchor, $head } = selection\n\n if ($anchor.sameParent($head)) {\n return\n }\n\n const nodeRangeSelection = NodeRangeSelection.create(doc, $anchor.pos, $head.pos, this.options.depth)\n\n tr.setSelection(nodeRangeSelection)\n view.dispatch(tr)\n }, { once: true })\n\n return false\n },\n },\n\n // when selecting some text we want to render some decorations\n // to preview a `NodeRangeSelection`\n decorations: state => {\n const { selection } = state\n const isNodeRange = isNodeRangeSelection(selection)\n\n hideTextSelection = false\n\n if (!activeMouseSelection) {\n if (!isNodeRange) {\n return null\n }\n\n hideTextSelection = true\n\n return getNodeRangeDecorations(selection.ranges as SelectionRange[])\n }\n\n const { $from, $to } = selection\n\n // selection is probably in the same node like a paragraph\n // so we don’t render decorations and show\n // a simple text selection instead\n if (!isNodeRange && $from.sameParent($to)) {\n return null\n }\n\n // try to calculate some node ranges\n const nodeRanges = getSelectionRanges($from, $to, this.options.depth)\n\n if (!nodeRanges.length) {\n return null\n }\n\n hideTextSelection = true\n\n return getNodeRangeDecorations(nodeRanges)\n },\n },\n }),\n ]\n },\n})\n"],"names":["DecorationSet","Decoration","NodeRange","SelectionRange","Selection","Extension","Plugin","PluginKey"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { Extension } from '@tiptap/core';
2
+ export interface NodeRangeOptions {
3
+ depth: number | undefined;
4
+ key: 'Shift' | 'Control' | 'Alt' | 'Meta' | 'Mod' | null | undefined;
5
+ }
6
+ export declare const NodeRange: Extension<NodeRangeOptions, any>;
7
+ //# sourceMappingURL=node-range.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-range.d.ts","sourceRoot":"","sources":["../src/node-range.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAQxC,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,GAAG,EAAE,OAAO,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;CACtE;AAED,eAAO,MAAM,SAAS,kCAiMpB,CAAA"}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@tiptap/extension-node-range",
3
+ "description": "node range extension for tiptap",
4
+ "version": "2.22.0",
5
+ "homepage": "https://tiptap.dev",
6
+ "keywords": [
7
+ "tiptap",
8
+ "tiptap extension"
9
+ ],
10
+ "license": "MIT",
11
+ "funding": {
12
+ "type": "github",
13
+ "url": "https://github.com/sponsors/ueberdosis"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/ueberdosis/tiptap",
18
+ "directory": "packages/extension-node-range"
19
+ },
20
+ "type": "module",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js",
25
+ "require": "./dist/index.cjs"
26
+ }
27
+ },
28
+ "main": "dist/index.cjs",
29
+ "module": "dist/index.js",
30
+ "umd": "dist/index.umd.js",
31
+ "types": "dist/index.d.ts",
32
+ "files": [
33
+ "src",
34
+ "dist"
35
+ ],
36
+ "peerDependencies": {
37
+ "@tiptap/core": "^2.7.0",
38
+ "@tiptap/pm": "^2.7.0"
39
+ },
40
+ "devDependencies": {
41
+ "@tiptap/core": "^2.22.0",
42
+ "@tiptap/pm": "^2.22.0"
43
+ },
44
+ "scripts": {
45
+ "clean": "rm -rf dist",
46
+ "build": "npm run clean && rollup -c"
47
+ }
48
+ }
@@ -0,0 +1,28 @@
1
+ import { Node as ProseMirrorNode } from '@tiptap/pm/model'
2
+ import { Mappable } from '@tiptap/pm/transform'
3
+
4
+ import { NodeRangeSelection } from './NodeRangeSelection.js'
5
+
6
+ export class NodeRangeBookmark {
7
+
8
+ anchor!: number
9
+
10
+ head!: number
11
+
12
+ constructor(anchor: number, head: number) {
13
+ this.anchor = anchor
14
+ this.head = head
15
+ }
16
+
17
+ map(mapping: Mappable) {
18
+ return new NodeRangeBookmark(mapping.map(this.anchor), mapping.map(this.head))
19
+ }
20
+
21
+ resolve(doc: ProseMirrorNode) {
22
+ const $anchor = doc.resolve(this.anchor)
23
+ const $head = doc.resolve(this.head)
24
+
25
+ return new NodeRangeSelection($anchor, $head)
26
+ }
27
+
28
+ }
@@ -0,0 +1,131 @@
1
+ import { Node as ProseMirrorNode, ResolvedPos } from '@tiptap/pm/model'
2
+ import { Selection } from '@tiptap/pm/state'
3
+ import { Mapping } from '@tiptap/pm/transform'
4
+
5
+ import { getSelectionRanges } from './getSelectionRanges.js'
6
+ import { NodeRangeBookmark } from './NodeRangeBookmark.js'
7
+
8
+ export class NodeRangeSelection extends Selection {
9
+
10
+ depth: number | undefined
11
+
12
+ constructor($anchor: ResolvedPos, $head: ResolvedPos, depth?: number, bias = 1) {
13
+ // if there is only a cursor we can’t calculate a direction of the selection
14
+ // that’s why we adjust the head position by 1 in the desired direction
15
+ const { doc } = $anchor
16
+ const isCursor = $anchor === $head
17
+ const isCursorAtEnd = $anchor.pos === doc.content.size && $head.pos === doc.content.size
18
+ const $correctedHead = isCursor && !isCursorAtEnd
19
+ ? doc.resolve($head.pos + (bias > 0 ? 1 : -1))
20
+ : $head
21
+ const $correctedAnchor = isCursor && isCursorAtEnd
22
+ ? doc.resolve($anchor.pos - (bias > 0 ? 1 : -1))
23
+ : $anchor
24
+
25
+ const ranges = getSelectionRanges(
26
+ $correctedAnchor.min($correctedHead),
27
+ $correctedAnchor.max($correctedHead),
28
+ depth,
29
+ )
30
+
31
+ // get the smallest range start position
32
+ // this will become the $anchor
33
+ const $rangeFrom = ($correctedHead.pos >= $anchor.pos)
34
+ ? ranges[0].$from
35
+ : ranges[ranges.length - 1].$to
36
+
37
+ // get the biggest range end position
38
+ // this will become the $head
39
+ const $rangeTo = ($correctedHead.pos >= $anchor.pos)
40
+ ? ranges[ranges.length - 1].$to
41
+ : ranges[0].$from
42
+
43
+ super($rangeFrom, $rangeTo, ranges)
44
+
45
+ this.depth = depth
46
+ }
47
+
48
+ // we can safely ignore this TypeScript error: https://github.com/Microsoft/TypeScript/issues/338
49
+ // @ts-ignore
50
+ get $to() {
51
+ return this.ranges[this.ranges.length - 1].$to
52
+ }
53
+
54
+ eq(other: Selection): boolean {
55
+ return other instanceof NodeRangeSelection
56
+ && other.$from.pos === this.$from.pos
57
+ && other.$to.pos === this.$to.pos
58
+ }
59
+
60
+ map(doc: ProseMirrorNode, mapping: Mapping): NodeRangeSelection {
61
+ const $anchor = doc.resolve(mapping.map(this.anchor))
62
+ const $head = doc.resolve(mapping.map(this.head))
63
+
64
+ return new NodeRangeSelection($anchor, $head)
65
+ }
66
+
67
+ toJSON() {
68
+ return {
69
+ type: 'nodeRange',
70
+ anchor: this.anchor,
71
+ head: this.head,
72
+ }
73
+ }
74
+
75
+ get isForwards(): boolean {
76
+ return this.head >= this.anchor
77
+ }
78
+
79
+ get isBackwards(): boolean {
80
+ return !this.isForwards
81
+ }
82
+
83
+ extendBackwards(): NodeRangeSelection {
84
+ const { doc } = this.$from
85
+
86
+ if (this.isForwards && this.ranges.length > 1) {
87
+ const ranges = this.ranges.slice(0, -1)
88
+ const $from = ranges[0].$from
89
+ const $to = ranges[ranges.length - 1].$to
90
+
91
+ return new NodeRangeSelection($from, $to, this.depth)
92
+ }
93
+
94
+ const firstRange = this.ranges[0]
95
+ const $from = doc.resolve(Math.max(0, firstRange.$from.pos - 1))
96
+
97
+ return new NodeRangeSelection(this.$anchor, $from, this.depth)
98
+ }
99
+
100
+ extendForwards(): NodeRangeSelection {
101
+ const { doc } = this.$from
102
+
103
+ if (this.isBackwards && this.ranges.length > 1) {
104
+ const ranges = this.ranges.slice(1)
105
+ const $from = ranges[0].$from
106
+ const $to = ranges[ranges.length - 1].$to
107
+
108
+ return new NodeRangeSelection($to, $from, this.depth)
109
+ }
110
+
111
+ const lastRange = this.ranges[this.ranges.length - 1]
112
+ const $to = doc.resolve(Math.min(doc.content.size, lastRange.$to.pos + 1))
113
+
114
+ return new NodeRangeSelection(this.$anchor, $to, this.depth)
115
+ }
116
+
117
+ static fromJSON(doc: ProseMirrorNode, json: any): NodeRangeSelection {
118
+ return new NodeRangeSelection(doc.resolve(json.anchor), doc.resolve(json.head))
119
+ }
120
+
121
+ static create(doc: ProseMirrorNode, anchor: number, head: number, depth?: number, bias = 1): NodeRangeSelection {
122
+ return new this(doc.resolve(anchor), doc.resolve(head), depth, bias)
123
+ }
124
+
125
+ getBookmark(): NodeRangeBookmark {
126
+ return new NodeRangeBookmark(this.anchor, this.head)
127
+ }
128
+
129
+ }
130
+
131
+ NodeRangeSelection.prototype.visible = false
@@ -0,0 +1,28 @@
1
+ import { SelectionRange } from '@tiptap/pm/state'
2
+ import { Decoration, DecorationSet } from '@tiptap/pm/view'
3
+
4
+ export function getNodeRangeDecorations(ranges: SelectionRange[]): DecorationSet {
5
+ if (!ranges.length) {
6
+ return DecorationSet.empty
7
+ }
8
+
9
+ const decorations: Decoration[] = []
10
+ const doc = ranges[0].$from.node(0)
11
+
12
+ ranges.forEach(range => {
13
+ const pos = range.$from.pos
14
+ const node = range.$from.nodeAfter
15
+
16
+ if (!node) {
17
+ return
18
+ }
19
+
20
+ decorations.push(
21
+ Decoration.node(pos, pos + node.nodeSize, {
22
+ class: 'ProseMirror-selectednoderange',
23
+ }),
24
+ )
25
+ })
26
+
27
+ return DecorationSet.create(doc, decorations)
28
+ }
@@ -0,0 +1,38 @@
1
+ import { NodeRange, ResolvedPos } from '@tiptap/pm/model'
2
+ import { SelectionRange } from '@tiptap/pm/state'
3
+
4
+ export function getSelectionRanges(
5
+ $from: ResolvedPos,
6
+ $to: ResolvedPos,
7
+ depth?: number,
8
+ ): SelectionRange[] {
9
+ const ranges: SelectionRange[] = []
10
+ const doc = $from.node(0)
11
+
12
+ // eslint-disable-next-line
13
+ depth = (typeof depth === 'number' && depth >= 0)
14
+ ? depth
15
+ : $from.sameParent($to)
16
+ ? Math.max(0, $from.sharedDepth($to.pos) - 1)
17
+ : $from.sharedDepth($to.pos)
18
+
19
+ const nodeRange = new NodeRange($from, $to, depth)
20
+ const offset = nodeRange.depth === 0
21
+ ? 0
22
+ : doc.resolve(nodeRange.start).posAtIndex(0)
23
+
24
+ nodeRange.parent.forEach((node, pos) => {
25
+ const from = offset + pos
26
+ const to = from + node.nodeSize
27
+
28
+ if (from < nodeRange.start || from >= nodeRange.end) {
29
+ return
30
+ }
31
+
32
+ const selectionRange = new SelectionRange(doc.resolve(from), doc.resolve(to))
33
+
34
+ ranges.push(selectionRange)
35
+ })
36
+
37
+ return ranges
38
+ }
@@ -0,0 +1,5 @@
1
+ import { NodeRangeSelection } from './NodeRangeSelection.js'
2
+
3
+ export function isNodeRangeSelection(value: unknown): value is NodeRangeSelection {
4
+ return value instanceof NodeRangeSelection
5
+ }