@meowdown/react 0.8.1 → 0.10.0
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.
- package/README.md +3 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +19 -8
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -47,6 +47,9 @@ The Markdown editor component. Renders inside a `div.meowdown` wrapper that fill
|
|
|
47
47
|
- `resolveImageUrl?: (src: string) => string | undefined`: maps an image `src` to a displayable URL (or `undefined` to skip). Enables inline image rendering: `` stays literal text and the image renders beneath its line. Pass a stable function. Ignored in source mode.
|
|
48
48
|
- `onImagePaste?: (file: File) => string | undefined | Promise<string | undefined>`: persists a pasted or dropped image file and returns its markdown `src` (or `undefined` to decline), synchronously or as a promise. Pass a stable function. Ignored in source mode.
|
|
49
49
|
- `onImageSaveError?: (error: unknown, file: File) => void`: called when `onImagePaste` throws. Defaults to `console.error`. Ignored in source mode.
|
|
50
|
+
- `embedPaste?: boolean`: auto-embeds a pasted tweet or YouTube link as a rich embed; one undo turns the embed back into the raw link. On by default; set `false` to disable. Only takes effect when `resolveImageUrl` is set, since embeds render through the image pipeline. Ignored in source mode.
|
|
51
|
+
- `bulletAfterHeading?: boolean`: pressing Enter at the end of the document's first heading (the title line) starts a fresh empty bullet on the next line instead of a plain paragraph. Off by default. Ignored in source mode.
|
|
52
|
+
- `blockHandle?: boolean`: shows the per-block gutter handle in the rich modes (a drag grip for reordering blocks and a `+` add button, plus the drop indicator). On by default; set `false` to hide the gutter affordance entirely, e.g. when the host does not want block reordering. Ignored in source mode and when `readOnly` is set.
|
|
50
53
|
- `placeholder?: string | ((state) => string)`: placeholder text shown when the whole document is empty. Pass a stable function. Ignored in source mode.
|
|
51
54
|
- `readOnly?: boolean`: makes the editor read-only, in both the rich and source modes.
|
|
52
55
|
- `spellCheck?: boolean`: toggles the browser's native spell checking in the rich modes. Defaults to the browser's behavior. Ignored in source mode.
|
package/dist/index.d.ts
CHANGED
|
@@ -130,6 +130,27 @@ interface EditorProps {
|
|
|
130
130
|
onImagePaste?: ImageOptions['onImagePaste'];
|
|
131
131
|
/** Called when persisting a pasted/dropped image throws. Ignored in source mode. */
|
|
132
132
|
onImageSaveError?: ImageOptions['onImageSaveError'];
|
|
133
|
+
/**
|
|
134
|
+
* Auto-embeds a pasted tweet or YouTube link as a rich embed; one undo turns
|
|
135
|
+
* the embed back into the raw link. On by default. Ignored in source mode, and
|
|
136
|
+
* only takes effect when `resolveImageUrl` is set, since embeds render through
|
|
137
|
+
* the same image pipeline.
|
|
138
|
+
*/
|
|
139
|
+
embedPaste?: boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Pressing Enter at the end of the document's first heading (the title line)
|
|
142
|
+
* starts a fresh empty bullet on the next line instead of a plain paragraph.
|
|
143
|
+
* Off by default. Ignored in source mode.
|
|
144
|
+
*/
|
|
145
|
+
bulletAfterHeading?: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Shows the per-block gutter handle in the rich modes: a drag grip for
|
|
148
|
+
* reordering blocks and a "+" add button, plus the drop indicator that
|
|
149
|
+
* visualizes where a dragged block will land. On by default. Set to `false`
|
|
150
|
+
* to hide the gutter affordance entirely, e.g. when the host does not want
|
|
151
|
+
* block reordering. Ignored in source mode and when `readOnly` is set.
|
|
152
|
+
*/
|
|
153
|
+
blockHandle?: boolean;
|
|
133
154
|
/**
|
|
134
155
|
* Placeholder text shown when the whole document is empty. A function
|
|
135
156
|
* receives the editor state. Pass a stable function. Ignored in source mode.
|
|
@@ -161,6 +182,9 @@ declare function MeowdownEditor({
|
|
|
161
182
|
resolveImageUrl,
|
|
162
183
|
onImagePaste,
|
|
163
184
|
onImageSaveError,
|
|
185
|
+
embedPaste,
|
|
186
|
+
bulletAfterHeading,
|
|
187
|
+
blockHandle,
|
|
164
188
|
placeholder,
|
|
165
189
|
readOnly,
|
|
166
190
|
spellCheck,
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { Compartment, EditorSelection, EditorState } from "@codemirror/state";
|
|
|
7
7
|
import { EditorView, keymap } from "@codemirror/view";
|
|
8
8
|
import { clamp } from "@ocavue/utils";
|
|
9
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
-
import { codeBlockLanguages, defineEditorExtension, defineImages, defineMarkMode, definePlaceholder, defineReadonly, defineWikilinkClickHandler, docToMarkdown, markdownToDoc } from "@meowdown/core";
|
|
10
|
+
import { codeBlockLanguages, defineBulletAfterHeading, defineEditorExtension, defineEmbedPaste, defineImages, defineMarkMode, definePlaceholder, defineReadonly, defineWikilinkClickHandler, docToMarkdown, markdownToDoc } from "@meowdown/core";
|
|
11
11
|
import { canUseRegexLookbehind, createEditor, defineDocChangeHandler, union } from "@prosekit/core";
|
|
12
12
|
import { Selection, TextSelection } from "@prosekit/pm/state";
|
|
13
13
|
import { ProseKit, defineReactNodeView, useEditor, useEditor as useEditor$1, useEditorDerivedValue, useExtension } from "@prosekit/react";
|
|
@@ -436,7 +436,7 @@ function DropIndicator$1() {
|
|
|
436
436
|
|
|
437
437
|
//#endregion
|
|
438
438
|
//#region src/components/editor-extensions.tsx
|
|
439
|
-
function EditorExtensions({ markMode, onDocChange, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, placeholder, readOnly }) {
|
|
439
|
+
function EditorExtensions({ markMode, onDocChange, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, embedPaste, bulletAfterHeading, placeholder, readOnly }) {
|
|
440
440
|
useExtension(useMemo(() => {
|
|
441
441
|
return defineMarkMode(markMode);
|
|
442
442
|
}, [markMode]));
|
|
@@ -460,6 +460,12 @@ function EditorExtensions({ markMode, onDocChange, onWikilinkClick, resolveImage
|
|
|
460
460
|
onImagePaste,
|
|
461
461
|
onImageSaveError
|
|
462
462
|
]));
|
|
463
|
+
useExtension(useMemo(() => {
|
|
464
|
+
return embedPaste && resolveImageUrl ? defineEmbedPaste() : null;
|
|
465
|
+
}, [embedPaste, resolveImageUrl]));
|
|
466
|
+
useExtension(useMemo(() => {
|
|
467
|
+
return bulletAfterHeading ? defineBulletAfterHeading() : null;
|
|
468
|
+
}, [bulletAfterHeading]));
|
|
463
469
|
useExtension(useMemo(() => {
|
|
464
470
|
return placeholder ? definePlaceholder({
|
|
465
471
|
placeholder,
|
|
@@ -907,10 +913,10 @@ function resolveSelection(doc, selection) {
|
|
|
907
913
|
return TextSelection.between(doc.resolve(anchor), doc.resolve(head));
|
|
908
914
|
}
|
|
909
915
|
}
|
|
910
|
-
function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, placeholder, readOnly, spellCheck, editorClassName, ref, children }) {
|
|
916
|
+
function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, embedPaste, bulletAfterHeading, blockHandle = true, placeholder, readOnly, spellCheck, editorClassName, ref, children }) {
|
|
911
917
|
const [editor] = useState(() => {
|
|
912
918
|
const editor = createEditor({ extension: union(defineEditorExtension(), defineCodeBlockView()) });
|
|
913
|
-
if (initialMarkdown) editor.setContent(markdownToDoc(
|
|
919
|
+
if (initialMarkdown) editor.setContent(markdownToDoc(initialMarkdown, editor.nodes));
|
|
914
920
|
return editor;
|
|
915
921
|
});
|
|
916
922
|
const suppressDocChangeRef = useRef(false);
|
|
@@ -928,7 +934,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
|
|
|
928
934
|
if (markdown == null && !selection) return;
|
|
929
935
|
const transaction = editor.state.tr;
|
|
930
936
|
if (markdown != null) {
|
|
931
|
-
const doc = markdownToDoc(
|
|
937
|
+
const doc = markdownToDoc(markdown, editor.nodes);
|
|
932
938
|
transaction.replaceWith(0, transaction.doc.content.size, doc.content);
|
|
933
939
|
}
|
|
934
940
|
if (selection) transaction.setSelection(resolveSelection(transaction.doc, selection)).scrollIntoView();
|
|
@@ -985,12 +991,14 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
|
|
|
985
991
|
resolveImageUrl,
|
|
986
992
|
onImagePaste,
|
|
987
993
|
onImageSaveError,
|
|
994
|
+
embedPaste,
|
|
995
|
+
bulletAfterHeading,
|
|
988
996
|
placeholder,
|
|
989
997
|
readOnly
|
|
990
998
|
}),
|
|
991
|
-
/* @__PURE__ */ jsx(BlockHandle, {}),
|
|
999
|
+
blockHandle && !readOnly && /* @__PURE__ */ jsx(BlockHandle, {}),
|
|
992
1000
|
!readOnly && /* @__PURE__ */ jsx(TableHandle, {}),
|
|
993
|
-
/* @__PURE__ */ jsx(DropIndicator$1, {}),
|
|
1001
|
+
blockHandle && !readOnly && /* @__PURE__ */ jsx(DropIndicator$1, {}),
|
|
994
1002
|
/* @__PURE__ */ jsx(SlashMenu, {}),
|
|
995
1003
|
onTagSearch && /* @__PURE__ */ jsx(TagMenu, { onTagSearch }),
|
|
996
1004
|
onWikilinkSearch && /* @__PURE__ */ jsx(WikilinkMenu, { onWikilinkSearch }),
|
|
@@ -1001,7 +1009,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
|
|
|
1001
1009
|
|
|
1002
1010
|
//#endregion
|
|
1003
1011
|
//#region src/components/editor.tsx
|
|
1004
|
-
function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, placeholder, readOnly, spellCheck, editorClassName, wrapperClassName, handleRef, children }) {
|
|
1012
|
+
function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, embedPaste = true, bulletAfterHeading = false, blockHandle = true, placeholder, readOnly, spellCheck, editorClassName, wrapperClassName, handleRef, children }) {
|
|
1005
1013
|
const childRef = useRef(null);
|
|
1006
1014
|
useImperativeHandle(handleRef, () => {
|
|
1007
1015
|
function getMarkdown() {
|
|
@@ -1069,6 +1077,9 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSea
|
|
|
1069
1077
|
resolveImageUrl,
|
|
1070
1078
|
onImagePaste,
|
|
1071
1079
|
onImageSaveError,
|
|
1080
|
+
embedPaste,
|
|
1081
|
+
bulletAfterHeading,
|
|
1082
|
+
blockHandle,
|
|
1072
1083
|
placeholder,
|
|
1073
1084
|
readOnly,
|
|
1074
1085
|
spellCheck,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meowdown/react",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.10.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
"@codemirror/state": "^6.6.0",
|
|
25
25
|
"@codemirror/view": "^6.43.1",
|
|
26
26
|
"@ocavue/utils": "^1.7.0",
|
|
27
|
-
"@prosekit/core": "^0.
|
|
27
|
+
"@prosekit/core": "^0.13.0-beta.1",
|
|
28
28
|
"@prosekit/pm": "^0.1.18",
|
|
29
|
-
"@prosekit/react": "^0.8.0-beta.
|
|
29
|
+
"@prosekit/react": "^0.8.0-beta.2",
|
|
30
30
|
"clsx": "^2.1.1",
|
|
31
|
-
"@meowdown/core": "0.
|
|
31
|
+
"@meowdown/core": "0.10.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"react": "^19.0.0",
|