-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathtiptap-extensions.ts
More file actions
128 lines (120 loc) · 3.53 KB
/
tiptap-extensions.ts
File metadata and controls
128 lines (120 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { Extensions, textblockTypeInputRule } from "@tiptap/core";
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
import DropCursor from "@tiptap/extension-dropcursor";
import { Heading, type Level } from "@tiptap/extension-heading";
import Image from "@tiptap/extension-image";
import Link from "@tiptap/extension-link";
import Typography from "@tiptap/extension-typography";
import StarterKit from "@tiptap/starter-kit";
import css from "highlight.js/lib/languages/css";
import js from "highlight.js/lib/languages/javascript";
import ts from "highlight.js/lib/languages/typescript";
import html from "highlight.js/lib/languages/xml";
import { common, createLowlight } from "lowlight";
import { Markdown } from "tiptap-markdown";
import { AraTiptapRenderedExtension } from "./AraTiptapRenderedExtension";
// Define needed heading levels
export const displayedHeadings = [4, 5, 6] as Array<Level>;
// LowLight languages
const lowlight = createLowlight(common);
lowlight.register("html", html);
lowlight.register("css", css);
lowlight.register("js", js);
lowlight.register("ts", ts);
const extendedLink = Link.extend({
addAttributes() {
// Default attributes are useful when pasting links in editor for example.
return {
...this.parent?.(),
// "class" is always reset
class: {
default: null,
renderHTML: () => {
return {
class: null
};
}
},
// "rel" is always reset to "noopener noreferrer"
rel: {
default: null,
renderHTML: () => {
return {
rel: "noopener noreferrer"
};
}
},
// "target" is reset to:
// - null (removed) when editing
// - "_blank" when rendered
target: {
default: null,
renderHTML: () => {
return {
target: this.options.HTMLAttributes.target
};
}
}
};
}
});
const commonExtensions: Extensions = [
Heading.extend({
// prevent all marks from being applied to headings
marks: "",
// Shift heading levels when typing markdown
// Example: "## Foobar" would render a `h5`
addInputRules() {
return this.options.levels.map((level) => {
return textblockTypeInputRule({
find: new RegExp(
`^(#{${Math.min(...this.options.levels) - 3},${level - 3}})\\s$`
),
type: this.type,
getAttributes: {
level
}
});
});
}
}).configure({
levels: displayedHeadings
}),
StarterKit.configure({
codeBlock: false,
dropcursor: false,
heading: false
}),
CodeBlockLowlight.configure({ lowlight, defaultLanguage: "html" }),
Typography.configure({
openDoubleQuote: "« ",
closeDoubleQuote: " »"
}),
Markdown.configure({ linkify: true }),
Image,
DropCursor.configure({ color: "var(--dsfr-outline)", width: 3 })
];
export const tiptapEditorExtensions: Extensions = [
...commonExtensions,
extendedLink.configure({
openOnClick: false,
defaultProtocol: "https",
shouldAutoLink: () => true,
HTMLAttributes: {
// Links do not open when editing, so not "new window"…
// Advantage: no extra icon when editing
target: null
}
})
];
export const tiptapRenderedExtensions: Extensions = [
...commonExtensions,
extendedLink.configure({
openOnClick: true,
HTMLAttributes: {
// Links open in a new window when displaying the editor in read-only mode
target: "_blank"
}
}),
...[AraTiptapRenderedExtension]
];