@meowdown/core 0.79.0 → 0.80.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/dist/index.d.ts +12 -28
- package/dist/index.js +126 -121
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { Command, EditorState, PluginKey } from "@prosekit/pm/state";
|
|
|
7
7
|
import { EditorView } from "@prosekit/pm/view";
|
|
8
8
|
import { EditorNode, Mark, ProseMirrorNode } from "@prosekit/pm/model";
|
|
9
9
|
import { ListAttrs } from "@prosekit/extensions/list";
|
|
10
|
-
import {
|
|
10
|
+
import { HorizontalRuleCommandsExtension, HorizontalRuleSpecExtension } from "@prosekit/extensions/horizontal-rule";
|
|
11
11
|
import { Resolver, XPostMediaClickEvent } from "@meowdown/embed/x";
|
|
12
12
|
import { YouTubeVideoClickEvent } from "@meowdown/embed/youtube";
|
|
13
13
|
import "prosemirror-flat-list";
|
|
@@ -117,7 +117,7 @@ type HorizontalRuleMarkerExtension = Extension<{
|
|
|
117
117
|
horizontalRule: MeowdownHorizontalRuleAttrs;
|
|
118
118
|
};
|
|
119
119
|
}>;
|
|
120
|
-
type MeowdownHorizontalRuleExtension = Union<[
|
|
120
|
+
type MeowdownHorizontalRuleExtension = Union<[HorizontalRuleSpecExtension, HorizontalRuleCommandsExtension, HorizontalRuleMarkerExtension]>;
|
|
121
121
|
//#endregion
|
|
122
122
|
//#region src/extensions/html-comment.d.ts
|
|
123
123
|
interface MeowdownHTMLCommentAttrs {
|
|
@@ -1101,6 +1101,13 @@ interface EditorConfig extends InlineMarkOptions, FollowLinkHandlers, FilePasteO
|
|
|
1101
1101
|
bulletAfterHeading?: boolean;
|
|
1102
1102
|
backspaceDeletesEmptyFirstBlock?: boolean;
|
|
1103
1103
|
substitution?: boolean;
|
|
1104
|
+
/**
|
|
1105
|
+
* Keep the document to one paragraph of inline Markdown: typed block
|
|
1106
|
+
* prefixes (`# `, `> `, `- `, ```` ``` ````) stay literal and pasted blocks
|
|
1107
|
+
* flatten into soft lines. Seed the editor with `paragraphMarkdownToDoc` and
|
|
1108
|
+
* read it with `docToParagraphMarkdown`.
|
|
1109
|
+
*/
|
|
1110
|
+
singleParagraph?: boolean;
|
|
1104
1111
|
wikilinkEnabled?: boolean;
|
|
1105
1112
|
placeholder?: PlaceholderOptions$1['placeholder'];
|
|
1106
1113
|
readOnly?: boolean;
|
|
@@ -1123,7 +1130,7 @@ declare function defineEditorExtensionImpl(options: EditorExtensionOptions): imp
|
|
|
1123
1130
|
frontmatter?: Frontmatter;
|
|
1124
1131
|
};
|
|
1125
1132
|
};
|
|
1126
|
-
}>, import("@prosekit/extensions/text").TextExtension, import("@prosekit/extensions/blockquote").
|
|
1133
|
+
}>, 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
1134
|
Nodes: {
|
|
1128
1135
|
list: {
|
|
1129
1136
|
marker?: ListMarker;
|
|
@@ -1176,7 +1183,7 @@ declare function defineEditorExtensionImpl(options: EditorExtensionOptions): imp
|
|
|
1176
1183
|
Nodes: {
|
|
1177
1184
|
tableHeaderCell: import("@prosekit/pm/model").Attrs;
|
|
1178
1185
|
};
|
|
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").
|
|
1186
|
+
}>]>, 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
1187
|
Nodes: {
|
|
1181
1188
|
codeBlock: {
|
|
1182
1189
|
fenceStyle?: CodeBlockFenceStyle | null;
|
|
@@ -1256,7 +1263,7 @@ declare function defineEditorExtensionImpl(options: EditorExtensionOptions): imp
|
|
|
1256
1263
|
Commands: {
|
|
1257
1264
|
insertSoftBreak: [];
|
|
1258
1265
|
};
|
|
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<{
|
|
1266
|
+
}>, 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
1267
|
Commands: {
|
|
1261
1268
|
toggleEm: [];
|
|
1262
1269
|
toggleStrong: [];
|
|
@@ -1681,27 +1688,4 @@ export declare function paragraphMarkdownToDoc(markdown: string, nodes?: TypedNo
|
|
|
1681
1688
|
*/
|
|
1682
1689
|
export declare function docToParagraphMarkdown(doc: ProseMirrorNode): string;
|
|
1683
1690
|
//#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
1691
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { LEZER_NODE_IDS, checkRoundTrip, collectInlineElements, getAutolinkHref, gfmParser, isSpaceChar, matchEmbed, parseInline, parseMarkdownAst, parseXPostId, serializeMarkdownAst } from "@meowdown/markdown";
|
|
2
2
|
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 {
|
|
3
|
+
import { codeBlockEnterRule, codeBlockInputRule, defineCodeBlockCommands, defineCodeBlockHighlight, defineCodeBlockKeymap, defineCodeBlockPreviewPlugin, defineCodeBlockSpec, isCodeBlockPreviewHiddenDecoration } from "@prosekit/extensions/code-block";
|
|
4
4
|
import { definePlaceholder, definePlaceholder as definePlaceholder$1 } from "@prosekit/extensions/placeholder";
|
|
5
5
|
import { defineSearchCommands, defineSearchQuery, defineSearchStatusHandler, getSearchStatus, getSearchStatus as getSearchStatus$1 } from "@prosekit/extensions/search";
|
|
6
6
|
import { isElementLike, isHTMLElement, isObject, once } from "@ocavue/utils";
|
|
7
|
-
import { defineBlockquote } from "@prosekit/extensions/blockquote";
|
|
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,
|
|
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 {
|
|
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,
|
|
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(),
|
|
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
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
});
|
|
1854
|
-
}
|
|
1940
|
+
const tildeFenceInputRule = {
|
|
1941
|
+
regex: /^~~~(\S*)\s$/,
|
|
1942
|
+
type: "codeBlock",
|
|
1943
|
+
attrs: getTildeFenceAttrs
|
|
1944
|
+
};
|
|
1855
1945
|
function defineTildeFenceEnterRule() {
|
|
1856
|
-
return
|
|
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
|
|
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
|
|
1873
|
-
return union(
|
|
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(
|
|
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, !
|
|
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 =
|
|
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 =
|
|
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 {
|
|
@@ -5818,36 +5839,20 @@ function normalizeTaskList(node) {
|
|
|
5818
5839
|
node.replaceChildren(...content.children);
|
|
5819
5840
|
textBlock.prepend(checkbox);
|
|
5820
5841
|
}
|
|
5821
|
-
const
|
|
5822
|
-
|
|
5823
|
-
|
|
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$/, {
|
|
5842
|
+
const circleTaskListInputRule = {
|
|
5843
|
+
regexp: /^\s?\+\s$/,
|
|
5844
|
+
getAttrs: {
|
|
5843
5845
|
kind: "task",
|
|
5844
5846
|
marker: "+",
|
|
5845
5847
|
checked: false,
|
|
5846
5848
|
collapsed: false
|
|
5847
|
-
}
|
|
5848
|
-
|
|
5849
|
+
}
|
|
5850
|
+
};
|
|
5851
|
+
function defineListInputRule({ regexp, getAttrs }) {
|
|
5852
|
+
return defineBlockInputRule(regexp, createListInputRuleHandler(getAttrs));
|
|
5853
|
+
}
|
|
5849
5854
|
function defineMeowdownListInputRules() {
|
|
5850
|
-
return union(
|
|
5855
|
+
return union(defineListInputRule(bulletListInputRule), defineListInputRule(orderedListInputRule), defineListInputRule(taskListInputRule), defineListInputRule(circleTaskListInputRule));
|
|
5851
5856
|
}
|
|
5852
5857
|
/**
|
|
5853
5858
|
* Circle checkbox task: a `task` list item with a `+` marker.
|
|
@@ -7343,7 +7348,7 @@ function defineYouTubeVideoClickHandler(getOnClick) {
|
|
|
7343
7348
|
//#endregion
|
|
7344
7349
|
//#region src/extensions/extension.ts
|
|
7345
7350
|
function defineEditorExtensionImpl(options) {
|
|
7346
|
-
return union(defineMeowdownParagraph(), defineDoc(), defineDocFrontmatterAttr(), defineText(),
|
|
7351
|
+
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
7352
|
placeholder: (state) => {
|
|
7348
7353
|
const placeholder = getEditorConfig(state).placeholder;
|
|
7349
7354
|
return typeof placeholder === "function" ? placeholder(state) : placeholder ?? "";
|
|
@@ -7355,7 +7360,7 @@ function defineEditorExtensionImpl(options) {
|
|
|
7355
7360
|
if (editorClassName) attributes.class += ` ${editorClassName}`;
|
|
7356
7361
|
if (spellCheck != null) attributes.spellcheck = String(spellCheck);
|
|
7357
7362
|
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) => ({
|
|
7363
|
+
}), 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
7364
|
name,
|
|
7360
7365
|
modes: [
|
|
7361
7366
|
"hide",
|
|
@@ -8134,4 +8139,4 @@ function getVirtualElementFromRange(view, range) {
|
|
|
8134
8139
|
}
|
|
8135
8140
|
|
|
8136
8141
|
//#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,
|
|
8142
|
+
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, 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.
|
|
4
|
+
"version": "0.80.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -32,7 +32,7 @@
|
|
|
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.
|
|
35
|
+
"@prosekit/extensions": "^0.18.4",
|
|
36
36
|
"@prosekit/pm": "^0.1.20",
|
|
37
37
|
"@prosekit/web": "^0.9.3",
|
|
38
38
|
"hast-util-to-mdast": "^10.1.2",
|
|
@@ -41,7 +41,8 @@
|
|
|
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-
|
|
44
|
+
"prosemirror-enter-rules": "^0.1.6",
|
|
45
|
+
"prosemirror-flat-list": "^0.7.3",
|
|
45
46
|
"prosemirror-highlight": "^0.16.0",
|
|
46
47
|
"rehype-parse": "^9.0.0",
|
|
47
48
|
"rehype-remark": "^10.0.1",
|