@docs.plus/extension-hyperlink 1.5.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +572 -0
- package/LICENSE +21 -0
- package/README.md +135 -385
- package/dist/index.cjs +22 -712
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +392 -0
- package/dist/index.d.ts +392 -9
- package/dist/index.js +22 -707
- package/dist/index.js.map +1 -1
- package/dist/styles.css +362 -0
- package/package.json +85 -33
- package/dist/helpers/autoHyperlink.d.ts +0 -8
- package/dist/helpers/clickHandler.d.ts +0 -11
- package/dist/helpers/editHyperlink.d.ts +0 -9
- package/dist/helpers/pasteHandler.d.ts +0 -9
- package/dist/helpers/tippyHelper.d.ts +0 -29
- package/dist/hyperlink.d.ts +0 -77
- package/dist/index.umd.js +0 -713
- package/dist/index.umd.js.map +0 -1
- package/dist/modals/editeHyperlink.d.ts +0 -11
- package/dist/modals/icons.d.ts +0 -9
- package/dist/modals/previewHyperlink.d.ts +0 -11
- package/dist/modals/setHyperlink.d.ts +0 -14
- package/src/helpers/autoHyperlink.ts +0 -167
- package/src/helpers/clickHandler.ts +0 -80
- package/src/helpers/editHyperlink.ts +0 -59
- package/src/helpers/pasteHandler.ts +0 -46
- package/src/helpers/tippyHelper.ts +0 -136
- package/src/hyperlink.ts +0 -277
- package/src/index.ts +0 -17
- package/src/modals/editeHyperlink.ts +0 -99
- package/src/modals/icons.ts +0 -46
- package/src/modals/previewHyperlink.ts +0 -85
- package/src/modals/setHyperlink.ts +0 -97
package/dist/index.js
CHANGED
|
@@ -1,707 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const changes = getChangedRanges(transform);
|
|
22
|
-
|
|
23
|
-
// at first we check if we have to remove links
|
|
24
|
-
getMarksBetween(oldRange.from, oldRange.to, oldState.doc)
|
|
25
|
-
.filter((item) => item.mark.type === options.type)
|
|
26
|
-
.forEach((oldMark) => {
|
|
27
|
-
const newFrom = mapping.map(oldMark.from);
|
|
28
|
-
const newTo = mapping.map(oldMark.to);
|
|
29
|
-
const newMarks = getMarksBetween(newFrom, newTo, newState.doc).filter((item) => item.mark.type === options.type);
|
|
30
|
-
if (!newMarks.length) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
const newMark = newMarks[0];
|
|
34
|
-
const oldLinkText = oldState.doc.textBetween(oldMark.from, oldMark.to, undefined, " ");
|
|
35
|
-
const newLinkText = newState.doc.textBetween(newMark.from, newMark.to, undefined, " ");
|
|
36
|
-
const wasLink = test(oldLinkText);
|
|
37
|
-
const isLink = test(newLinkText);
|
|
38
|
-
// remove only the link, if it was a link before too
|
|
39
|
-
// because we don’t want to remove links that were set manually
|
|
40
|
-
if (wasLink && !isLink) {
|
|
41
|
-
tr.removeMark(newMark.from, newMark.to, options.type);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
// now let’s see if we can add new links
|
|
45
|
-
const nodesInChangedRanges = findChildrenInRange(newState.doc, newRange, (node) => node.isTextblock);
|
|
46
|
-
let textBlock;
|
|
47
|
-
let textBeforeWhitespace;
|
|
48
|
-
if (nodesInChangedRanges.length > 1) {
|
|
49
|
-
// Grab the first node within the changed ranges (ex. the first of two paragraphs when hitting enter)
|
|
50
|
-
textBlock = nodesInChangedRanges[0];
|
|
51
|
-
textBeforeWhitespace = newState.doc.textBetween(textBlock.pos, textBlock.pos + textBlock.node.nodeSize, undefined, " ");
|
|
52
|
-
}
|
|
53
|
-
else if (nodesInChangedRanges.length &&
|
|
54
|
-
// We want to make sure to include the block seperator argument to treat hard breaks like spaces
|
|
55
|
-
newState.doc
|
|
56
|
-
.textBetween(newRange.from, newRange.to, " ", " ")
|
|
57
|
-
.endsWith(" ")) {
|
|
58
|
-
textBlock = nodesInChangedRanges[0];
|
|
59
|
-
textBeforeWhitespace = newState.doc.textBetween(textBlock.pos, newRange.to, undefined, " ");
|
|
60
|
-
}
|
|
61
|
-
if (textBlock && textBeforeWhitespace) {
|
|
62
|
-
const wordsBeforeWhitespace = textBeforeWhitespace
|
|
63
|
-
.split(" ")
|
|
64
|
-
.filter((s) => s !== "");
|
|
65
|
-
if (wordsBeforeWhitespace.length <= 0) {
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
const lastWordBeforeSpace = wordsBeforeWhitespace[wordsBeforeWhitespace.length - 1];
|
|
69
|
-
const lastWordAndBlockOffset = textBlock.pos +
|
|
70
|
-
textBeforeWhitespace.lastIndexOf(lastWordBeforeSpace);
|
|
71
|
-
if (!lastWordBeforeSpace) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
find(lastWordBeforeSpace)
|
|
75
|
-
.filter((link) => link.isLink)
|
|
76
|
-
.filter((link) => {
|
|
77
|
-
if (options.validate) {
|
|
78
|
-
return options.validate(link.value);
|
|
79
|
-
}
|
|
80
|
-
return true;
|
|
81
|
-
})
|
|
82
|
-
// calculate link position
|
|
83
|
-
.map((link) => ({
|
|
84
|
-
...link,
|
|
85
|
-
from: lastWordAndBlockOffset + link.start + 1,
|
|
86
|
-
to: lastWordAndBlockOffset + link.end + 1,
|
|
87
|
-
}))
|
|
88
|
-
// add link mark
|
|
89
|
-
.forEach((link) => {
|
|
90
|
-
tr.addMark(link.from, link.to, options.type.create({
|
|
91
|
-
href: link.href,
|
|
92
|
-
}));
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
if (!tr.steps.length) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
return tr;
|
|
100
|
-
},
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
class Tooltip {
|
|
105
|
-
constructor(options) {
|
|
106
|
-
this.preventHide = false;
|
|
107
|
-
this.mousedownHandler = () => {
|
|
108
|
-
this.preventHide = true;
|
|
109
|
-
};
|
|
110
|
-
this.dragstartHandler = () => {
|
|
111
|
-
this.hide();
|
|
112
|
-
};
|
|
113
|
-
this.blurHandler = ({ event }) => {
|
|
114
|
-
var _a;
|
|
115
|
-
if (this.preventHide) {
|
|
116
|
-
this.preventHide = false;
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
if ((event === null || event === void 0 ? void 0 : event.relatedTarget) &&
|
|
120
|
-
((_a = this.tippyWrapper.parentNode) === null || _a === void 0 ? void 0 : _a.contains(event.relatedTarget))) {
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
this.hide();
|
|
124
|
-
};
|
|
125
|
-
this.tippyBlurHandler = (event) => {
|
|
126
|
-
this.blurHandler({ event });
|
|
127
|
-
};
|
|
128
|
-
this.editor = options.editor;
|
|
129
|
-
this.view = this.editor.view;
|
|
130
|
-
this.tippyWrapper = document.createElement("div");
|
|
131
|
-
this.tippyWrapper.addEventListener("mousedown", this.mousedownHandler, {
|
|
132
|
-
capture: true,
|
|
133
|
-
});
|
|
134
|
-
this.view.dom.addEventListener("dragstart", this.dragstartHandler);
|
|
135
|
-
this.editor.on("blur", this.blurHandler);
|
|
136
|
-
}
|
|
137
|
-
init() {
|
|
138
|
-
this.tippyWrapper.innerHTML = "";
|
|
139
|
-
return { tippyModal: this.tippyWrapper, tippyInstance: this.tippyInstance };
|
|
140
|
-
}
|
|
141
|
-
show() {
|
|
142
|
-
var _a;
|
|
143
|
-
(_a = this.tippyInstance) === null || _a === void 0 ? void 0 : _a.show();
|
|
144
|
-
return true;
|
|
145
|
-
}
|
|
146
|
-
hide() {
|
|
147
|
-
setTimeout(() => { var _a; return (_a = this.tippyInstance) === null || _a === void 0 ? void 0 : _a.hide(); });
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
createTooltip() {
|
|
151
|
-
if (!this.editor || !this.editor.options)
|
|
152
|
-
return;
|
|
153
|
-
const { element: editorElement } = this.editor.options;
|
|
154
|
-
const editorIsAttached = !!editorElement.parentElement;
|
|
155
|
-
if (this.tippyInstance || !editorIsAttached) {
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
this.tippyInstance = tippy(editorElement, {
|
|
159
|
-
duration: 0,
|
|
160
|
-
getReferenceClientRect: null,
|
|
161
|
-
content: this.tippyWrapper,
|
|
162
|
-
interactive: true,
|
|
163
|
-
trigger: "manual",
|
|
164
|
-
placement: "bottom",
|
|
165
|
-
hideOnClick: true,
|
|
166
|
-
onClickOutside: (instance, event) => {
|
|
167
|
-
this.hide();
|
|
168
|
-
},
|
|
169
|
-
onAfterUpdate: (instance, partialProps) => {
|
|
170
|
-
this.show();
|
|
171
|
-
},
|
|
172
|
-
});
|
|
173
|
-
if (this.tippyInstance.popper.firstChild) {
|
|
174
|
-
this.tippyInstance.popper.firstChild.addEventListener("blur", this.tippyBlurHandler);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
update(view, option = {}) {
|
|
178
|
-
var _a;
|
|
179
|
-
this.createTooltip();
|
|
180
|
-
option.arrow = (_a = option === null || option === void 0 ? void 0 : option.arrow) !== null && _a !== void 0 ? _a : false;
|
|
181
|
-
if (this.tippyInstance) {
|
|
182
|
-
this.tippyInstance.setProps({
|
|
183
|
-
...option,
|
|
184
|
-
getReferenceClientRect: () => {
|
|
185
|
-
const pos = view.state.selection.from;
|
|
186
|
-
// width: 0 is a hack to prevent tippy display in the wrong position
|
|
187
|
-
return { ...posToDOMRect(view, pos, pos), width: 0 };
|
|
188
|
-
},
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
return {};
|
|
192
|
-
}
|
|
193
|
-
destroyTooltip() {
|
|
194
|
-
if (this.tippyInstance) {
|
|
195
|
-
this.tippyInstance.destroy();
|
|
196
|
-
this.tippyInstance = undefined;
|
|
197
|
-
this.tippyWrapper.removeEventListener("mousedown", this.mousedownHandler, {
|
|
198
|
-
capture: true,
|
|
199
|
-
});
|
|
200
|
-
this.view.dom.removeEventListener("dragstart", this.dragstartHandler);
|
|
201
|
-
this.editor.off("blur", this.blurHandler);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
function clickHandler(options) {
|
|
207
|
-
// Create the tooltip instance
|
|
208
|
-
let tooltip = new Tooltip(options);
|
|
209
|
-
// Initialize the tooltip
|
|
210
|
-
let { tippyModal, tippyInstance } = tooltip.init();
|
|
211
|
-
return new Plugin({
|
|
212
|
-
key: new PluginKey("handleClickHyperlink"),
|
|
213
|
-
props: {
|
|
214
|
-
handleClick: (view, pos, event) => {
|
|
215
|
-
var _a, _b;
|
|
216
|
-
if (event.button !== 0)
|
|
217
|
-
return false;
|
|
218
|
-
// Get the target HTML element and its position
|
|
219
|
-
const nodeTarget = event.target;
|
|
220
|
-
const nodePos = view.posAtDOM(nodeTarget, 0);
|
|
221
|
-
// Find the closest link element to the target element
|
|
222
|
-
const link = nodeTarget === null || nodeTarget === void 0 ? void 0 : nodeTarget.closest("a");
|
|
223
|
-
// Extract attributes from the state
|
|
224
|
-
const attrs = getAttributes(view.state, options.type.name);
|
|
225
|
-
// Extract href and target attributes from the link element or the state
|
|
226
|
-
const href = (_a = link === null || link === void 0 ? void 0 : link.href) !== null && _a !== void 0 ? _a : attrs.href;
|
|
227
|
-
const target = (_b = link === null || link === void 0 ? void 0 : link.target) !== null && _b !== void 0 ? _b : attrs.target;
|
|
228
|
-
// If there is no previewHyperlink modal provided, then open the link in new window
|
|
229
|
-
if (!options.modal) {
|
|
230
|
-
if (link && href) {
|
|
231
|
-
window.open(href, target);
|
|
232
|
-
}
|
|
233
|
-
return true;
|
|
234
|
-
}
|
|
235
|
-
// if the link does not contain href attribute, hide the tooltip
|
|
236
|
-
if (!(link === null || link === void 0 ? void 0 : link.href))
|
|
237
|
-
return tooltip.hide();
|
|
238
|
-
// Create a preview of the hyperlink
|
|
239
|
-
const hyperlinkPreview = options.modal({
|
|
240
|
-
link,
|
|
241
|
-
nodePos,
|
|
242
|
-
tippy: tooltip,
|
|
243
|
-
...options,
|
|
244
|
-
});
|
|
245
|
-
// If there is no hyperlink preview, hide the modal
|
|
246
|
-
if (!hyperlinkPreview)
|
|
247
|
-
return tooltip.hide();
|
|
248
|
-
// Empty the modal and append the hyperlink preview box
|
|
249
|
-
while (tippyModal.firstChild) {
|
|
250
|
-
tippyModal.removeChild(tippyModal.firstChild);
|
|
251
|
-
}
|
|
252
|
-
tippyModal.append(hyperlinkPreview);
|
|
253
|
-
// Update the modal position
|
|
254
|
-
tooltip.update(options.editor.view);
|
|
255
|
-
return false;
|
|
256
|
-
},
|
|
257
|
-
},
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function pasteHandler(options) {
|
|
262
|
-
return new Plugin({
|
|
263
|
-
key: new PluginKey("handlePasteHyperlink"),
|
|
264
|
-
props: {
|
|
265
|
-
handlePaste: (view, event, slice) => {
|
|
266
|
-
const { state } = view;
|
|
267
|
-
const { selection } = state;
|
|
268
|
-
const { empty } = selection;
|
|
269
|
-
if (empty) {
|
|
270
|
-
return false;
|
|
271
|
-
}
|
|
272
|
-
let textContent = "";
|
|
273
|
-
slice.content.forEach((node) => {
|
|
274
|
-
textContent += node.textContent;
|
|
275
|
-
});
|
|
276
|
-
const link = find(textContent).find((item) => item.isLink && item.value === textContent);
|
|
277
|
-
if (!textContent || !link) {
|
|
278
|
-
return false;
|
|
279
|
-
}
|
|
280
|
-
options.editor.commands.setMark(options.type, {
|
|
281
|
-
href: link.href,
|
|
282
|
-
});
|
|
283
|
-
return true;
|
|
284
|
-
},
|
|
285
|
-
},
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function editHyperlink(options) {
|
|
290
|
-
var _a;
|
|
291
|
-
const { state, dispatch } = options.editor.view;
|
|
292
|
-
const { from, to } = state.selection;
|
|
293
|
-
let link = null;
|
|
294
|
-
const selectedNode = options.editor.view.domAtPos(from - 1).node;
|
|
295
|
-
const nodeName = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.nodeName;
|
|
296
|
-
if (nodeName === "#text") {
|
|
297
|
-
link = (_a = selectedNode.parentNode) === null || _a === void 0 ? void 0 : _a.closest("a");
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
300
|
-
link = selectedNode === null || selectedNode === void 0 ? void 0 : selectedNode.closest("a");
|
|
301
|
-
}
|
|
302
|
-
// If no link found and node is paragraph, try finding link in sibling/parent
|
|
303
|
-
if (!link && options.editor.view.domAtPos(from).node.nodeName === "P" && selectedNode.nextSibling)
|
|
304
|
-
link =
|
|
305
|
-
selectedNode.nextSibling ||
|
|
306
|
-
selectedNode.parentElement;
|
|
307
|
-
if (!link)
|
|
308
|
-
return true;
|
|
309
|
-
const text = options.newText || (link === null || link === void 0 ? void 0 : link.innerText);
|
|
310
|
-
// Get the position of the link in the editor view
|
|
311
|
-
const nodePos = options.editor.view.posAtDOM(link, 0);
|
|
312
|
-
const sanitizeURL = find(options.newURL || link.href)
|
|
313
|
-
.filter((link) => link.isLink)
|
|
314
|
-
.filter((link) => (options.validate ? options.validate(link.value) : true))
|
|
315
|
-
.at(0);
|
|
316
|
-
return options.editor
|
|
317
|
-
.chain()
|
|
318
|
-
.focus()
|
|
319
|
-
.command(({ tr }) => {
|
|
320
|
-
var _a;
|
|
321
|
-
tr.deleteRange(nodePos, nodePos + ((_a = ((link === null || link === void 0 ? void 0 : link.innerText) || "")) === null || _a === void 0 ? void 0 : _a.length)).replaceWith(nodePos, nodePos, options.editor.schema.text(text, [
|
|
322
|
-
options.editor.schema.marks.hyperlink.create({
|
|
323
|
-
href: sanitizeURL === null || sanitizeURL === void 0 ? void 0 : sanitizeURL.href,
|
|
324
|
-
}),
|
|
325
|
-
]));
|
|
326
|
-
return true;
|
|
327
|
-
})
|
|
328
|
-
.run();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
const Hyperlink = Mark.create({
|
|
332
|
-
name: "hyperlink",
|
|
333
|
-
priority: 1000,
|
|
334
|
-
keepOnSplit: false,
|
|
335
|
-
onCreate() {
|
|
336
|
-
this.options.protocols.forEach((protocol) => {
|
|
337
|
-
if (typeof protocol === "string") {
|
|
338
|
-
registerCustomProtocol(protocol);
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
registerCustomProtocol(protocol.scheme, protocol.optionalSlashes);
|
|
342
|
-
});
|
|
343
|
-
},
|
|
344
|
-
onDestroy() {
|
|
345
|
-
reset();
|
|
346
|
-
},
|
|
347
|
-
inclusive() {
|
|
348
|
-
return this.options.autoHyperlink;
|
|
349
|
-
},
|
|
350
|
-
addOptions() {
|
|
351
|
-
return {
|
|
352
|
-
openOnClick: true,
|
|
353
|
-
hyperlinkOnPaste: true,
|
|
354
|
-
autoHyperlink: true,
|
|
355
|
-
protocols: [],
|
|
356
|
-
HTMLAttributes: {
|
|
357
|
-
target: "_blank",
|
|
358
|
-
rel: "noopener noreferrer nofollow",
|
|
359
|
-
class: null,
|
|
360
|
-
},
|
|
361
|
-
modals: {
|
|
362
|
-
previewHyperlink: null,
|
|
363
|
-
setHyperlink: null,
|
|
364
|
-
},
|
|
365
|
-
validate: undefined,
|
|
366
|
-
};
|
|
367
|
-
},
|
|
368
|
-
addAttributes() {
|
|
369
|
-
return {
|
|
370
|
-
href: {
|
|
371
|
-
default: null,
|
|
372
|
-
},
|
|
373
|
-
target: {
|
|
374
|
-
default: this.options.HTMLAttributes.target,
|
|
375
|
-
},
|
|
376
|
-
class: {
|
|
377
|
-
default: this.options.HTMLAttributes.class,
|
|
378
|
-
},
|
|
379
|
-
};
|
|
380
|
-
},
|
|
381
|
-
parseHTML() {
|
|
382
|
-
return [{ tag: 'a[href]:not([href *= "javascript:" i])' }];
|
|
383
|
-
},
|
|
384
|
-
renderHTML({ HTMLAttributes }) {
|
|
385
|
-
return ["a", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
|
|
386
|
-
},
|
|
387
|
-
addCommands() {
|
|
388
|
-
return {
|
|
389
|
-
setHyperlink: (attributes) => ({ editor, chain }) => {
|
|
390
|
-
if (!this.options.modals.setHyperlink) {
|
|
391
|
-
return chain()
|
|
392
|
-
.setMark(this.name, attributes)
|
|
393
|
-
.setMeta("preventAutohyperlink", true)
|
|
394
|
-
.run();
|
|
395
|
-
}
|
|
396
|
-
else {
|
|
397
|
-
this.options.modals.setHyperlink({
|
|
398
|
-
editor,
|
|
399
|
-
validate: this.options.validate,
|
|
400
|
-
extentionName: this.name,
|
|
401
|
-
attributes,
|
|
402
|
-
Tooltip,
|
|
403
|
-
roundArrow,
|
|
404
|
-
});
|
|
405
|
-
return true;
|
|
406
|
-
}
|
|
407
|
-
},
|
|
408
|
-
editHyperlink: (attributes) => ({ editor }) => {
|
|
409
|
-
return editHyperlink({
|
|
410
|
-
...attributes,
|
|
411
|
-
editor,
|
|
412
|
-
validate: this.options.validate,
|
|
413
|
-
});
|
|
414
|
-
},
|
|
415
|
-
editHyperLinkText: (newText) => ({ editor }) => {
|
|
416
|
-
return editHyperlink({
|
|
417
|
-
editor,
|
|
418
|
-
newText,
|
|
419
|
-
validate: this.options.validate,
|
|
420
|
-
});
|
|
421
|
-
},
|
|
422
|
-
editHyperLinkHref: (newURL) => ({ editor }) => {
|
|
423
|
-
return editHyperlink({
|
|
424
|
-
editor,
|
|
425
|
-
validate: this.options.validate,
|
|
426
|
-
newURL,
|
|
427
|
-
});
|
|
428
|
-
},
|
|
429
|
-
unsetHyperlink: () => ({ chain }) => {
|
|
430
|
-
return chain()
|
|
431
|
-
.unsetMark(this.name, { extendEmptyMarkRange: true })
|
|
432
|
-
.setMeta("preventAutohyperlink", true)
|
|
433
|
-
.run();
|
|
434
|
-
},
|
|
435
|
-
};
|
|
436
|
-
},
|
|
437
|
-
addPasteRules() {
|
|
438
|
-
return [
|
|
439
|
-
markPasteRule({
|
|
440
|
-
find: (text) => find(text)
|
|
441
|
-
.filter((link) => {
|
|
442
|
-
if (this.options.validate) {
|
|
443
|
-
return this.options.validate(link.value);
|
|
444
|
-
}
|
|
445
|
-
return true;
|
|
446
|
-
})
|
|
447
|
-
.filter((link) => link.isLink)
|
|
448
|
-
.map((link) => ({
|
|
449
|
-
text: link.value,
|
|
450
|
-
index: link.start,
|
|
451
|
-
data: link,
|
|
452
|
-
})),
|
|
453
|
-
type: this.type,
|
|
454
|
-
getAttributes: (match) => {
|
|
455
|
-
var _a;
|
|
456
|
-
return ({
|
|
457
|
-
href: (_a = match.data) === null || _a === void 0 ? void 0 : _a.href,
|
|
458
|
-
});
|
|
459
|
-
},
|
|
460
|
-
}),
|
|
461
|
-
];
|
|
462
|
-
},
|
|
463
|
-
addProseMirrorPlugins() {
|
|
464
|
-
const plugins = [];
|
|
465
|
-
if (this.options.autoHyperlink) {
|
|
466
|
-
plugins.push(autoHyperlink({
|
|
467
|
-
type: this.type,
|
|
468
|
-
validate: this.options.validate,
|
|
469
|
-
}));
|
|
470
|
-
}
|
|
471
|
-
if (this.options.openOnClick) {
|
|
472
|
-
plugins.push(clickHandler({
|
|
473
|
-
type: this.type,
|
|
474
|
-
editor: this.editor,
|
|
475
|
-
validate: this.options.validate,
|
|
476
|
-
modal: this.options.modals.previewHyperlink,
|
|
477
|
-
}));
|
|
478
|
-
}
|
|
479
|
-
if (this.options.hyperlinkOnPaste) {
|
|
480
|
-
plugins.push(pasteHandler({
|
|
481
|
-
editor: this.editor,
|
|
482
|
-
type: this.type,
|
|
483
|
-
}));
|
|
484
|
-
}
|
|
485
|
-
return plugins;
|
|
486
|
-
},
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
const editHyperlinkHandler = (options) => {
|
|
490
|
-
var _a;
|
|
491
|
-
// Create the form
|
|
492
|
-
const form = document.createElement("form");
|
|
493
|
-
const buttonsWrapper = document.createElement("div");
|
|
494
|
-
const inputsWrapper = document.createElement("div");
|
|
495
|
-
const linkTextInput = document.createElement("input");
|
|
496
|
-
const hrefInput = document.createElement("input");
|
|
497
|
-
const applyButton = document.createElement("button");
|
|
498
|
-
buttonsWrapper.classList.add("hyperlink-edit-modal__buttons-wrapper");
|
|
499
|
-
inputsWrapper.classList.add("hyperlink-edit-modal__inputs-wrapper");
|
|
500
|
-
linkTextInput.type = "text";
|
|
501
|
-
linkTextInput.value = ((_a = options.link) === null || _a === void 0 ? void 0 : _a.innerText) || "";
|
|
502
|
-
linkTextInput.placeholder = "Enter link text";
|
|
503
|
-
hrefInput.type = "text";
|
|
504
|
-
hrefInput.value = options.link.href;
|
|
505
|
-
hrefInput.placeholder = "Enter href";
|
|
506
|
-
applyButton.type = "submit";
|
|
507
|
-
applyButton.classList.add("hyperlink-edit-modal__apply-button");
|
|
508
|
-
applyButton.innerText = "Apply";
|
|
509
|
-
buttonsWrapper.append(applyButton);
|
|
510
|
-
inputsWrapper.append(linkTextInput, hrefInput);
|
|
511
|
-
// Append to form
|
|
512
|
-
form.append(inputsWrapper, buttonsWrapper);
|
|
513
|
-
options.hyperlinkModal.innerHTML = "";
|
|
514
|
-
options.hyperlinkModal.appendChild(form);
|
|
515
|
-
hrefInput.addEventListener("keydown", () => {
|
|
516
|
-
hrefInput.style.outlineColor = " #dadce0";
|
|
517
|
-
});
|
|
518
|
-
hrefInput.addEventListener("keydown", () => {
|
|
519
|
-
linkTextInput.style.outlineColor = " #dadce0";
|
|
520
|
-
});
|
|
521
|
-
// Handle form submission
|
|
522
|
-
form.addEventListener("submit", (e) => {
|
|
523
|
-
e.preventDefault();
|
|
524
|
-
const newLinkText = linkTextInput.value;
|
|
525
|
-
const newHref = hrefInput.value;
|
|
526
|
-
if (!newHref || !newLinkText) {
|
|
527
|
-
if (!newHref)
|
|
528
|
-
hrefInput.style.outlineColor = "red";
|
|
529
|
-
if (!newLinkText)
|
|
530
|
-
linkTextInput.style.outlineColor = "red";
|
|
531
|
-
return;
|
|
532
|
-
}
|
|
533
|
-
const sanitizeURL = find(newHref)
|
|
534
|
-
.filter((link) => link.isLink)
|
|
535
|
-
.filter((link) => {
|
|
536
|
-
if (options.validate) {
|
|
537
|
-
return options.validate(link.value);
|
|
538
|
-
}
|
|
539
|
-
return true;
|
|
540
|
-
})
|
|
541
|
-
.at(0);
|
|
542
|
-
if (!(sanitizeURL === null || sanitizeURL === void 0 ? void 0 : sanitizeURL.href)) {
|
|
543
|
-
hrefInput.style.outlineColor = "red";
|
|
544
|
-
return;
|
|
545
|
-
}
|
|
546
|
-
options.editor.chain().focus().extendMarkRange("hyperlink").editHyperlink({
|
|
547
|
-
newURL: newHref,
|
|
548
|
-
newText: newLinkText,
|
|
549
|
-
});
|
|
550
|
-
options.tippy.hide();
|
|
551
|
-
});
|
|
552
|
-
// Show tooltip
|
|
553
|
-
options.tippy.update(options.editor.view, {
|
|
554
|
-
arrow: roundArrow,
|
|
555
|
-
});
|
|
556
|
-
setTimeout(() => linkTextInput.focus());
|
|
557
|
-
};
|
|
558
|
-
|
|
559
|
-
// prettier-ignore
|
|
560
|
-
const Copy = ({ size = 24, fill = 'rgb(104, 81, 255)' } = {}) => {
|
|
561
|
-
return `
|
|
562
|
-
<svg fill=${fill} viewBox="0 0 24 24" width=${size} xmlns="http://www.w3.org/2000/svg">
|
|
563
|
-
<path d="m13 20a5.006 5.006 0 0 0 5-5v-8.757a3.972 3.972 0 0 0 -1.172-2.829l-2.242-2.242a3.972 3.972 0 0 0 -2.829-1.172h-4.757a5.006 5.006 0 0 0 -5 5v10a5.006 5.006 0 0 0 5 5zm-9-5v-10a3 3 0 0 1 3-3s4.919.014 5 .024v1.976a2 2 0 0 0 2 2h1.976c.01.081.024 9 .024 9a3 3 0 0 1 -3 3h-6a3 3 0 0 1 -3-3zm18-7v11a5.006 5.006 0 0 1 -5 5h-9a1 1 0 0 1 0-2h9a3 3 0 0 0 3-3v-11a1 1 0 0 1 2 0z"/>
|
|
564
|
-
</svg>
|
|
565
|
-
`;
|
|
566
|
-
};
|
|
567
|
-
const LinkSlash = ({ size = 24, fill = "rgb(104, 81, 255)", } = {}) => {
|
|
568
|
-
return `
|
|
569
|
-
<svg fill=${fill} viewBox="0 0 24 24" width=${size} xmlns="http://www.w3.org/2000/svg">
|
|
570
|
-
<path d="M11.953,17.993c-1.557-.074-3.021-.722-4.121-1.823-.23-.23-.446-.482-.641-.748-.325-.446-.227-1.072,.22-1.397,.446-.325,1.071-.227,1.397,.219,.129,.178,.274,.349,.437,.511,.749,.75,1.744,1.19,2.802,1.24,.552,.026,.979,.495,.952,1.046-.025,.536-.468,.953-.998,.953h-.048ZM1.831,13.331C.65,14.511,0,16.081,0,17.75c0,1.669,.65,3.239,1.831,4.419,1.18,1.181,2.749,1.831,4.419,1.831s3.239-.65,4.419-1.831l1.058-1.058c.391-.391,.391-1.023,0-1.414s-1.023-.391-1.414,0l-1.058,1.058c-.803,.803-1.87,1.245-3.005,1.245s-2.202-.442-3.005-1.245-1.245-1.87-1.245-3.005,.442-2.203,1.245-3.005l3.037-3.038c.391-.391,.391-1.024,0-1.414-.391-.391-1.023-.391-1.414,0l-3.037,3.038ZM.293,1.707L22.293,23.707c.195,.195,.451,.293,.707,.293s.512-.098,.707-.293c.391-.391,.391-1.023,0-1.414l-6.581-6.581,5.043-5.043c1.181-1.18,1.831-2.75,1.831-4.419,0-1.669-.65-3.239-1.831-4.419C20.989,.65,19.42,0,17.75,0s-3.239,.65-4.419,1.831l-1.058,1.058c-.391,.391-.391,1.023,0,1.414s1.023,.391,1.414,0l1.058-1.058c.803-.803,1.87-1.245,3.005-1.245s2.202,.442,3.005,1.245,1.245,1.87,1.245,3.005-.442,2.203-1.245,3.005l-5.043,5.043-5.852-5.852c1.612-.808,3.575-.52,4.894,.798,.162,.162,.308,.333,.437,.511,.196,.269,.501,.411,.81,.411,.204,0,.41-.063,.588-.192,.446-.325,.545-.951,.22-1.397-.194-.266-.41-.518-.641-.748-2.095-2.095-5.297-2.408-7.76-.835L1.707,.293c-.391-.391-1.023-.391-1.414,0s-.391,1.023,0,1.414Z"/>
|
|
571
|
-
</svg>
|
|
572
|
-
`;
|
|
573
|
-
};
|
|
574
|
-
const Pencil = ({ size = 24, fill = "rgb(104, 81, 255)", } = {}) => {
|
|
575
|
-
return `
|
|
576
|
-
<svg fill=${fill} viewBox="0 0 24 24" width=${size} xmlns="http://www.w3.org/2000/svg">
|
|
577
|
-
<path d="M22.853,1.148a3.626,3.626,0,0,0-5.124,0L1.465,17.412A4.968,4.968,0,0,0,0,20.947V23a1,1,0,0,0,1,1H3.053a4.966,4.966,0,0,0,3.535-1.464L22.853,6.271A3.626,3.626,0,0,0,22.853,1.148ZM5.174,21.122A3.022,3.022,0,0,1,3.053,22H2V20.947a2.98,2.98,0,0,1,.879-2.121L15.222,6.483l2.3,2.3ZM21.438,4.857,18.932,7.364l-2.3-2.295,2.507-2.507a1.623,1.623,0,1,1,2.295,2.3Z"/>
|
|
578
|
-
</svg>
|
|
579
|
-
`;
|
|
580
|
-
};
|
|
581
|
-
|
|
582
|
-
function previewHyperlinkModal(options) {
|
|
583
|
-
const href = options.link.href;
|
|
584
|
-
const hyperlinkModal = document.createElement("div");
|
|
585
|
-
const removeButton = document.createElement("button");
|
|
586
|
-
const copyButton = document.createElement("button");
|
|
587
|
-
const editButton = document.createElement("button");
|
|
588
|
-
const newBubble = document.createElement("div");
|
|
589
|
-
newBubble.classList.add("hyperlink-preview-modal__metadata");
|
|
590
|
-
const hrefTitle = document.createElement("a");
|
|
591
|
-
hrefTitle.setAttribute("target", "_blank");
|
|
592
|
-
hrefTitle.setAttribute("rel", "noreferrer");
|
|
593
|
-
hrefTitle.setAttribute("href", href);
|
|
594
|
-
hrefTitle.innerText = href;
|
|
595
|
-
newBubble.append(hrefTitle);
|
|
596
|
-
fetch("/api/metadata", {
|
|
597
|
-
method: "POST",
|
|
598
|
-
headers: { "Content-Type": "application/json" },
|
|
599
|
-
body: JSON.stringify({ url: href }),
|
|
600
|
-
})
|
|
601
|
-
.then((response) => response.json())
|
|
602
|
-
.then((data) => {
|
|
603
|
-
// Create a new bubble with the title
|
|
604
|
-
hrefTitle.setAttribute("href", href);
|
|
605
|
-
hrefTitle.innerText = data.title || data["og:title"] || href;
|
|
606
|
-
newBubble.replaceChildren(hrefTitle);
|
|
607
|
-
// Create an image element if image exists in metadata
|
|
608
|
-
if (data.icon || data.image || data["og:image"]) {
|
|
609
|
-
const img = document.createElement("img");
|
|
610
|
-
img.src = data.icon || data.image || data["og:image"];
|
|
611
|
-
img.alt = data.title || data["og:title"] || "hyperlink image";
|
|
612
|
-
newBubble.appendChild(img);
|
|
613
|
-
}
|
|
614
|
-
})
|
|
615
|
-
.catch((error) => {
|
|
616
|
-
console.error("Error fetching metadata:", error);
|
|
617
|
-
});
|
|
618
|
-
hyperlinkModal.classList.add("hyperlink-preview-modal");
|
|
619
|
-
removeButton.classList.add("hyperlink-preview-modal__remove-button");
|
|
620
|
-
removeButton.innerHTML = LinkSlash();
|
|
621
|
-
editButton.classList.add("hyperlink-preview-modal__edit-button");
|
|
622
|
-
editButton.innerHTML = Pencil();
|
|
623
|
-
copyButton.classList.add("hyperlink-preview-modal__copy-button");
|
|
624
|
-
copyButton.innerHTML = Copy();
|
|
625
|
-
removeButton.addEventListener("click", () => {
|
|
626
|
-
options.tippy.hide();
|
|
627
|
-
return options.editor.chain().focus().unsetHyperlink().run();
|
|
628
|
-
});
|
|
629
|
-
editButton.addEventListener("click", () => editHyperlinkHandler({ ...options, hyperlinkModal }));
|
|
630
|
-
copyButton.addEventListener("click", () => {
|
|
631
|
-
options.tippy.hide();
|
|
632
|
-
navigator.clipboard.writeText(href);
|
|
633
|
-
});
|
|
634
|
-
hyperlinkModal.append(newBubble, copyButton, editButton, removeButton);
|
|
635
|
-
return hyperlinkModal;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
let tooltip = undefined;
|
|
639
|
-
function setHyperlinkModal(options) {
|
|
640
|
-
// Create the tooltip instance
|
|
641
|
-
if (!tooltip)
|
|
642
|
-
tooltip = new options.Tooltip(options);
|
|
643
|
-
// Initialize the tooltip
|
|
644
|
-
let { tippyModal } = tooltip.init();
|
|
645
|
-
const hyperlinkModal = document.createElement("div");
|
|
646
|
-
const buttonsWrapper = document.createElement("div");
|
|
647
|
-
const inputsWrapper = document.createElement("div");
|
|
648
|
-
hyperlinkModal.classList.add("hyperlink-set-modal");
|
|
649
|
-
buttonsWrapper.classList.add("hyperlink-set-modal__buttons-wrapper");
|
|
650
|
-
inputsWrapper.classList.add("hyperlink-set-modal__inputs-wrapper");
|
|
651
|
-
// create a form that contain url input and a button for submit
|
|
652
|
-
const form = document.createElement("form");
|
|
653
|
-
const input = document.createElement("input");
|
|
654
|
-
const button = document.createElement("button");
|
|
655
|
-
input.setAttribute("type", "text");
|
|
656
|
-
input.setAttribute("placeholder", "https://example.com");
|
|
657
|
-
button.setAttribute("type", "submit");
|
|
658
|
-
button.innerText = "Submit";
|
|
659
|
-
inputsWrapper.append(input);
|
|
660
|
-
buttonsWrapper.append(button);
|
|
661
|
-
form.append(inputsWrapper, buttonsWrapper);
|
|
662
|
-
hyperlinkModal.append(form);
|
|
663
|
-
tippyModal.innerHTML = "";
|
|
664
|
-
tippyModal.append(hyperlinkModal);
|
|
665
|
-
tooltip.update(options.editor.view, {
|
|
666
|
-
arrow: options.roundArrow,
|
|
667
|
-
});
|
|
668
|
-
// make sure
|
|
669
|
-
setTimeout(() => {
|
|
670
|
-
input.focus();
|
|
671
|
-
input.style.outlineColor = " #dadce0";
|
|
672
|
-
}, 100);
|
|
673
|
-
input.addEventListener("keydown", () => {
|
|
674
|
-
input.style.outlineColor = " #dadce0";
|
|
675
|
-
});
|
|
676
|
-
// event listenr for submit button
|
|
677
|
-
form.addEventListener("submit", (event) => {
|
|
678
|
-
event.preventDefault();
|
|
679
|
-
const url = input.value;
|
|
680
|
-
if (!url) {
|
|
681
|
-
input.style.outlineColor = "red";
|
|
682
|
-
return;
|
|
683
|
-
}
|
|
684
|
-
const sanitizeURL = find(url)
|
|
685
|
-
.filter((link) => link.isLink)
|
|
686
|
-
.filter((link) => {
|
|
687
|
-
if (options.validate) {
|
|
688
|
-
return options.validate(link.value);
|
|
689
|
-
}
|
|
690
|
-
return true;
|
|
691
|
-
})
|
|
692
|
-
.at(0);
|
|
693
|
-
if (!(sanitizeURL === null || sanitizeURL === void 0 ? void 0 : sanitizeURL.href)) {
|
|
694
|
-
input.style.outlineColor = "red";
|
|
695
|
-
return;
|
|
696
|
-
}
|
|
697
|
-
tooltip === null || tooltip === void 0 ? void 0 : tooltip.hide();
|
|
698
|
-
return options.editor
|
|
699
|
-
.chain()
|
|
700
|
-
.setMark(options.extentionName, { href: sanitizeURL.href })
|
|
701
|
-
.setMeta("preventautohyperlink", true)
|
|
702
|
-
.run();
|
|
703
|
-
});
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
export { Hyperlink, Tooltip, previewHyperlinkModal, setHyperlinkModal };
|
|
707
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import{Mark as Cr,mergeAttributes as Pr}from"@tiptap/core";import{registerCustomProtocol as Tr}from"linkifyjs";var M="hyperlink",ee="preventAutolink";var B="noopener,noreferrer";function Ue({markName:e,urls:t}){let r=(n,{commands:i,tr:s,dispatch:a})=>{if(!n.href)return!1;let[l]=t.forWrite({kind:"href",href:n.href});if(!l)return!1;let c=i.setMark(e,{...n,href:l.href});return c&&a&&s.setMeta(ee,!0),c},o=({commands:n,tr:i,dispatch:s})=>{let a=n.unsetMark(e,{extendEmptyMarkRange:!0});return a&&s&&i.setMeta(ee,!0),a};return{set:n=>i=>r(n,i),unset:()=>n=>o(n),toggle:n=>i=>i.editor.isActive(e)?o(i):r(n,i)}}import{computePosition as ct,flip as ut,offset as mt,shift as dt}from"@floating-ui/dom";var ft=400,Se="visible",N=null,te=null;function yt(){return N||(N=document.createElement("div"),N.className="floating-tooltip",N.setAttribute("role","tooltip"),document.body.append(N)),N}function Ne(){te!==null&&(clearTimeout(te),te=null)}async function gt(e,t){if(!e.isConnected)return;let r=yt();r.textContent=t;let{x:o,y:n}=await ct(e,r,{strategy:"fixed",placement:"top",middleware:[mt(6),ut(),dt({padding:8})]});r.style.left=`${o}px`,r.style.top=`${n}px`,r.classList.add(Se)}function x(){Ne(),N?.classList.remove(Se)}function Le(e,t){let r=()=>{Ne(),te=setTimeout(()=>{te=null,gt(e,t)},ft)},o=()=>{e.matches(":focus-visible")&&r()};return e.addEventListener("mouseenter",r),e.addEventListener("focus",o),e.addEventListener("mouseleave",x),e.addEventListener("blur",x),e.addEventListener("pointerdown",x),e.addEventListener("click",x),()=>{e.removeEventListener("mouseenter",r),e.removeEventListener("focus",o),e.removeEventListener("mouseleave",x),e.removeEventListener("blur",x),e.removeEventListener("pointerdown",x),e.removeEventListener("click",x),x()}}import{arrow as vt,autoUpdate as _e,computePosition as Et,flip as Lt,hide as Ht,offset as xt,shift as bt}from"@floating-ui/dom";function ht(){let e=null,t=new Set,r=()=>e===null?{kind:"idle"}:{kind:"mounted",popoverKind:e.kind,element:e.metadata.element,referenceElement:e.metadata.referenceElement},o=()=>{let n=r();t.forEach(i=>i(n))};return{adopt(n,i,s){let a=e;return e={popover:n,kind:i,metadata:s},a&&a.popover!==n&&a.popover.destroy(),o(),()=>{e?.popover===n&&(e=null,o())}},close(){if(e===null)return;let{popover:n}=e;e=null,n.hide(),o()},reposition(n,i){e?.popover.updateReference(n,i)},getState:r,subscribe(n){return t.add(n),()=>{t.delete(n)}}}}var kt=ht();function h(){return kt}var We=8,wt=9999,At=8,Ct="-5px",Pt=50,Tt=150,De={top:"bottom",bottom:"top",left:"right",right:"left"};function Fe(e){return{getBoundingClientRect:()=>{let{x:t,y:r,width:o,height:n}=e.getBoundingClientRect();return{width:o,height:n,top:r,right:t+o,bottom:r+n,left:t,x:t,y:r}},contextElement:e.contextElement||document.body}}function Mt(e){let t=e.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');if(!t.length)return[];let r=[];return t.forEach((o,n)=>{let i=s=>{if(s.key!=="Tab")return;s.preventDefault();let a=s.shiftKey?(n-1+t.length)%t.length:(n+1)%t.length;t[a].focus()};o.addEventListener("keydown",i),r.push(()=>o.removeEventListener("keydown",i))}),r}function _(e){let t=h(),{referenceElement:r,coordinates:o,content:n,placement:i="bottom-start",offset:s=We,showArrow:a=!1,className:l="",zIndex:c=wt,role:p,ariaLabel:m,ignoreOutsideClickOn:v,crossAxisShift:f=!0,onShow:H,onHide:R}=e;if(!r&&!o)throw new Error("Either referenceElement or coordinates must be provided");let L=r||Fe(o),A=v?Array.isArray(v)?[...v]:[v]:r?[r]:[],C=[],g=!1,k=!1,y=null,b=E=>E?u.contains(E)?!1:!A.some(T=>T===E||T.contains(E)):!0,u=document.createElement("div");u.className=`floating-popover ${l}`.trim(),p&&u.setAttribute("role",p),m&&u.setAttribute("aria-label",m),u.setAttribute("tabindex","-1"),u.style.zIndex=String(c),u.style.position="fixed";let P=null;a&&(P=document.createElement("div"),P.className="floating-popover-arrow",u.appendChild(P));let O=document.createElement("div");O.className="floating-popover-content",u.appendChild(O);let G=[],ae=()=>{for(;G.length;)G.pop()()},le=E=>{ae(),O.innerHTML="",O.appendChild(E),G.push(...Mt(u))};le(n);let Y=async()=>{if(!g)return;let E=[xt(s),Lt(),bt({padding:At,crossAxis:f})];P&&E.push(vt({element:P})),E.push(Ht({strategy:"referenceHidden"}));let{x:T,y:ce,placement:S,middlewareData:Q}=await Et(L,u,{placement:i,strategy:"fixed",middleware:E});if(!g)return;Object.assign(u.style,{left:`${T}px`,top:`${ce}px`}),u.style.visibility=Q.hide?.referenceHidden?"hidden":"visible";let Ee=S.split("-")[0];if(u.style.transformOrigin=De[Ee]??"center",P&&Q.arrow){let{x:Oe,y:Ie}=Q.arrow,pt=De[Ee];P.className=`floating-popover-arrow floating-popover-arrow-${Ee}`,Object.assign(P.style,{left:Oe!=null?`${Oe}px`:"",top:Ie!=null?`${Ie}px`:"",right:"",bottom:"",[pt]:Ct})}},X=null,pe=null,j=null,lt=()=>{pe&&(clearTimeout(pe),pe=null),j&&(u.removeEventListener("transitionend",j),j=null)},ve=()=>{lt(),u.remove()},J=()=>{g&&(g=!1,k=!0,y?.(),y=null,ae(),C.forEach(E=>E()),C.length=0,X?.(),X=null,u.classList.remove("visible"),j=E=>{E.target===u&&ve()},u.addEventListener("transitionend",j),pe=setTimeout(ve,Tt),R?.())},Re={element:u,show:()=>{if(g||k)return;document.body.appendChild(u),g=!0,y=_e(L,u,Y),requestAnimationFrame(()=>u.classList.add("visible")),setTimeout(()=>{if(!g)return;let T=S=>{b(S.target)&&J()},ce=S=>{if(!S.touches.length)return;let Q=document.elementFromPoint(S.touches[0].clientX,S.touches[0].clientY);b(Q)&&J()};document.addEventListener("mousedown",T,{passive:!0}),document.addEventListener("touchstart",ce,{passive:!0}),C.push(()=>document.removeEventListener("mousedown",T),()=>document.removeEventListener("touchstart",ce))},Pt);let E=T=>{T.key==="Escape"&&(T.preventDefault(),J())};u.addEventListener("keydown",E),C.push(()=>u.removeEventListener("keydown",E)),H?.()},hide:J,destroy:()=>{J(),k=!0,ve()},isVisible:()=>g,setContent:le,updateReference:(E,T)=>{E?L=E:T&&(L=Fe(T)),g?(y?.(),y=_e(L,u,Y)):Y()}};return X=t.adopt(Re,"unknown",{element:u,referenceElement:r??null}),Re}var Be="[extension-hyperlink]",D={warn:(...e)=>console.warn(Be,...e),error:(...e)=>console.error(Be,...e)};var He=async(e,t)=>{try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(e);else{let r=document.createElement("textarea");r.value=e,document.body.appendChild(r);let o=!1;try{r.select(),o=document.execCommand("copy")}finally{document.body.removeChild(r)}if(!o)return D.warn("copyToClipboard failed","execCommand returned false"),t?.(!1),!1}return t?.(!0),!0}catch(r){return D.warn("copyToClipboard failed",r),t?.(!1),!1}};var d=(e,t)=>{let r=document.createElement(e);return t&&Object.assign(r,t),r};var xe=({size:e=24,fill:t="currentColor"}={})=>`
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="${e}" viewBox="0 -960 960 960" width="${e}" fill="${t}" aria-hidden="true">
|
|
3
|
+
<path d="M360-240q-33 0-56.5-23.5T280-320v-480q0-33 23.5-56.5T360-880h360q33 0 56.5 23.5T800-800v480q0 33-23.5 56.5T720-240H360Zm0-80h360v-480H360v480ZM200-80q-33 0-56.5-23.5T120-160v-560h80v560h440v80H200Zm160-240v-480 480Z"/>
|
|
4
|
+
</svg>
|
|
5
|
+
`,be=({size:e=24,fill:t="currentColor"}={})=>`
|
|
6
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="${e}" viewBox="0 -960 960 960" width="${e}" fill="${t}" aria-hidden="true">
|
|
7
|
+
<path d="m770-302-60-62q40-11 65-42.5t25-73.5q0-50-35-85t-85-35H520v-80h160q83 0 141.5 58.5T880-480q0 57-29.5 105T770-302ZM634-440l-80-80h86v80h-6ZM792-56 56-792l56-56 736 736-56 56ZM440-280H280q-83 0-141.5-58.5T80-480q0-69 42-123t108-71l74 74h-24q-50 0-85 35t-35 85q0 50 35 85t85 35h160v80ZM320-440v-80h65l79 80H320Z"/>
|
|
8
|
+
</svg>
|
|
9
|
+
`,ue=({size:e=24,fill:t="currentColor"}={})=>`
|
|
10
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="${e}" viewBox="0 -960 960 960" width="${e}" fill="${t}" aria-hidden="true">
|
|
11
|
+
<path d="M440-280H280q-83 0-141.5-58.5T80-480q0-83 58.5-141.5T280-680h160v80H280q-50 0-85 35t-35 85q0 50 35 85t85 35h160v80ZM320-440v-80h320v80H320Zm200 160v-80h160q50 0 85-35t35-85q0-50-35-85t-85-35H520v-80h160q83 0 141.5 58.5T880-480q0 83-58.5 141.5T680-280H520Z"/>
|
|
12
|
+
</svg>
|
|
13
|
+
`,we=({size:e=24,fill:t="currentColor"}={})=>`
|
|
14
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="${e}" viewBox="0 -960 960 960" width="${e}" fill="${t}" aria-hidden="true">
|
|
15
|
+
<path d="M200-200h57l391-391-57-57-391 391v57Zm-80 80v-170l528-527q12-11 26.5-17t30.5-6q16 0 31 6t26 18l55 56q12 11 17.5 26t5.5 30q0 16-5.5 30.5T817-647L290-120H120Zm640-584-56-56 56 56Zm-141 85-28-29 57 57-29-28Z"/>
|
|
16
|
+
</svg>
|
|
17
|
+
`,$e=({size:e=24,fill:t="currentColor"}={})=>`
|
|
18
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="${e}" viewBox="0 -960 960 960" width="${e}" fill="${t}" aria-hidden="true">
|
|
19
|
+
<path d="M160-560v-80h360v80H160Zm0 160v-80h640v80H160Z"/>
|
|
20
|
+
</svg>
|
|
21
|
+
`;import{find as It}from"linkifyjs";var Rt=/^\+\d[\d\s.\-()]{4,18}\d$/,Ot=/\D/g,$=e=>{if(!Rt.test(e))return{ok:!1};let t=e.replace(Ot,"");return t.length<8||t.length>15?{ok:!1}:{ok:!0,href:`tel:+${t}`}};var Ut=/^([a-z][a-z0-9+.-]*):/i,St=/^([#?/]|\.\.?\/)/,Nt=e=>{if(e.startsWith("//"))return!0;let t=e.match(Ut);if(!t)return!1;if(e.includes("://"))return!0;let r=t[1].toLowerCase();return!(r==="localhost"||r.includes("."))},_t=e=>{if(!e.includes("@"))return{ok:!1};let t=It(e);if(t.length!==1)return{ok:!1};let r=t[0];return r.type!=="email"||r.value!==e?{ok:!1}:{ok:!0,href:r.href}},F="https",q=(e,t=F)=>{let r=e.trim();if(!r)return"";let o=$(r);if(o.ok)return o.href;let n=_t(r);return n.ok?n.href:Nt(r)||St.test(r)?r:`${t}://${r}`},Ae=(e,t=F)=>e.type==="url"?q(e.value,t):e.href;var Dt={"mailto:":{type:"email",title:"Email",category:"communication"},"tel:":{type:"phone",title:"Phone",category:"communication"},"telprompt:":{type:"phone",title:"Phone",category:"communication"},"sms:":{type:"sms",title:"SMS",category:"communication"},"facetime:":{type:"facetime",title:"FaceTime",category:"communication"},"facetime-audio:":{type:"facetime-audio",title:"FaceTime Audio",category:"communication"}},Ft={"whatsapp:":{type:"whatsapp",title:"WhatsApp",category:"social"},"tg:":{type:"telegram",title:"Telegram",category:"social"},"discord:":{type:"discord",title:"Discord",category:"social"},"skype:":{type:"skype",title:"Skype",category:"social"},"slack:":{type:"slack",title:"Slack",category:"social"},"twitter:":{type:"twitter",title:"Twitter",category:"social"},"fb:":{type:"facebook",title:"Facebook",category:"social"},"instagram:":{type:"instagram",title:"Instagram",category:"social"},"linkedin:":{type:"linkedin",title:"LinkedIn",category:"social"},"snapchat:":{type:"snapchat",title:"Snapchat",category:"social"},"reddit:":{type:"reddit",title:"Reddit",category:"social"},"tiktok:":{type:"tiktok",title:"TikTok",category:"social"}},Wt={"zoommtg:":{type:"zoom",title:"Zoom Meeting",category:"communication"},"zoomus:":{type:"zoom",title:"Zoom",category:"communication"},"msteams:":{type:"teams",title:"Microsoft Teams",category:"communication"},"webex:":{type:"webex",title:"Cisco Webex",category:"communication"}},Bt={"calshow:":{type:"calendar",title:"Calendar",category:"apple"},"x-apple-calevent:":{type:"calendar",title:"Calendar Event",category:"apple"},"x-apple-reminder:":{type:"reminders",title:"Reminders",category:"apple"},"contacts:":{type:"contacts",title:"Contacts",category:"apple"},"maps:":{type:"maps",title:"Maps",category:"apple"},"map:":{type:"maps",title:"Maps",category:"apple"},"music:":{type:"music",title:"Apple Music",category:"apple"},"videos:":{type:"apple-tv",title:"Apple TV",category:"apple"},"mobilenotes:":{type:"notes",title:"Notes",category:"apple"},"photos-redirect:":{type:"photos",title:"Photos",category:"apple"},"shortcuts:":{type:"shortcuts",title:"Shortcuts",category:"apple"},"itms-apps:":{type:"app-store",title:"App Store",category:"apple"}},$t={"github:":{type:"github",title:"GitHub",category:"development"},"gitlab:":{type:"gitlab",title:"GitLab",category:"development"},"vscode:":{type:"vscode",title:"VS Code",category:"development"},"notion:":{type:"notion",title:"Notion",category:"productivity"},"obsidian:":{type:"obsidian",title:"Obsidian",category:"productivity"},"figma:":{type:"figma",title:"Figma",category:"development"}},qt={"youtube:":{type:"youtube",title:"YouTube",category:"entertainment"},"spotify:":{type:"spotify",title:"Spotify",category:"entertainment"},"netflix:":{type:"netflix",title:"Netflix",category:"entertainment"},"twitch:":{type:"twitch",title:"Twitch",category:"entertainment"}},Kt={"amazon:":{type:"amazon",title:"Amazon",category:"shopping"},"uber:":{type:"uber",title:"Uber",category:"other"},"lyft:":{type:"lyft",title:"Lyft",category:"other"}},zt={...Dt,...Ft,...Wt,...Bt,...$t,...qt,...Kt},Vt={"wa.me":{type:"whatsapp",title:"WhatsApp",category:"social"},"t.me":{type:"telegram",title:"Telegram",category:"social"},"discord.gg":{type:"discord",title:"Discord Invite",category:"social"},"zoom.us":{type:"zoom",title:"Zoom Meeting",category:"communication"},"meet.google.com":{type:"meet",title:"Google Meet",category:"communication"},"teams.microsoft.com":{type:"teams",title:"Microsoft Teams",category:"communication"},"github.com":{type:"github",title:"GitHub",category:"development"},"gitlab.com":{type:"gitlab",title:"GitLab",category:"development"},"figma.com":{type:"figma",title:"Figma",category:"development"},"notion.so":{type:"notion",title:"Notion",category:"productivity"},"twitter.com":{type:"twitter",title:"Twitter",category:"social"},"x.com":{type:"twitter",title:"X (Twitter)",category:"social"},"instagram.com":{type:"instagram",title:"Instagram",category:"social"},"linkedin.com":{type:"linkedin",title:"LinkedIn",category:"social"},"youtube.com":{type:"youtube",title:"YouTube",category:"entertainment"},"spotify.com":{type:"spotify",title:"Spotify",category:"entertainment"}},Ce=e=>{let t=e.toLowerCase();for(let[r,o]of Object.entries(zt))if(t.startsWith(r))return o;try{let o=new URL(e).hostname.toLowerCase(),n=o.startsWith("www.")?o.slice(4):o;for(let[i,s]of Object.entries(Vt))if(n===i||n.endsWith(`.${i}`))return s}catch{}return null};import{find as Zt}from"linkifyjs";var qe=/^\s*(javascript|data|vbscript|file|blob):/i,w=e=>typeof e!="string"||e.length===0?!1:!qe.test(e.replace(/[\u0000-\u0020]+/g,"")),Gt=new Set(["http","https","ftp","ftps"]),Yt=/^\d{1,3}(\.\d{1,3}){3}$/,Xt=e=>Ce(e)!==null,jt=e=>{let t;try{t=new URL(e)}catch{return!1}let r=t.hostname;return r?r==="localhost"||Yt.test(r)||r.includes(":")?!0:r.includes("."):!1},I=(e,t)=>{let r=e.trim();if(!r||!w(r))return!1;try{if($(r).ok||Xt(e))return t?.customValidator?t.customValidator(e):!0;let o=Zt(e).find(n=>n.isLink&&(t?.customValidator?t.customValidator(n.value):!0));return o?.href?Qt(o.href)?jt(o.href):!0:!1}catch(o){return D.error("validateURL threw",o),!1}},Jt=e=>{if(!e.trim())return null;let t=e.indexOf(":");return t===-1?null:e.substring(0,t).toLowerCase()},Qt=e=>{let t=Jt(e);return t!==null&&Gt.has(t)};var er=e=>{let t=d("div",{className:"hyperlink-create-popover"}),r=d("div",{className:"buttons-wrapper"}),o=d("div",{className:"inputs-wrapper"}),n=d("form",{}),i=d("input",{type:"text",inputMode:"url",name:"hyperlink-url",placeholder:"https://example.com",autocomplete:"new-password",spellcheck:!1,value:e}),s=d("button",{type:"submit",textContent:"Apply",disabled:e.trim().length===0}),a=d("div",{className:"error-message",textContent:"Please enter a valid URL"}),l=d("div",{className:"search-icon",innerHTML:ue({size:24})});return o.append(l,i,a),r.append(s),n.append(o,r),t.append(n),{root:t,form:n,input:i,button:s,inputsWrapper:o,errorMessage:a}},tr=(e,t)=>{let{form:r,input:o,button:n,inputsWrapper:i,errorMessage:s}=e,{editor:a}=t,l=()=>{i.classList.add("error"),s.classList.add("show")},c=()=>{i.classList.remove("error"),s.classList.remove("show")},p=()=>{let m=o.value.trim().length>0;n.disabled=!m,m&&c()};o.addEventListener("input",p),o.addEventListener("paste",()=>setTimeout(p,0)),i.addEventListener("click",()=>o.focus()),o.addEventListener("keydown",m=>{m.key==="Escape"&&(m.preventDefault(),h().close(),a.commands.focus())}),r.addEventListener("submit",m=>{if(m.preventDefault(),n.disabled)return;let v=o.value.trim();if(!I(v,{customValidator:t.validate})){l();return}if(!a.can().setHyperlink({href:v})){l();return}let f=a.chain().setHyperlink({href:v});if(a.state.selection.empty&&f.insertContent({type:"text",text:v}),!f.run()){l();return}h().close(),a.commands.focus()})};function re(e){let t=er(e.attributes?.href??"");return tr(t,e),t.root}function K(e,t){let r=e.extensionManager.extensions.find(o=>o.name===M);if(!r)throw new Error(`${t}: Hyperlink extension not registered on editor`);return r.options}var U=null,z=null;function V(e,t){U={editor:e,popover:t},rr()}function rr(){z||(z=h().subscribe(e=>{U&&e.kind==="mounted"&&e.element===U.popover.element||(U=null,z?.(),z=null)}))}function Ke(e){if(!U||U.editor!==e)return;let{popover:t}=U;U=null,z?.(),z=null;let r=h(),o=r.getState();o.kind==="mounted"&&o.element===t.element&&r.close()}var or=100;function de(e,t={}){let r=K(e,"openCreateHyperlink"),o=r.popovers.createHyperlink??re,n={editor:e,validate:r.validate,extensionName:M,attributes:t},i=o(n);if(!i)return!1;let{from:s,to:a}=e.state.selection,l=null,c=_({coordinates:{getBoundingClientRect:()=>{try{let p=e.view.coordsAtPos(s),m=e.view.coordsAtPos(a);return{x:Math.min(p.left,m.left),y:p.top,width:Math.abs(m.left-p.left),height:m.bottom-p.top}}catch{return queueMicrotask(()=>c.hide()),{x:-9999,y:-9999,width:0,height:0}}},contextElement:e.view.dom},content:i,placement:"bottom",showArrow:!0,role:"dialog",ariaLabel:"Add link",onShow:()=>{let p=i.querySelector("input");p&&(l=setTimeout(()=>p.focus(),or))},onHide:()=>{l!=null&&(clearTimeout(l),l=null),x()}});return h().adopt(c,"create",{element:c.element,referenceElement:null}),V(e,c),c.show(),!0}import{getMarkRange as lr}from"@tiptap/core";import{find as nr}from"linkifyjs";var ir=/\b[a-zA-Z][a-zA-Z0-9+.-]*:[^\s]+/g,sr=/[.,;:!?)\]}]+$/,ar=e=>{let t=e.value.match(sr);if(!t)return e;let r=t[0].length;return{...e,value:e.value.slice(0,-r),href:e.href.endsWith(t[0])?e.href.slice(0,-r):e.href,end:e.end-r}},Pe=e=>{let t=[],r=nr(e).filter(n=>n.isLink);if(t.push(...r),e.includes(":"))for(let n of e.matchAll(ir)){let i=n[0],s=n.index,a=s+i.length;!r.some(c=>s>=c.start&&a<=c.end)&&I(i)&&t.push({type:"url",href:i,value:i,start:s,end:a,isLink:!0})}let o=$(e);return o.ok&&t.push({type:"phone",href:o.href,value:e,start:0,end:e.length,isLink:!0}),t.map(ar)};function ze(e={}){let t=e.defaultProtocol??F,r=e.protocols??[],o=e.isAllowedUri;return n=>w(n)?o?o(n,{defaultValidate:w,protocols:r,defaultProtocol:t}):!0:!1}function fe(e={}){let t=e.defaultProtocol??F,r=e.gate??w,o=(n,i)=>{if(!r(n))return!1;let s=i?.validate??e.validate;if(s&&!s(n))return!1;let a=e.shouldAutoLink;return!(a&&!a(n))};return{forWrite(n,i){if(n.kind==="href"){let s=n.href.trim();if(!s)return[];let a=q(s,t);if(!r(a))return[];let l=i?.validate??e.validate;return l&&!l(a)?[]:[{href:a,start:0,end:n.href.length}]}if(n.kind==="match"){let s=Ae(n.match,t);return o(s,i)?[{href:s,start:0,end:n.match.value.length}]:[]}return Pe(n.text).filter(s=>s.isLink).map(s=>({href:Ae(s,t),start:s.start,end:s.end})).filter(s=>o(s.href,i))},forRead(n){let i=typeof n=="string"?n:"";return{navigable:w(i)&&r(i)}},detect(n){return Pe(n).some(i=>i.isLink)}}}var ye=(e={})=>({tr:t,dispatch:r})=>{let{newURL:o,newText:n,title:i,image:s,validate:a,markName:l=M,urls:c=fe()}=e;if(o&&!I(o,{customValidator:a}))return!1;let p=t.doc.type.schema.marks[l];if(!p)return!1;let{from:m}=t.selection,v=t.doc.resolve(m),f=lr(v,p);if(!f)return!1;let H;try{H=t.doc.nodeAt(f.from)?.marks.find(k=>k.type===p)}catch(k){return D.warn("editHyperlink: failed to read mark at position",k),!1}if(!H)return!1;let R=H.attrs.href;if(o){let[k]=c.forWrite({kind:"href",href:o},{validate:a});if(!k)return!1;R=k.href}if(!r)return!0;let L=t.doc.textBetween(f.from,f.to),A=n||L,C=p.create({...H.attrs,href:R,...i!==void 0&&{title:i},...s!==void 0&&{image:s}});if(A===L)return t.removeMark(f.from,f.to,p),t.addMark(f.from,f.to,C),!0;let g=t.doc.nodeAt(f.from)?.marks.filter(k=>k.type!==p)??[];return t.replaceWith(f.from,f.to,t.doc.type.schema.text(A,[...g,C])),!0};function Ve(e){return{setHyperlink:e.set,unsetHyperlink:e.unset,toggleHyperlink:e.toggle,setLink:e.set,unsetLink:e.unset,toggleLink:e.toggle}}function Ze(e){let t={markName:e.markName,urls:e.urls,validate:e.validate};return{editHyperlink:r=>ye({...r,...t}),editHyperlinkText:r=>ye({newText:r,...t}),editHyperlinkHref:r=>ye({newURL:r,...t})}}function Ge(){return{openCreateHyperlinkPopover:e=>({editor:t,dispatch:r})=>r?de(t,e??{}):!0}}function Ye(e){let t=Ue({markName:e.markName,urls:e.urls});return{...Ve(t),...Ze({markName:e.markName,urls:e.urls,validate:e.options.validate}),...Ge()}}import{combineTransactionSteps as pr,findChildrenInRange as cr,getChangedRanges as ur,getMarksBetween as Xe}from"@tiptap/core";import{Plugin as mr,PluginKey as dr}from"@tiptap/pm/state";var fr=/\s$/,yr=15,gr=e=>e.split(/\s+/).filter(t=>t!=="");function je(e){let{urls:t,type:r}=e;return new mr({key:new dr("hyperlinkAutolink"),appendTransaction:(o,n,i)=>{let s=o.some(f=>f.docChanged)&&!n.doc.eq(i.doc),a=o.some(f=>f.getMeta(ee));if(!s||a)return;let{tr:l}=i,c=pr(n.doc,[...o]),{mapping:p}=c,m=ur(c),v=i.schema.marks.code??null;for(let{oldRange:f,newRange:H}of m){for(let y of Xe(f.from,f.to,n.doc).filter(b=>b.mark.type===r)){let b=p.map(y.from),u=p.map(y.to),P=Xe(b,u,i.doc).filter(X=>X.mark.type===r);if(!P.length)continue;let O=P[0],G=n.doc.textBetween(y.from,y.to,void 0," "),ae=i.doc.textBetween(O.from,O.to,void 0," "),le=t.detect(G),Y=t.detect(ae);le&&!Y&&l.removeMark(O.from,O.to,r)}let R=cr(i.doc,H,y=>y.isTextblock),L,A;if(R.length>1?(L=R[0],A=i.doc.textBetween(L.pos,L.pos+L.node.nodeSize,void 0," ")):R.length&&fr.test(i.doc.textBetween(H.from,H.to," "," "))&&(L=R[0],A=i.doc.textBetween(L.pos,H.to,void 0," ")),!L||!A)continue;let C=gr(A);if(!C.length)continue;let g=C[C.length-1],k=L.pos+A.lastIndexOf(g);t.forWrite({kind:"text",text:g}).map(y=>({href:y.href,from:k+y.start+1,to:k+y.end+1})).filter(({from:y})=>{let b=Math.max(0,y-yr),u=i.doc.textBetween(b,y," "," ");return!(u.includes(")}).filter(({from:y})=>v?!i.doc.nodeAt(y)?.marks.some(u=>u.type===v):!0).forEach(({from:y,to:b,href:u})=>{l.addMark(y,b,r.create({href:u}))})}if(l.steps.length)return l}})}import{getMarkRange as Je}from"@tiptap/core";import{Plugin as hr,PluginKey as kr}from"@tiptap/pm/state";function oe(e,t,r){if(t.isConnected)return t;if(typeof r=="number")try{let{node:s}=e.view.domAtPos(r),l=("closest"in s?s:s.parentElement)?.closest("a");if(l&&e.view.dom.contains(l))return l}catch{}let o=t.getAttribute("href"),n=t.textContent;return Array.from(e.view.dom.querySelectorAll("a")).find(s=>s.getAttribute("href")===o&&s.textContent===n)??null}function W({editor:e,link:t,nodePos:r,validate:o,isAllowedUri:n,markName:i=M}){let s=e.view,a=oe(e,t,r)??t,l=r??-1,c=null;try{l=s.posAtDOM(a,0),l>=0&&(c=s.state.doc.nodeAt(l))}catch{c=null}let m=c?.marks.find(v=>v.type.name===i)?.attrs??{href:a.getAttribute("href"),target:null,rel:null,class:null,title:null,image:null};return{editor:e,link:a,nodePos:l,attrs:m,validate:o,isAllowedUri:n}}function ne(e){let{editor:t,link:r,validate:o}=e,n=d("form",{className:"hyperlink-edit-popover"}),i=d("div",{className:"inputs-wrapper"}),s=d("div",{className:"buttons-wrapper"}),a=d("div",{className:"text-wrapper"}),l=d("div",{className:"search-icon",innerHTML:$e({size:24})}),c=d("input",{type:"text",value:r.innerText||"",placeholder:"Enter link text"}),p=d("div",{className:"error-message",textContent:"Please enter link text"}),m=d("div",{className:"href-wrapper"}),v=d("div",{className:"search-icon",innerHTML:ue({size:24})}),f=d("input",{type:"text",inputMode:"url",value:r.getAttribute("href")??"",placeholder:"Enter URL",autocomplete:"new-password",spellcheck:!1}),H=d("div",{className:"error-message",textContent:"Please enter a valid URL"}),R=d("button",{type:"button",textContent:"Back",className:"back-button"}),L=d("button",{type:"submit",textContent:"Apply",className:"apply-button"}),A=(g,k)=>{g.classList.add("error"),k.classList.add("show")},C=(g,k)=>{g.classList.remove("error"),k.classList.remove("show")};return c.addEventListener("input",()=>C(a,p)),f.addEventListener("input",()=>C(m,H)),n.addEventListener("keydown",g=>{g.key==="Escape"&&(g.preventDefault(),h().close(),t.commands.focus())}),R.addEventListener("click",()=>{if(e.onBack){e.onBack();return}Z(W({editor:t,link:r,validate:o,isAllowedUri:e.isAllowedUri,nodePos:e.nodePos,markName:e.markName}))}),n.addEventListener("submit",g=>{g.preventDefault();let k=c.value.trim(),y=f.value.trim(),b=!1;if(k||(A(a,p),b=!0),I(y,{customValidator:o})||(A(m,H),b=!0),b)return;let u=e.markName??M;if(!t.chain().focus().extendMarkRange(u).editHyperlink({newURL:y,newText:k}).run()){if(!t.isActive(u)){h().close();return}A(m,H);return}h().close()}),a.append(l,c,p),m.append(v,f,H),i.append(a,m),s.append(R,L),n.append(i,s),queueMicrotask(()=>c.focus()),n}function ge(e){let{editor:t}=e,{popovers:r}=K(t,"openEditHyperlink"),n=(r.editHyperlink??ne)(e);if(!n)return;let i=oe(t,e.link,e.nodePos),s=!1,a=_({coordinates:{getBoundingClientRect:()=>{if(i=i?oe(t,i,e.nodePos):null,!i)return s||(s=!0,queueMicrotask(()=>a.hide())),{x:-9999,y:-9999,width:0,height:0};let l=i.getBoundingClientRect();return{x:l.left,y:l.top,width:l.width,height:l.height}},contextElement:t.view.dom},content:n,placement:"bottom",showArrow:!0,role:"dialog",ariaLabel:"Edit link",onHide:x});h().adopt(a,"edit",{element:a.element,referenceElement:null}),V(t,a),a.show()}var Te=(e,t,r)=>{let o=d("button",{type:"button",className:e,innerHTML:r});return o.setAttribute("aria-label",t),Le(o,t),o};function ie(e){let{link:t,editor:r}=e,o=e.attrs.href??"",n=w(o)?o:"",i=e.isAllowedUri??w,s=d("div",{className:"hyperlink-preview-popover"}),a=Te("remove","Remove link",be()),l=Te("copy","Copy link",xe()),c=Te("edit","Edit link",we()),p=d("a",{target:"_blank",rel:"noopener noreferrer",href:n,innerText:o});return p.addEventListener("click",m=>{m.preventDefault(),n&&i(n)&&window.open(n,"_blank",B)}),a.addEventListener("click",()=>{h().close(),r.chain().focus().unsetHyperlink().run()}),c.addEventListener("click",()=>{ge({editor:r,link:t,nodePos:e.nodePos,validate:e.validate,isAllowedUri:e.isAllowedUri})}),l.addEventListener("click",()=>{He(o,m=>{m&&h().close()})}),s.append(p,l,c,a),s}function Z(e){let{editor:t}=e,{popovers:r}=K(t,"openPreviewHyperlink"),n=(r.previewHyperlink??ie)(e);if(!n)return!1;let i=_({referenceElement:e.link,content:n,placement:"bottom",showArrow:!0,role:"toolbar",onHide:x});return h().adopt(i,"preview",{element:i.element,referenceElement:e.link}),V(t,i),i.show(),!0}function se(e,t){let r=e.target;if(!r)return null;let o=r.closest("a");return!o||!t.contains(o)?null:o}function et(e,t){return t.urls.forRead(e).navigable}function Qe(e,t,r,o){let n=W({editor:r.editor,link:t,validate:r.validate,isAllowedUri:l=>r.urls.forRead(l).navigable}),i=n.attrs.href??t.getAttribute("href"),s=t.target||n.attrs.target||"_blank";if(!r.previewPopover)return!e.editable&&et(i,r)&&window.open(i,s,B),!e.editable;if(!i)return h().close(),!0;if(!Z(n))return!0;if(o!==void 0){let{from:l,to:c}=e.state.selection;if(r.options.enableClickSelection&&e.editable&&l===c){let p=Je(e.state.doc.resolve(o),r.type);p?r.editor.chain().focus(o).setTextSelection(p).run():r.editor.chain().focus(o===0?"start":o).run()}else{let p=Je(e.state.doc.resolve(o),r.type),m=!!p&&l<p.to&&c>p.from,v=l===c||!m?o:{from:l,to:c};r.editor.chain().focus(o===0?"start":o).setTextSelection(v).run()}}return!0}function tt(e){return new hr({key:new kr("hyperlinkClickHandler"),view(t){let r=i=>{i.button!==0||!se(i,t.dom)||(i.preventDefault(),i.stopPropagation())},o=i=>{if(i.button!==0)return;se(i,t.dom)&&i.preventDefault()},n=i=>{if(i.button!==1)return;let s=se(i,t.dom);if(!s)return;i.preventDefault(),i.stopPropagation();let{attrs:a}=W({editor:e.editor,link:s}),l=a.href??s.getAttribute("href");et(l,e)&&window.open(l,"_blank",B)};return t.dom.addEventListener("mousedown",r,!0),t.dom.addEventListener("click",o,!0),t.dom.addEventListener("auxclick",n,!0),{destroy(){t.dom.removeEventListener("mousedown",r,!0),t.dom.removeEventListener("click",o,!0),t.dom.removeEventListener("auxclick",n,!0)}}},props:{handleDOMEvents:{touchend:(t,r)=>{let o=se(r,t.dom);if(!o)return!1;r.preventDefault();let{clientX:n,clientY:i}=r.changedTouches[0],s=t.posAtCoords({left:n,top:i});return Qe(t,o,e,s?.pos)},click:(t,r)=>{if(r.button!==0)return!1;let o=se(r,t.dom);if(!o)return!1;r.preventDefault();let n=t.posAtCoords({left:r.clientX,top:r.clientY});return Qe(t,o,e,n?.pos)}}}})}import{InputRule as vr}from"@tiptap/core";var Er=/(\[([^\]]+)\]\(([^)]+)\))$/;function rt(e){return new vr({find:Er,handler:({state:t,range:r,match:o})=>{let[,,n,i]=o,{tr:s}=t,a=r.from,l=r.to,[c]=e.urls.forWrite({kind:"href",href:i});if(!c)return;let p=t.doc.nodeAt(a)?.marks.filter(m=>m.type!==e.type)??[];s.replaceWith(a,l,t.schema.text(n,p)),s.addMark(a,a+n.length,e.type.create({href:c.href}))}})}import{Plugin as Lr,PluginKey as Hr}from"@tiptap/pm/state";import{find as xr}from"linkifyjs";function ot(e){return new Lr({key:new Hr("hyperlinkPasteHandler"),props:{handlePaste:(t,r,o)=>{let{selection:n}=t.state;if(n.empty)return!1;let i="";o.content.forEach(l=>{i+=l.textContent});let s=xr(i).find(l=>l.isLink&&l.value===i);if(!i||!s)return!1;let[a]=e.urls.forWrite({kind:"match",match:s});return a?e.editor.chain().setHyperlink({href:a.href}).run():!1}}})}import{markPasteRule as br}from"@tiptap/core";import{find as wr}from"linkifyjs";function nt(e){return br({find:t=>wr(t).filter(r=>r.isLink).flatMap(r=>{let[o]=e.urls.forWrite({kind:"match",match:r});return o?[{text:r.value,index:r.start,data:{href:o.href}}]:[]}),type:e.type,getAttributes:t=>({href:t.data.href})})}function Ar(e){return fe({defaultProtocol:e.defaultProtocol,gate:ze({isAllowedUri:e.isAllowedUri,protocols:e.protocols,defaultProtocol:e.defaultProtocol}),validate:e.validate,shouldAutoLink:e.shouldAutoLink})}function Me({editor:e,type:t,options:r}){return{type:t,editor:e,urls:Ar(r),options:r,validate:r.validate,previewPopover:r.popovers.previewHyperlink??null}}function he(e){let t=[];return e.options.autolink&&t.push(je(e)),e.options.openOnClick&&t.push(tt(e)),e.options.linkOnPaste&&t.push(ot(e)),{inputRules:[rt(e)],pasteRules:[nt(e)],plugins:t}}var it=new Set;function st(e,t){it.has(e)||(it.add(e),Tr(e,t))}var at=Cr.create({name:M,priority:1e3,keepOnSplit:!1,inclusive:!1,markdownTokenName:"link",parseMarkdown:(e,t)=>{let r=q(e.href||"");return t.applyMark(M,t.parseInline(e.tokens??[]),{href:w(r)?r:""})},renderMarkdown:(e,t,r)=>{let o=t.renderChildren(e),n=e.attrs?.href||"",i=(w(n)?n:"").replace(/\)/g,"%29").replace(/\s/g,"%20");return`[${o}](${i})`},addStorage(){return{context:null}},onCreate(){this.options.protocols.forEach(e=>{typeof e=="string"?st(e):st(e.scheme,e.optionalSlashes)})},onDestroy(){Ke(this.editor)},addOptions(){return{openOnClick:!0,linkOnPaste:!0,autolink:!0,protocols:[],HTMLAttributes:{target:null,rel:"noopener noreferrer nofollow",class:null},popovers:{previewHyperlink:null,editHyperlink:null,createHyperlink:null},validate:void 0,defaultProtocol:F,isAllowedUri:void 0,shouldAutoLink:void 0,enableClickSelection:!1,exitable:!1}},addAttributes(){return{href:{default:null},target:{default:this.options.HTMLAttributes.target,rendered:!1},rel:{default:this.options.HTMLAttributes.rel},class:{default:this.options.HTMLAttributes.class,parseHTML:()=>null,rendered:!1},title:{default:null},image:{default:null,rendered:!1}}},parseHTML(){return[{tag:"a[href]",getAttrs:e=>{if(typeof e=="string")return!1;let t=e.getAttribute("href")??"";return w(t)?null:!1}}]},renderHTML({HTMLAttributes:e}){let t=w(e.href)?e:{...e,href:""};return["a",Pr(this.options.HTMLAttributes,t),0]},addCommands(){return Ye({markName:this.name,options:this.options,urls:ke(this).urls})},addKeyboardShortcuts(){let e={"Mod-k":()=>this.editor.commands.openCreateHyperlinkPopover()};return this.options.exitable&&(e.ArrowRight=()=>Mr(this.editor,this.type)),e},addInputRules(){return he(ke(this)).inputRules},addPasteRules(){return he(ke(this)).pasteRules},addProseMirrorPlugins(){return he(ke(this)).plugins}});function ke(e){if(e.storage.context)return e.storage.context;let t=Me({editor:e.editor,type:e.type,options:e.options});return e.storage.context=t,t}function Mr(e,t){let{state:r}=e,{selection:o,tr:n}=r;if(!o.empty)return!1;let i=o.$from,s=i.nodeAfter;return(i.nodeBefore?.marks.some(p=>p.type===t)??!1)&&(!s||!s.marks.some(p=>p.type===t))&&(n.setStoredMarks((r.storedMarks??i.marks()).filter(p=>p.type!==t)),e.view.dispatch(n)),!1}import{registerCustomProtocol as bi}from"linkifyjs";var fi=at;export{xe as Copy,qe as DANGEROUS_SCHEME_RE,We as DEFAULT_OFFSET,at as Hyperlink,be as LinkOff,we as Pencil,B as SAFE_WINDOW_FEATURES,Le as attachTooltip,W as buildPreviewOptionsFromAnchor,He as copyToClipboard,d as createHTMLElement,re as createHyperlinkPopover,_ as createPopover,fi as default,ne as editHyperlinkPopover,h as getDefaultController,Ce as getSpecialUrlInfo,x as hideTooltip,w as isSafeHref,q as normalizeHref,de as openCreateHyperlink,ge as openEditHyperlink,Z as openPreviewHyperlink,ie as previewHyperlinkPopover,bi as registerCustomProtocol,I as validateURL};
|
|
22
|
+
//# sourceMappingURL=index.js.map
|