@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 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: `![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.
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(editor, initialMarkdown));
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(editor, markdown);
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.8.1",
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.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.10.0"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "react": "^19.0.0",