@meowdown/react 0.8.1 → 0.9.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 CHANGED
@@ -47,6 +47,7 @@ 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: `![alt](src)` 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.
50
51
  - `placeholder?: string | ((state) => string)`: placeholder text shown when the whole document is empty. Pass a stable function. Ignored in source mode.
51
52
  - `readOnly?: boolean`: makes the editor read-only, in both the rich and source modes.
52
53
  - `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,13 @@ 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;
133
140
  /**
134
141
  * Placeholder text shown when the whole document is empty. A function
135
142
  * receives the editor state. Pass a stable function. Ignored in source mode.
@@ -161,6 +168,7 @@ declare function MeowdownEditor({
161
168
  resolveImageUrl,
162
169
  onImagePaste,
163
170
  onImageSaveError,
171
+ embedPaste,
164
172
  placeholder,
165
173
  readOnly,
166
174
  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, 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, placeholder, readOnly }) {
440
440
  useExtension(useMemo(() => {
441
441
  return defineMarkMode(markMode);
442
442
  }, [markMode]));
@@ -460,6 +460,9 @@ 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]));
463
466
  useExtension(useMemo(() => {
464
467
  return placeholder ? definePlaceholder({
465
468
  placeholder,
@@ -907,10 +910,10 @@ function resolveSelection(doc, selection) {
907
910
  return TextSelection.between(doc.resolve(anchor), doc.resolve(head));
908
911
  }
909
912
  }
910
- function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, placeholder, readOnly, spellCheck, editorClassName, ref, children }) {
913
+ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, embedPaste, placeholder, readOnly, spellCheck, editorClassName, ref, children }) {
911
914
  const [editor] = useState(() => {
912
915
  const editor = createEditor({ extension: union(defineEditorExtension(), defineCodeBlockView()) });
913
- if (initialMarkdown) editor.setContent(markdownToDoc(editor, initialMarkdown));
916
+ if (initialMarkdown) editor.setContent(markdownToDoc(initialMarkdown, editor.nodes));
914
917
  return editor;
915
918
  });
916
919
  const suppressDocChangeRef = useRef(false);
@@ -928,7 +931,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
928
931
  if (markdown == null && !selection) return;
929
932
  const transaction = editor.state.tr;
930
933
  if (markdown != null) {
931
- const doc = markdownToDoc(editor, markdown);
934
+ const doc = markdownToDoc(markdown, editor.nodes);
932
935
  transaction.replaceWith(0, transaction.doc.content.size, doc.content);
933
936
  }
934
937
  if (selection) transaction.setSelection(resolveSelection(transaction.doc, selection)).scrollIntoView();
@@ -985,6 +988,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
985
988
  resolveImageUrl,
986
989
  onImagePaste,
987
990
  onImageSaveError,
991
+ embedPaste,
988
992
  placeholder,
989
993
  readOnly
990
994
  }),
@@ -1001,7 +1005,7 @@ function ProseKitEditor({ markMode = "focus", initialMarkdown, onDocChange, onTa
1001
1005
 
1002
1006
  //#endregion
1003
1007
  //#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 }) {
1008
+ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSearch, onWikilinkSearch, onWikilinkClick, resolveImageUrl, onImagePaste, onImageSaveError, embedPaste = true, placeholder, readOnly, spellCheck, editorClassName, wrapperClassName, handleRef, children }) {
1005
1009
  const childRef = useRef(null);
1006
1010
  useImperativeHandle(handleRef, () => {
1007
1011
  function getMarkdown() {
@@ -1069,6 +1073,7 @@ function MeowdownEditor({ mode = "focus", initialMarkdown, onDocChange, onTagSea
1069
1073
  resolveImageUrl,
1070
1074
  onImagePaste,
1071
1075
  onImageSaveError,
1076
+ embedPaste,
1072
1077
  placeholder,
1073
1078
  readOnly,
1074
1079
  spellCheck,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/react",
3
3
  "type": "module",
4
- "version": "0.8.1",
4
+ "version": "0.9.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.12.3",
27
+ "@prosekit/core": "^0.13.0-beta.1",
28
28
  "@prosekit/pm": "^0.1.18",
29
- "@prosekit/react": "^0.8.0-beta.0",
29
+ "@prosekit/react": "^0.8.0-beta.2",
30
30
  "clsx": "^2.1.1",
31
- "@meowdown/core": "0.8.1"
31
+ "@meowdown/core": "0.9.0"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "react": "^19.0.0",