@meowdown/core 0.79.0 → 0.81.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +105 -122
  2. package/dist/index.js +133 -135
  3. package/package.json +10 -9
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { CheckRoundTripOptions, RoundTripFidelity, checkRoundTrip } from "@meowdown/markdown";
2
1
  import { Editor, Extension, ExtractMarkBuilders, ExtractNodeBuilders, PlainExtension, Priority, Union, withPriority } from "@prosekit/core";
3
2
  import { CodeBlockAttrs, CodeBlockAttrs as CodeBlockAttrs$1, defineCodeBlockPreviewPlugin, isCodeBlockPreviewHiddenDecoration } from "@prosekit/extensions/code-block";
4
3
  import { PlaceholderOptions, PlaceholderOptions as PlaceholderOptions$1, definePlaceholder } from "@prosekit/extensions/placeholder";
@@ -7,7 +6,7 @@ import { Command, EditorState, PluginKey } from "@prosekit/pm/state";
7
6
  import { EditorView } from "@prosekit/pm/view";
8
7
  import { EditorNode, Mark, ProseMirrorNode } from "@prosekit/pm/model";
9
8
  import { ListAttrs } from "@prosekit/extensions/list";
10
- import { HorizontalRuleExtension } from "@prosekit/extensions/horizontal-rule";
9
+ import { HorizontalRuleCommandsExtension, HorizontalRuleSpecExtension } from "@prosekit/extensions/horizontal-rule";
11
10
  import { Resolver, XPostMediaClickEvent } from "@meowdown/embed/x";
12
11
  import { YouTubeVideoClickEvent } from "@meowdown/embed/youtube";
13
12
  import "prosemirror-flat-list";
@@ -44,9 +43,9 @@ type ListMarker = '.' | ')' | '-' | '*' | '+' | null;
44
43
  */
45
44
  type TaskMarker = 'x' | 'X' | null;
46
45
  interface MeowdownListAttrs extends ListAttrs {
47
- marker?: ListMarker;
48
- taskMarker?: TaskMarker;
49
- markerGap?: number;
46
+ marker?: ListMarker | undefined;
47
+ taskMarker?: TaskMarker | undefined;
48
+ markerGap?: number | undefined;
50
49
  }
51
50
  //#endregion
52
51
  //#region src/extensions/table-column-align.d.ts
@@ -61,7 +60,7 @@ interface MeowdownTableCellAttrs {
61
60
  * renders with the default left alignment and serializes the delimiter
62
61
  * column as `---`.
63
62
  */
64
- align?: TableColumnAlign | null;
63
+ align?: TableColumnAlign | null | undefined;
65
64
  }
66
65
  type TableCellAlignExtension = Extension<{
67
66
  Nodes: {
@@ -95,13 +94,13 @@ interface MeowdownCodeBlockAttrs extends CodeBlockAttrs$1 {
95
94
  * default) is a backtick fence, so a block created in the editor serializes
96
95
  * to the canonical form.
97
96
  */
98
- fenceStyle?: CodeBlockFenceStyle | null;
97
+ fenceStyle?: CodeBlockFenceStyle | null | undefined;
99
98
  /**
100
99
  * The number of characters in the opening fence, kept only when it exceeds
101
100
  * CommonMark's three-character minimum. `null` (the default) lets the
102
101
  * serializer pick the shortest fence the content allows.
103
102
  */
104
- fenceLength?: number | null;
103
+ fenceLength?: number | null | undefined;
105
104
  }
106
105
  //#endregion
107
106
  //#region src/extensions/horizontal-rule.d.ts
@@ -110,14 +109,14 @@ interface MeowdownHorizontalRuleAttrs {
110
109
  * The literal markdown marker of a thematic break, e.g. `***`, `___`, or
111
110
  * `- - -`. Defaults to null, which the serializer emits as the canonical `---`.
112
111
  */
113
- marker?: string | null;
112
+ marker?: string | null | undefined;
114
113
  }
115
114
  type HorizontalRuleMarkerExtension = Extension<{
116
115
  Nodes: {
117
116
  horizontalRule: MeowdownHorizontalRuleAttrs;
118
117
  };
119
118
  }>;
120
- type MeowdownHorizontalRuleExtension = Union<[HorizontalRuleExtension, HorizontalRuleMarkerExtension]>;
119
+ type MeowdownHorizontalRuleExtension = Union<[HorizontalRuleSpecExtension, HorizontalRuleCommandsExtension, HorizontalRuleMarkerExtension]>;
121
120
  //#endregion
122
121
  //#region src/extensions/html-comment.d.ts
123
122
  interface MeowdownHTMLCommentAttrs {
@@ -251,53 +250,53 @@ interface MdMathAttrs {
251
250
  */
252
251
  type MdPackAttrs = {
253
252
  key: 'italic' | 'bold' | 'code' | 'del' | 'highlight';
254
- data?: null;
255
- slot?: 1 | null;
253
+ data?: null | undefined;
254
+ slot?: 1 | null | undefined;
256
255
  revealInFocus: true;
257
- revealInHide?: null;
256
+ revealInHide?: null | undefined;
258
257
  } | {
259
258
  key: 'link-inline' | 'link-reference';
260
259
  data: {
261
260
  href: string;
262
261
  title: string;
263
262
  };
264
- slot?: 1 | null;
263
+ slot?: 1 | null | undefined;
265
264
  revealInFocus: true;
266
- revealInHide?: null;
265
+ revealInHide?: null | undefined;
267
266
  } | {
268
267
  key: 'link-angle';
269
268
  data: {
270
269
  href: string;
271
270
  };
272
- slot?: 1 | null;
271
+ slot?: 1 | null | undefined;
273
272
  revealInFocus: true;
274
- revealInHide?: null;
273
+ revealInHide?: null | undefined;
275
274
  } | {
276
275
  key: 'link-bare';
277
276
  data: {
278
277
  href: string;
279
278
  };
280
- slot?: 1 | null;
281
- revealInFocus?: null;
282
- revealInHide?: null;
279
+ slot?: 1 | null | undefined;
280
+ revealInFocus?: null | undefined;
281
+ revealInHide?: null | undefined;
283
282
  } | {
284
283
  key: 'noLink';
285
- data?: null;
286
- slot?: 1 | null;
284
+ data?: null | undefined;
285
+ slot?: 1 | null | undefined;
287
286
  revealInFocus: true;
288
- revealInHide?: null;
287
+ revealInHide?: null | undefined;
289
288
  } | {
290
289
  key: 'math';
291
- data?: null;
292
- slot?: 1 | null;
290
+ data?: null | undefined;
291
+ slot?: 1 | null | undefined;
293
292
  revealInFocus: true;
294
293
  revealInHide: true;
295
294
  } | {
296
295
  key: 'wikilink' | 'image' | 'file';
297
- data?: null;
298
- slot?: 1 | null;
299
- revealInFocus?: null;
300
- revealInHide?: null;
296
+ data?: null | undefined;
297
+ slot?: 1 | null | undefined;
298
+ revealInFocus?: null | undefined;
299
+ revealInHide?: null | undefined;
301
300
  };
302
301
  //#endregion
303
302
  //#region src/utils/range.d.ts
@@ -361,9 +360,9 @@ export declare function getLinkUnitAt(state: EditorState, pos: number): LinkUnit
361
360
  //#endregion
362
361
  //#region src/extensions/link-commands.d.ts
363
362
  interface LinkAttrs {
364
- href?: string;
365
- title?: string;
366
- text?: string;
363
+ href?: string | undefined;
364
+ title?: string | undefined;
365
+ text?: string | undefined;
367
366
  }
368
367
  /**
369
368
  * Normalize a typed URL with the existing autolink logic, else keep it verbatim.
@@ -378,10 +377,10 @@ export declare function getLinkText(link: LinkUnit): string;
378
377
  */
379
378
  export declare function isLinkTextForHref(text: string, href: string): boolean;
380
379
  interface InsertLinkOptions {
381
- href?: string;
382
- title?: string;
383
- text?: string;
384
- wrapText?: boolean;
380
+ href?: string | undefined;
381
+ title?: string | undefined;
382
+ text?: string | undefined;
383
+ wrapText?: boolean | undefined;
385
384
  }
386
385
  export declare function insertLink({ href, title, text, wrapText }?: InsertLinkOptions): Command;
387
386
  /**
@@ -458,7 +457,7 @@ interface AcceptPendingReplacementOptions {
458
457
  /**
459
458
  * Overrides the staged mode for this accept (e.g. "Insert below" on a replace stage).
460
459
  */
461
- mode?: PendingReplacementMode;
460
+ mode?: PendingReplacementMode | undefined;
462
461
  }
463
462
  /**
464
463
  * A pending-replacement change: text/range updates, or how the stage ended.
@@ -516,11 +515,11 @@ interface FilePasteOptions {
516
515
  * An image (`image/*` MIME type or a recognized image filename extension)
517
516
  * inserts `![](src)`; any other file inserts a `[name](src)` link.
518
517
  */
519
- onFilePaste?: FilePasteHandler;
518
+ onFilePaste?: FilePasteHandler | undefined;
520
519
  /**
521
520
  * Called when persisting a pasted/dropped file throws. Defaults to `console.error`.
522
521
  */
523
- onFileSaveError?: FileSaveErrorHandler;
522
+ onFileSaveError?: FileSaveErrorHandler | undefined;
524
523
  }
525
524
  /**
526
525
  * The markdown a saved file becomes: `![](destination)` for an image (a
@@ -531,7 +530,7 @@ interface FilePasteOptions {
531
530
  */
532
531
  export declare function buildFileMarkdown(file: {
533
532
  name: string;
534
- type?: string;
533
+ type?: string | undefined;
535
534
  }, destination: string): string;
536
535
  /**
537
536
  * Persist pasted/dropped files via `onFilePaste` and insert the returned
@@ -548,7 +547,7 @@ interface FileInfo {
548
547
  /**
549
548
  * File size in bytes, shown as a human-readable suffix (e.g. `1.4 MB`).
550
549
  */
551
- size?: number;
550
+ size?: number | undefined;
552
551
  }
553
552
  /**
554
553
  * Resolve display metadata for a file `href`, directly or as a promise; the
@@ -565,7 +564,7 @@ interface FileViewOptions {
565
564
  /**
566
565
  * Resolve the metadata (file size) shown on a pill. Omit to show none.
567
566
  */
568
- resolveFileInfo?: FileInfoResolver;
567
+ resolveFileInfo?: FileInfoResolver | undefined;
569
568
  }
570
569
  /**
571
570
  * Classify a file destination for the pill's `data-file-kind` attribute.
@@ -733,11 +732,11 @@ export declare function defineWikilinkClickHandler(getOnClick?: (state: EditorSt
733
732
  //#endregion
734
733
  //#region src/extensions/follow-link.d.ts
735
734
  interface FollowLinkHandlers {
736
- onWikilinkClick?: WikilinkClickHandler;
737
- onTagClick?: TagClickHandler;
738
- onFileClick?: FileClickHandler;
739
- onLinkClick?: LinkClickHandler;
740
- onImageClick?: ImageClickHandler;
735
+ onWikilinkClick?: WikilinkClickHandler | undefined;
736
+ onTagClick?: TagClickHandler | undefined;
737
+ onFileClick?: FileClickHandler | undefined;
738
+ onLinkClick?: LinkClickHandler | undefined;
739
+ onImageClick?: ImageClickHandler | undefined;
741
740
  }
742
741
  /**
743
742
  * Binds `Mod-Enter` to follow the wikilink, tag, file pill, or Markdown link
@@ -799,22 +798,22 @@ interface ImageOptions {
799
798
  * resolved image does not shift the layout. Defaults to
800
799
  * `defaultResolveImageUrl`.
801
800
  */
802
- resolveImageUrl?: ImageUrlResolver;
801
+ resolveImageUrl?: ImageUrlResolver | undefined;
803
802
  /**
804
803
  * Resolve the data behind an X post URL.
805
804
  * When omitted, public posts use `defaultResolveXPost`.
806
805
  */
807
- resolveXPost?: XPostResolver;
806
+ resolveXPost?: XPostResolver | undefined;
808
807
  /**
809
808
  * Additional trusted protocols for X media URLs, such as `reflect-asset:`.
810
809
  */
811
- mediaUrlProtocols?: string[];
810
+ mediaUrlProtocols?: string[] | undefined;
812
811
  /**
813
812
  * Resolve the data behind a YouTube video URL, rendered as a
814
813
  * `meowdown-embed-youtube` card. Defaults to `defaultResolveYouTubeVideo`,
815
814
  * which reads YouTube's oEmbed endpoint.
816
815
  */
817
- resolveYouTubeVideo?: YouTubeVideoResolver;
816
+ resolveYouTubeVideo?: YouTubeVideoResolver | undefined;
818
817
  }
819
818
  /**
820
819
  * Show an `src` as-is when it is an http(s) URL, otherwise skip rendering it.
@@ -879,35 +878,35 @@ type WikiEmbedResolution = {
879
878
  /**
880
879
  * Source passed to `resolveImageUrl` and image click handlers. Defaults to `target`.
881
880
  */
882
- src?: string;
881
+ src?: string | undefined;
883
882
  /**
884
883
  * Image alt text. Defaults to the alias or target basename.
885
884
  */
886
- alt?: string;
885
+ alt?: string | undefined;
887
886
  } | {
888
887
  kind: 'file';
889
888
  /**
890
889
  * Destination passed to file metadata and click handlers. Defaults to `target`.
891
890
  */
892
- href?: string;
891
+ href?: string | undefined;
893
892
  /**
894
893
  * File pill label. Defaults to the alias or target basename.
895
894
  */
896
- name?: string;
895
+ name?: string | undefined;
897
896
  /**
898
897
  * Optional file title.
899
898
  */
900
- title?: string;
899
+ title?: string | undefined;
901
900
  } | {
902
901
  kind: 'note';
903
902
  /**
904
903
  * Target passed to wikilink click handlers. Defaults to the source target.
905
904
  */
906
- target?: string;
905
+ target?: string | undefined;
907
906
  /**
908
907
  * Chip label. Defaults to the source alias or resolved target.
909
908
  */
910
- display?: string;
909
+ display?: string | undefined;
911
910
  };
912
911
  /**
913
912
  * Classifies one wiki embed for rendering. Return `undefined` to leave the
@@ -919,7 +918,7 @@ type WikiEmbedResolver = (embed: ParsedWikiEmbed) => WikiEmbedResolution | undef
919
918
  * Host options for wiki-embed parsing.
920
919
  */
921
920
  interface WikiEmbedOptions {
922
- resolveWikiEmbed?: WikiEmbedResolver;
921
+ resolveWikiEmbed?: WikiEmbedResolver | undefined;
923
922
  }
924
923
  /**
925
924
  * Parse `![[target]]`, `![[target|alias]]`, `![[target|width]]`, or `![[target|widthxheight]]`.
@@ -952,11 +951,11 @@ interface WikilinkResolution {
952
951
  /**
953
952
  * Target passed to click and hover handlers. Defaults to the bracketed text.
954
953
  */
955
- target?: string;
954
+ target?: string | undefined;
956
955
  /**
957
956
  * Label shown in place of the source. Defaults to the target.
958
957
  */
959
- display?: string;
958
+ display?: string | undefined;
960
959
  }
961
960
  /**
962
961
  * Resolves one `[[...]]` wikilink into the target its handlers receive and
@@ -970,7 +969,7 @@ type WikilinkResolver = (link: WikilinkPayload) => WikilinkResolution | undefine
970
969
  * Host options for wikilink parsing.
971
970
  */
972
971
  interface WikilinkOptions {
973
- resolveWikilink?: WikilinkResolver;
972
+ resolveWikilink?: WikilinkResolver | undefined;
974
973
  }
975
974
  //#endregion
976
975
  //#region src/extensions/inline-text-to-mark-chunks.d.ts
@@ -1007,7 +1006,7 @@ interface FileLinkOptions {
1007
1006
  * Claim `[label](url)` links as file attachments; see {@link FileLinkResolver}.
1008
1007
  * Updates existing content when the configured resolver changes.
1009
1008
  */
1010
- resolveFileLink?: FileLinkResolver;
1009
+ resolveFileLink?: FileLinkResolver | undefined;
1011
1010
  }
1012
1011
  /**
1013
1012
  * Host options that influence source-backed inline atom parsing.
@@ -1016,21 +1015,21 @@ type InlineMarkOptions = FileLinkOptions & WikiEmbedOptions & WikilinkOptions &
1016
1015
  /**
1017
1016
  * Definitions supplied by the containing document.
1018
1017
  */
1019
- referenceDefinitions?: ReferenceDefinitions;
1018
+ referenceDefinitions?: ReferenceDefinitions | undefined;
1020
1019
  };
1021
1020
  interface InlineMarkContext {
1022
1021
  /**
1023
1022
  * Effective document-wide definitions, keyed by normalized reference label.
1024
1023
  */
1025
- referenceDefinitions?: ReferenceDefinitions;
1024
+ referenceDefinitions?: ReferenceDefinitions | undefined;
1026
1025
  /**
1027
1026
  * Prevent this definition block's own label from resolving as a shortcut reference.
1028
1027
  */
1029
- isReferenceDefinition?: boolean;
1028
+ isReferenceDefinition?: boolean | undefined;
1030
1029
  /**
1031
1030
  * Receives every normalized key read by this block, including unresolved references.
1032
1031
  */
1033
- referencedKeys?: Set<string>;
1032
+ referencedKeys?: Set<string> | undefined;
1034
1033
  }
1035
1034
  /**
1036
1035
  * Walk a textblock's inline content and produce a list of mark chunks
@@ -1092,20 +1091,27 @@ export declare function defineYouTubeVideoClickHandler(getOnClick?: (state: Edit
1092
1091
  //#endregion
1093
1092
  //#region src/extensions/editor-config-types.d.ts
1094
1093
  interface EditorConfig extends InlineMarkOptions, FollowLinkHandlers, FilePasteOptions, FileViewOptions, ImageOptions {
1095
- markMode?: MarkMode;
1096
- onExitBoundary?: ExitBoundaryHandler;
1097
- onXPostMediaClick?: XPostMediaClickHandler;
1098
- onYouTubeVideoClick?: YouTubeVideoClickHandler;
1099
- embedPaste?: boolean;
1100
- linkPaste?: boolean;
1101
- bulletAfterHeading?: boolean;
1102
- backspaceDeletesEmptyFirstBlock?: boolean;
1103
- substitution?: boolean;
1104
- wikilinkEnabled?: boolean;
1105
- placeholder?: PlaceholderOptions$1['placeholder'];
1106
- readOnly?: boolean;
1107
- spellCheck?: boolean;
1108
- editorClassName?: string;
1094
+ markMode?: MarkMode | undefined;
1095
+ onExitBoundary?: ExitBoundaryHandler | undefined;
1096
+ onXPostMediaClick?: XPostMediaClickHandler | undefined;
1097
+ onYouTubeVideoClick?: YouTubeVideoClickHandler | undefined;
1098
+ embedPaste?: boolean | undefined;
1099
+ linkPaste?: boolean | undefined;
1100
+ bulletAfterHeading?: boolean | undefined;
1101
+ backspaceDeletesEmptyFirstBlock?: boolean | undefined;
1102
+ substitution?: boolean | undefined;
1103
+ /**
1104
+ * Keep the document to one paragraph of inline Markdown: typed block
1105
+ * prefixes (`# `, `> `, `- `, ```` ``` ````) stay literal and pasted blocks
1106
+ * flatten into soft lines. Seed the editor with `paragraphMarkdownToDoc` and
1107
+ * read it with `docToParagraphMarkdown`.
1108
+ */
1109
+ singleParagraph?: boolean | undefined;
1110
+ wikilinkEnabled?: boolean | undefined;
1111
+ placeholder?: PlaceholderOptions$1['placeholder'] | undefined;
1112
+ readOnly?: boolean | undefined;
1113
+ spellCheck?: boolean | undefined;
1114
+ editorClassName?: string | undefined;
1109
1115
  }
1110
1116
  //#endregion
1111
1117
  //#region src/extensions/extension.d.ts
@@ -1120,25 +1126,25 @@ declare function defineEditorExtensionImpl(options: EditorExtensionOptions): imp
1120
1126
  }>, import("@prosekit/extensions/doc").DocExtension, import("@prosekit/core").Extension<{
1121
1127
  Nodes: {
1122
1128
  doc: {
1123
- frontmatter?: Frontmatter;
1129
+ frontmatter?: Frontmatter | undefined;
1124
1130
  };
1125
1131
  };
1126
- }>, import("@prosekit/extensions/text").TextExtension, import("@prosekit/extensions/blockquote").BlockquoteExtension, import("@prosekit/core").Union<readonly [import("@prosekit/extensions/list").ListSpecExtension, import("@prosekit/core").PlainExtension, import("@prosekit/extensions/list").ListCommandsExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").Extension<{
1132
+ }>, import("@prosekit/extensions/text").TextExtension, import("@prosekit/core").Union<readonly [import("@prosekit/extensions/blockquote").BlockquoteSpecExtension, import("@prosekit/extensions/blockquote").BlockquoteCommandsExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension]>, import("@prosekit/core").Union<readonly [import("@prosekit/extensions/list").ListSpecExtension, import("@prosekit/core").PlainExtension, import("@prosekit/extensions/list").ListCommandsExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").Extension<{
1127
1133
  Nodes: {
1128
1134
  list: {
1129
- marker?: ListMarker;
1135
+ marker?: ListMarker | undefined;
1130
1136
  };
1131
1137
  };
1132
1138
  }>, import("@prosekit/core").Extension<{
1133
1139
  Nodes: {
1134
1140
  list: {
1135
- taskMarker?: "x" | "X" | null;
1141
+ taskMarker?: ("x" | "X" | null) | undefined;
1136
1142
  };
1137
1143
  };
1138
1144
  }>, import("@prosekit/core").Extension<{
1139
1145
  Nodes: {
1140
1146
  list: {
1141
- markerGap?: number;
1147
+ markerGap?: number | undefined;
1142
1148
  };
1143
1149
  };
1144
1150
  }>, import("@prosekit/core").Extension<{
@@ -1159,13 +1165,13 @@ declare function defineEditorExtensionImpl(options: EditorExtensionOptions): imp
1159
1165
  }>, import("@prosekit/core").Extension<{
1160
1166
  Nodes: {
1161
1167
  heading: {
1162
- setextUnderline?: number | null;
1168
+ setextUnderline?: number | null | undefined;
1163
1169
  };
1164
1170
  };
1165
1171
  }>, import("@prosekit/core").Extension<{
1166
1172
  Nodes: {
1167
1173
  heading: {
1168
- closingHashes?: number | null;
1174
+ closingHashes?: number | null | undefined;
1169
1175
  };
1170
1176
  };
1171
1177
  }>, import("@prosekit/core").PlainExtension, import("@prosekit/extensions/heading").HeadingCommandsExtension, import("@prosekit/core").PlainExtension]>, import("@prosekit/core").Union<readonly [import("@prosekit/extensions/table").TableSpecExtension, import("@prosekit/extensions/table").TableRowSpecExtension, import("@prosekit/extensions/table").TableCellSpecExtension, import("@prosekit/extensions/table").TableHeaderCellSpecExtension, import("@prosekit/core").Union<readonly [import("@prosekit/core").Extension<{
@@ -1176,16 +1182,16 @@ declare function defineEditorExtensionImpl(options: EditorExtensionOptions): imp
1176
1182
  Nodes: {
1177
1183
  tableHeaderCell: import("@prosekit/pm/model").Attrs;
1178
1184
  };
1179
- }>]>, TableColumnAlignExtension, import("@prosekit/core").PlainExtension, import("@prosekit/extensions/table").TableCommandsExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension]>, import("@prosekit/core").Union<readonly [import("@prosekit/extensions/code-block").CodeBlockExtension, import("@prosekit/core").Extension<{
1185
+ }>]>, TableColumnAlignExtension, import("@prosekit/core").PlainExtension, import("@prosekit/extensions/table").TableCommandsExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension]>, import("@prosekit/core").Union<readonly [import("@prosekit/extensions/code-block").CodeBlockSpecExtension, import("@prosekit/core").PlainExtension, import("@prosekit/extensions/code-block").CodeBlockCommandsExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").Extension<{
1180
1186
  Nodes: {
1181
1187
  codeBlock: {
1182
- fenceStyle?: CodeBlockFenceStyle | null;
1188
+ fenceStyle?: CodeBlockFenceStyle | null | undefined;
1183
1189
  };
1184
1190
  };
1185
1191
  }>, import("@prosekit/core").Extension<{
1186
1192
  Nodes: {
1187
1193
  codeBlock: {
1188
- fenceLength?: number | null;
1194
+ fenceLength?: number | null | undefined;
1189
1195
  };
1190
1196
  };
1191
1197
  }>, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension]>, MeowdownHorizontalRuleExtension, import("@prosekit/core").Extension<{
@@ -1256,7 +1262,7 @@ declare function defineEditorExtensionImpl(options: EditorExtensionOptions): imp
1256
1262
  Commands: {
1257
1263
  insertSoftBreak: [];
1258
1264
  };
1259
- }>, import("@prosekit/core").PlainExtension]>, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").Union<readonly [import("@prosekit/core").Extension<{
1265
+ }>, import("@prosekit/core").PlainExtension]>, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").PlainExtension, import("@prosekit/core").Union<readonly [import("@prosekit/core").Extension<{
1260
1266
  Commands: {
1261
1267
  toggleEm: [];
1262
1268
  toggleStrong: [];
@@ -1311,11 +1317,11 @@ interface MarkdownToDocOptions {
1311
1317
  /**
1312
1318
  * Node builders to build the document with. Defaults to the shared schema's builders.
1313
1319
  */
1314
- nodes?: TypedNodeBuilders;
1320
+ nodes?: TypedNodeBuilders | undefined;
1315
1321
  /**
1316
1322
  * Whether to peel a leading `---` frontmatter block onto the doc's `frontmatter` attribute. Off by default.
1317
1323
  */
1318
- frontmatter?: boolean;
1324
+ frontmatter?: boolean | undefined;
1319
1325
  }
1320
1326
  /**
1321
1327
  * Convert a markdown string into a ProseMirror document node.
@@ -1341,7 +1347,7 @@ interface DocToMarkdownOptions {
1341
1347
  /**
1342
1348
  * Whether to serialize the doc's `frontmatter` attribute as a leading `---` block. Off by default.
1343
1349
  */
1344
- frontmatter?: boolean;
1350
+ frontmatter?: boolean | undefined;
1345
1351
  }
1346
1352
  /**
1347
1353
  * Convert persisted editor content to Markdown through the shared block serializer.
@@ -1460,7 +1466,7 @@ interface LinkHoverOptions {
1460
1466
  * Return `false` while the pointer is on the popup the link opened: a
1461
1467
  * pending leave then re-checks later instead of firing.
1462
1468
  */
1463
- canLeave?: () => boolean;
1469
+ canLeave?: (() => boolean) | undefined;
1464
1470
  }
1465
1471
  /**
1466
1472
  * Track the link under the user's attention: a mouse hover after a short
@@ -1499,8 +1505,8 @@ export declare function defineLinkPaste(enabled?: (state: EditorState) => boolea
1499
1505
  */
1500
1506
  interface LinkPreview {
1501
1507
  readonly title: string;
1502
- readonly description?: string;
1503
- readonly iconSrc?: string;
1508
+ readonly description?: string | undefined;
1509
+ readonly iconSrc?: string | undefined;
1504
1510
  }
1505
1511
  /**
1506
1512
  * Resolve display metadata for a link, or return `undefined` when unavailable.
@@ -1681,27 +1687,4 @@ export declare function paragraphMarkdownToDoc(markdown: string, nodes?: TypedNo
1681
1687
  */
1682
1688
  export declare function docToParagraphMarkdown(doc: ProseMirrorNode): string;
1683
1689
  //#endregion
1684
- //#region src/extensions/single-paragraph.d.ts
1685
- /**
1686
- * Keep editing and pasted content within one paragraph.
1687
- * Opt into this extension for inline Markdown fields such as task paragraphs.
1688
- * Register it alongside `defineMeowdown`, seed content with
1689
- * `paragraphMarkdownToDoc`, and read edits with `docToParagraphMarkdown`.
1690
- * Ordinary note editors should keep their full document behavior.
1691
- *
1692
- * Text input stays literal, before block input rules can consume prefixes.
1693
- * Transactions and pasted blocks flatten to paragraph text separated by soft
1694
- * lines. Reference definitions come from `referenceDefinitions` in the editor
1695
- * config; definition-looking content in the field remains visible literal text.
1696
- * Enter/submit, focus, and persistence remain the caller's responsibility.
1697
- *
1698
- * @example
1699
- * const editor = createEditor({
1700
- * extension: union(defineMeowdown({ referenceDefinitions }), defineSingleParagraph()),
1701
- * defaultContent: paragraphMarkdownToDoc('Buy **milk**'),
1702
- * })
1703
- * const markdown = docToParagraphMarkdown(editor.state.doc)
1704
- */
1705
- export declare function defineSingleParagraph(): PlainExtension;
1706
- //#endregion
1707
- export { type AcceptPendingReplacementOptions, type CheckRoundTripOptions, type CodeBlockAttrs, type CodeBlockFenceStyle, type CodeToken, type DocToMarkdownOptions, type EditorConfig, type EditorExtension, type EditorExtensionOptions, type ExitBoundaryHandler, type ExitBoundaryOptions, type FileClickHandler, type FileClickPayload, type FileInfo, type FileInfoResolver, type FileLinkOptions, type FileLinkPayload, type FileLinkResolver, type FilePasteHandler, type FilePasteOptions, type FileSaveErrorHandler, type FileViewOptions, type FollowLinkHandlers, type ImageClickHandler, type ImageClickPayload, type ImageOptions, type ImageUrlResolver, type InlineMarkContext, type InlineMarkOptions, type KaTeXRender, type LanguageItem, type LinkAttrs, type LinkClickHandler, type LinkClickPayload, type LinkCopyHandler, type LinkCopyPayload, type LinkEditHandler, type LinkEditOptions, type LinkHoverHandler, type LinkHoverOptions, type LinkPreview, type LinkPreviewResolver, type LinkUnit, type ListMarker, type MarkChunk, type MarkMode, type MarkName, type MarkdownToDocOptions, type MdFileAttrs, type MdImageAttrs, type MdLinkTextAttrs, type MdMathAttrs, type MdWikilinkAttrs, type MeowdownCodeBlockAttrs, type MeowdownHTMLCommentAttrs, type MeowdownListAttrs, type MeowdownTableCellAttrs, type NodeName, type ParsedWikiEmbed, type PendingReplacement, type PendingReplacementEvent, type PendingReplacementHandler, type PendingReplacementMode, type PendingReplacementOutcome, type PlaceholderOptions, type PositionRange, type PostEmbedSnapshot, Priority, type ReferenceDefinition, type ReferenceDefinitionIndex, type ReferenceDefinitions, type RoundTripFidelity, type SearchStatus, type SearchStatusHandler, type StartPendingReplacementOptions, type TableColumnAlign, type TagClickHandler, type TagClickPayload, type TypedEditor, type TypedMarkBuilders, type VirtualElement, type WikiEmbedOptions, type WikiEmbedResolution, type WikiEmbedResolver, type WikilinkClickHandler, type WikilinkClickPayload, type WikilinkHoverHandler, type WikilinkHoverHit, type WikilinkOptions, type WikilinkPayload, type WikilinkResolution, type WikilinkResolver, type XPostMediaClickHandler, type XPostResolver, type YouTubeVideoClickHandler, type YouTubeVideoResolver, checkRoundTrip, defineCodeBlockPreviewPlugin, definePlaceholder, defineSearchStatusHandler, getSearchStatus, isCodeBlockPreviewHiddenDecoration, withPriority };
1690
+ export { type AcceptPendingReplacementOptions, type CodeBlockAttrs, type CodeBlockFenceStyle, type CodeToken, type DocToMarkdownOptions, type EditorConfig, type EditorExtension, type EditorExtensionOptions, type ExitBoundaryHandler, type ExitBoundaryOptions, type FileClickHandler, type FileClickPayload, type FileInfo, type FileInfoResolver, type FileLinkOptions, type FileLinkPayload, type FileLinkResolver, type FilePasteHandler, type FilePasteOptions, type FileSaveErrorHandler, type FileViewOptions, type FollowLinkHandlers, type ImageClickHandler, type ImageClickPayload, type ImageOptions, type ImageUrlResolver, type InlineMarkContext, type InlineMarkOptions, type KaTeXRender, type LanguageItem, type LinkAttrs, type LinkClickHandler, type LinkClickPayload, type LinkCopyHandler, type LinkCopyPayload, type LinkEditHandler, type LinkEditOptions, type LinkHoverHandler, type LinkHoverOptions, type LinkPreview, type LinkPreviewResolver, type LinkUnit, type ListMarker, type MarkChunk, type MarkMode, type MarkName, type MarkdownToDocOptions, type MdFileAttrs, type MdImageAttrs, type MdLinkTextAttrs, type MdMathAttrs, type MdWikilinkAttrs, type MeowdownCodeBlockAttrs, type MeowdownHTMLCommentAttrs, type MeowdownListAttrs, type MeowdownTableCellAttrs, type NodeName, type ParsedWikiEmbed, type PendingReplacement, type PendingReplacementEvent, type PendingReplacementHandler, type PendingReplacementMode, type PendingReplacementOutcome, type PlaceholderOptions, type PositionRange, type PostEmbedSnapshot, Priority, type ReferenceDefinition, type ReferenceDefinitionIndex, type ReferenceDefinitions, type SearchStatus, type SearchStatusHandler, type StartPendingReplacementOptions, type TableColumnAlign, type TagClickHandler, type TagClickPayload, type TypedEditor, type TypedMarkBuilders, type VirtualElement, type WikiEmbedOptions, type WikiEmbedResolution, type WikiEmbedResolver, type WikilinkClickHandler, type WikilinkClickPayload, type WikilinkHoverHandler, type WikilinkHoverHit, type WikilinkOptions, type WikilinkPayload, type WikilinkResolution, type WikilinkResolver, type XPostMediaClickHandler, type XPostResolver, type YouTubeVideoClickHandler, type YouTubeVideoResolver, defineCodeBlockPreviewPlugin, definePlaceholder, defineSearchStatusHandler, getSearchStatus, isCodeBlockPreviewHiddenDecoration, withPriority };
package/dist/index.js CHANGED
@@ -1,10 +1,9 @@
1
- import { LEZER_NODE_IDS, checkRoundTrip, collectInlineElements, getAutolinkHref, gfmParser, isSpaceChar, matchEmbed, parseInline, parseMarkdownAst, parseXPostId, serializeMarkdownAst } from "@meowdown/markdown";
2
1
  import { Priority, Priority as Priority$1, createMarkBuilders, createNodeBuilders, defaultBlockAt, defineBaseCommands, defineBaseKeymap, defineClipboardSerializer, defineCommands, defineHistory, defineKeymap, defineMarkSpec, defineMarkView, defineNodeAttr, defineNodeSpec, definePlugin, findMarkRange, getMarkRange, getMarkType, getNodeType, isAllSelection, isApple, isAtBlockStart, isNodeSelection, isTextSelection, setBlockType, toggleNode, union, unsetBlockType, withPriority, withPriority as withPriority$1, withSkipCodeBlock } from "@prosekit/core";
3
- import { defineCodeBlock, defineCodeBlockHighlight, defineCodeBlockPreviewPlugin, isCodeBlockPreviewHiddenDecoration } from "@prosekit/extensions/code-block";
2
+ import { codeBlockEnterRule, codeBlockInputRule, defineCodeBlockCommands, defineCodeBlockHighlight, defineCodeBlockKeymap, defineCodeBlockPreviewPlugin, defineCodeBlockSpec, isCodeBlockPreviewHiddenDecoration } from "@prosekit/extensions/code-block";
4
3
  import { definePlaceholder, definePlaceholder as definePlaceholder$1 } from "@prosekit/extensions/placeholder";
5
4
  import { defineSearchCommands, defineSearchQuery, defineSearchStatusHandler, getSearchStatus, getSearchStatus as getSearchStatus$1 } from "@prosekit/extensions/search";
6
- import { isElementLike, isHTMLElement, isObject, once } from "@ocavue/utils";
7
- import { defineBlockquote } from "@prosekit/extensions/blockquote";
5
+ import { LEZER_NODE_IDS, collectInlineElements, getAutolinkHref, gfmParser, isSpaceChar, matchEmbed, parseInline, parseMarkdownAst, parseXPostId, serializeMarkdownAst } from "@meowdown/markdown";
6
+ import { debounce, isElementLike, isHTMLElement, isObject, once } from "@ocavue/utils";
8
7
  import { defineDoc } from "@prosekit/extensions/doc";
9
8
  import { defineGapCursor } from "@prosekit/extensions/gap-cursor";
10
9
  import { defineModClickPrevention } from "@prosekit/extensions/mod-click-prevention";
@@ -12,6 +11,11 @@ import { defineText } from "@prosekit/extensions/text";
12
11
  import { defineVirtualSelection } from "@prosekit/extensions/virtual-selection";
13
12
  import { NodeSelection, Plugin, PluginKey, Selection, TextSelection } from "@prosekit/pm/state";
14
13
  import { Decoration, DecorationSet } from "@prosekit/pm/view";
14
+ import { blockquoteInputRule, defineBlockquoteCommands, defineBlockquoteKeymap, defineBlockquoteSpec } from "@prosekit/extensions/blockquote";
15
+ import { createTextBlockInputRuleHandler, createWrappingInputRuleHandler, defineInputRule } from "@prosekit/extensions/input-rule";
16
+ import { defineEnterRule } from "@prosekit/extensions/enter-rule";
17
+ import { InputRule } from "@prosekit/pm/inputrules";
18
+ import { createTextBlockEnterRule } from "prosemirror-enter-rules";
15
19
  import { NO_BREAK_SPACE } from "unicode-by-name";
16
20
  import { defaultHandlers } from "hast-util-to-mdast";
17
21
  import { defaultHandlers as defaultHandlers$1 } from "mdast-util-to-markdown";
@@ -21,19 +25,17 @@ import remarkGfm from "remark-gfm";
21
25
  import remarkStringify from "remark-stringify";
22
26
  import { unified } from "unified";
23
27
  import { DOMParser, DOMSerializer, Fragment, Mark, Slice } from "@prosekit/pm/model";
24
- import { defineHeadingCommands, defineHeadingInputRule, defineHeadingSpec } from "@prosekit/extensions/heading";
28
+ import { defineHeadingCommands, defineHeadingSpec, headingInputRule } from "@prosekit/extensions/heading";
25
29
  import { defineParagraphCommands, defineParagraphKeymap } from "@prosekit/extensions/paragraph";
26
30
  import { LanguageDescription } from "@codemirror/language";
27
31
  import { languages } from "@codemirror/language-data";
28
32
  import { classHighlighter, highlightTree } from "@lezer/highlight";
29
33
  import { createParser } from "prosemirror-highlight/lezer";
30
- import { defineEnterRule, defineTextBlockEnterRule } from "@prosekit/extensions/enter-rule";
31
- import { defineInputRule, defineTextBlockInputRule } from "@prosekit/extensions/input-rule";
32
34
  import { triggerAutocomplete } from "@prosekit/extensions/autocomplete";
33
35
  import { defineListCommands, defineListDropIndicator, defineListSpec, moveList, toggleList, unwrapList, wrapInList } from "@prosekit/extensions/list";
34
36
  import { chainCommands, deleteSelection, lift, newlineInCode, splitBlock } from "@prosekit/pm/commands";
35
37
  import { closeHistory } from "@prosekit/pm/history";
36
- import { defineHorizontalRule } from "@prosekit/extensions/horizontal-rule";
38
+ import { defineHorizontalRuleCommands, defineHorizontalRuleSpec, horizontalRuleInputRule } from "@prosekit/extensions/horizontal-rule";
37
39
  import { X_POST_MEDIA_CLICK, registerXPost } from "@meowdown/embed/x";
38
40
  import { YOUTUBE_VIDEO_CLICK, registerYouTubeVideo } from "@meowdown/embed/youtube";
39
41
  import { registerResizableHandleElement, registerResizableRootElement } from "@prosekit/web/resizable";
@@ -44,9 +46,8 @@ import * as v from "valibot";
44
46
  import { AttrStep, ReplaceStep, Step, StepResult, Transform } from "@prosekit/pm/transform";
45
47
  import { decodeString } from "micromark-util-decode-string";
46
48
  import { normalizeIdentifier } from "micromark-util-normalize-identifier";
47
- import { createDedentListCommand, createIndentListCommand, createListRenderingPlugin, createSafariInputMethodWorkaroundPlugin, createSplitListCommand, createToggleCollapsedCommand, defaultAttributesGetter, deleteCommand, enterCommand, findCheckboxInListItem, handleListMarkerMouseDown, joinCollapsedListBackward, joinListElements, joinListUp, listToDOM, protectCollapsed, unwrapListSlice, wrappingListInputRule } from "prosemirror-flat-list";
49
+ import { bulletListInputRule, createDedentListCommand, createIndentListCommand, createListInputRuleHandler, createListRenderingPlugin, createSafariInputMethodWorkaroundPlugin, createSplitListCommand, createToggleCollapsedCommand, defaultAttributesGetter, deleteCommand, enterCommand, findCheckboxInListItem, handleListMarkerMouseDown, joinCollapsedListBackward, joinListElements, joinListUp, listToDOM, orderedListInputRule, protectCollapsed, taskListInputRule, unwrapListSlice } from "prosemirror-flat-list";
48
50
  import { defineTableCellSpec, defineTableCommands, defineTableDropIndicator, defineTableEditingPlugin, defineTableHeaderCellSpec, defineTableRowSpec, defineTableSpec, deleteTable, isCellSelection } from "@prosekit/extensions/table";
49
- import { InputRule } from "@prosekit/pm/inputrules";
50
51
 
51
52
  //#region src/utils/composition.ts
52
53
  const COMPOSITION_TAIL_MS = 50;
@@ -661,6 +662,97 @@ function defineBackspaceEmptyFirstBlock(enabled) {
661
662
  } }), Priority$1.lowest);
662
663
  }
663
664
 
665
+ //#endregion
666
+ //#region src/converters/paragraph.ts
667
+ /**
668
+ * Build one paragraph without interpreting block-opening Markdown.
669
+ */
670
+ function paragraphMarkdownToDoc(markdown, nodes = getNodeBuilders()) {
671
+ return astToDoc({
672
+ type: "document",
673
+ children: [{
674
+ type: "paragraph",
675
+ value: markdown.replaceAll(/\r\n?/g, "\n").replaceAll(/\n[ \t]*\n+/g, "\n")
676
+ }]
677
+ }, nodes);
678
+ }
679
+ /**
680
+ * Flatten textblocks into one paragraph's source content.
681
+ */
682
+ function docToParagraphMarkdown(doc) {
683
+ const paragraphs = [];
684
+ doc.descendants((node) => {
685
+ if (!node.isTextblock) return true;
686
+ paragraphs.push(node.textContent);
687
+ return false;
688
+ });
689
+ return paragraphs.join("\n").replaceAll(/\n[ \t]*\n+/g, "\n");
690
+ }
691
+
692
+ //#endregion
693
+ //#region src/extensions/single-paragraph.ts
694
+ const singleParagraphPluginKey = new PluginKey("single-paragraph");
695
+ /**
696
+ * Whether the editor holds one paragraph of inline Markdown (the
697
+ * `singleParagraph` editor config option).
698
+ */
699
+ function isSingleParagraph(state) {
700
+ return !!getEditorConfig(state).singleParagraph;
701
+ }
702
+ /**
703
+ * Keep the document to one paragraph while `singleParagraph` is set. Input
704
+ * rules and enter rules that open a block stay inert on their own (see
705
+ * `block-rule.ts`); this flattens what still arrives as blocks, such as a
706
+ * paste or a command, into paragraph text separated by soft lines.
707
+ */
708
+ function defineSingleParagraph() {
709
+ return withPriority$1(definePlugin(new Plugin({
710
+ key: singleParagraphPluginKey,
711
+ appendTransaction(transactions, _oldState, state) {
712
+ if (!isSingleParagraph(state)) return;
713
+ if (!transactions.some((transaction) => transaction.docChanged)) return;
714
+ const markdown = docToParagraphMarkdown(state.doc);
715
+ if (state.doc.childCount === 1 && isNodeOfType(state.doc.child(0), "paragraph") && state.doc.child(0).textContent === markdown) return;
716
+ const doc = paragraphMarkdownToDoc(markdown, getNodeBuildersForSchema(state.schema));
717
+ const position = Math.min(state.selection.head, doc.content.size - 1);
718
+ const transaction = state.tr.replaceWith(0, state.doc.content.size, doc.content);
719
+ return transaction.setSelection(TextSelection.create(transaction.doc, Math.max(1, position)));
720
+ }
721
+ })), Priority$1.highest);
722
+ }
723
+
724
+ //#endregion
725
+ //#region src/extensions/block-rule.ts
726
+ /**
727
+ * An input rule whose match turns the textblock into, or wraps it in, a block
728
+ * node. In a single paragraph the match is left as typed text: there is no
729
+ * block for it to open.
730
+ */
731
+ function defineBlockInputRule(regex, handler) {
732
+ return defineInputRule(new InputRule(regex, (state, match, start, end) => {
733
+ return isSingleParagraph(state) ? null : handler(state, match, start, end);
734
+ }));
735
+ }
736
+ /**
737
+ * An enter rule whose match turns the textblock into a block node. In a single
738
+ * paragraph the match is left as typed text, like {@link defineBlockInputRule}.
739
+ */
740
+ function defineBlockEnterRule(options) {
741
+ const rule = createTextBlockEnterRule(options);
742
+ return defineEnterRule({
743
+ ...rule,
744
+ handler: (handlerOptions) => {
745
+ return isSingleParagraph(handlerOptions.state) ? null : rule.handler(handlerOptions);
746
+ }
747
+ });
748
+ }
749
+
750
+ //#endregion
751
+ //#region src/extensions/blockquote.ts
752
+ function defineMeowdownBlockquote() {
753
+ return union(defineBlockquoteSpec(), defineBlockquoteCommands(), defineBlockquoteKeymap(), defineBlockInputRule(blockquoteInputRule.regex, createWrappingInputRuleHandler(blockquoteInputRule)));
754
+ }
755
+
664
756
  //#endregion
665
757
  //#region src/extensions/bullet-after-heading.ts
666
758
  /**
@@ -1124,7 +1216,7 @@ function defineHeadingKeymap() {
1124
1216
  });
1125
1217
  }
1126
1218
  function defineHeading() {
1127
- return union(defineHeadingSpec(), defineHeadingWhitespace(), defineSetextUnderlineAttr(), defineHeadingClosingHashesAttr(), defineHeadingInputRule(), defineHeadingCommands(), defineHeadingKeymap());
1219
+ return union(defineHeadingSpec(), defineHeadingWhitespace(), defineSetextUnderlineAttr(), defineHeadingClosingHashesAttr(), defineBlockInputRule(headingInputRule.regex, createTextBlockInputRuleHandler(headingInputRule)), defineHeadingCommands(), defineHeadingKeymap());
1128
1220
  }
1129
1221
 
1130
1222
  //#endregion
@@ -1845,22 +1937,20 @@ function getTildeFenceAttrs(match) {
1845
1937
  fenceStyle: "tilde"
1846
1938
  };
1847
1939
  }
1848
- function defineTildeFenceInputRule() {
1849
- return defineTextBlockInputRule({
1850
- regex: /^~~~(\S*)\s$/,
1851
- type: "codeBlock",
1852
- attrs: getTildeFenceAttrs
1853
- });
1854
- }
1940
+ const tildeFenceInputRule = {
1941
+ regex: /^~~~(\S*)\s$/,
1942
+ type: "codeBlock",
1943
+ attrs: getTildeFenceAttrs
1944
+ };
1855
1945
  function defineTildeFenceEnterRule() {
1856
- return defineTextBlockEnterRule({
1946
+ return defineBlockEnterRule({
1857
1947
  regex: /^~~~(\S*)$/,
1858
1948
  type: "codeBlock",
1859
1949
  attrs: getTildeFenceAttrs
1860
1950
  });
1861
1951
  }
1862
1952
  function defineDollarFenceEnterRule() {
1863
- return defineTextBlockEnterRule({
1953
+ return defineBlockEnterRule({
1864
1954
  regex: /^\$\$$/,
1865
1955
  type: "codeBlock",
1866
1956
  attrs: () => ({
@@ -1869,8 +1959,8 @@ function defineDollarFenceEnterRule() {
1869
1959
  })
1870
1960
  });
1871
1961
  }
1872
- function defineCodeBlock$1() {
1873
- return union(defineCodeBlock(), defineFenceStyleAttr(), defineFenceLengthAttr(), defineTildeFenceInputRule(), defineTildeFenceEnterRule(), defineDollarFenceEnterRule(), defineCodeBlockExitKeymap());
1962
+ function defineCodeBlock() {
1963
+ return union(defineCodeBlockSpec(), defineCodeBlockKeymap(), defineCodeBlockCommands(), defineBlockInputRule(codeBlockInputRule.regex, createTextBlockInputRuleHandler(codeBlockInputRule)), defineBlockEnterRule(codeBlockEnterRule), defineFenceStyleAttr(), defineFenceLengthAttr(), defineBlockInputRule(tildeFenceInputRule.regex, createTextBlockInputRuleHandler(tildeFenceInputRule)), defineTildeFenceEnterRule(), defineDollarFenceEnterRule(), defineCodeBlockExitKeymap());
1874
1964
  }
1875
1965
 
1876
1966
  //#endregion
@@ -3067,7 +3157,7 @@ function defineHorizontalRuleMarkerAttr() {
3067
3157
  });
3068
3158
  }
3069
3159
  function defineMeowdownHorizontalRule() {
3070
- return union(defineHorizontalRule(), defineHorizontalRuleMarkerAttr());
3160
+ return union(defineHorizontalRuleSpec(), defineHorizontalRuleCommands(), defineHorizontalRuleMarkerAttr(), defineBlockInputRule(horizontalRuleInputRule.regex, horizontalRuleInputRule.handler));
3071
3161
  }
3072
3162
 
3073
3163
  //#endregion
@@ -4550,75 +4640,6 @@ function emit(out, from, to, marks) {
4550
4640
  ]);
4551
4641
  }
4552
4642
 
4553
- //#endregion
4554
- //#region src/converters/paragraph.ts
4555
- /**
4556
- * Build one paragraph without interpreting block-opening Markdown.
4557
- */
4558
- function paragraphMarkdownToDoc(markdown, nodes = getNodeBuilders()) {
4559
- return astToDoc({
4560
- type: "document",
4561
- children: [{
4562
- type: "paragraph",
4563
- value: markdown.replaceAll(/\r\n?/g, "\n").replaceAll(/\n[ \t]*\n+/g, "\n")
4564
- }]
4565
- }, nodes);
4566
- }
4567
- /**
4568
- * Flatten textblocks into one paragraph's source content.
4569
- */
4570
- function docToParagraphMarkdown(doc) {
4571
- const paragraphs = [];
4572
- doc.descendants((node) => {
4573
- if (!node.isTextblock) return true;
4574
- paragraphs.push(node.textContent);
4575
- return false;
4576
- });
4577
- return paragraphs.join("\n").replaceAll(/\n[ \t]*\n+/g, "\n");
4578
- }
4579
-
4580
- //#endregion
4581
- //#region src/extensions/single-paragraph.ts
4582
- const singleParagraphPluginKey = new PluginKey("single-paragraph");
4583
- /**
4584
- * Keep editing and pasted content within one paragraph.
4585
- * Opt into this extension for inline Markdown fields such as task paragraphs.
4586
- * Register it alongside `defineMeowdown`, seed content with
4587
- * `paragraphMarkdownToDoc`, and read edits with `docToParagraphMarkdown`.
4588
- * Ordinary note editors should keep their full document behavior.
4589
- *
4590
- * Text input stays literal, before block input rules can consume prefixes.
4591
- * Transactions and pasted blocks flatten to paragraph text separated by soft
4592
- * lines. Reference definitions come from `referenceDefinitions` in the editor
4593
- * config; definition-looking content in the field remains visible literal text.
4594
- * Enter/submit, focus, and persistence remain the caller's responsibility.
4595
- *
4596
- * @example
4597
- * const editor = createEditor({
4598
- * extension: union(defineMeowdown({ referenceDefinitions }), defineSingleParagraph()),
4599
- * defaultContent: paragraphMarkdownToDoc('Buy **milk**'),
4600
- * })
4601
- * const markdown = docToParagraphMarkdown(editor.state.doc)
4602
- */
4603
- function defineSingleParagraph() {
4604
- return withPriority$1(definePlugin(new Plugin({
4605
- key: singleParagraphPluginKey,
4606
- props: { handleTextInput(view, from, to, text) {
4607
- view.dispatch(view.state.tr.insertText(text, from, to));
4608
- return true;
4609
- } },
4610
- appendTransaction(transactions, _oldState, state) {
4611
- if (!transactions.some((transaction) => transaction.docChanged)) return;
4612
- const markdown = docToParagraphMarkdown(state.doc);
4613
- if (state.doc.childCount === 1 && isNodeOfType(state.doc.child(0), "paragraph") && state.doc.child(0).textContent === markdown) return;
4614
- const doc = paragraphMarkdownToDoc(markdown, getNodeBuildersForSchema(state.schema));
4615
- const position = Math.min(state.selection.head, doc.content.size - 1);
4616
- const transaction = state.tr.replaceWith(0, state.doc.content.size, doc.content);
4617
- return transaction.setSelection(TextSelection.create(transaction.doc, Math.max(1, position)));
4618
- }
4619
- })), Priority$1.highest);
4620
- }
4621
-
4622
4643
  //#endregion
4623
4644
  //#region src/extensions/inline-mark-plugin.ts
4624
4645
  const META_KEY = "inline-marks-applied";
@@ -4715,7 +4736,7 @@ function createInlineMarkPlugin(getOptions) {
4715
4736
  const touchesRange = pos <= range.to && pos + node.nodeSize >= range.from;
4716
4737
  const dependsOnChange = cached == null || setsIntersect(cached.referencedKeys, changedKeys);
4717
4738
  if (!touchesRange && !dependsOnChange) return false;
4718
- const nodeChunks = chunksForTextblock(node, pos + 1, state.schema, options, references, changedKeys, !singleParagraphPluginKey.get(state) && isReferenceDefinitionNode(node, parent, index));
4739
+ const nodeChunks = chunksForTextblock(node, pos + 1, state.schema, options, references, changedKeys, !isSingleParagraph(state) && isReferenceDefinitionNode(node, parent, index));
4719
4740
  if (nodeChunks.length > 0) chunks.push(...nodeChunks);
4720
4741
  const updated = chunkCache.get(node);
4721
4742
  if (updated != null) processed.push({
@@ -4738,7 +4759,7 @@ function createInlineMarkPlugin(getOptions) {
4738
4759
  }
4739
4760
  }
4740
4761
  function collectReferences(doc, external, state) {
4741
- const local = singleParagraphPluginKey.get(state) ? {
4762
+ const local = isSingleParagraph(state) ? {
4742
4763
  nodes: /* @__PURE__ */ new Set(),
4743
4764
  definitions: /* @__PURE__ */ new Map()
4744
4765
  } : collectReferenceDefinitions(doc);
@@ -4764,7 +4785,7 @@ function createInlineMarkPlugin(getOptions) {
4764
4785
  };
4765
4786
  if (transaction.getMeta(META_KEY)) return value;
4766
4787
  const externalDefinitions = getOptions?.(oldState)?.referenceDefinitions;
4767
- const references = singleParagraphPluginKey.get(oldState) || externalDefinitions !== value.externalDefinitions || externalDefinitions && transaction.docChanged ? collectReferences(newState.doc, externalDefinitions, newState) : updateReferenceDefinitions(value.references, transaction, newState.doc);
4788
+ const references = isSingleParagraph(oldState) || externalDefinitions !== value.externalDefinitions || externalDefinitions && transaction.docChanged ? collectReferences(newState.doc, externalDefinitions, newState) : updateReferenceDefinitions(value.references, transaction, newState.doc);
4768
4789
  if (references === value.references) return value;
4769
4790
  const changedKeys = getChangedReferenceKeys(value.references.definitions, references.definitions);
4770
4791
  if (changedKeys.size === 0) return {
@@ -4803,28 +4824,21 @@ function createInlineMarkPlugin(getOptions) {
4803
4824
  },
4804
4825
  view(view) {
4805
4826
  view.dispatch(triggerInlineMarks(view.state));
4806
- let timer;
4827
+ const controller = new AbortController();
4807
4828
  const flush = (currentView) => {
4808
- timer = void 0;
4809
4829
  if (currentView.isDestroyed) return;
4810
4830
  if ((pluginKey.getState(currentView.state)?.pendingReferenceKeys.size ?? 0) === 0) return;
4811
4831
  currentView.dispatch(currentView.state.tr.setMeta(RESTYLE_KEY, true));
4812
4832
  };
4833
+ const scheduleFlush = debounce(flush, RESTYLE_DEBOUNCE_MS, { signal: controller.signal });
4813
4834
  return {
4814
4835
  update(currentView, previousState) {
4815
4836
  const current = pluginKey.getState(currentView.state);
4816
- if ((current?.pendingReferenceKeys.size ?? 0) === 0) {
4817
- if (timer != null) clearTimeout(timer);
4818
- timer = void 0;
4819
- return;
4820
- }
4821
- if (timer == null || pluginKey.getState(previousState) !== current) {
4822
- if (timer != null) clearTimeout(timer);
4823
- timer = setTimeout(() => flush(currentView), RESTYLE_DEBOUNCE_MS);
4824
- }
4837
+ if ((current?.pendingReferenceKeys.size ?? 0) === 0) return;
4838
+ if (pluginKey.getState(previousState) !== current) scheduleFlush(currentView);
4825
4839
  },
4826
4840
  destroy() {
4827
- if (timer != null) clearTimeout(timer);
4841
+ controller.abort();
4828
4842
  }
4829
4843
  };
4830
4844
  }
@@ -5818,36 +5832,20 @@ function normalizeTaskList(node) {
5818
5832
  node.replaceChildren(...content.children);
5819
5833
  textBlock.prepend(checkbox);
5820
5834
  }
5821
- const listInputRules = [
5822
- wrappingListInputRule(/^\s?([*-])\s$/, {
5823
- kind: "bullet",
5824
- collapsed: false
5825
- }),
5826
- wrappingListInputRule(/^\s?(\d+)\.\s$/, ({ match }) => {
5827
- const text = match[1];
5828
- const num = text ? parseInt(text, 10) : void 0;
5829
- return {
5830
- kind: "ordered",
5831
- collapsed: false,
5832
- order: num && num >= 2 && Number.isSafeInteger(num) ? num : null
5833
- };
5834
- }),
5835
- wrappingListInputRule(/^\s?\[([\sX]?)\]\s$/i, ({ match }) => {
5836
- return {
5837
- kind: "task",
5838
- checked: ["x", "X"].includes(match[1]),
5839
- collapsed: false
5840
- };
5841
- }),
5842
- wrappingListInputRule(/^\s?\+\s$/, {
5835
+ const circleTaskListInputRule = {
5836
+ regexp: /^\s?\+\s$/,
5837
+ getAttrs: {
5843
5838
  kind: "task",
5844
5839
  marker: "+",
5845
5840
  checked: false,
5846
5841
  collapsed: false
5847
- })
5848
- ];
5842
+ }
5843
+ };
5844
+ function defineListInputRule({ regexp, getAttrs }) {
5845
+ return defineBlockInputRule(regexp, createListInputRuleHandler(getAttrs));
5846
+ }
5849
5847
  function defineMeowdownListInputRules() {
5850
- return union(listInputRules.map(defineInputRule));
5848
+ return union(defineListInputRule(bulletListInputRule), defineListInputRule(orderedListInputRule), defineListInputRule(taskListInputRule), defineListInputRule(circleTaskListInputRule));
5851
5849
  }
5852
5850
  /**
5853
5851
  * Circle checkbox task: a `task` list item with a `+` marker.
@@ -7343,7 +7341,7 @@ function defineYouTubeVideoClickHandler(getOnClick) {
7343
7341
  //#endregion
7344
7342
  //#region src/extensions/extension.ts
7345
7343
  function defineEditorExtensionImpl(options) {
7346
- return union(defineMeowdownParagraph(), defineDoc(), defineDocFrontmatterAttr(), defineText(), defineBlockquote(), defineMeowdownList(), defineHeading(), defineTable(), defineCodeBlock$1(), defineMeowdownHorizontalRule(), defineHTMLComment(), defineInlineMarks(), defineEditorConfig(options), defineImage(getEditorConfig), defineFileView(getEditorConfig), defineModClickPrevention(), defineFileClickHandler((state) => getEditorConfig(state).onFileClick), defineImageClickHandler((state) => getEditorConfig(state).onImageClick), defineXPostMediaClickHandler((state) => getEditorConfig(state).onXPostMediaClick), defineYouTubeVideoClickHandler((state) => getEditorConfig(state).onYouTubeVideoClick), defineWikilinkClickHandler((state) => getEditorConfig(state).onWikilinkClick), defineTagClickHandler((state) => getEditorConfig(state).onTagClick), defineLinkClickHandler((state) => getEditorConfig(state).onLinkClick), defineFollowLinkHandler(getEditorConfig), defineExitBoundaryHandler((state) => getEditorConfig(state).onExitBoundary), defineFilePaste(getEditorConfig), defineEmbedPaste((state) => !!getEditorConfig(state).embedPaste), defineLinkPaste((state) => !!getEditorConfig(state).linkPaste), defineBulletAfterHeading((state) => !!getEditorConfig(state).bulletAfterHeading), defineBackspaceEmptyFirstBlock((state) => !!getEditorConfig(state).backspaceDeletesEmptyFirstBlock), defineSubstitution((state) => !!getEditorConfig(state).substitution), defineWikilinkTrigger((state) => !!getEditorConfig(state).wikilinkEnabled), definePlaceholder$1({
7344
+ return union(defineMeowdownParagraph(), defineDoc(), defineDocFrontmatterAttr(), defineText(), defineMeowdownBlockquote(), defineMeowdownList(), defineHeading(), defineTable(), defineCodeBlock(), defineMeowdownHorizontalRule(), defineHTMLComment(), defineInlineMarks(), defineEditorConfig(options), defineImage(getEditorConfig), defineFileView(getEditorConfig), defineModClickPrevention(), defineFileClickHandler((state) => getEditorConfig(state).onFileClick), defineImageClickHandler((state) => getEditorConfig(state).onImageClick), defineXPostMediaClickHandler((state) => getEditorConfig(state).onXPostMediaClick), defineYouTubeVideoClickHandler((state) => getEditorConfig(state).onYouTubeVideoClick), defineWikilinkClickHandler((state) => getEditorConfig(state).onWikilinkClick), defineTagClickHandler((state) => getEditorConfig(state).onTagClick), defineLinkClickHandler((state) => getEditorConfig(state).onLinkClick), defineFollowLinkHandler(getEditorConfig), defineExitBoundaryHandler((state) => getEditorConfig(state).onExitBoundary), defineFilePaste(getEditorConfig), defineEmbedPaste((state) => !!getEditorConfig(state).embedPaste), defineLinkPaste((state) => !!getEditorConfig(state).linkPaste), defineBulletAfterHeading((state) => !!getEditorConfig(state).bulletAfterHeading), defineBackspaceEmptyFirstBlock((state) => !!getEditorConfig(state).backspaceDeletesEmptyFirstBlock), defineSubstitution((state) => !!getEditorConfig(state).substitution), defineWikilinkTrigger((state) => !!getEditorConfig(state).wikilinkEnabled), definePlaceholder$1({
7347
7345
  placeholder: (state) => {
7348
7346
  const placeholder = getEditorConfig(state).placeholder;
7349
7347
  return typeof placeholder === "function" ? placeholder(state) : placeholder ?? "";
@@ -7355,7 +7353,7 @@ function defineEditorExtensionImpl(options) {
7355
7353
  if (editorClassName) attributes.class += ` ${editorClassName}`;
7356
7354
  if (spellCheck != null) attributes.spellcheck = String(spellCheck);
7357
7355
  return attributes;
7358
- }), defineCodeBlockSyntaxHighlight(), defineCrossEditorDrag(), defineClickBelow(), defineEscapeCollapse(), defineSoftBreak(), defineMoveBlock(), defineSelectDocBoundary(), defineInlineMarkPlugin(getEditorConfig), defineInlineToggle(), defineLinkCommands(), defineWikilink(), defineMath(), defineMarkMode(getMarkMode), defineClipboard(), defineScrollToSelection(), defineHiddenRunCaret(), defineSystemSubstitutionGuard(), defineAtomMarkNavigation({ marks: ATOM_SOURCE_MARK_NAMES.map((name) => ({
7356
+ }), defineCodeBlockSyntaxHighlight(), defineCrossEditorDrag(), defineClickBelow(), defineEscapeCollapse(), defineSoftBreak(), defineMoveBlock(), defineSelectDocBoundary(), defineSingleParagraph(), defineInlineMarkPlugin(getEditorConfig), defineInlineToggle(), defineLinkCommands(), defineWikilink(), defineMath(), defineMarkMode(getMarkMode), defineClipboard(), defineScrollToSelection(), defineHiddenRunCaret(), defineSystemSubstitutionGuard(), defineAtomMarkNavigation({ marks: ATOM_SOURCE_MARK_NAMES.map((name) => ({
7359
7357
  name,
7360
7358
  modes: [
7361
7359
  "hide",
@@ -8134,4 +8132,4 @@ function getVirtualElementFromRange(view, range) {
8134
8132
  }
8135
8133
 
8136
8134
  //#endregion
8137
- export { EDITOR_KEY_BINDINGS, Priority, buildFileMarkdown, checkRoundTrip, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defaultResolveXPost, defaultResolveYouTubeVideo, defineBackspaceEmptyFirstBlock, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineCodeBlockSyntaxHighlight, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLComment, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkCommands, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMath, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSingleParagraph, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, defineXPostMediaClickHandler, defineYouTubeVideoClickHandler, dismissLinkHover, docToMarkdown, docToParagraphMarkdown, formatFileSize, formatSizedWikiEmbed, getCodeTokens, getEditorConfig, getFileKind, getIsComposing, getLinkText, getLinkUnitAt, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunks, inlineTextToMarkChunksWithContext, insertLink, isCodeBlockPreviewHiddenDecoration, isLinkTextForHref, isMarkOfType, isModEvent, isNodeOfType, isReferenceDefinitionNode, isSelectionInTableCell, loadKaTeX, markdownToDoc, normalizeHref, paragraphMarkdownToDoc, parsePostEmbedSnapshot, parseWikiEmbed, removeLink, renderMathInto, updateEditorConfig, updateLink, wikiEmbedBasename, withPriority };
8135
+ export { EDITOR_KEY_BINDINGS, Priority, buildFileMarkdown, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defaultResolveXPost, defaultResolveYouTubeVideo, defineBackspaceEmptyFirstBlock, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineCodeBlockSyntaxHighlight, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLComment, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkCommands, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMath, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, defineXPostMediaClickHandler, defineYouTubeVideoClickHandler, dismissLinkHover, docToMarkdown, docToParagraphMarkdown, formatFileSize, formatSizedWikiEmbed, getCodeTokens, getEditorConfig, getFileKind, getIsComposing, getLinkText, getLinkUnitAt, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunks, inlineTextToMarkChunksWithContext, insertLink, isCodeBlockPreviewHiddenDecoration, isLinkTextForHref, isMarkOfType, isModEvent, isNodeOfType, isReferenceDefinitionNode, isSelectionInTableCell, loadKaTeX, markdownToDoc, normalizeHref, paragraphMarkdownToDoc, parsePostEmbedSnapshot, parseWikiEmbed, removeLink, renderMathInto, updateEditorConfig, updateLink, wikiEmbedBasename, withPriority };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meowdown/core",
3
3
  "type": "module",
4
- "version": "0.79.0",
4
+ "version": "0.81.0",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -26,24 +26,25 @@
26
26
  "@floating-ui/dom": "^1.8.0",
27
27
  "@lezer/highlight": "^1.2.5",
28
28
  "@meowdown/embed": "0.3.1",
29
- "@meowdown/markdown": "0.76.0",
30
- "@ocavue/utils": "^1.8.0",
29
+ "@meowdown/markdown": "0.76.1",
30
+ "@ocavue/utils": "^1.9.0",
31
31
  "@post-embed/exporter": "^0.5.0",
32
32
  "@post-embed/schema": "^0.5.2",
33
33
  "@post-embed/types": "^0.5.0",
34
34
  "@prosekit/core": "^0.13.3",
35
- "@prosekit/extensions": "^0.18.3",
35
+ "@prosekit/extensions": "^0.18.4",
36
36
  "@prosekit/pm": "^0.1.20",
37
- "@prosekit/web": "^0.9.3",
37
+ "@prosekit/web": "^0.9.4",
38
38
  "hast-util-to-mdast": "^10.1.2",
39
39
  "katex": "^0.19.0",
40
40
  "lru.min": "^1.1.5",
41
41
  "mdast-util-to-markdown": "^2.2.0",
42
42
  "micromark-util-decode-string": "^2.0.1",
43
43
  "micromark-util-normalize-identifier": "^2.0.1",
44
- "prosemirror-flat-list": "^0.7.2",
44
+ "prosemirror-enter-rules": "^0.1.6",
45
+ "prosemirror-flat-list": "^0.7.3",
45
46
  "prosemirror-highlight": "^0.16.0",
46
- "rehype-parse": "^9.0.0",
47
+ "rehype-parse": "^9.0.1",
47
48
  "rehype-remark": "^10.0.1",
48
49
  "remark-gfm": "^4.0.1",
49
50
  "remark-stringify": "^11.0.0",
@@ -54,13 +55,13 @@
54
55
  "devDependencies": {
55
56
  "@meowdown/vitest": "0.0.0",
56
57
  "@ocavue/tsconfig": "^0.7.1",
57
- "@tsdown/css": "^0.23.0",
58
+ "@tsdown/css": "^0.23.1",
58
59
  "@types/hast": "^3.0.5",
59
60
  "@types/mdast": "^4.0.4",
60
61
  "@vitest/browser-playwright": "^5.0.3",
61
62
  "dedent": "^1.7.2",
62
63
  "diffable-html-snapshot": "^0.3.0",
63
- "tsdown": "^0.23.0",
64
+ "tsdown": "^0.23.1",
64
65
  "vitest": "^5.0.3"
65
66
  },
66
67
  "publishConfig": {