@welshman/editor 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +1 -1
  2. package/dist/components/EditBolt11.svelte +10 -0
  3. package/dist/components/EditBolt11.svelte.d.ts +20 -0
  4. package/dist/components/EditEvent.svelte +11 -0
  5. package/dist/components/EditEvent.svelte.d.ts +20 -0
  6. package/dist/components/EditMedia.svelte +10 -0
  7. package/dist/components/EditMedia.svelte.d.ts +20 -0
  8. package/dist/components/EditMention.svelte +10 -0
  9. package/dist/components/EditMention.svelte.d.ts +20 -0
  10. package/dist/components/SuggestionString.svelte +4 -0
  11. package/dist/components/SuggestionString.svelte.d.ts +18 -0
  12. package/dist/components/Suggestions.svelte +71 -0
  13. package/dist/components/Suggestions.svelte.d.ts +41 -0
  14. package/dist/components/index.d.ts +6 -0
  15. package/dist/components/index.js +6 -0
  16. package/dist/extensions/BreakOrSubmit.d.ts +8 -0
  17. package/dist/extensions/BreakOrSubmit.js +12 -0
  18. package/dist/extensions/CodeInline.d.ts +4 -0
  19. package/dist/extensions/CodeInline.js +65 -0
  20. package/dist/extensions/Welshman.d.ts +45 -0
  21. package/dist/extensions/Welshman.js +153 -0
  22. package/dist/extensions/WordCount.d.ts +2 -0
  23. package/dist/extensions/WordCount.js +15 -0
  24. package/dist/extensions/index.d.ts +4 -0
  25. package/dist/extensions/index.js +4 -0
  26. package/dist/index.css +105 -0
  27. package/dist/index.d.ts +4 -0
  28. package/dist/index.js +4 -0
  29. package/dist/plugins/TippySuggestion.d.ts +20 -0
  30. package/dist/plugins/TippySuggestion.js +98 -0
  31. package/dist/plugins/index.d.ts +1 -0
  32. package/dist/plugins/index.js +1 -0
  33. package/package.json +78 -56
  34. package/build/index.js +0 -51735
  35. package/build/index.js.map +0 -1
  36. package/build/tsconfig.tsbuildinfo +0 -1
package/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # @welshman/editor [![version](https://badgen.net/npm/v/@welshman/editor)](https://npmjs.com/package/@welshman/editor)
2
2
 
3
- A good batteries-included configuration of nostr-editor for svelte apps.
3
+ A batteries-included nostr-editor.
@@ -0,0 +1,10 @@
1
+ <script>import { NodeViewWrapper } from "svelte-tiptap";
2
+ export let node;
3
+ export let selected;
4
+ </script>
5
+
6
+ <NodeViewWrapper as="span">
7
+ <button class="tiptap-object {selected ? 'tiptap-active' : ''}">
8
+ {node.attrs.lnbc.slice(0, 16)}...
9
+ </button>
10
+ </NodeViewWrapper>
@@ -0,0 +1,20 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { NodeViewProps } from "@tiptap/core";
3
+ declare const __propDef: {
4
+ props: {
5
+ node: NodeViewProps["node"];
6
+ selected: NodeViewProps["selected"];
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {};
12
+ exports?: {} | undefined;
13
+ bindings?: string | undefined;
14
+ };
15
+ export type EditBolt11Props = typeof __propDef.props;
16
+ export type EditBolt11Events = typeof __propDef.events;
17
+ export type EditBolt11Slots = typeof __propDef.slots;
18
+ export default class EditBolt11 extends SvelteComponent<EditBolt11Props, EditBolt11Events, EditBolt11Slots> {
19
+ }
20
+ export {};
@@ -0,0 +1,11 @@
1
+ <script>import { fromNostrURI } from "@welshman/util";
2
+ import { NodeViewWrapper } from "svelte-tiptap";
3
+ export let node;
4
+ export let selected;
5
+ </script>
6
+
7
+ <NodeViewWrapper as="span">
8
+ <button class="tiptap-object {selected ? 'tiptap-active' : ''}">
9
+ {fromNostrURI(node.attrs.nevent).slice(0, 16)}...
10
+ </button>
11
+ </NodeViewWrapper>
@@ -0,0 +1,20 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { NodeViewProps } from "@tiptap/core";
3
+ declare const __propDef: {
4
+ props: {
5
+ node: NodeViewProps["node"];
6
+ selected: NodeViewProps["selected"];
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {};
12
+ exports?: {} | undefined;
13
+ bindings?: string | undefined;
14
+ };
15
+ export type EditEventProps = typeof __propDef.props;
16
+ export type EditEventEvents = typeof __propDef.events;
17
+ export type EditEventSlots = typeof __propDef.slots;
18
+ export default class EditEvent extends SvelteComponent<EditEventProps, EditEventEvents, EditEventSlots> {
19
+ }
20
+ export {};
@@ -0,0 +1,10 @@
1
+ <script>import { NodeViewWrapper } from "svelte-tiptap";
2
+ export let node;
3
+ export let selected;
4
+ $: selectedClass = selected ? "tiptap-active" : "";
5
+ $: uploadingClass = node.attrs.uploading ? "tiptap-uploading" : "";
6
+ </script>
7
+
8
+ <NodeViewWrapper as="span" class="tiptap-object {selectedClass} {uploadingClass}">
9
+ {node.attrs.file?.name || node.attrs.src}
10
+ </NodeViewWrapper>
@@ -0,0 +1,20 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { NodeViewProps } from "@tiptap/core";
3
+ declare const __propDef: {
4
+ props: {
5
+ node: NodeViewProps["node"];
6
+ selected: NodeViewProps["selected"];
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {};
12
+ exports?: {} | undefined;
13
+ bindings?: string | undefined;
14
+ };
15
+ export type EditMediaProps = typeof __propDef.props;
16
+ export type EditMediaEvents = typeof __propDef.events;
17
+ export type EditMediaSlots = typeof __propDef.slots;
18
+ export default class EditMedia extends SvelteComponent<EditMediaProps, EditMediaEvents, EditMediaSlots> {
19
+ }
20
+ export {};
@@ -0,0 +1,10 @@
1
+ <script>import { NodeViewWrapper } from "svelte-tiptap";
2
+ export let node;
3
+ export let selected;
4
+ </script>
5
+
6
+ <NodeViewWrapper as="span">
7
+ <button class="tiptap-object {selected ? 'tiptap-active' : ''}">
8
+ @{node.attrs.nprofile.slice(0, 16)}...
9
+ </button>
10
+ </NodeViewWrapper>
@@ -0,0 +1,20 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { NodeViewProps } from "@tiptap/core";
3
+ declare const __propDef: {
4
+ props: {
5
+ node: NodeViewProps["node"];
6
+ selected: NodeViewProps["selected"];
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {};
12
+ exports?: {} | undefined;
13
+ bindings?: string | undefined;
14
+ };
15
+ export type EditMentionProps = typeof __propDef.props;
16
+ export type EditMentionEvents = typeof __propDef.events;
17
+ export type EditMentionSlots = typeof __propDef.slots;
18
+ export default class EditMention extends SvelteComponent<EditMentionProps, EditMentionEvents, EditMentionSlots> {
19
+ }
20
+ export {};
@@ -0,0 +1,4 @@
1
+ <script>export let value;
2
+ </script>
3
+
4
+ {value}
@@ -0,0 +1,18 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ value: any;
5
+ };
6
+ events: {
7
+ [evt: string]: CustomEvent<any>;
8
+ };
9
+ slots: {};
10
+ exports?: {} | undefined;
11
+ bindings?: string | undefined;
12
+ };
13
+ export type SuggestionStringProps = typeof __propDef.props;
14
+ export type SuggestionStringEvents = typeof __propDef.events;
15
+ export type SuggestionStringSlots = typeof __propDef.slots;
16
+ export default class SuggestionString extends SvelteComponent<SuggestionStringProps, SuggestionStringEvents, SuggestionStringSlots> {
17
+ }
18
+ export {};
@@ -0,0 +1,71 @@
1
+ <svelte:options accessors />
2
+
3
+ <script>import { fly } from "svelte/transition";
4
+ import { throttle, clamp } from "@welshman/lib";
5
+ export let term;
6
+ export let search;
7
+ export let select;
8
+ export let component;
9
+ export let allowCreate = false;
10
+ let index = 0;
11
+ let element;
12
+ let items = [];
13
+ $: populateItems(term);
14
+ const populateItems = throttle(300, (term2) => {
15
+ items = $search(term2).slice(0, 5);
16
+ });
17
+ const setIndex = (newIndex, block) => {
18
+ index = clamp([0, items.length - 1], newIndex);
19
+ };
20
+ export const onKeyDown = (e) => {
21
+ if (["Enter", "Tab"].includes(e.code)) {
22
+ const value = items[index];
23
+ if (value) {
24
+ select(value);
25
+ return true;
26
+ } else if (term && allowCreate) {
27
+ select(term);
28
+ return true;
29
+ }
30
+ }
31
+ if (e.code === "Space" && term && allowCreate) {
32
+ select(term);
33
+ return true;
34
+ }
35
+ if (e.code === "ArrowUp") {
36
+ setIndex(index - 1, "start");
37
+ return true;
38
+ }
39
+ if (e.code === "ArrowDown") {
40
+ setIndex(index + 1, "start");
41
+ return true;
42
+ }
43
+ };
44
+ </script>
45
+
46
+ {#if term}
47
+ <div bind:this={element} transition:fly|local={{duration: 200}} class="tiptap-suggestions">
48
+ <div class="tiptap-suggestions__content">
49
+ {#if term && allowCreate && !items.includes(term)}
50
+ <button
51
+ class="tiptap-suggestions__create"
52
+ on:mousedown|preventDefault|stopPropagation
53
+ on:click|preventDefault|stopPropagation={() => select(term)}>
54
+ Use "<svelte:component this={component} value={term} />"
55
+ </button>
56
+ {/if}
57
+ {#each items as value, i (value)}
58
+ <button
59
+ class="tiptap-suggestions__item"
60
+ class:tiptap-suggestions__selected={index === i}
61
+ on:mousedown|preventDefault|stopPropagation
62
+ on:click|preventDefault|stopPropagation={() => select(value)}>
63
+ <svelte:component this={component} {value} />
64
+ </button>
65
+ {/each}
66
+ </div>
67
+ {#if items.length === 0}
68
+ <div class="tiptap-suggestions__empty">No results</div>
69
+ {/if}
70
+ </div>
71
+ {/if}
@@ -0,0 +1,41 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ term: any;
5
+ search: any;
6
+ select: any;
7
+ component: any;
8
+ allowCreate?: boolean;
9
+ onKeyDown?: (e: any) => true | undefined;
10
+ };
11
+ events: {
12
+ mousedown: MouseEvent;
13
+ } & {
14
+ [evt: string]: CustomEvent<any>;
15
+ };
16
+ slots: {};
17
+ exports?: {} | undefined;
18
+ bindings?: string | undefined;
19
+ };
20
+ export type SuggestionsProps = typeof __propDef.props;
21
+ export type SuggestionsEvents = typeof __propDef.events;
22
+ export type SuggestionsSlots = typeof __propDef.slots;
23
+ export default class Suggestions extends SvelteComponent<SuggestionsProps, SuggestionsEvents, SuggestionsSlots> {
24
+ get onKeyDown(): (e: any) => true | undefined;
25
+ get term(): any;
26
+ /**accessor*/
27
+ set term(_: any);
28
+ get search(): any;
29
+ /**accessor*/
30
+ set search(_: any);
31
+ get select(): any;
32
+ /**accessor*/
33
+ set select(_: any);
34
+ get component(): any;
35
+ /**accessor*/
36
+ set component(_: any);
37
+ get allowCreate(): boolean | undefined;
38
+ /**accessor*/
39
+ set allowCreate(_: boolean | undefined);
40
+ }
41
+ export {};
@@ -0,0 +1,6 @@
1
+ export { default as Suggestions } from "./Suggestions.svelte";
2
+ export { default as SuggestionString } from "./SuggestionString.svelte";
3
+ export { default as EditBolt11 } from "./EditBolt11.svelte";
4
+ export { default as EditMedia } from "./EditMedia.svelte";
5
+ export { default as EditEvent } from "./EditEvent.svelte";
6
+ export { default as EditMention } from "./EditMention.svelte";
@@ -0,0 +1,6 @@
1
+ export { default as Suggestions } from "./Suggestions.svelte";
2
+ export { default as SuggestionString } from "./SuggestionString.svelte";
3
+ export { default as EditBolt11 } from "./EditBolt11.svelte";
4
+ export { default as EditMedia } from "./EditMedia.svelte";
5
+ export { default as EditEvent } from "./EditEvent.svelte";
6
+ export { default as EditMention } from "./EditMention.svelte";
@@ -0,0 +1,8 @@
1
+ import { type HardBreakOptions } from "@tiptap/extension-hard-break";
2
+ export interface BreakOrSubmitOptions extends HardBreakOptions {
3
+ /** Handler for when enter is pressed. */
4
+ submit: () => void;
5
+ /** Whether to call `submit` on unmodified Enter */
6
+ aggressive?: boolean;
7
+ }
8
+ export declare const BreakOrSubmit: import("@tiptap/core").Node<BreakOrSubmitOptions, any>;
@@ -0,0 +1,12 @@
1
+ import { HardBreak } from "@tiptap/extension-hard-break";
2
+ export const BreakOrSubmit = HardBreak.extend({
3
+ addKeyboardShortcuts() {
4
+ return {
5
+ "Shift-Enter": () => this.editor.commands.setHardBreak(),
6
+ "Mod-Enter": () => {
7
+ this.options.submit();
8
+ return true;
9
+ },
10
+ };
11
+ },
12
+ });
@@ -0,0 +1,4 @@
1
+ import { Node } from "@tiptap/core";
2
+ import type { CodeOptions } from "@tiptap/extension-code";
3
+ export type CodeInlineOptions = object;
4
+ export declare const CodeInline: Node<CodeOptions, any>;
@@ -0,0 +1,65 @@
1
+ import { InputRule, mergeAttributes, Node, PasteRule } from "@tiptap/core";
2
+ const inputRegex = /(?:^|\s)(`(?!\s+`)((?:[^`]+))`(?!\s+`))$/;
3
+ const pasteRegex = /(?:^|\s)(`(?!\s+`)((?:[^`]+))`(?!\s+`))/g;
4
+ export const CodeInline = Node.create({
5
+ name: "codeInline",
6
+ content: "text*",
7
+ marks: "",
8
+ group: "inline",
9
+ inline: true,
10
+ code: true,
11
+ defining: true,
12
+ addOptions() {
13
+ return {
14
+ HTMLAttributes: {},
15
+ };
16
+ },
17
+ parseHTML() {
18
+ return [{ tag: "code" }];
19
+ },
20
+ renderHTML({ HTMLAttributes }) {
21
+ return ["code", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
22
+ },
23
+ addKeyboardShortcuts() {
24
+ return {
25
+ // remove code block when at start of document or code block is empty
26
+ Backspace: () => {
27
+ const { empty, $anchor, $from } = this.editor.state.selection;
28
+ const isAtEnd = $from.parentOffset === $from.parent.nodeSize - 2;
29
+ if (!empty || $anchor.parent.type.name !== this.name) {
30
+ return false;
31
+ }
32
+ if (isAtEnd) {
33
+ const { tr } = this.editor.state;
34
+ tr.delete($from.start(), $from.end() + 1);
35
+ this.editor.view.dispatch(tr);
36
+ }
37
+ return false;
38
+ },
39
+ };
40
+ },
41
+ addInputRules() {
42
+ return [
43
+ new InputRule({
44
+ find: inputRegex,
45
+ handler: ({ state, range, match }) => {
46
+ const textNode = state.schema.text(match[2]);
47
+ const codeNode = this.type.create(null, textNode);
48
+ state.tr.replaceWith(range.from, range.to, codeNode).insertText(" ");
49
+ },
50
+ }),
51
+ ];
52
+ },
53
+ addPasteRules() {
54
+ return [
55
+ new PasteRule({
56
+ find: pasteRegex,
57
+ handler: ({ state, range, match }) => {
58
+ const textNode = state.schema.text(match[2]);
59
+ const codeNode = this.type.create(null, textNode);
60
+ state.tr.replaceWith(range.from, range.to, codeNode).insertText(" ");
61
+ },
62
+ }),
63
+ ];
64
+ },
65
+ });
@@ -0,0 +1,45 @@
1
+ import type { StampedEvent, SignedEvent } from "@welshman/util";
2
+ import type { CodeBlockOptions } from "@tiptap/extension-code-block";
3
+ import type { DropcursorOptions } from "@tiptap/extension-dropcursor";
4
+ import type { HistoryOptions } from "@tiptap/extension-history";
5
+ import type { ParagraphOptions } from "@tiptap/extension-paragraph";
6
+ import type { PlaceholderOptions } from "@tiptap/extension-placeholder";
7
+ import type { NostrOptions, FileUploadOptions, ImageOptions, LinkOptions, NSecRejectOptions } from "nostr-editor";
8
+ import { type CodeInlineOptions } from "./CodeInline.js";
9
+ import { type BreakOrSubmitOptions } from "./BreakOrSubmit.js";
10
+ export type ChildExtensionOptions<C = any, E = any> = false | {
11
+ extend?: Partial<E>;
12
+ config?: Partial<C>;
13
+ };
14
+ export type EmptyOptions = object;
15
+ export type WelshmanExtensionOptions = {
16
+ bolt11?: false;
17
+ breakOrSubmit: ChildExtensionOptions<BreakOrSubmitOptions>;
18
+ codeInline?: ChildExtensionOptions<CodeInlineOptions>;
19
+ codeBlock?: ChildExtensionOptions<CodeBlockOptions>;
20
+ document?: false;
21
+ dropcursor?: ChildExtensionOptions<DropcursorOptions>;
22
+ fileUpload?: ChildExtensionOptions<FileUploadOptions>;
23
+ gapcursor?: false;
24
+ history?: ChildExtensionOptions<HistoryOptions>;
25
+ image?: ChildExtensionOptions<ImageOptions>;
26
+ link?: ChildExtensionOptions<LinkOptions>;
27
+ naddr?: ChildExtensionOptions<EmptyOptions>;
28
+ nevent?: ChildExtensionOptions<EmptyOptions>;
29
+ nprofile?: ChildExtensionOptions<EmptyOptions>;
30
+ nsecReject?: ChildExtensionOptions<NSecRejectOptions>;
31
+ paragraph?: ChildExtensionOptions<ParagraphOptions>;
32
+ placeholder?: ChildExtensionOptions<PlaceholderOptions>;
33
+ tag?: false;
34
+ text?: false;
35
+ video?: false;
36
+ wordCount?: false;
37
+ };
38
+ export interface WelshmanOptions extends NostrOptions {
39
+ submit?: () => void;
40
+ sign?: (event: StampedEvent) => Promise<SignedEvent>;
41
+ defaultUploadUrl?: string;
42
+ defaultUploadType?: "nip96" | "blossom";
43
+ extensions?: WelshmanExtensionOptions;
44
+ }
45
+ export declare const WelshmanExtension: import("@tiptap/core").Extension<WelshmanOptions, import("nostr-editor").NostrStorage>;
@@ -0,0 +1,153 @@
1
+ import { toNostrURI } from "@welshman/util";
2
+ import { deepMergeLeft } from "@welshman/lib";
3
+ import { SvelteNodeViewRenderer } from "svelte-tiptap";
4
+ import { CodeBlock } from "@tiptap/extension-code-block";
5
+ import { Document } from "@tiptap/extension-document";
6
+ import { Dropcursor } from "@tiptap/extension-dropcursor";
7
+ import { Gapcursor } from "@tiptap/extension-gapcursor";
8
+ import { History } from "@tiptap/extension-history";
9
+ import { Paragraph } from "@tiptap/extension-paragraph";
10
+ import { Text } from "@tiptap/extension-text";
11
+ import { Placeholder } from "@tiptap/extension-placeholder";
12
+ import { NostrExtension, Bolt11Extension, FileUploadExtension, ImageExtension, LinkExtension, NAddrExtension, NEventExtension, NProfileExtension, TagExtension, VideoExtension, NSecRejectExtension, } from "nostr-editor";
13
+ import { WordCount } from "./WordCount.js";
14
+ import { CodeInline } from "./CodeInline.js";
15
+ import { BreakOrSubmit } from "./BreakOrSubmit.js";
16
+ import { EditBolt11, EditMedia, EditEvent, EditMention } from "../components/index.js";
17
+ export const WelshmanExtension = NostrExtension.extend({
18
+ name: "welshman",
19
+ // Return an empty object or else options can't be passed
20
+ addOptions() {
21
+ return {};
22
+ },
23
+ addExtensions() {
24
+ const { sign, submit, defaultUploadUrl = "https://nostr.build", defaultUploadType = "nip96", } = this.options;
25
+ if (!sign)
26
+ throw new Error("sign is a required argument to WelshmanExtension");
27
+ if (!submit)
28
+ throw new Error("submit is a required argument to WelshmanExtension");
29
+ const extensionOptions = deepMergeLeft(this.options.extensions || {}, {
30
+ codeInline: {
31
+ extend: {
32
+ renderText: (props) => "`" + props.node.textContent + "`",
33
+ },
34
+ },
35
+ codeBlock: {
36
+ extend: {
37
+ renderText: (props) => "```" + props.node.textContent + "```",
38
+ },
39
+ },
40
+ bolt11: {
41
+ config: {
42
+ inline: true,
43
+ group: "inline",
44
+ },
45
+ extend: {
46
+ addNodeView: () => SvelteNodeViewRenderer(EditBolt11),
47
+ },
48
+ },
49
+ image: {
50
+ config: {
51
+ inline: true,
52
+ group: "inline",
53
+ defaultUploadUrl,
54
+ defaultUploadType,
55
+ },
56
+ extend: {
57
+ addNodeView: () => SvelteNodeViewRenderer(EditMedia),
58
+ },
59
+ },
60
+ video: {
61
+ config: {
62
+ inline: true,
63
+ group: "inline",
64
+ defaultUploadUrl,
65
+ defaultUploadType,
66
+ },
67
+ extend: {
68
+ addNodeView: () => SvelteNodeViewRenderer(EditMedia),
69
+ },
70
+ },
71
+ nevent: {
72
+ config: {
73
+ inline: true,
74
+ group: "inline",
75
+ },
76
+ extend: {
77
+ renderText: (props) => toNostrURI(props.node.attrs.nevent),
78
+ addNodeView: () => SvelteNodeViewRenderer(EditEvent),
79
+ },
80
+ },
81
+ naddr: {
82
+ config: {
83
+ inline: true,
84
+ group: "inline",
85
+ },
86
+ extend: {
87
+ renderText: (props) => toNostrURI(props.node.attrs.naddr),
88
+ addNodeView: () => SvelteNodeViewRenderer(EditEvent),
89
+ },
90
+ },
91
+ nprofile: {
92
+ extend: {
93
+ renderText: (props) => toNostrURI(props.node.attrs.nprofile),
94
+ addNodeView: () => SvelteNodeViewRenderer(EditMention),
95
+ },
96
+ },
97
+ breakOrSubmit: {
98
+ config: {
99
+ submit,
100
+ },
101
+ },
102
+ fileUpload: {
103
+ config: {
104
+ sign,
105
+ immediateUpload: true,
106
+ allowedMimeTypes: [
107
+ "image/jpeg",
108
+ "image/png",
109
+ "image/gif",
110
+ "image/webp",
111
+ "video/mp4",
112
+ "video/mpeg",
113
+ "video/webm",
114
+ ],
115
+ },
116
+ },
117
+ });
118
+ const extensions = [];
119
+ const addExtension = (extension, options) => {
120
+ if (options === false)
121
+ return;
122
+ if (options?.extend) {
123
+ extension = extension.extend(options.extend);
124
+ }
125
+ if (options?.config) {
126
+ extension = extension.configure(options.config);
127
+ }
128
+ extensions.push(extension);
129
+ };
130
+ addExtension(Document, extensionOptions.document);
131
+ addExtension(Text, extensionOptions.text);
132
+ addExtension(Paragraph, extensionOptions.paragraph);
133
+ addExtension(History, extensionOptions.history);
134
+ addExtension(CodeBlock, extensionOptions.codeBlock);
135
+ addExtension(CodeInline, extensionOptions.codeInline);
136
+ addExtension(Dropcursor, extensionOptions.dropcursor);
137
+ addExtension(FileUploadExtension, extensionOptions.fileUpload);
138
+ addExtension(Gapcursor, extensionOptions.gapcursor);
139
+ addExtension(BreakOrSubmit, extensionOptions.breakOrSubmit);
140
+ addExtension(ImageExtension, extensionOptions.image);
141
+ addExtension(LinkExtension, extensionOptions.link);
142
+ addExtension(NAddrExtension, extensionOptions.naddr);
143
+ addExtension(NEventExtension, extensionOptions.nevent);
144
+ addExtension(NProfileExtension, extensionOptions.nprofile);
145
+ addExtension(NSecRejectExtension, extensionOptions.nsecReject);
146
+ addExtension(Placeholder, extensionOptions.placeholder);
147
+ addExtension(TagExtension, extensionOptions.tag);
148
+ addExtension(VideoExtension, extensionOptions.video);
149
+ addExtension(Bolt11Extension, extensionOptions.bolt11);
150
+ addExtension(WordCount, extensionOptions.wordCount);
151
+ return extensions;
152
+ },
153
+ });
@@ -0,0 +1,2 @@
1
+ import { Extension } from "@tiptap/core";
2
+ export declare const WordCount: Extension<any, any>;
@@ -0,0 +1,15 @@
1
+ import { Extension } from "@tiptap/core";
2
+ export const WordCount = Extension.create({
3
+ name: "wordCount",
4
+ addStorage() {
5
+ return {
6
+ words: 0,
7
+ chars: 0,
8
+ };
9
+ },
10
+ onUpdate() {
11
+ const text = this.editor.state.doc.textContent;
12
+ this.storage.words = text.split(/\s+/).filter(word => word.length > 0).length;
13
+ this.storage.chars = text.length;
14
+ },
15
+ });
@@ -0,0 +1,4 @@
1
+ export * from "./BreakOrSubmit.js";
2
+ export * from "./CodeInline.js";
3
+ export * from "./Welshman.js";
4
+ export * from "./WordCount.js";
@@ -0,0 +1,4 @@
1
+ export * from "./BreakOrSubmit.js";
2
+ export * from "./CodeInline.js";
3
+ export * from "./Welshman.js";
4
+ export * from "./WordCount.js";