···24 'site.standard.publication',
25 'site.standard.document',
26 'xyz.statusphere.status',
27- 'community.lexicon.calendar.rsvp'
028 ],
2930 // what types of authenticated proxied requests you can make to services
···24 'site.standard.publication',
25 'site.standard.document',
26 'xyz.statusphere.status',
27+ 'community.lexicon.calendar.rsvp',
28+ 'community.lexicon.calendar.event'
29 ],
3031 // what types of authenticated proxied requests you can make to services
···1+// from https://github.com/Doist/typist/blob/main/src/extensions/rich-text/rich-text-link.ts
2+import { InputRule, markInputRule, markPasteRule, PasteRule } from '@tiptap/core';
3+import { Link } from '@tiptap/extension-link';
4+5+import type { LinkOptions } from '@tiptap/extension-link';
6+7+/**
8+ * The input regex for Markdown links with title support, and multiple quotation marks (required
9+ * in case the `Typography` extension is being included).
10+ */
11+const inputRegex = /(?:^|\s)\[([^\]]*)?\]\((\S+)(?: ["“](.+)["”])?\)$/i;
12+13+/**
14+ * The paste regex for Markdown links with title support, and multiple quotation marks (required
15+ * in case the `Typography` extension is being included).
16+ */
17+const pasteRegex = /(?:^|\s)\[([^\]]*)?\]\((\S+)(?: ["“](.+)["”])?\)/gi;
18+19+/**
20+ * Input rule built specifically for the `Link` extension, which ignores the auto-linked URL in
21+ * parentheses (e.g., `(https://doist.dev)`).
22+ *
23+ * @see https://github.com/ueberdosis/tiptap/discussions/1865
24+ */
25+function linkInputRule(config: Parameters<typeof markInputRule>[0]) {
26+ const defaultMarkInputRule = markInputRule(config);
27+28+ return new InputRule({
29+ find: config.find,
30+ handler(props) {
31+ const { tr } = props.state;
32+33+ defaultMarkInputRule.handler(props);
34+ tr.setMeta('preventAutolink', true);
35+ }
36+ });
37+}
38+39+/**
40+ * Paste rule built specifically for the `Link` extension, which ignores the auto-linked URL in
41+ * parentheses (e.g., `(https://doist.dev)`). This extension was inspired from the multiple
42+ * implementations found in a Tiptap discussion at GitHub.
43+ *
44+ * @see https://github.com/ueberdosis/tiptap/discussions/1865
45+ */
46+function linkPasteRule(config: Parameters<typeof markPasteRule>[0]) {
47+ const defaultMarkPasteRule = markPasteRule(config);
48+49+ return new PasteRule({
50+ find: config.find,
51+ handler(props) {
52+ const { tr } = props.state;
53+54+ defaultMarkPasteRule.handler(props);
55+ tr.setMeta('preventAutolink', true);
56+ }
57+ });
58+}
59+60+/**
61+ * The options available to customize the `RichTextLink` extension.
62+ */
63+type RichTextLinkOptions = LinkOptions;
64+65+/**
66+ * Custom extension that extends the built-in `Link` extension to add additional input/paste rules
67+ * for converting the Markdown link syntax (i.e. `[Doist](https://doist.com)`) into links, and also
68+ * adds support for the `title` attribute.
69+ */
70+const RichTextLink = Link.extend<RichTextLinkOptions>({
71+ inclusive: false,
72+ addOptions() {
73+ return {
74+ ...this.parent?.(),
75+ openOnClick: 'whenNotEditable' as const
76+ } as RichTextLinkOptions;
77+ },
78+ addAttributes() {
79+ return {
80+ ...this.parent?.(),
81+ title: {
82+ default: null
83+ }
84+ };
85+ },
86+ addInputRules() {
87+ return [
88+ linkInputRule({
89+ find: inputRegex,
90+ type: this.type,
91+92+ // We need to use `pop()` to remove the last capture groups from the match to
93+ // satisfy Tiptap's `markPasteRule` expectation of having the content as the last
94+ // capture group in the match (this makes the attribute order important)
95+ getAttributes(match) {
96+ return {
97+ title: match.pop()?.trim(),
98+ href: match.pop()?.trim()
99+ };
100+ }
101+ })
102+ ];
103+ },
104+ addPasteRules() {
105+ return [
106+ linkPasteRule({
107+ find: pasteRegex,
108+ type: this.type,
109+110+ // We need to use `pop()` to remove the last capture groups from the match to
111+ // satisfy Tiptap's `markInputRule` expectation of having the content as the last
112+ // capture group in the match (this makes the attribute order important)
113+ getAttributes(match) {
114+ return {
115+ title: match.pop()?.trim(),
116+ href: match.pop()?.trim()
117+ };
118+ }
119+ })
120+ ];
121+ }
122+});
123+124+export { RichTextLink };
125+126+export type { RichTextLinkOptions };