Hey is a decentralized and permissionless social media app built with Lens Protocol 馃尶
1import { LENS_NAMESPACE } from "@hey/data/constants";
2import {
3 defineBaseCommands,
4 defineBaseKeymap,
5 defineHistory,
6 defineNodeSpec,
7 union
8} from "prosekit/core";
9import { defineBold } from "prosekit/extensions/bold";
10import { defineDoc } from "prosekit/extensions/doc";
11import { defineItalic } from "prosekit/extensions/italic";
12import { defineLinkMarkRule, defineLinkSpec } from "prosekit/extensions/link";
13import type { MentionAttrs } from "prosekit/extensions/mention";
14import { defineMentionCommands } from "prosekit/extensions/mention";
15import { defineModClickPrevention } from "prosekit/extensions/mod-click-prevention";
16import { defineParagraph } from "prosekit/extensions/paragraph";
17import { definePlaceholder } from "prosekit/extensions/placeholder";
18import { defineText } from "prosekit/extensions/text";
19import { defineVirtualSelection } from "prosekit/extensions/virtual-selection";
20
21const defineAutoLink = () => {
22 return union([defineLinkSpec(), defineLinkMarkRule()]);
23};
24
25const defineMentionSpec = () => {
26 return defineNodeSpec({
27 atom: true,
28 attrs: { id: {}, kind: { default: "" }, value: {} },
29 group: "inline",
30 inline: true,
31 name: "mention",
32 parseDOM: [
33 {
34 getAttrs: (dom): MentionAttrs => {
35 const el = dom as HTMLElement;
36 const id = el.getAttribute("data-id") || "";
37 const kind = el.getAttribute("data-mention") || "";
38 const value = el.textContent?.replace(/^@(?:lens\/)?/g, "") || "";
39 return { id, kind, value };
40 },
41 tag: "span[data-mention]"
42 }
43 ],
44 toDOM(node) {
45 const attrs = node.attrs as MentionAttrs;
46 const value = attrs.value.toString();
47
48 const children =
49 attrs.kind === "account"
50 ? [
51 ["span", "@"],
52 ["span", { class: "hidden" }, LENS_NAMESPACE],
53 ["span", value]
54 ]
55 : [["span", value]];
56
57 return [
58 "span",
59 {
60 "data-id": attrs.id.toString(),
61 "data-mention": attrs.kind.toString()
62 },
63 ...children
64 ];
65 }
66 });
67};
68
69const defineMention = () => {
70 return union([defineMentionSpec(), defineMentionCommands()]);
71};
72
73export const defineEditorExtension = () => {
74 return union([
75 defineDoc(),
76 defineText(),
77 defineParagraph(),
78 defineHistory(),
79 defineBaseKeymap(),
80 defineBaseCommands(),
81 defineItalic(),
82 defineBold(),
83 defineAutoLink(),
84 defineVirtualSelection(),
85 defineMention(),
86 defineModClickPrevention(),
87 definePlaceholder({ placeholder: "What's new?!", strategy: "doc" })
88 ]);
89};
90
91export type EditorExtension = ReturnType<typeof defineEditorExtension>;