@docs.plus/extension-hyperlink 1.3.7 → 1.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -28
- package/dist/dialogBoxs/editeHyperlink.d.ts +13 -0
- package/dist/dialogBoxs/icons.d.ts +9 -0
- package/dist/dialogBoxs/previewHyperlink.d.ts +14 -0
- package/dist/dialogBoxs/setHyperlink.d.ts +9 -0
- package/dist/helpers/clickHandler.d.ts +1 -4
- package/dist/hyperlink.d.ts +4 -4
- package/dist/index.cjs +229 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -4
- package/dist/index.js +229 -12
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +229 -13
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/dialogBoxs/editeHyperlink.ts +101 -0
- package/src/dialogBoxs/icons.ts +46 -0
- package/src/dialogBoxs/previewHyperlink.ts +89 -0
- package/src/dialogBoxs/setHyperlink.ts +96 -0
- package/src/helpers/clickHandler.ts +7 -10
- package/src/hyperlink.ts +8 -8
- package/src/index.ts +14 -4
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@docs.plus/extension-hyperlink)
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
The Link extension adds support for `<a>` tags to the editor. The extension is headless too, there is no actual UI to add, modify or delete links. The usage example below uses the native JavaScript prompt to show you how that could work.
|
|
8
|
+
The Link extension adds support for `<a>` tags to the editor. The extension is headless too, there is no actual <u>**UI**</u> to add, modify or delete links. The usage example below uses the native JavaScript prompt to show you how that could work.
|
|
9
9
|
|
|
10
10
|
In a real world application, you would probably add a more sophisticated user interface.
|
|
11
11
|
|
|
@@ -92,17 +92,17 @@ Hyperlink.configure({
|
|
|
92
92
|
})
|
|
93
93
|
````
|
|
94
94
|
|
|
95
|
-
###
|
|
95
|
+
### DialogBoxs
|
|
96
96
|
|
|
97
|
-
The
|
|
97
|
+
The DialogBox configuration option lets you incorporate an interactive user interface similar to Google Docs for **setting** and **previewing** hyperlinks. This provides users with a more intuitive and interactive experience;
|
|
98
98
|
- [Dive into the code](https://github.com/HMarzban/extension-hyperlink/blob/4f37ffa18237f10d76c316844b1c2ab20b751fe9/packages/nextjs/src/components/Tiptap.tsx#L21-L28)
|
|
99
99
|
- [Demo](https://github.com/HMarzban/extension-hyperlink#test-drive-with-our-demo-)
|
|
100
100
|
|
|
101
101
|
<details>
|
|
102
|
-
<summary>The `
|
|
102
|
+
<summary>The `previewHyperlinkDialogBox` function</summary>
|
|
103
103
|
|
|
104
104
|
```ts
|
|
105
|
-
type
|
|
105
|
+
type HyperlinkDialogBoxOptions = {
|
|
106
106
|
editor: Editor;
|
|
107
107
|
validate?: (url: string) => boolean;
|
|
108
108
|
view: EditorView;
|
|
@@ -112,9 +112,9 @@ type HyperlinkModalOptions = {
|
|
|
112
112
|
tippy: Tooltip;
|
|
113
113
|
};
|
|
114
114
|
|
|
115
|
-
const previewHyperlink(options:
|
|
115
|
+
const previewHyperlink(options: HyperlinkDialogBoxOptions): HTMLElement {
|
|
116
116
|
const href = options.link.href;
|
|
117
|
-
const
|
|
117
|
+
const hyperlinkLinkDialogBox = document.createElement("div");
|
|
118
118
|
|
|
119
119
|
const hrefTitle = document.createElement("a");
|
|
120
120
|
hrefTitle.setAttribute("target", "_blank");
|
|
@@ -122,9 +122,9 @@ const previewHyperlink(options: HyperlinkModalOptions): HTMLElement {
|
|
|
122
122
|
hrefTitle.setAttribute("href", href);
|
|
123
123
|
hrefTitle.innerText = href;
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
hyperlinkLinkDialogBox.append(hrefTitle);
|
|
126
126
|
|
|
127
|
-
return
|
|
127
|
+
return hyperlinkLinkDialogBox;
|
|
128
128
|
}
|
|
129
129
|
```
|
|
130
130
|
|
|
@@ -134,7 +134,7 @@ const previewHyperlink(options: HyperlinkModalOptions): HTMLElement {
|
|
|
134
134
|
<summary>The `setHyperlinks` function</summary>
|
|
135
135
|
|
|
136
136
|
```ts
|
|
137
|
-
type
|
|
137
|
+
type setHyperlinkDialogOptions = {
|
|
138
138
|
editor: Editor;
|
|
139
139
|
validate?: (url: string) => boolean;
|
|
140
140
|
extentionName: string;
|
|
@@ -144,18 +144,18 @@ type setHyperlinkModalOptions = {
|
|
|
144
144
|
let tooltip: Tooltip = undefined;
|
|
145
145
|
|
|
146
146
|
|
|
147
|
-
const setHyperlink(options:
|
|
147
|
+
const setHyperlink(options: setHyperlinkDialogOptions): void {
|
|
148
148
|
// Create the tooltip instance
|
|
149
149
|
if (!tooltip) tooltip = new Tooltip({ ...options, view: options.editor.view });
|
|
150
150
|
|
|
151
151
|
// Initialize the tooltip
|
|
152
152
|
let { tippyModal } = tooltip.init();
|
|
153
153
|
|
|
154
|
-
const
|
|
154
|
+
const hyperlinkLinkDialog = document.createElement("div");
|
|
155
155
|
const buttonsWrapper = document.createElement("div");
|
|
156
156
|
const inputsWrapper = document.createElement("div");
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
hyperlinkLinkDialog.classList.add("hyperlinkLinkDialog");
|
|
159
159
|
|
|
160
160
|
buttonsWrapper.classList.add("buttonsWrapper");
|
|
161
161
|
inputsWrapper.classList.add("inputsWrapper");
|
|
@@ -174,10 +174,10 @@ const setHyperlink(options: setHyperlinkModalOptions): void {
|
|
|
174
174
|
buttonsWrapper.append(button);
|
|
175
175
|
form.append(inputsWrapper, buttonsWrapper);
|
|
176
176
|
|
|
177
|
-
|
|
177
|
+
hyperlinkLinkDialog.append(form);
|
|
178
178
|
|
|
179
179
|
tippyModal.innerHTML = "";
|
|
180
|
-
tippyModal.append(
|
|
180
|
+
tippyModal.append(hyperlinkLinkDialog);
|
|
181
181
|
|
|
182
182
|
// event listenr for submit button
|
|
183
183
|
form.addEventListener("submit", (event) => {
|
|
@@ -197,17 +197,25 @@ const setHyperlink(options: setHyperlinkModalOptions): void {
|
|
|
197
197
|
</details>
|
|
198
198
|
|
|
199
199
|
````ts
|
|
200
|
+
import {
|
|
201
|
+
Hyperlink,
|
|
202
|
+
previewHyperlink,
|
|
203
|
+
setHyperlink
|
|
204
|
+
} from "@docs.plus/extension-hyperlink";
|
|
205
|
+
|
|
200
206
|
Hyperlink.configure({
|
|
201
|
-
|
|
207
|
+
dialogBoxs: {
|
|
202
208
|
previewHyperlink: (data) => {
|
|
203
|
-
return
|
|
209
|
+
return previewHyperlink(data);
|
|
204
210
|
},
|
|
205
211
|
setHyperlink: (data) => {
|
|
206
|
-
return
|
|
212
|
+
return setHyperlink(data);
|
|
207
213
|
},
|
|
208
214
|
},
|
|
209
215
|
})
|
|
210
216
|
````
|
|
217
|
+
> Note: The `previewHyperlink` and `setHyperlink` dialogs are prebuilt dialog boxes. You can use them or create your own dialog boxes. To learn how to create your own dialog boxes, please check the [source code](https://github.com/HMarzban/extension-hyperlink/tree/main/packages/extension-hyperlink/src/dialogBoxs)
|
|
218
|
+
|
|
211
219
|
|
|
212
220
|
### Removing and overriding existing html attributes
|
|
213
221
|
|
|
@@ -227,8 +235,6 @@ Hyperlink.configure({
|
|
|
227
235
|
})
|
|
228
236
|
````
|
|
229
237
|
|
|
230
|
-
|
|
231
|
-
|
|
232
238
|
### validate
|
|
233
239
|
|
|
234
240
|
A function that validates every autolinked link. If it exists, it will be called with the link href as argument. If it returns `false`, the link will be removed.
|
|
@@ -249,11 +255,12 @@ Hyperlink.configure({
|
|
|
249
255
|
These commands allow you to edit the text and href value of a hyperlink.
|
|
250
256
|
|
|
251
257
|
```js
|
|
252
|
-
this.editor.commands.editHyperLinkText('New Text')
|
|
253
|
-
this.editor.commands.editHyperLinkHref('https://new-url.com')
|
|
258
|
+
this.editor.commands.editHyperLinkText('New Text');
|
|
259
|
+
this.editor.commands.editHyperLinkHref('https://new-url.com');
|
|
254
260
|
this.editor.commands.editHyperlink({
|
|
255
|
-
newText: 'New Text',
|
|
256
|
-
|
|
261
|
+
newText: 'New Text',
|
|
262
|
+
newURL: 'https://new-url.com'
|
|
263
|
+
});
|
|
257
264
|
```
|
|
258
265
|
|
|
259
266
|
### setHyperlink()
|
|
@@ -261,9 +268,16 @@ this.editor.commands.editHyperlink({
|
|
|
261
268
|
Links the selected text.
|
|
262
269
|
|
|
263
270
|
````js
|
|
264
|
-
this.editor.commands.setHyperlink({
|
|
265
|
-
|
|
266
|
-
|
|
271
|
+
this.editor.commands.setHyperlink({
|
|
272
|
+
href: '<https://example.com>'
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
this.editor.commands.setHyperlink({
|
|
276
|
+
href: '<https://example.com>',
|
|
277
|
+
target: '_blank'
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
this.editor.commands.unsetHyperlink();
|
|
267
281
|
````
|
|
268
282
|
|
|
269
283
|
### unsetHyperlink()
|
|
@@ -271,7 +285,7 @@ this.editor.commands.unsetHyperlink()
|
|
|
271
285
|
Removes a Hyperlink.
|
|
272
286
|
|
|
273
287
|
````js
|
|
274
|
-
this.editor.commands.unsetHyperlink()
|
|
288
|
+
this.editor.commands.unsetHyperlink();
|
|
275
289
|
````
|
|
276
290
|
|
|
277
291
|
## Keyboard shortcuts
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/core";
|
|
2
|
+
import { EditorView } from "@tiptap/pm/view";
|
|
3
|
+
import Tooltip from "../helpers/tippyHelper";
|
|
4
|
+
type EditHyperlinkModalOptions = {
|
|
5
|
+
editor: Editor;
|
|
6
|
+
validate?: (url: string) => boolean;
|
|
7
|
+
view: EditorView;
|
|
8
|
+
link: HTMLAnchorElement;
|
|
9
|
+
hyperlinkLinkModal: HTMLElement;
|
|
10
|
+
tippy: Tooltip;
|
|
11
|
+
};
|
|
12
|
+
export declare const editeHyperlinkHandler: (options: EditHyperlinkModalOptions) => void;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface IconProps {
|
|
2
|
+
size?: number;
|
|
3
|
+
fill?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare const Copy: ({ size, fill }?: IconProps) => string;
|
|
6
|
+
export declare const LinkSlash: ({ size, fill, }?: IconProps) => string;
|
|
7
|
+
export declare const Pencil: ({ size, fill, }?: IconProps) => string;
|
|
8
|
+
export declare const AngleUp: ({ size, fill, }?: IconProps) => string;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/core";
|
|
2
|
+
import { EditorView } from "@tiptap/pm/view";
|
|
3
|
+
import Tooltip from "../helpers/tippyHelper";
|
|
4
|
+
type HyperlinkModalOptions = {
|
|
5
|
+
editor: Editor;
|
|
6
|
+
validate?: (url: string) => boolean;
|
|
7
|
+
view: EditorView;
|
|
8
|
+
link: HTMLAnchorElement;
|
|
9
|
+
node?: any;
|
|
10
|
+
nodePos: number;
|
|
11
|
+
tippy: Tooltip;
|
|
12
|
+
};
|
|
13
|
+
export declare function previewHyperlink(options: HyperlinkModalOptions): HTMLElement;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/core";
|
|
2
|
+
type setHyperlinkModalOptions = {
|
|
3
|
+
editor: Editor;
|
|
4
|
+
validate?: (url: string) => boolean;
|
|
5
|
+
extentionName: string;
|
|
6
|
+
attributes: Record<string, any>;
|
|
7
|
+
};
|
|
8
|
+
export declare function setHyperlink(options: setHyperlinkModalOptions): void;
|
|
9
|
+
export {};
|
|
@@ -7,10 +7,7 @@ type ClickHandlerOptions = {
|
|
|
7
7
|
editor: Editor;
|
|
8
8
|
validate?: (url: string) => boolean;
|
|
9
9
|
view: EditorView;
|
|
10
|
-
|
|
11
|
-
previewHyperlink?: ((options: any) => HTMLElement) | null;
|
|
12
|
-
setHyperlink?: ((options: any) => HTMLElement) | null;
|
|
13
|
-
};
|
|
10
|
+
dialogBox?: ((options: any) => void | HTMLElement) | null;
|
|
14
11
|
};
|
|
15
12
|
export default function clickHandler(options: ClickHandlerOptions): Plugin;
|
|
16
13
|
export {};
|
package/dist/hyperlink.d.ts
CHANGED
|
@@ -25,13 +25,13 @@ export interface HyperlinkOptions {
|
|
|
25
25
|
*/
|
|
26
26
|
HTMLAttributes: Record<string, any>;
|
|
27
27
|
/**
|
|
28
|
-
* A list of
|
|
28
|
+
* A list of dialogBoxs to be rendered.
|
|
29
29
|
* @default null
|
|
30
30
|
* @example
|
|
31
31
|
*/
|
|
32
|
-
|
|
33
|
-
previewHyperlink?: ((options: any) => HTMLElement) | null;
|
|
34
|
-
setHyperlink?: ((options: any) => HTMLElement) | null;
|
|
32
|
+
dialogBoxs: {
|
|
33
|
+
previewHyperlink?: ((options: any) => void | HTMLElement) | null;
|
|
34
|
+
setHyperlink?: ((options: any) => void | HTMLElement) | null;
|
|
35
35
|
};
|
|
36
36
|
/**
|
|
37
37
|
* A validation function that modifies link verification for the auto linker.
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var core = require('@tiptap/core');
|
|
6
4
|
var linkifyjs = require('linkifyjs');
|
|
7
5
|
var state = require('@tiptap/pm/state');
|
|
@@ -229,8 +227,8 @@ function clickHandler(options) {
|
|
|
229
227
|
// Extract href and target attributes from the link element or the state
|
|
230
228
|
const href = (_a = link === null || link === void 0 ? void 0 : link.href) !== null && _a !== void 0 ? _a : attrs.href;
|
|
231
229
|
const target = (_b = link === null || link === void 0 ? void 0 : link.target) !== null && _b !== void 0 ? _b : attrs.target;
|
|
232
|
-
// If there is no previewHyperlink
|
|
233
|
-
if (!options.
|
|
230
|
+
// If there is no previewHyperlink dialogBox provided, then open the link in new window
|
|
231
|
+
if (!options.dialogBox) {
|
|
234
232
|
if (link && href) {
|
|
235
233
|
window.open(href, target);
|
|
236
234
|
}
|
|
@@ -240,21 +238,21 @@ function clickHandler(options) {
|
|
|
240
238
|
if (!(link === null || link === void 0 ? void 0 : link.href))
|
|
241
239
|
return tooltip.hide();
|
|
242
240
|
// Create a preview of the hyperlink
|
|
243
|
-
const hyperlinkPreview = options.
|
|
241
|
+
const hyperlinkPreview = options.dialogBox({
|
|
244
242
|
link,
|
|
245
243
|
nodePos,
|
|
246
244
|
tippy: tooltip,
|
|
247
245
|
...options,
|
|
248
246
|
});
|
|
249
|
-
// If there is no hyperlink preview, hide the
|
|
247
|
+
// If there is no hyperlink preview, hide the dialogBox
|
|
250
248
|
if (!hyperlinkPreview)
|
|
251
249
|
return tooltip.hide();
|
|
252
|
-
// Empty the
|
|
250
|
+
// Empty the dialogBox and append the hyperlink preview box
|
|
253
251
|
while (tippyModal.firstChild) {
|
|
254
252
|
tippyModal.removeChild(tippyModal.firstChild);
|
|
255
253
|
}
|
|
256
254
|
tippyModal.append(hyperlinkPreview);
|
|
257
|
-
// Update the
|
|
255
|
+
// Update the dialogBox position
|
|
258
256
|
tooltip.update(options.view);
|
|
259
257
|
return false;
|
|
260
258
|
},
|
|
@@ -362,7 +360,7 @@ const Hyperlink = core.Mark.create({
|
|
|
362
360
|
rel: "noopener noreferrer nofollow",
|
|
363
361
|
class: null,
|
|
364
362
|
},
|
|
365
|
-
|
|
363
|
+
dialogBoxs: {
|
|
366
364
|
previewHyperlink: null,
|
|
367
365
|
setHyperlink: null,
|
|
368
366
|
},
|
|
@@ -391,14 +389,14 @@ const Hyperlink = core.Mark.create({
|
|
|
391
389
|
addCommands() {
|
|
392
390
|
return {
|
|
393
391
|
setHyperlink: (attributes) => ({ editor, chain }) => {
|
|
394
|
-
if (!this.options.
|
|
392
|
+
if (!this.options.dialogBoxs.setHyperlink) {
|
|
395
393
|
return chain()
|
|
396
394
|
.setMark(this.name, attributes)
|
|
397
395
|
.setMeta("preventAutohyperlink", true)
|
|
398
396
|
.run();
|
|
399
397
|
}
|
|
400
398
|
else {
|
|
401
|
-
this.options.
|
|
399
|
+
this.options.dialogBoxs.setHyperlink({
|
|
402
400
|
editor,
|
|
403
401
|
validate: this.options.validate,
|
|
404
402
|
extentionName: this.name,
|
|
@@ -476,7 +474,7 @@ const Hyperlink = core.Mark.create({
|
|
|
476
474
|
editor: this.editor,
|
|
477
475
|
validate: this.options.validate,
|
|
478
476
|
view: this.editor.view,
|
|
479
|
-
|
|
477
|
+
dialogBox: this.options.dialogBoxs.previewHyperlink,
|
|
480
478
|
}));
|
|
481
479
|
}
|
|
482
480
|
if (this.options.hyperlinkOnPaste) {
|
|
@@ -489,7 +487,225 @@ const Hyperlink = core.Mark.create({
|
|
|
489
487
|
},
|
|
490
488
|
});
|
|
491
489
|
|
|
490
|
+
const editeHyperlinkHandler = (options) => {
|
|
491
|
+
var _a;
|
|
492
|
+
// Create the form
|
|
493
|
+
const form = document.createElement("form");
|
|
494
|
+
const buttonsWrapper = document.createElement("div");
|
|
495
|
+
const inputsWrapper = document.createElement("div");
|
|
496
|
+
const linkTextInput = document.createElement("input");
|
|
497
|
+
const hrefInput = document.createElement("input");
|
|
498
|
+
const applyButton = document.createElement("button");
|
|
499
|
+
buttonsWrapper.classList.add("buttonsWrapper");
|
|
500
|
+
inputsWrapper.classList.add("inputsWrapper");
|
|
501
|
+
linkTextInput.type = "text";
|
|
502
|
+
linkTextInput.value = ((_a = options.link) === null || _a === void 0 ? void 0 : _a.innerText) || "";
|
|
503
|
+
linkTextInput.placeholder = "Enter link text";
|
|
504
|
+
hrefInput.type = "text";
|
|
505
|
+
hrefInput.value = options.link.href;
|
|
506
|
+
hrefInput.placeholder = "Enter href";
|
|
507
|
+
applyButton.type = "submit";
|
|
508
|
+
applyButton.classList.add("btn_applyModal");
|
|
509
|
+
applyButton.innerText = "Apply";
|
|
510
|
+
buttonsWrapper.append(applyButton);
|
|
511
|
+
inputsWrapper.append(linkTextInput, hrefInput);
|
|
512
|
+
// Append to form
|
|
513
|
+
form.append(inputsWrapper, buttonsWrapper);
|
|
514
|
+
options.hyperlinkLinkModal.innerHTML = "";
|
|
515
|
+
options.hyperlinkLinkModal.appendChild(form);
|
|
516
|
+
hrefInput.addEventListener("keydown", () => {
|
|
517
|
+
hrefInput.style.outlineColor = " #dadce0";
|
|
518
|
+
});
|
|
519
|
+
hrefInput.addEventListener("keydown", () => {
|
|
520
|
+
linkTextInput.style.outlineColor = " #dadce0";
|
|
521
|
+
});
|
|
522
|
+
// Handle form submission
|
|
523
|
+
form.addEventListener("submit", (e) => {
|
|
524
|
+
e.preventDefault();
|
|
525
|
+
const newLinkText = linkTextInput.value;
|
|
526
|
+
const newHref = hrefInput.value;
|
|
527
|
+
if (!newHref || !newLinkText) {
|
|
528
|
+
if (!newHref)
|
|
529
|
+
hrefInput.style.outlineColor = "red";
|
|
530
|
+
if (!newLinkText)
|
|
531
|
+
linkTextInput.style.outlineColor = "red";
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
const sanitizeURL = linkifyjs.find(newHref)
|
|
535
|
+
.filter((link) => link.isLink)
|
|
536
|
+
.filter((link) => {
|
|
537
|
+
if (options.validate) {
|
|
538
|
+
return options.validate(link.value);
|
|
539
|
+
}
|
|
540
|
+
return true;
|
|
541
|
+
})
|
|
542
|
+
.at(0);
|
|
543
|
+
if (!(sanitizeURL === null || sanitizeURL === void 0 ? void 0 : sanitizeURL.href)) {
|
|
544
|
+
hrefInput.style.outlineColor = "red";
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
options.editor.chain().focus().extendMarkRange("hyperlink").editHyperlink({
|
|
548
|
+
newURL: newHref,
|
|
549
|
+
newText: newLinkText,
|
|
550
|
+
});
|
|
551
|
+
options.tippy.hide();
|
|
552
|
+
});
|
|
553
|
+
// Show tooltip
|
|
554
|
+
options.tippy.update(options.view, {
|
|
555
|
+
arrow: tippy.roundArrow,
|
|
556
|
+
});
|
|
557
|
+
setTimeout(() => linkTextInput.focus());
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
// prettier-ignore
|
|
561
|
+
const Copy = ({ size = 24, fill = 'rgb(104, 81, 255)' } = {}) => {
|
|
562
|
+
return `
|
|
563
|
+
<svg fill=${fill} viewBox="0 0 24 24" width=${size} xmlns="http://www.w3.org/2000/svg">
|
|
564
|
+
<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"/>
|
|
565
|
+
</svg>
|
|
566
|
+
`;
|
|
567
|
+
};
|
|
568
|
+
const LinkSlash = ({ size = 24, fill = "rgb(104, 81, 255)", } = {}) => {
|
|
569
|
+
return `
|
|
570
|
+
<svg fill=${fill} viewBox="0 0 24 24" width=${size} xmlns="http://www.w3.org/2000/svg">
|
|
571
|
+
<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"/>
|
|
572
|
+
</svg>
|
|
573
|
+
`;
|
|
574
|
+
};
|
|
575
|
+
const Pencil = ({ size = 24, fill = "rgb(104, 81, 255)", } = {}) => {
|
|
576
|
+
return `
|
|
577
|
+
<svg fill=${fill} viewBox="0 0 24 24" width=${size} xmlns="http://www.w3.org/2000/svg">
|
|
578
|
+
<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"/>
|
|
579
|
+
</svg>
|
|
580
|
+
`;
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
function previewHyperlink(options) {
|
|
584
|
+
const href = options.link.href;
|
|
585
|
+
const hyperlinkLinkModal = document.createElement("div");
|
|
586
|
+
const removeButton = document.createElement("button");
|
|
587
|
+
const copyButton = document.createElement("button");
|
|
588
|
+
const editButton = document.createElement("button");
|
|
589
|
+
const newBubble = document.createElement("div");
|
|
590
|
+
newBubble.classList.add("metadata");
|
|
591
|
+
const hrefTitle = document.createElement("a");
|
|
592
|
+
hrefTitle.setAttribute("target", "_blank");
|
|
593
|
+
hrefTitle.setAttribute("rel", "noreferrer");
|
|
594
|
+
hrefTitle.setAttribute("href", href);
|
|
595
|
+
hrefTitle.innerText = href;
|
|
596
|
+
newBubble.append(hrefTitle);
|
|
597
|
+
fetch("/api/metadata", {
|
|
598
|
+
method: "POST",
|
|
599
|
+
headers: { "Content-Type": "application/json" },
|
|
600
|
+
body: JSON.stringify({ url: href }),
|
|
601
|
+
})
|
|
602
|
+
.then((response) => response.json())
|
|
603
|
+
.then((data) => {
|
|
604
|
+
// Create a new bubble with the title
|
|
605
|
+
hrefTitle.setAttribute("href", href);
|
|
606
|
+
hrefTitle.innerText = data.title || data["og:title"] || href;
|
|
607
|
+
newBubble.replaceChildren(hrefTitle);
|
|
608
|
+
// Create an image element if image exists in metadata
|
|
609
|
+
if (data.icon || data.image || data["og:image"]) {
|
|
610
|
+
const img = document.createElement("img");
|
|
611
|
+
img.src = data.icon || data.image || data["og:image"];
|
|
612
|
+
img.alt = data.title || data["og:title"] || "hyperlink image";
|
|
613
|
+
newBubble.appendChild(img);
|
|
614
|
+
}
|
|
615
|
+
})
|
|
616
|
+
.catch((error) => {
|
|
617
|
+
console.error("Error fetching metadata:", error);
|
|
618
|
+
});
|
|
619
|
+
hyperlinkLinkModal.classList.add("hyperlinkLinkModal");
|
|
620
|
+
removeButton.classList.add("remove");
|
|
621
|
+
removeButton.innerHTML = LinkSlash();
|
|
622
|
+
editButton.classList.add("edit");
|
|
623
|
+
editButton.innerHTML = Pencil();
|
|
624
|
+
copyButton.classList.add("copy");
|
|
625
|
+
copyButton.innerHTML = Copy();
|
|
626
|
+
removeButton.addEventListener("click", () => {
|
|
627
|
+
options.tippy.hide();
|
|
628
|
+
return options.editor.chain().focus().unsetHyperlink().run();
|
|
629
|
+
});
|
|
630
|
+
editButton.addEventListener("click", () => editeHyperlinkHandler({ ...options, hyperlinkLinkModal }));
|
|
631
|
+
copyButton.addEventListener("click", () => {
|
|
632
|
+
options.tippy.hide();
|
|
633
|
+
navigator.clipboard.writeText(href);
|
|
634
|
+
});
|
|
635
|
+
hyperlinkLinkModal.append(newBubble, copyButton, editButton, removeButton);
|
|
636
|
+
return hyperlinkLinkModal;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
let tooltip = undefined;
|
|
640
|
+
function setHyperlink(options) {
|
|
641
|
+
// Create the tooltip instance
|
|
642
|
+
if (!tooltip)
|
|
643
|
+
tooltip = new Tooltip({ ...options, view: options.editor.view });
|
|
644
|
+
// Initialize the tooltip
|
|
645
|
+
let { tippyModal } = tooltip.init();
|
|
646
|
+
const hyperlinkLinkModal = document.createElement("div");
|
|
647
|
+
const buttonsWrapper = document.createElement("div");
|
|
648
|
+
const inputsWrapper = document.createElement("div");
|
|
649
|
+
hyperlinkLinkModal.classList.add("hyperlinkLinkModal");
|
|
650
|
+
buttonsWrapper.classList.add("buttonsWrapper");
|
|
651
|
+
inputsWrapper.classList.add("inputsWrapper");
|
|
652
|
+
// create a form that contain url input and a button for submit
|
|
653
|
+
const form = document.createElement("form");
|
|
654
|
+
const input = document.createElement("input");
|
|
655
|
+
const button = document.createElement("button");
|
|
656
|
+
input.setAttribute("type", "text");
|
|
657
|
+
input.setAttribute("placeholder", "https://example.com");
|
|
658
|
+
button.setAttribute("type", "submit");
|
|
659
|
+
button.innerText = "Submit";
|
|
660
|
+
inputsWrapper.append(input);
|
|
661
|
+
buttonsWrapper.append(button);
|
|
662
|
+
form.append(inputsWrapper, buttonsWrapper);
|
|
663
|
+
hyperlinkLinkModal.append(form);
|
|
664
|
+
tippyModal.innerHTML = "";
|
|
665
|
+
tippyModal.append(hyperlinkLinkModal);
|
|
666
|
+
tooltip.update(options.editor.view, {
|
|
667
|
+
arrow: tippy.roundArrow,
|
|
668
|
+
});
|
|
669
|
+
// make sure
|
|
670
|
+
setTimeout(() => {
|
|
671
|
+
input.focus();
|
|
672
|
+
input.style.outlineColor = " #dadce0";
|
|
673
|
+
}, 100);
|
|
674
|
+
input.addEventListener("keydown", () => {
|
|
675
|
+
input.style.outlineColor = " #dadce0";
|
|
676
|
+
});
|
|
677
|
+
// event listenr for submit button
|
|
678
|
+
form.addEventListener("submit", (event) => {
|
|
679
|
+
event.preventDefault();
|
|
680
|
+
const url = input.value;
|
|
681
|
+
if (!url) {
|
|
682
|
+
input.style.outlineColor = "red";
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
const sanitizeURL = linkifyjs.find(url)
|
|
686
|
+
.filter((link) => link.isLink)
|
|
687
|
+
.filter((link) => {
|
|
688
|
+
if (options.validate) {
|
|
689
|
+
return options.validate(link.value);
|
|
690
|
+
}
|
|
691
|
+
return true;
|
|
692
|
+
})
|
|
693
|
+
.at(0);
|
|
694
|
+
if (!(sanitizeURL === null || sanitizeURL === void 0 ? void 0 : sanitizeURL.href)) {
|
|
695
|
+
input.style.outlineColor = "red";
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
tooltip === null || tooltip === void 0 ? void 0 : tooltip.hide();
|
|
699
|
+
return options.editor
|
|
700
|
+
.chain()
|
|
701
|
+
.setMark(options.extentionName, { href: sanitizeURL.href })
|
|
702
|
+
.setMeta("preventautohyperlink", true)
|
|
703
|
+
.run();
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
|
|
492
707
|
exports.Hyperlink = Hyperlink;
|
|
493
708
|
exports.Tooltip = Tooltip;
|
|
494
|
-
exports.
|
|
709
|
+
exports.previewHyperlink = previewHyperlink;
|
|
710
|
+
exports.setHyperlink = setHyperlink;
|
|
495
711
|
//# sourceMappingURL=index.cjs.map
|