Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/editors/slate/elements/link/editable.tsx
1698 views
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { Text } from "slate";
7
import { register } from "../register";
8
import { useProcessLinks } from "../hooks";
9
import { open_new_tab } from "@cocalc/frontend/misc";
10
const linkify = require("linkify-it")();
11
import { Link, LINK_STYLE } from "./index";
12
import { Tooltip } from "antd";
13
14
register({
15
slateType: "link",
16
17
Element: ({ attributes, children, element }) => {
18
const node = element as Link;
19
const { url, title } = node;
20
const ref = useProcessLinks([url], { doubleClick: true });
21
return (
22
<span {...attributes}>
23
<span ref={ref}>
24
<Tooltip title={url ? `Double click to open ${url}...` : undefined}>
25
<a
26
href={url}
27
title={title}
28
onDoubleClick={() => {
29
if (url) {
30
open_new_tab(url);
31
}
32
}}
33
style={LINK_STYLE}
34
>
35
{children}
36
{element.children.length == 1 &&
37
Text.isText(element.children[0]) &&
38
!element.children[0].text.trim() && (
39
<span contentEditable={false}>(blank link)</span>
40
)}
41
</a>
42
</Tooltip>
43
</span>
44
</span>
45
);
46
},
47
48
fromSlate: ({ node, children, info }) => {
49
let url = node.url ?? "";
50
if (info.references != null) {
51
// might be able to use a reference link; if so, we will.
52
for (const name in info.references) {
53
if (info.references[name].href == url) {
54
// get to use this.
55
const c = `${children}`;
56
if (c.toLowerCase() == name.toLowerCase()) {
57
return `[${c}]`;
58
}
59
return `[${children}][${name}]`;
60
}
61
}
62
}
63
64
// [my website](wstein.org "here")
65
let title = node.title ?? "";
66
if (title.length > 0) {
67
title = ` \"${title}\"`;
68
}
69
if (title == "" && children == url && linkify.test(url)) {
70
// special case where the url is easily parsed by the linkify plugin,
71
// and there is no title.
72
return url;
73
} else {
74
if (/\s/.test(url)) {
75
// See https://superuser.com/questions/1170654/how-do-i-add-a-hyperlink-with-spaces-in-it-using-markdown
76
url = `<${url}>`;
77
}
78
return `[${children}](${url}${title})`;
79
}
80
},
81
});
82
83
// This is a workaround for https://github.com/ianstormtaylor/slate/issues/3772
84
import { Editor, Element, Path, Range, Transforms } from "slate";
85
86
export const withInsertBreakHack = (editor) => {
87
const { insertBreak } = editor;
88
89
editor.insertBreak = () => {
90
let selectedElement, path;
91
try {
92
[selectedElement, path] = Editor.parent(editor, editor.selection);
93
} catch (_err) {
94
// document is empty so no need to do this workaround.
95
insertBreak();
96
return;
97
}
98
99
if (Element.isElement(selectedElement) && selectedElement.type === "link") {
100
const endPoint = Range.end(editor.selection);
101
const [selectedLeaf] = Editor.node(editor, endPoint);
102
if (
103
Text.isText(selectedLeaf) &&
104
selectedLeaf.text.length === endPoint.offset
105
) {
106
if (Range.isExpanded(editor.selection)) {
107
Transforms.delete(editor);
108
}
109
Transforms.select(editor, Path.next(path));
110
}
111
}
112
insertBreak();
113
};
114
115
return editor;
116
};
117
118