Files
flotilla/src/lib/editor/index.ts
2024-12-17 08:42:36 -08:00

156 lines
4.7 KiB
TypeScript

import {nprofileEncode} from "nostr-tools/nip19"
import {SvelteNodeViewRenderer} from "svelte-tiptap"
import Placeholder from "@tiptap/extension-placeholder"
import Code from "@tiptap/extension-code"
import CodeBlock from "@tiptap/extension-code-block"
import Document from "@tiptap/extension-document"
import Dropcursor from "@tiptap/extension-dropcursor"
import Gapcursor from "@tiptap/extension-gapcursor"
import History from "@tiptap/extension-history"
import Paragraph from "@tiptap/extension-paragraph"
import Text from "@tiptap/extension-text"
import HardBreakExtension from "@tiptap/extension-hard-break"
import {
Bolt11Extension,
NProfileExtension,
NEventExtension,
NAddrExtension,
ImageExtension,
VideoExtension,
TagExtension,
} from "nostr-editor"
import type {StampedEvent} from "@welshman/util"
import {toNostrURI} from "@welshman/util"
import {signer, profileSearch} from "@welshman/app"
import {FileUploadExtension} from "./FileUpload"
import {createSuggestions} from "./Suggestions"
import EditMention from "./EditMention.svelte"
import EditEvent from "./EditEvent.svelte"
import EditImage from "./EditImage.svelte"
import EditBolt11 from "./EditBolt11.svelte"
import EditVideo from "./EditVideo.svelte"
import Suggestions from "./Suggestions.svelte"
import SuggestionProfile from "./SuggestionProfile.svelte"
import {asInline} from "./util"
import {getSetting} from "@app/state"
export {
createSuggestions,
EditMention,
EditEvent,
EditImage,
EditBolt11,
EditVideo,
Suggestions,
SuggestionProfile,
}
export * from "./util"
type UploadType = "nip96" | "blossom"
type EditorOptions = {
submit: () => void
getPubkeyHints: (pubkey: string) => string[]
submitOnEnter?: boolean
placeholder?: string
autofocus?: boolean
uploadType?: UploadType
defaultUploadUrl?: string
}
export const getEditorOptions = ({
submit,
getPubkeyHints,
submitOnEnter,
placeholder = "",
autofocus = false,
uploadType = getSetting("upload_type") as UploadType,
defaultUploadUrl = getSetting("upload_type") == "nip96"
? (getSetting("nip96_urls") as string[])[0] || "https://nostr.build"
: (getSetting("blossom_urls") as string[])[0] || "https://cdn.satellite.earth",
}: EditorOptions) => ({
autofocus,
content: "",
extensions: [
Code,
CodeBlock,
Document,
Dropcursor,
Gapcursor,
History,
Paragraph,
Text,
TagExtension,
Placeholder.configure({placeholder}),
HardBreakExtension.extend({
addKeyboardShortcuts() {
return {
"Shift-Enter": () => this.editor.commands.setHardBreak(),
"Mod-Enter": () => {
if (this.editor.getText().trim()) {
submit()
return true
}
return this.editor.commands.setHardBreak()
},
Enter: () => {
if (submitOnEnter && this.editor.getText().trim()) {
submit()
return true
}
return this.editor.commands.setHardBreak()
},
}
},
}),
Bolt11Extension.extend(asInline({addNodeView: () => SvelteNodeViewRenderer(EditBolt11)})),
NProfileExtension.extend({
addNodeView: () => SvelteNodeViewRenderer(EditMention),
renderText: props => toNostrURI(props.node.attrs.nprofile),
addProseMirrorPlugins() {
return [
createSuggestions({
char: "@",
name: "nprofile",
editor: this.editor,
search: profileSearch,
select: (pubkey: string, props: any) => {
const relays = getPubkeyHints(pubkey)
const nprofile = nprofileEncode({pubkey, relays})
return props.command({pubkey, nprofile, relays})
},
suggestionComponent: SuggestionProfile,
suggestionsComponent: Suggestions,
}),
]
},
}),
NEventExtension.extend(
asInline({
addNodeView: () => SvelteNodeViewRenderer(EditEvent),
renderText: (props: any) => toNostrURI(props.node.attrs.nevent),
}),
),
NAddrExtension.extend(
asInline({
addNodeView: () => SvelteNodeViewRenderer(EditEvent),
renderText: (props: any) => toNostrURI(props.node.attrs.nevent),
}),
),
ImageExtension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(EditImage)}),
).configure({defaultUploadUrl, defaultUploadType: uploadType}),
VideoExtension.extend(
asInline({addNodeView: () => SvelteNodeViewRenderer(EditVideo)}),
).configure({defaultUploadUrl, defaultUploadType: uploadType}),
FileUploadExtension.configure({
immediateUpload: true,
allowedMimeTypes: ["image/*", "video/*"],
sign: (event: StampedEvent) => signer.get()!.sign(event),
}),
],
})