@meowdown/core 0.82.0 → 0.83.1
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 +6 -133
- package/dist/index.js +264 -267
- package/dist/style.css +127 -21
- package/package.json +12 -12
package/dist/index.js
CHANGED
|
@@ -49,7 +49,7 @@ import { normalizeIdentifier } from "micromark-util-normalize-identifier";
|
|
|
49
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";
|
|
50
50
|
import { defineTableCellSpec, defineTableCommands, defineTableDropIndicator, defineTableEditingPlugin, defineTableHeaderCellSpec, defineTableRowSpec, defineTableSpec, deleteTable, isCellSelection } from "@prosekit/extensions/table";
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
// src/utils/composition.ts
|
|
53
53
|
const COMPOSITION_TAIL_MS = 50;
|
|
54
54
|
let compositionEndedAt = -1;
|
|
55
55
|
let isComposing = false;
|
|
@@ -72,8 +72,40 @@ function getIsComposing() {
|
|
|
72
72
|
return isComposing || compositionEndedAt > 0 && Date.now() - compositionEndedAt <= COMPOSITION_TAIL_MS;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
// src/utils/guard-plugin.ts
|
|
76
|
+
/**
|
|
77
|
+
* Wrap an `appendTransaction` so that a throw is reported with `reportError`
|
|
78
|
+
* and appends nothing. Otherwise the whole dispatch fails, and text the
|
|
79
|
+
* browser already inserted never reaches the editor state.
|
|
80
|
+
*/
|
|
81
|
+
function guardAppendTransaction(appendTransaction) {
|
|
82
|
+
return (transactions, oldState, newState) => {
|
|
83
|
+
try {
|
|
84
|
+
return appendTransaction(transactions, oldState, newState);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
reportError(error);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Wrap a `decorations` prop so that a throw is reported with `reportError` and
|
|
93
|
+
* draws no decorations. ProseMirror reads decorations in the middle of a view
|
|
94
|
+
* update and in `EditorView.destroy`, where a throw leaves the view half
|
|
95
|
+
* updated.
|
|
96
|
+
*/
|
|
97
|
+
function guardDecorations(decorations) {
|
|
98
|
+
return (state) => {
|
|
99
|
+
try {
|
|
100
|
+
return decorations(state);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
reportError(error);
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/utils/input-modality.ts
|
|
77
109
|
const KEYBOARD_MODALITY_KEYS = /* @__PURE__ */ new Set([
|
|
78
110
|
"ArrowLeft",
|
|
79
111
|
"ArrowRight",
|
|
@@ -146,8 +178,7 @@ function onIsTouchInputChange(listener) {
|
|
|
146
178
|
};
|
|
147
179
|
}
|
|
148
180
|
|
|
149
|
-
|
|
150
|
-
//#region src/utils/transaction.ts
|
|
181
|
+
// src/utils/transaction.ts
|
|
151
182
|
/**
|
|
152
183
|
* Whether any of the given transactions are selection transactions directly caused by mouse or touch input.
|
|
153
184
|
*/
|
|
@@ -155,8 +186,7 @@ function hasPointerSelectionTransaction(transactions) {
|
|
|
155
186
|
return getIsPointerSelection() && transactions.some((tr) => tr.selectionSet && !tr.docChanged);
|
|
156
187
|
}
|
|
157
188
|
|
|
158
|
-
|
|
159
|
-
//#region src/extensions/editor-config-getter.ts
|
|
189
|
+
// src/extensions/editor-config-getter.ts
|
|
160
190
|
const defaultConfig = Object.freeze({});
|
|
161
191
|
const configKey = new PluginKey("meowdown-editor-config");
|
|
162
192
|
/**
|
|
@@ -166,8 +196,7 @@ function getEditorConfig(state) {
|
|
|
166
196
|
return configKey.getState(state)?.config ?? defaultConfig;
|
|
167
197
|
}
|
|
168
198
|
|
|
169
|
-
|
|
170
|
-
//#region src/extensions/mark-mode-config.ts
|
|
199
|
+
// src/extensions/mark-mode-config.ts
|
|
171
200
|
/**
|
|
172
201
|
* The active mark mode, defaulting to focus when no configuration is provided.
|
|
173
202
|
*/
|
|
@@ -175,8 +204,7 @@ function getMarkMode(state) {
|
|
|
175
204
|
return getEditorConfig(state).markMode ?? "focus";
|
|
176
205
|
}
|
|
177
206
|
|
|
178
|
-
|
|
179
|
-
//#region src/extensions/mark-names.ts
|
|
207
|
+
// src/extensions/mark-names.ts
|
|
180
208
|
function isMarkOfType(mark, name) {
|
|
181
209
|
return mark.type.name === name;
|
|
182
210
|
}
|
|
@@ -200,8 +228,7 @@ const ATOM_SOURCE_MARK_NAMES = [
|
|
|
200
228
|
"mdFile"
|
|
201
229
|
];
|
|
202
230
|
|
|
203
|
-
|
|
204
|
-
//#region src/extensions/hidden-run.ts
|
|
231
|
+
// src/extensions/hidden-run.ts
|
|
205
232
|
function getCharMarks(state, pos) {
|
|
206
233
|
if (pos < 0 || pos + 1 > state.doc.content.size) return;
|
|
207
234
|
const $pos = state.doc.resolve(pos);
|
|
@@ -341,8 +368,7 @@ function getUnitMarkerRuns(state, charPos) {
|
|
|
341
368
|
return runs;
|
|
342
369
|
}
|
|
343
370
|
|
|
344
|
-
|
|
345
|
-
//#region src/extensions/mark-range.ts
|
|
371
|
+
// src/extensions/mark-range.ts
|
|
346
372
|
/**
|
|
347
373
|
* Returns the resolved position, or `undefined` when it falls outside the
|
|
348
374
|
* document or in a place that carries no inline marks: marks describe inline
|
|
@@ -425,8 +451,7 @@ function getMarkRangeStrictlyAround(state, pos, markNames) {
|
|
|
425
451
|
}
|
|
426
452
|
}
|
|
427
453
|
|
|
428
|
-
|
|
429
|
-
//#region src/extensions/atom-mark-navigation.ts
|
|
454
|
+
// src/extensions/atom-mark-navigation.ts
|
|
430
455
|
function getActiveMarkNames(marks, state) {
|
|
431
456
|
const mode = getMarkMode(state);
|
|
432
457
|
const result = [];
|
|
@@ -563,7 +588,7 @@ function getUnitEdge(range, oldPos, newPos, isPointer) {
|
|
|
563
588
|
function createCaretSnapPlugin(marks) {
|
|
564
589
|
return new Plugin({
|
|
565
590
|
key: new PluginKey("atom-mark-caret-snap"),
|
|
566
|
-
appendTransaction: (transactions, oldState, newState) => {
|
|
591
|
+
appendTransaction: guardAppendTransaction((transactions, oldState, newState) => {
|
|
567
592
|
if (getIsComposing()) return null;
|
|
568
593
|
const markNames = getActiveMarkNames(marks, newState);
|
|
569
594
|
if (markNames.length === 0) return null;
|
|
@@ -583,14 +608,14 @@ function createCaretSnapPlugin(marks) {
|
|
|
583
608
|
const isPointer = hasPointerSelectionTransaction(transactions);
|
|
584
609
|
const head = getUnitEdge(range, oldState.selection.head, selection.head, isPointer);
|
|
585
610
|
return newState.tr.setSelection(TextSelection.create(newState.doc, head));
|
|
586
|
-
}
|
|
611
|
+
})
|
|
587
612
|
});
|
|
588
613
|
}
|
|
589
614
|
const SELECTED_CLASS = "md-atom-selected";
|
|
590
615
|
function createSelectionPlugin(marks) {
|
|
591
616
|
return new Plugin({
|
|
592
617
|
key: new PluginKey("atom-mark-selection"),
|
|
593
|
-
props: { decorations: (state) => {
|
|
618
|
+
props: { decorations: guardDecorations((state) => {
|
|
594
619
|
const markNames = getActiveMarkNames(marks, state);
|
|
595
620
|
if (markNames.length === 0) return;
|
|
596
621
|
if (isNodeSelection(state.selection)) return;
|
|
@@ -603,7 +628,7 @@ function createSelectionPlugin(marks) {
|
|
|
603
628
|
if (node.marks.some((mark) => markNames.includes(mark.type.name))) decorations.push(Decoration.inline(pos, pos + node.nodeSize, { class: SELECTED_CLASS }));
|
|
604
629
|
});
|
|
605
630
|
return DecorationSet.create(state.doc, decorations);
|
|
606
|
-
} }
|
|
631
|
+
}) }
|
|
607
632
|
});
|
|
608
633
|
}
|
|
609
634
|
/**
|
|
@@ -624,14 +649,12 @@ function defineAtomMarkNavigation({ marks }) {
|
|
|
624
649
|
}), Priority$1.high), definePlugin(createCaretSnapPlugin(marks)), definePlugin(createSelectionPlugin(marks)));
|
|
625
650
|
}
|
|
626
651
|
|
|
627
|
-
|
|
628
|
-
//#region src/extensions/node-names.ts
|
|
652
|
+
// src/extensions/node-names.ts
|
|
629
653
|
function isNodeOfType(node, name) {
|
|
630
654
|
return node.type.name === name;
|
|
631
655
|
}
|
|
632
656
|
|
|
633
|
-
|
|
634
|
-
//#region src/extensions/backspace-empty-first-block.ts
|
|
657
|
+
// src/extensions/backspace-empty-first-block.ts
|
|
635
658
|
/**
|
|
636
659
|
* Claim Backspace only when the selection is an empty caret in an empty
|
|
637
660
|
* paragraph that is the document's first block and has a block after it.
|
|
@@ -662,8 +685,7 @@ function defineBackspaceEmptyFirstBlock(enabled) {
|
|
|
662
685
|
} }), Priority$1.lowest);
|
|
663
686
|
}
|
|
664
687
|
|
|
665
|
-
|
|
666
|
-
//#region src/converters/paragraph.ts
|
|
688
|
+
// src/converters/paragraph.ts
|
|
667
689
|
/**
|
|
668
690
|
* Build one paragraph without interpreting block-opening Markdown.
|
|
669
691
|
*/
|
|
@@ -689,8 +711,7 @@ function docToParagraphMarkdown(doc) {
|
|
|
689
711
|
return paragraphs.join("\n").replaceAll(/\n[ \t]*\n+/g, "\n");
|
|
690
712
|
}
|
|
691
713
|
|
|
692
|
-
|
|
693
|
-
//#region src/extensions/single-paragraph.ts
|
|
714
|
+
// src/extensions/single-paragraph.ts
|
|
694
715
|
const singleParagraphPluginKey = new PluginKey("single-paragraph");
|
|
695
716
|
/**
|
|
696
717
|
* Whether the editor holds one paragraph of inline Markdown (the
|
|
@@ -708,7 +729,7 @@ function isSingleParagraph(state) {
|
|
|
708
729
|
function defineSingleParagraph() {
|
|
709
730
|
return withPriority$1(definePlugin(new Plugin({
|
|
710
731
|
key: singleParagraphPluginKey,
|
|
711
|
-
appendTransaction(transactions, _oldState, state) {
|
|
732
|
+
appendTransaction: guardAppendTransaction((transactions, _oldState, state) => {
|
|
712
733
|
if (!isSingleParagraph(state)) return;
|
|
713
734
|
if (!transactions.some((transaction) => transaction.docChanged)) return;
|
|
714
735
|
const markdown = docToParagraphMarkdown(state.doc);
|
|
@@ -717,12 +738,11 @@ function defineSingleParagraph() {
|
|
|
717
738
|
const position = Math.min(state.selection.head, doc.content.size - 1);
|
|
718
739
|
const transaction = state.tr.replaceWith(0, state.doc.content.size, doc.content);
|
|
719
740
|
return transaction.setSelection(TextSelection.create(transaction.doc, Math.max(1, position)));
|
|
720
|
-
}
|
|
741
|
+
})
|
|
721
742
|
})), Priority$1.highest);
|
|
722
743
|
}
|
|
723
744
|
|
|
724
|
-
|
|
725
|
-
//#region src/extensions/block-rule.ts
|
|
745
|
+
// src/extensions/block-rule.ts
|
|
726
746
|
/**
|
|
727
747
|
* An input rule whose match turns the textblock into, or wraps it in, a block
|
|
728
748
|
* node. In a single paragraph the match is left as typed text: there is no
|
|
@@ -747,14 +767,12 @@ function defineBlockEnterRule(options) {
|
|
|
747
767
|
});
|
|
748
768
|
}
|
|
749
769
|
|
|
750
|
-
|
|
751
|
-
//#region src/extensions/blockquote.ts
|
|
770
|
+
// src/extensions/blockquote.ts
|
|
752
771
|
function defineMeowdownBlockquote() {
|
|
753
772
|
return union(defineBlockquoteSpec(), defineBlockquoteCommands(), defineBlockquoteKeymap(), defineBlockInputRule(blockquoteInputRule.regex, createWrappingInputRuleHandler(blockquoteInputRule)));
|
|
754
773
|
}
|
|
755
774
|
|
|
756
|
-
|
|
757
|
-
//#region src/extensions/bullet-after-heading.ts
|
|
775
|
+
// src/extensions/bullet-after-heading.ts
|
|
758
776
|
/**
|
|
759
777
|
* Claim Enter only when the selection is an empty caret at the very end of the
|
|
760
778
|
* document's first heading (the note's title line). Every other Enter (a later
|
|
@@ -788,8 +806,7 @@ function defineBulletAfterHeading(enabled) {
|
|
|
788
806
|
} }), Priority$1.high);
|
|
789
807
|
}
|
|
790
808
|
|
|
791
|
-
|
|
792
|
-
//#region src/extensions/click-below.ts
|
|
809
|
+
// src/extensions/click-below.ts
|
|
793
810
|
const clickBelowKey = new PluginKey("meowdown-click-below");
|
|
794
811
|
function acceptsCaretAtEnd(node) {
|
|
795
812
|
return node.isTextblock && !node.type.spec.code;
|
|
@@ -827,8 +844,7 @@ function defineClickBelow() {
|
|
|
827
844
|
}));
|
|
828
845
|
}
|
|
829
846
|
|
|
830
|
-
|
|
831
|
-
//#region src/converters/html-to-md.ts
|
|
847
|
+
// src/converters/html-to-md.ts
|
|
832
848
|
/**
|
|
833
849
|
* Convert a `<mark>` element into a `highlight` node. There is no built-in
|
|
834
850
|
* `hast-util-to-mdast` handler for `<mark>`, so without this the highlight is
|
|
@@ -974,8 +990,7 @@ function htmlToMarkdown(html, parser) {
|
|
|
974
990
|
return processor.stringify(processor.runSync(hast));
|
|
975
991
|
}
|
|
976
992
|
|
|
977
|
-
|
|
978
|
-
//#region src/utils/parse-integer.ts
|
|
993
|
+
// src/utils/parse-integer.ts
|
|
979
994
|
function parseInteger(raw) {
|
|
980
995
|
if (raw == null) return void 0;
|
|
981
996
|
const value = Number.parseInt(raw, 10);
|
|
@@ -986,8 +1001,7 @@ function parsePositiveInteger(raw) {
|
|
|
986
1001
|
return value != null && value > 0 ? value : void 0;
|
|
987
1002
|
}
|
|
988
1003
|
|
|
989
|
-
|
|
990
|
-
//#region src/extensions/inline-runs.ts
|
|
1004
|
+
// src/extensions/inline-runs.ts
|
|
991
1005
|
function findAtomMark(marks) {
|
|
992
1006
|
return marks.find((mark) => isMarkOfTypes(mark, ATOM_MARK_NAMES));
|
|
993
1007
|
}
|
|
@@ -1029,8 +1043,7 @@ function groupInlineRuns(textblock) {
|
|
|
1029
1043
|
return runs;
|
|
1030
1044
|
}
|
|
1031
1045
|
|
|
1032
|
-
|
|
1033
|
-
//#region src/extensions/clipboard/semantic-inline.ts
|
|
1046
|
+
// src/extensions/clipboard/semantic-inline.ts
|
|
1034
1047
|
const SEMANTIC_TAGS = {
|
|
1035
1048
|
mdStrong: "strong",
|
|
1036
1049
|
mdEm: "em",
|
|
@@ -1134,8 +1147,7 @@ function atomUnitToDOM(atom, sourceText) {
|
|
|
1134
1147
|
}
|
|
1135
1148
|
}
|
|
1136
1149
|
|
|
1137
|
-
|
|
1138
|
-
//#region src/extensions/heading.ts
|
|
1150
|
+
// src/extensions/heading.ts
|
|
1139
1151
|
/**
|
|
1140
1152
|
* Merge `whitespace: 'pre'` onto the base heading spec. A multi-line setext
|
|
1141
1153
|
* heading keeps a soft line break as a literal `\n`; without `whitespace: 'pre'`
|
|
@@ -1222,8 +1234,7 @@ function defineHeading() {
|
|
|
1222
1234
|
return union(defineHeadingSpec(), defineHeadingWhitespace(), defineSetextUnderlineAttr(), defineHeadingClosingHashesAttr(), defineBlockInputRule(headingInputRule.regex, createTextBlockInputRuleHandler(headingInputRule)), defineHeadingCommands(), defineHeadingKeymap());
|
|
1223
1235
|
}
|
|
1224
1236
|
|
|
1225
|
-
|
|
1226
|
-
//#region src/extensions/paragraph.ts
|
|
1237
|
+
// src/extensions/paragraph.ts
|
|
1227
1238
|
function defineMeowdownParagraphSpec() {
|
|
1228
1239
|
return defineNodeSpec({
|
|
1229
1240
|
name: "paragraph",
|
|
@@ -1252,8 +1263,7 @@ function defineMeowdownParagraph() {
|
|
|
1252
1263
|
return union(withPriority$1(defineMeowdownParagraphSpec(), Priority$1.highest), defineParagraphCommands(), defineParagraphKeymap());
|
|
1253
1264
|
}
|
|
1254
1265
|
|
|
1255
|
-
|
|
1256
|
-
//#region src/extensions/clipboard/clipboard-serializer.ts
|
|
1266
|
+
// src/extensions/clipboard/clipboard-serializer.ts
|
|
1257
1267
|
function withSemanticTextblocks(nodes) {
|
|
1258
1268
|
return {
|
|
1259
1269
|
...nodes,
|
|
@@ -1297,8 +1307,7 @@ function getSemanticDOMSerializer(schema) {
|
|
|
1297
1307
|
return serializer;
|
|
1298
1308
|
}
|
|
1299
1309
|
|
|
1300
|
-
|
|
1301
|
-
//#region src/extensions/html-paste.ts
|
|
1310
|
+
// src/extensions/html-paste.ts
|
|
1302
1311
|
const htmlPasteKey = new PluginKey("meowdown-html-paste");
|
|
1303
1312
|
/**
|
|
1304
1313
|
* meowdown's own clipboard HTML, which must skip the markdown conversion and
|
|
@@ -1422,8 +1431,7 @@ function defineHTMLPaste() {
|
|
|
1422
1431
|
}));
|
|
1423
1432
|
}
|
|
1424
1433
|
|
|
1425
|
-
|
|
1426
|
-
//#region src/extensions/clipboard/clipboard-parser.ts
|
|
1434
|
+
// src/extensions/clipboard/clipboard-parser.ts
|
|
1427
1435
|
/**
|
|
1428
1436
|
* The clipboard parser: schema rules plus the `data-md` rules that restore a
|
|
1429
1437
|
* textblock's source text from meowdown's own clipboard HTML. Registered as
|
|
@@ -1446,8 +1454,7 @@ function defineClipboardParser() {
|
|
|
1446
1454
|
});
|
|
1447
1455
|
}
|
|
1448
1456
|
|
|
1449
|
-
|
|
1450
|
-
//#region src/extensions/clipboard/plain-paste.ts
|
|
1457
|
+
// src/extensions/clipboard/plain-paste.ts
|
|
1451
1458
|
/**
|
|
1452
1459
|
* Parse pasted plain text as markdown: `- [ ] task`, `# heading`, fenced code
|
|
1453
1460
|
* and the other block constructs become real nodes, while inline syntax stays
|
|
@@ -1504,8 +1511,7 @@ function definePlainTextPaste() {
|
|
|
1504
1511
|
}));
|
|
1505
1512
|
}
|
|
1506
1513
|
|
|
1507
|
-
|
|
1508
|
-
//#region src/converters/pm-to-ast.ts
|
|
1514
|
+
// src/converters/pm-to-ast.ts
|
|
1509
1515
|
/**
|
|
1510
1516
|
* Read persisted block data. Editor marks do not add Markdown delimiters.
|
|
1511
1517
|
*/
|
|
@@ -1513,6 +1519,7 @@ function docToAst(node) {
|
|
|
1513
1519
|
if (isNodeOfType(node, "doc")) return {
|
|
1514
1520
|
type: "document",
|
|
1515
1521
|
frontmatter: node.attrs.frontmatter ?? void 0,
|
|
1522
|
+
frontmatterTight: node.attrs.frontmatterTight ? true : void 0,
|
|
1516
1523
|
children: readBlocks(node)
|
|
1517
1524
|
};
|
|
1518
1525
|
if (isNodeOfType(node, "tableRow")) return readTableRow(node);
|
|
@@ -1642,8 +1649,7 @@ function readTableCell(node) {
|
|
|
1642
1649
|
};
|
|
1643
1650
|
}
|
|
1644
1651
|
|
|
1645
|
-
|
|
1646
|
-
//#region src/converters/pm-to-md.ts
|
|
1652
|
+
// src/converters/pm-to-md.ts
|
|
1647
1653
|
/**
|
|
1648
1654
|
* Convert persisted editor content to Markdown through the shared block serializer.
|
|
1649
1655
|
*/
|
|
@@ -1651,8 +1657,7 @@ function docToMarkdown(node, options = {}) {
|
|
|
1651
1657
|
return serializeMarkdownAst(docToAst(node), options);
|
|
1652
1658
|
}
|
|
1653
1659
|
|
|
1654
|
-
|
|
1655
|
-
//#region src/utils/top-level-block-boundary.ts
|
|
1660
|
+
// src/utils/top-level-block-boundary.ts
|
|
1656
1661
|
function isAtTopLevelBlockStart($pos) {
|
|
1657
1662
|
if ($pos.depth === 0) return true;
|
|
1658
1663
|
if ($pos.parentOffset !== 0) return false;
|
|
@@ -1666,8 +1671,7 @@ function isAtTopLevelBlockEnd($pos) {
|
|
|
1666
1671
|
return true;
|
|
1667
1672
|
}
|
|
1668
1673
|
|
|
1669
|
-
|
|
1670
|
-
//#region src/extensions/clipboard/plain-text.ts
|
|
1674
|
+
// src/extensions/clipboard/plain-text.ts
|
|
1671
1675
|
/**
|
|
1672
1676
|
* Serialize a slice to Markdown. A block whose content start is not selected is
|
|
1673
1677
|
* flattened so its opening markers are not synthesized. Incomplete fenced code
|
|
@@ -1783,8 +1787,7 @@ function filterTextblock(textblock) {
|
|
|
1783
1787
|
return textblock.copy(Fragment.from(parts));
|
|
1784
1788
|
}
|
|
1785
1789
|
|
|
1786
|
-
|
|
1787
|
-
//#region src/extensions/clipboard/clipboard.ts
|
|
1790
|
+
// src/extensions/clipboard/clipboard.ts
|
|
1788
1791
|
/**
|
|
1789
1792
|
* The clipboard pipeline: semantic HTML with `data-md` round-trip attributes
|
|
1790
1793
|
* plus a markdown-shaped `text/plain` on copy; the matching `data-md` parser,
|
|
@@ -1795,8 +1798,7 @@ function defineClipboard() {
|
|
|
1795
1798
|
return union(defineSemanticClipboardSerializer(), definePlainTextSerializer(), defineClipboardParser(), defineHTMLPaste(), definePlainTextPaste());
|
|
1796
1799
|
}
|
|
1797
1800
|
|
|
1798
|
-
|
|
1799
|
-
//#region src/extensions/code-block-highlight.ts
|
|
1801
|
+
// src/extensions/code-block-highlight.ts
|
|
1800
1802
|
const supportCache = /* @__PURE__ */ new Map();
|
|
1801
1803
|
const parserCache = /* @__PURE__ */ new Map();
|
|
1802
1804
|
const LANGUAGE_ALIASES = { math: "latex" };
|
|
@@ -1876,8 +1878,7 @@ function getCodeTokens(code, language) {
|
|
|
1876
1878
|
return loadLanguageSupport(trimmed).then((loaded) => loaded ? tokenize(code, loaded) : []);
|
|
1877
1879
|
}
|
|
1878
1880
|
|
|
1879
|
-
|
|
1880
|
-
//#region src/extensions/code-block-exit.ts
|
|
1881
|
+
// src/extensions/code-block-exit.ts
|
|
1881
1882
|
/**
|
|
1882
1883
|
* With the caret at the end of a code block, move it into the block below when
|
|
1883
1884
|
* that block is an empty paragraph, and into a new default block otherwise.
|
|
@@ -1908,8 +1909,7 @@ function defineCodeBlockExitKeymap() {
|
|
|
1908
1909
|
return defineKeymap({ "Mod-Enter": exitCodeBlockAtEnd });
|
|
1909
1910
|
}
|
|
1910
1911
|
|
|
1911
|
-
|
|
1912
|
-
//#region src/extensions/code-block.ts
|
|
1912
|
+
// src/extensions/code-block.ts
|
|
1913
1913
|
function defineFenceStyleAttr() {
|
|
1914
1914
|
return defineNodeAttr({
|
|
1915
1915
|
type: "codeBlock",
|
|
@@ -1934,6 +1934,29 @@ function defineFenceLengthAttr() {
|
|
|
1934
1934
|
}
|
|
1935
1935
|
});
|
|
1936
1936
|
}
|
|
1937
|
+
/**
|
|
1938
|
+
* Re-declare the code block `toDOM` with a `data-code-block` root attribute.
|
|
1939
|
+
*/
|
|
1940
|
+
function defineCodeBlockDOM() {
|
|
1941
|
+
return defineNodeSpec({
|
|
1942
|
+
name: "codeBlock",
|
|
1943
|
+
toDOM: (node) => {
|
|
1944
|
+
const { language } = node.attrs;
|
|
1945
|
+
return [
|
|
1946
|
+
"pre",
|
|
1947
|
+
{
|
|
1948
|
+
"data-code-block": "",
|
|
1949
|
+
"data-language": language || void 0
|
|
1950
|
+
},
|
|
1951
|
+
[
|
|
1952
|
+
"code",
|
|
1953
|
+
{ class: language ? `language-${language}` : void 0 },
|
|
1954
|
+
0
|
|
1955
|
+
]
|
|
1956
|
+
];
|
|
1957
|
+
}
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1937
1960
|
function getTildeFenceAttrs(match) {
|
|
1938
1961
|
return {
|
|
1939
1962
|
language: match[1] || "",
|
|
@@ -1963,11 +1986,10 @@ function defineDollarFenceEnterRule() {
|
|
|
1963
1986
|
});
|
|
1964
1987
|
}
|
|
1965
1988
|
function defineCodeBlock() {
|
|
1966
|
-
return union(defineCodeBlockSpec(), defineCodeBlockKeymap(), defineCodeBlockCommands(), defineBlockInputRule(codeBlockInputRule.regex, createTextBlockInputRuleHandler(codeBlockInputRule)), defineBlockEnterRule(codeBlockEnterRule), defineFenceStyleAttr(), defineFenceLengthAttr(), defineBlockInputRule(tildeFenceInputRule.regex, createTextBlockInputRuleHandler(tildeFenceInputRule)), defineTildeFenceEnterRule(), defineDollarFenceEnterRule(), defineCodeBlockExitKeymap());
|
|
1989
|
+
return union(defineCodeBlockSpec(), defineCodeBlockDOM(), defineCodeBlockKeymap(), defineCodeBlockCommands(), defineBlockInputRule(codeBlockInputRule.regex, createTextBlockInputRuleHandler(codeBlockInputRule)), defineBlockEnterRule(codeBlockEnterRule), defineFenceStyleAttr(), defineFenceLengthAttr(), defineBlockInputRule(tildeFenceInputRule.regex, createTextBlockInputRuleHandler(tildeFenceInputRule)), defineTildeFenceEnterRule(), defineDollarFenceEnterRule(), defineCodeBlockExitKeymap());
|
|
1967
1990
|
}
|
|
1968
1991
|
|
|
1969
|
-
|
|
1970
|
-
//#region src/extensions/commands.ts
|
|
1992
|
+
// src/extensions/commands.ts
|
|
1971
1993
|
function selectText(anchor, head) {
|
|
1972
1994
|
return (state, dispatch) => {
|
|
1973
1995
|
if (dispatch) {
|
|
@@ -2052,8 +2074,7 @@ function defineEditorCommands() {
|
|
|
2052
2074
|
});
|
|
2053
2075
|
}
|
|
2054
2076
|
|
|
2055
|
-
|
|
2056
|
-
//#region src/extensions/cross-editor-drag.ts
|
|
2077
|
+
// src/extensions/cross-editor-drag.ts
|
|
2057
2078
|
function deleteDraggedContent(view, dragging) {
|
|
2058
2079
|
const tr = view.state.tr;
|
|
2059
2080
|
if (dragging.node) {
|
|
@@ -2100,8 +2121,7 @@ function defineCrossEditorDrag() {
|
|
|
2100
2121
|
return definePlugin(createCrossEditorDragPlugin());
|
|
2101
2122
|
}
|
|
2102
2123
|
|
|
2103
|
-
|
|
2104
|
-
//#region src/extensions/editor-config.ts
|
|
2124
|
+
// src/extensions/editor-config.ts
|
|
2105
2125
|
var ConfigController = class {
|
|
2106
2126
|
constructor(config) {
|
|
2107
2127
|
this.config = config;
|
|
@@ -2158,16 +2178,14 @@ function defineEditorConfig(initialConfig) {
|
|
|
2158
2178
|
}));
|
|
2159
2179
|
}
|
|
2160
2180
|
|
|
2161
|
-
|
|
2162
|
-
//#region src/extensions/paste.ts
|
|
2181
|
+
// src/extensions/paste.ts
|
|
2163
2182
|
function getPastedText(event, slice) {
|
|
2164
2183
|
const fromClipboard = event.clipboardData?.getData("text/plain");
|
|
2165
2184
|
if (fromClipboard) return fromClipboard;
|
|
2166
2185
|
return slice.content.textBetween(0, slice.content.size, "\n");
|
|
2167
2186
|
}
|
|
2168
2187
|
|
|
2169
|
-
|
|
2170
|
-
//#region src/extensions/embed-paste.ts
|
|
2188
|
+
// src/extensions/embed-paste.ts
|
|
2171
2189
|
const embedPasteKey = new PluginKey("meowdown-embed-paste");
|
|
2172
2190
|
function detectEmbedUrl(text) {
|
|
2173
2191
|
const trimmed = text.trim();
|
|
@@ -2203,8 +2221,7 @@ function defineEmbedPaste(enabled) {
|
|
|
2203
2221
|
}));
|
|
2204
2222
|
}
|
|
2205
2223
|
|
|
2206
|
-
|
|
2207
|
-
//#region src/extensions/escape-collapse.ts
|
|
2224
|
+
// src/extensions/escape-collapse.ts
|
|
2208
2225
|
/**
|
|
2209
2226
|
* Collapses a non-empty selection to a caret at its head. Leaves an empty
|
|
2210
2227
|
* selection alone so Escape can serve whoever binds it next.
|
|
@@ -2224,8 +2241,7 @@ function defineEscapeCollapse() {
|
|
|
2224
2241
|
return withPriority$1(defineKeymap({ Escape: collapseSelection }), Priority$1.low);
|
|
2225
2242
|
}
|
|
2226
2243
|
|
|
2227
|
-
|
|
2228
|
-
//#region src/extensions/exit-boundary.ts
|
|
2244
|
+
// src/extensions/exit-boundary.ts
|
|
2229
2245
|
const exitBoundaryKey = new PluginKey("meowdown-exit-boundary");
|
|
2230
2246
|
function canMoveBlockwise(state, direction) {
|
|
2231
2247
|
const { $anchor, $head } = state.selection;
|
|
@@ -2266,8 +2282,7 @@ function defineExitBoundaryHandler(getExitBoundaryHandler) {
|
|
|
2266
2282
|
return withPriority$1(definePlugin(createExitBoundaryPlugin(getExitBoundaryHandler)), Priority$1.low);
|
|
2267
2283
|
}
|
|
2268
2284
|
|
|
2269
|
-
|
|
2270
|
-
//#region src/utils/is-mod-event.ts
|
|
2285
|
+
// src/utils/is-mod-event.ts
|
|
2271
2286
|
/**
|
|
2272
2287
|
* Whether the platform's mod key is held on `event`: `Command` on Apple, `Ctrl` elsewhere.
|
|
2273
2288
|
*/
|
|
@@ -2275,8 +2290,7 @@ function isModEvent(event) {
|
|
|
2275
2290
|
return isApple ? event.metaKey : event.ctrlKey;
|
|
2276
2291
|
}
|
|
2277
2292
|
|
|
2278
|
-
|
|
2279
|
-
//#region src/extensions/file-click.ts
|
|
2293
|
+
// src/extensions/file-click.ts
|
|
2280
2294
|
const fileClickKey = new PluginKey("meowdown-file-click");
|
|
2281
2295
|
function findFileAt(state, pos) {
|
|
2282
2296
|
const range = getMarkRangeAt(state, pos, "mdFile");
|
|
@@ -2317,8 +2331,7 @@ function defineFileClickHandler(getOnClick) {
|
|
|
2317
2331
|
}));
|
|
2318
2332
|
}
|
|
2319
2333
|
|
|
2320
|
-
|
|
2321
|
-
//#region src/extensions/file-paste.ts
|
|
2334
|
+
// src/extensions/file-paste.ts
|
|
2322
2335
|
const filePasteKey = new PluginKey("file-paste");
|
|
2323
2336
|
const IMAGE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
2324
2337
|
"avif",
|
|
@@ -2421,8 +2434,7 @@ function defineFilePaste(getOptions) {
|
|
|
2421
2434
|
return withPriority$1(definePlugin(createFilePastePlugin(getOptions)), Priority$1.high);
|
|
2422
2435
|
}
|
|
2423
2436
|
|
|
2424
|
-
|
|
2425
|
-
//#region src/utils/format-file-size.ts
|
|
2437
|
+
// src/utils/format-file-size.ts
|
|
2426
2438
|
const UNITS = [
|
|
2427
2439
|
"KB",
|
|
2428
2440
|
"MB",
|
|
@@ -2445,8 +2457,46 @@ function formatFileSize(bytes) {
|
|
|
2445
2457
|
return `${value < 9.95 ? Math.round(value * 10) / 10 : Math.round(value)} ${unit}`;
|
|
2446
2458
|
}
|
|
2447
2459
|
|
|
2448
|
-
|
|
2449
|
-
|
|
2460
|
+
// src/utils/guard-mark-view.ts
|
|
2461
|
+
/**
|
|
2462
|
+
* Wrap a mark view constructor so that a throw from it, or from the view's
|
|
2463
|
+
* `update` or `destroy`, is reported with `reportError` instead of leaving
|
|
2464
|
+
* ProseMirror's view tree half updated. A constructor that throws gets a bare
|
|
2465
|
+
* `<span>`, which keeps the mark's source text editable.
|
|
2466
|
+
*/
|
|
2467
|
+
function guardMarkView(constructor) {
|
|
2468
|
+
return (mark, view, inline) => {
|
|
2469
|
+
let markView;
|
|
2470
|
+
try {
|
|
2471
|
+
markView = constructor(mark, view, inline);
|
|
2472
|
+
} catch (error) {
|
|
2473
|
+
reportError(error);
|
|
2474
|
+
return { dom: document.createElement("span") };
|
|
2475
|
+
}
|
|
2476
|
+
return {
|
|
2477
|
+
dom: markView.dom,
|
|
2478
|
+
contentDOM: markView.contentDOM,
|
|
2479
|
+
ignoreMutation: markView.ignoreMutation?.bind(markView),
|
|
2480
|
+
update: (next) => {
|
|
2481
|
+
try {
|
|
2482
|
+
return markView.update?.(next) ?? false;
|
|
2483
|
+
} catch (error) {
|
|
2484
|
+
reportError(error);
|
|
2485
|
+
return false;
|
|
2486
|
+
}
|
|
2487
|
+
},
|
|
2488
|
+
destroy: () => {
|
|
2489
|
+
try {
|
|
2490
|
+
markView.destroy?.();
|
|
2491
|
+
} catch (error) {
|
|
2492
|
+
reportError(error);
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
};
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
// src/extensions/file-view.ts
|
|
2450
2500
|
/**
|
|
2451
2501
|
* `data-file-kind` values by file extension, for host CSS theming.
|
|
2452
2502
|
*/
|
|
@@ -2596,17 +2646,16 @@ var FileMarkView = class {
|
|
|
2596
2646
|
function defineFileView(getOptions) {
|
|
2597
2647
|
return defineMarkView({
|
|
2598
2648
|
name: "mdFile",
|
|
2599
|
-
constructor: (mark, view) => new FileMarkView(mark, getOptions?.(view.state))
|
|
2649
|
+
constructor: guardMarkView((mark, view) => new FileMarkView(mark, getOptions?.(view.state)))
|
|
2600
2650
|
});
|
|
2601
2651
|
}
|
|
2602
2652
|
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
const revealActiveMatch = new Plugin({ props: { decorations: (state) => {
|
|
2653
|
+
// src/extensions/find.ts
|
|
2654
|
+
const revealActiveMatch = new Plugin({ props: { decorations: guardDecorations((state) => {
|
|
2606
2655
|
const { from, to, empty } = state.selection;
|
|
2607
2656
|
if (empty || getSearchStatus$1(state).active === 0) return;
|
|
2608
2657
|
return DecorationSet.create(state.doc, [Decoration.inline(from, to, { class: "show" })]);
|
|
2609
|
-
} } });
|
|
2658
|
+
}) } });
|
|
2610
2659
|
/**
|
|
2611
2660
|
* Find over the editor's text. `setSearchQuery` highlights every match and
|
|
2612
2661
|
* selects the first one at or after the caret; `findNext` and `findPrev` walk
|
|
@@ -2617,8 +2666,7 @@ function defineFind() {
|
|
|
2617
2666
|
return union(defineSearchQuery(), defineSearchCommands(), definePlugin(revealActiveMatch));
|
|
2618
2667
|
}
|
|
2619
2668
|
|
|
2620
|
-
|
|
2621
|
-
//#region src/extensions/get-link-unit-at.ts
|
|
2669
|
+
// src/extensions/get-link-unit-at.ts
|
|
2622
2670
|
/**
|
|
2623
2671
|
* The last text run carrying `markName` inside `range`. "Last" so a linked
|
|
2624
2672
|
* image's inner url/title (which comes first) never shadows the link's own.
|
|
@@ -2712,8 +2760,7 @@ function getLinkUnitAt(state, pos) {
|
|
|
2712
2760
|
}
|
|
2713
2761
|
}
|
|
2714
2762
|
|
|
2715
|
-
|
|
2716
|
-
//#region src/extensions/image-click.ts
|
|
2763
|
+
// src/extensions/image-click.ts
|
|
2717
2764
|
const imageClickKey = new PluginKey("meowdown-image-click");
|
|
2718
2765
|
/**
|
|
2719
2766
|
* The image preview wrapper around `target`, or nothing when the wrapper holds
|
|
@@ -2850,8 +2897,7 @@ function defineImageClickHandler(getOnClick) {
|
|
|
2850
2897
|
}));
|
|
2851
2898
|
}
|
|
2852
2899
|
|
|
2853
|
-
|
|
2854
|
-
//#region src/extensions/mark-click.ts
|
|
2900
|
+
// src/extensions/mark-click.ts
|
|
2855
2901
|
/**
|
|
2856
2902
|
* Shared click plumbing for text-backed marks (wikilinks, Markdown links, tags):
|
|
2857
2903
|
* a click anywhere on the rendered mark fires `onClick`.
|
|
@@ -2872,8 +2918,7 @@ function defineMarkClickHandler(config) {
|
|
|
2872
2918
|
}));
|
|
2873
2919
|
}
|
|
2874
2920
|
|
|
2875
|
-
|
|
2876
|
-
//#region src/extensions/tag-click.ts
|
|
2921
|
+
// src/extensions/tag-click.ts
|
|
2877
2922
|
const tagClickKey = new PluginKey("meowdown-tag-click");
|
|
2878
2923
|
/**
|
|
2879
2924
|
* The tag covering `pos`, found via the `mdTag` run. The tag name is read from
|
|
@@ -2914,8 +2959,7 @@ function defineTagClickHandler(getOnClick) {
|
|
|
2914
2959
|
});
|
|
2915
2960
|
}
|
|
2916
2961
|
|
|
2917
|
-
|
|
2918
|
-
//#region src/extensions/wikilink-click.ts
|
|
2962
|
+
// src/extensions/wikilink-click.ts
|
|
2919
2963
|
const wikilinkClickKey = new PluginKey("meowdown-wikilink-click");
|
|
2920
2964
|
/**
|
|
2921
2965
|
* Exported for tests.
|
|
@@ -2966,8 +3010,7 @@ function defineWikilinkClickHandler(getOnClick) {
|
|
|
2966
3010
|
});
|
|
2967
3011
|
}
|
|
2968
3012
|
|
|
2969
|
-
|
|
2970
|
-
//#region src/extensions/follow-link.ts
|
|
3013
|
+
// src/extensions/follow-link.ts
|
|
2971
3014
|
const followLinkKey = new PluginKey("meowdown-follow-link");
|
|
2972
3015
|
function createFollowLinkPlugin(getHandlers) {
|
|
2973
3016
|
return new Plugin({
|
|
@@ -3059,33 +3102,35 @@ function defineFollowLinkHandler(getHandlers) {
|
|
|
3059
3102
|
return withPriority$1(definePlugin(createFollowLinkPlugin(getHandlers)), Priority$1.high);
|
|
3060
3103
|
}
|
|
3061
3104
|
|
|
3062
|
-
|
|
3063
|
-
//#region src/extensions/frontmatter.ts
|
|
3105
|
+
// src/extensions/frontmatter.ts
|
|
3064
3106
|
/**
|
|
3065
|
-
* Stores YAML frontmatter as a non-rendered attribute on the root `doc` node
|
|
3107
|
+
* Stores YAML frontmatter as a non-rendered attribute on the root `doc` node,
|
|
3108
|
+
* plus whether the first block starts right under its closing fence.
|
|
3066
3109
|
*/
|
|
3067
3110
|
function defineDocFrontmatterAttr() {
|
|
3068
|
-
return defineNodeAttr({
|
|
3111
|
+
return union(defineNodeAttr({
|
|
3069
3112
|
type: "doc",
|
|
3070
3113
|
attr: "frontmatter",
|
|
3071
3114
|
default: null
|
|
3072
|
-
})
|
|
3115
|
+
}), defineNodeAttr({
|
|
3116
|
+
type: "doc",
|
|
3117
|
+
attr: "frontmatterTight",
|
|
3118
|
+
default: false
|
|
3119
|
+
}));
|
|
3073
3120
|
}
|
|
3074
3121
|
|
|
3075
|
-
|
|
3076
|
-
//#region src/utils/execute-command.ts
|
|
3122
|
+
// src/utils/execute-command.ts
|
|
3077
3123
|
function executeCommand(view, command) {
|
|
3078
3124
|
return command(view.state, view.dispatch, view);
|
|
3079
3125
|
}
|
|
3080
3126
|
|
|
3081
|
-
|
|
3082
|
-
//#region src/extensions/hidden-run-caret.ts
|
|
3127
|
+
// src/extensions/hidden-run-caret.ts
|
|
3083
3128
|
const snapKey = new PluginKey("meowdown-hidden-run-snap");
|
|
3084
3129
|
const beforeInputKey = new PluginKey("meowdown-hidden-run-beforeinput");
|
|
3085
3130
|
function createSnapPlugin() {
|
|
3086
3131
|
return new Plugin({
|
|
3087
3132
|
key: snapKey,
|
|
3088
|
-
appendTransaction: (transactions, oldState, newState) => {
|
|
3133
|
+
appendTransaction: guardAppendTransaction((transactions, oldState, newState) => {
|
|
3089
3134
|
if (getIsComposing()) return null;
|
|
3090
3135
|
if (getMarkMode(newState) !== "hide") return null;
|
|
3091
3136
|
const selection = newState.selection;
|
|
@@ -3102,7 +3147,7 @@ function createSnapPlugin() {
|
|
|
3102
3147
|
const anchor = selection.anchor === selection.from ? from : to;
|
|
3103
3148
|
const head = selection.head === selection.from ? from : to;
|
|
3104
3149
|
return newState.tr.setSelection(TextSelection.create(newState.doc, anchor, head));
|
|
3105
|
-
}
|
|
3150
|
+
})
|
|
3106
3151
|
});
|
|
3107
3152
|
}
|
|
3108
3153
|
const relocateEnterSplit = (state, dispatch) => {
|
|
@@ -3155,8 +3200,7 @@ function defineHiddenRunCaret() {
|
|
|
3155
3200
|
}), Priority$1.highest));
|
|
3156
3201
|
}
|
|
3157
3202
|
|
|
3158
|
-
|
|
3159
|
-
//#region src/extensions/horizontal-rule.ts
|
|
3203
|
+
// src/extensions/horizontal-rule.ts
|
|
3160
3204
|
function defineHorizontalRuleMarkerAttr() {
|
|
3161
3205
|
return defineNodeAttr({
|
|
3162
3206
|
type: "horizontalRule",
|
|
@@ -3170,8 +3214,7 @@ function defineMeowdownHorizontalRule() {
|
|
|
3170
3214
|
return union(defineHorizontalRuleSpec(), defineHorizontalRuleCommands(), defineHorizontalRuleMarkerAttr(), defineBlockInputRule(horizontalRuleInputRule.regex, horizontalRuleInputRule.handler));
|
|
3171
3215
|
}
|
|
3172
3216
|
|
|
3173
|
-
|
|
3174
|
-
//#region src/utils/non-prose-attrs.ts
|
|
3217
|
+
// src/utils/non-prose-attrs.ts
|
|
3175
3218
|
const NON_PROSE_ATTRS = {
|
|
3176
3219
|
spellcheck: "false",
|
|
3177
3220
|
autocorrect: "off",
|
|
@@ -3179,8 +3222,7 @@ const NON_PROSE_ATTRS = {
|
|
|
3179
3222
|
writingsuggestions: "false"
|
|
3180
3223
|
};
|
|
3181
3224
|
|
|
3182
|
-
|
|
3183
|
-
//#region src/extensions/html-comment.ts
|
|
3225
|
+
// src/extensions/html-comment.ts
|
|
3184
3226
|
/**
|
|
3185
3227
|
* A block-level HTML comment (`<!-- ... -->`) as an invisible, atomic node.
|
|
3186
3228
|
*
|
|
@@ -3219,8 +3261,7 @@ function defineHTMLComment() {
|
|
|
3219
3261
|
});
|
|
3220
3262
|
}
|
|
3221
3263
|
|
|
3222
|
-
|
|
3223
|
-
//#region src/utils/to-positive-number.ts
|
|
3264
|
+
// src/utils/to-positive-number.ts
|
|
3224
3265
|
/**
|
|
3225
3266
|
* The value rounded to an integer, or nothing unless it is a finite number
|
|
3226
3267
|
* above zero.
|
|
@@ -3229,8 +3270,7 @@ function toPositiveNumber(value) {
|
|
|
3229
3270
|
if (typeof value === "number" && Number.isFinite(value) && value > 0) return Math.round(value);
|
|
3230
3271
|
}
|
|
3231
3272
|
|
|
3232
|
-
|
|
3233
|
-
//#region src/extensions/magic-comment.ts
|
|
3273
|
+
// src/extensions/magic-comment.ts
|
|
3234
3274
|
const MAGIC_COMMENT_RE = /^<!--\s*(\{[\s\S]*?\})\s*-->/;
|
|
3235
3275
|
const TRAILING_MAGIC_COMMENT_RE = /(?:<!--\s*\{[\s\S]*?\}\s*-->)+$/;
|
|
3236
3276
|
/**
|
|
@@ -3277,8 +3317,7 @@ function stripMagicComment(source) {
|
|
|
3277
3317
|
return source.replace(TRAILING_MAGIC_COMMENT_RE, "");
|
|
3278
3318
|
}
|
|
3279
3319
|
|
|
3280
|
-
|
|
3281
|
-
//#region src/extensions/post-embed.ts
|
|
3320
|
+
// src/extensions/post-embed.ts
|
|
3282
3321
|
/**
|
|
3283
3322
|
* Wrap a loader in a 64-entry LRU keyed by URL. A settled URL answers
|
|
3284
3323
|
* synchronously, so a revisited document renders its cards in the first
|
|
@@ -3339,8 +3378,7 @@ function parsePostEmbedSnapshot(value) {
|
|
|
3339
3378
|
return result.success ? result.output : void 0;
|
|
3340
3379
|
}
|
|
3341
3380
|
|
|
3342
|
-
|
|
3343
|
-
//#region src/extensions/wiki-embed.ts
|
|
3381
|
+
// src/extensions/wiki-embed.ts
|
|
3344
3382
|
const WIKI_EMBED_SIZE = /^(\d+)(?:x(\d+))?$/i;
|
|
3345
3383
|
function positiveInteger(value) {
|
|
3346
3384
|
if (!value) return null;
|
|
@@ -3402,8 +3440,7 @@ function wikiEmbedBasename(target) {
|
|
|
3402
3440
|
}
|
|
3403
3441
|
}
|
|
3404
3442
|
|
|
3405
|
-
|
|
3406
|
-
//#region src/extensions/image.ts
|
|
3443
|
+
// src/extensions/image.ts
|
|
3407
3444
|
/**
|
|
3408
3445
|
* Show an `src` as-is when it is an http(s) URL, otherwise skip rendering it.
|
|
3409
3446
|
*/
|
|
@@ -3762,12 +3799,11 @@ var ImageMarkView = class {
|
|
|
3762
3799
|
function defineImage(getOptions) {
|
|
3763
3800
|
return defineMarkView({
|
|
3764
3801
|
name: "mdImage",
|
|
3765
|
-
constructor: (mark, view) => new ImageMarkView(mark, view, getOptions?.(view.state) ?? {})
|
|
3802
|
+
constructor: guardMarkView((mark, view) => new ImageMarkView(mark, view, getOptions?.(view.state) ?? {}))
|
|
3766
3803
|
});
|
|
3767
3804
|
}
|
|
3768
3805
|
|
|
3769
|
-
|
|
3770
|
-
//#region src/extensions/mark-chunk.ts
|
|
3806
|
+
// src/extensions/mark-chunk.ts
|
|
3771
3807
|
function markChunkToJSON(chunk) {
|
|
3772
3808
|
const [from, to, marks] = chunk;
|
|
3773
3809
|
return [
|
|
@@ -3785,8 +3821,7 @@ function markChunkFromJSON(schema, json) {
|
|
|
3785
3821
|
];
|
|
3786
3822
|
}
|
|
3787
3823
|
|
|
3788
|
-
|
|
3789
|
-
//#region src/extensions/marks-equal.ts
|
|
3824
|
+
// src/extensions/marks-equal.ts
|
|
3790
3825
|
/**
|
|
3791
3826
|
* Position-wise equality on two mark arrays. Returns `true` only when
|
|
3792
3827
|
* the arrays have the same length and `a[i].eq(b[i])` for every index.
|
|
@@ -3798,8 +3833,7 @@ function marksEqual(a, b) {
|
|
|
3798
3833
|
return true;
|
|
3799
3834
|
}
|
|
3800
3835
|
|
|
3801
|
-
|
|
3802
|
-
//#region src/extensions/batch-set-mark-step.ts
|
|
3836
|
+
// src/extensions/batch-set-mark-step.ts
|
|
3803
3837
|
const SPARSE_CHUNK_LIMIT = 32;
|
|
3804
3838
|
/**
|
|
3805
3839
|
* Apply a small batch by visiting each chunk's narrow range independently.
|
|
@@ -3968,8 +4002,7 @@ var BatchSetMarkStep = class BatchSetMarkStep extends Step {
|
|
|
3968
4002
|
Step.jsonID("batchSetMark", BatchSetMarkStep);
|
|
3969
4003
|
const emptyBatchSetMarkStep = new BatchSetMarkStep([]);
|
|
3970
4004
|
|
|
3971
|
-
|
|
3972
|
-
//#region src/extensions/reference-links.ts
|
|
4005
|
+
// src/extensions/reference-links.ts
|
|
3973
4006
|
const MAX_DEFINITION_LENGTH = 1024;
|
|
3974
4007
|
function normalizeReferenceLabel(label) {
|
|
3975
4008
|
return normalizeIdentifier(label);
|
|
@@ -4076,8 +4109,7 @@ function updateReferenceDefinitions(previous, transaction, doc) {
|
|
|
4076
4109
|
return collectReferenceDefinitions(doc);
|
|
4077
4110
|
}
|
|
4078
4111
|
|
|
4079
|
-
|
|
4080
|
-
//#region src/extensions/inline-text-to-mark-chunks.ts
|
|
4112
|
+
// src/extensions/inline-text-to-mark-chunks.ts
|
|
4081
4113
|
/**
|
|
4082
4114
|
* Lookup from Lezer node type id to the ProseMirror mark.
|
|
4083
4115
|
*
|
|
@@ -4650,8 +4682,7 @@ function emit(out, from, to, marks) {
|
|
|
4650
4682
|
]);
|
|
4651
4683
|
}
|
|
4652
4684
|
|
|
4653
|
-
|
|
4654
|
-
//#region src/extensions/inline-mark-plugin.ts
|
|
4685
|
+
// src/extensions/inline-mark-plugin.ts
|
|
4655
4686
|
const META_KEY = "inline-marks-applied";
|
|
4656
4687
|
const TRIGGER_KEY = "inline-marks-trigger";
|
|
4657
4688
|
const RESTYLE_KEY = "inline-marks-restyle";
|
|
@@ -4810,7 +4841,7 @@ function createInlineMarkPlugin(getOptions) {
|
|
|
4810
4841
|
};
|
|
4811
4842
|
}
|
|
4812
4843
|
},
|
|
4813
|
-
appendTransaction(transactions, oldState, newState) {
|
|
4844
|
+
appendTransaction: guardAppendTransaction((transactions, oldState, newState) => {
|
|
4814
4845
|
for (const tr of transactions) if (tr.getMeta(META_KEY)) return null;
|
|
4815
4846
|
const restyle = transactions.some((transaction) => transaction.getMeta(RESTYLE_KEY));
|
|
4816
4847
|
if (!(restyle || transactions.some((transaction) => {
|
|
@@ -4831,9 +4862,13 @@ function createInlineMarkPlugin(getOptions) {
|
|
|
4831
4862
|
tr.setMeta(META_KEY, true);
|
|
4832
4863
|
tr.setMeta("addToHistory", false);
|
|
4833
4864
|
return tr;
|
|
4834
|
-
},
|
|
4865
|
+
}),
|
|
4835
4866
|
view(view) {
|
|
4836
|
-
|
|
4867
|
+
try {
|
|
4868
|
+
view.dispatch(triggerInlineMarks(view.state));
|
|
4869
|
+
} catch (error) {
|
|
4870
|
+
reportError(error);
|
|
4871
|
+
}
|
|
4837
4872
|
const controller = new AbortController();
|
|
4838
4873
|
const flush = (currentView) => {
|
|
4839
4874
|
if (currentView.isDestroyed) return;
|
|
@@ -4877,8 +4912,7 @@ function defineInlineMarkPlugin(getOptions) {
|
|
|
4877
4912
|
return definePlugin(createInlineMarkPlugin(getOptions));
|
|
4878
4913
|
}
|
|
4879
4914
|
|
|
4880
|
-
|
|
4881
|
-
//#region src/extensions/inline-marks.ts
|
|
4915
|
+
// src/extensions/inline-marks.ts
|
|
4882
4916
|
function defineMdImage() {
|
|
4883
4917
|
return defineMarkSpec({
|
|
4884
4918
|
name: "mdImage",
|
|
@@ -5107,8 +5141,7 @@ function defineInlineMarks() {
|
|
|
5107
5141
|
return union(defineMdMark(), defineMdEm(), defineMdStrong(), defineMdCode(), defineMdLinkText(), defineMdLinkUri(), defineMdLinkTitle(), defineMdDel(), defineMdHighlight(), defineMdTag(), defineMdWikilink(), defineMdImage(), defineMdFile(), defineMdMath(), defineMdPack());
|
|
5108
5142
|
}
|
|
5109
5143
|
|
|
5110
|
-
|
|
5111
|
-
//#region src/utils/backticks.ts
|
|
5144
|
+
// src/utils/backticks.ts
|
|
5112
5145
|
/**
|
|
5113
5146
|
* Length of the longest run of `charCode` in `text`, at least `min`.
|
|
5114
5147
|
*/
|
|
@@ -5128,8 +5161,7 @@ function longestBacktickRun(text, min = 0) {
|
|
|
5128
5161
|
return longestCharRun(text, 96, min);
|
|
5129
5162
|
}
|
|
5130
5163
|
|
|
5131
|
-
|
|
5132
|
-
//#region src/extensions/inline-toggle.ts
|
|
5164
|
+
// src/extensions/inline-toggle.ts
|
|
5133
5165
|
const TOGGLE_SPECS = {
|
|
5134
5166
|
em: {
|
|
5135
5167
|
node: LEZER_NODE_IDS.Emphasis,
|
|
@@ -5383,8 +5415,7 @@ function insideAtom(nodes, pos) {
|
|
|
5383
5415
|
return false;
|
|
5384
5416
|
}
|
|
5385
5417
|
|
|
5386
|
-
|
|
5387
|
-
//#region src/extensions/inline-toggle-commands.ts
|
|
5418
|
+
// src/extensions/inline-toggle-commands.ts
|
|
5388
5419
|
function toggleInline(spec) {
|
|
5389
5420
|
return (state, dispatch) => {
|
|
5390
5421
|
if (state.selection.empty) return caretToggle(spec, state, dispatch);
|
|
@@ -5466,8 +5497,7 @@ function defineInlineToggle() {
|
|
|
5466
5497
|
return union(defineInlineToggleCommands(), defineInlineToggleKeymap());
|
|
5467
5498
|
}
|
|
5468
5499
|
|
|
5469
|
-
|
|
5470
|
-
//#region src/extensions/link-click.ts
|
|
5500
|
+
// src/extensions/link-click.ts
|
|
5471
5501
|
const linkClickKey = new PluginKey("meowdown-link-click");
|
|
5472
5502
|
/**
|
|
5473
5503
|
* Call `onClick` when the user clicks a rendered Markdown link
|
|
@@ -5492,8 +5522,7 @@ function defineLinkClickHandler(getOnClick) {
|
|
|
5492
5522
|
});
|
|
5493
5523
|
}
|
|
5494
5524
|
|
|
5495
|
-
|
|
5496
|
-
//#region src/extensions/link-commands.ts
|
|
5525
|
+
// src/extensions/link-commands.ts
|
|
5497
5526
|
/**
|
|
5498
5527
|
* Normalize a typed URL with the existing autolink logic, else keep it verbatim.
|
|
5499
5528
|
*/
|
|
@@ -5661,8 +5690,7 @@ function defineLinkEditKeymap(onLinkEdit) {
|
|
|
5661
5690
|
return defineKeymap({ "Mod-k": openLinkEdit(onLinkEdit) });
|
|
5662
5691
|
}
|
|
5663
5692
|
|
|
5664
|
-
|
|
5665
|
-
//#region src/extensions/link-paste.ts
|
|
5693
|
+
// src/extensions/link-paste.ts
|
|
5666
5694
|
const linkPasteKey = new PluginKey("meowdown-link-paste");
|
|
5667
5695
|
/**
|
|
5668
5696
|
* The pasted text as a link `href` when the clipboard holds exactly one URL:
|
|
@@ -5704,8 +5732,7 @@ function defineLinkPaste(enabled) {
|
|
|
5704
5732
|
})), Priority$1.high);
|
|
5705
5733
|
}
|
|
5706
5734
|
|
|
5707
|
-
|
|
5708
|
-
//#region src/extensions/list.ts
|
|
5735
|
+
// src/extensions/list.ts
|
|
5709
5736
|
function serializeListMarker(value) {
|
|
5710
5737
|
return value === ")" || value === "*" || value === "+" ? value : void 0;
|
|
5711
5738
|
}
|
|
@@ -6092,15 +6119,14 @@ function defineMeowdownList() {
|
|
|
6092
6119
|
return union(defineListSpec(), defineMeowdownListPlugins(), defineListCommands(), defineMeowdownListSerializer(), defineListDropIndicator(), defineMeowdownListInputRules(), defineMeowdownListKeymap(), defineListMarkerAttr(), defineListTaskMarkerAttr(), defineListMarkerGapAttr(), defineMeowdownListCommands());
|
|
6093
6120
|
}
|
|
6094
6121
|
|
|
6095
|
-
|
|
6096
|
-
//#region src/extensions/mark-mode.ts
|
|
6122
|
+
// src/extensions/mark-mode.ts
|
|
6097
6123
|
function createMarkModePlugin(getMode) {
|
|
6098
6124
|
return new Plugin({ props: {
|
|
6099
6125
|
attributes: (state) => ({ "data-mark-mode": getMode(state) }),
|
|
6100
|
-
decorations: (state) => {
|
|
6126
|
+
decorations: guardDecorations((state) => {
|
|
6101
6127
|
const mode = getMode(state);
|
|
6102
6128
|
return mode === "focus" || mode === "hide" ? computeRevealDecorations(state, mode) : void 0;
|
|
6103
|
-
}
|
|
6129
|
+
})
|
|
6104
6130
|
} });
|
|
6105
6131
|
}
|
|
6106
6132
|
function findRevealablePack($pos, mode, direction) {
|
|
@@ -6150,8 +6176,7 @@ function defineMarkMode(getMode) {
|
|
|
6150
6176
|
return definePlugin(createMarkModePlugin(getMode));
|
|
6151
6177
|
}
|
|
6152
6178
|
|
|
6153
|
-
|
|
6154
|
-
//#region src/utils/katex.ts
|
|
6179
|
+
// src/utils/katex.ts
|
|
6155
6180
|
let katexRenderPromise;
|
|
6156
6181
|
/**
|
|
6157
6182
|
* Load KaTeX's render function on first use and cache it. Most documents
|
|
@@ -6179,8 +6204,7 @@ function renderMathInto(katexRender, element, formula, displayMode) {
|
|
|
6179
6204
|
}
|
|
6180
6205
|
}
|
|
6181
6206
|
|
|
6182
|
-
|
|
6183
|
-
//#region src/extensions/math.ts
|
|
6207
|
+
// src/extensions/math.ts
|
|
6184
6208
|
/**
|
|
6185
6209
|
* Renders one inline math unit: a KaTeX preview next to the editable
|
|
6186
6210
|
* `$formula$` source. CSS decides which of the two is visible; in hide and
|
|
@@ -6247,12 +6271,11 @@ var MathMarkView = class {
|
|
|
6247
6271
|
function defineMath() {
|
|
6248
6272
|
return defineMarkView({
|
|
6249
6273
|
name: "mdMath",
|
|
6250
|
-
constructor: (mark, view) => new MathMarkView(mark, view)
|
|
6274
|
+
constructor: guardMarkView((mark, view) => new MathMarkView(mark, view))
|
|
6251
6275
|
});
|
|
6252
6276
|
}
|
|
6253
6277
|
|
|
6254
|
-
|
|
6255
|
-
//#region src/extensions/table-column-align.ts
|
|
6278
|
+
// src/extensions/table-column-align.ts
|
|
6256
6279
|
function parseTableColumnAlign(value) {
|
|
6257
6280
|
return value === "left" || value === "center" || value === "right" ? value : null;
|
|
6258
6281
|
}
|
|
@@ -6345,7 +6368,7 @@ function unionOfChangedRanges(transactions) {
|
|
|
6345
6368
|
function createTableAlignSyncPlugin() {
|
|
6346
6369
|
return new Plugin({
|
|
6347
6370
|
key: new PluginKey("table-align-sync"),
|
|
6348
|
-
appendTransaction(transactions, _oldState, newState) {
|
|
6371
|
+
appendTransaction: guardAppendTransaction((transactions, _oldState, newState) => {
|
|
6349
6372
|
if (!transactions.some((transaction) => transaction.docChanged)) return;
|
|
6350
6373
|
const range = unionOfChangedRanges(transactions);
|
|
6351
6374
|
if (!range) return;
|
|
@@ -6360,7 +6383,7 @@ function createTableAlignSyncPlugin() {
|
|
|
6360
6383
|
return false;
|
|
6361
6384
|
});
|
|
6362
6385
|
return tr?.docChanged ? tr : void 0;
|
|
6363
|
-
}
|
|
6386
|
+
})
|
|
6364
6387
|
});
|
|
6365
6388
|
}
|
|
6366
6389
|
function defineTableAlignSync() {
|
|
@@ -6446,8 +6469,7 @@ function defineTableColumnAlign() {
|
|
|
6446
6469
|
return union(defineTableCellAlignAttr(), defineTableHeaderCellAlignAttr(), defineTableAlignSync(), defineTableColumnAlignCommands());
|
|
6447
6470
|
}
|
|
6448
6471
|
|
|
6449
|
-
|
|
6450
|
-
//#region src/extensions/table.ts
|
|
6472
|
+
// src/extensions/table.ts
|
|
6451
6473
|
/**
|
|
6452
6474
|
* Whether the selection sits inside a table cell (data or header). Useful for
|
|
6453
6475
|
* gating block-creating UI, since cells hold inline content only.
|
|
@@ -6486,8 +6508,7 @@ function defineTable() {
|
|
|
6486
6508
|
return union(defineTableSpec(), defineTableRowSpec(), defineTableCellSpec(), defineTableHeaderCellSpec(), defineTableCellContent(), defineTableColumnAlign(), defineTableEditingPlugin({ allowTableNodeSelection: true }), defineTableCommands(), defineTableDropIndicator(), defineTableKeymap());
|
|
6487
6509
|
}
|
|
6488
6510
|
|
|
6489
|
-
|
|
6490
|
-
//#region src/extensions/move-block.ts
|
|
6511
|
+
// src/extensions/move-block.ts
|
|
6491
6512
|
/**
|
|
6492
6513
|
* The index of the top-level block holding the whole selection, or undefined
|
|
6493
6514
|
* when the selection spans several top-level blocks or floats between them (a
|
|
@@ -6549,8 +6570,7 @@ function defineMoveBlock() {
|
|
|
6549
6570
|
});
|
|
6550
6571
|
}
|
|
6551
6572
|
|
|
6552
|
-
|
|
6553
|
-
//#region src/extensions/pending-replacement.ts
|
|
6573
|
+
// src/extensions/pending-replacement.ts
|
|
6554
6574
|
const pendingReplacementKey = new PluginKey("meowdownPendingReplacement");
|
|
6555
6575
|
/**
|
|
6556
6576
|
* The active pending replacement, or null when there is none.
|
|
@@ -6620,11 +6640,11 @@ const pendingReplacementPlugin = new Plugin({
|
|
|
6620
6640
|
return value;
|
|
6621
6641
|
}
|
|
6622
6642
|
},
|
|
6623
|
-
props: { decorations: (state) => {
|
|
6643
|
+
props: { decorations: guardDecorations((state) => {
|
|
6624
6644
|
const pending = getPendingReplacement(state);
|
|
6625
6645
|
if (!pending || pending.from >= pending.to) return null;
|
|
6626
6646
|
return DecorationSet.create(state.doc, [Decoration.inline(pending.from, pending.to, { class: "md-pending-replacement" })]);
|
|
6627
|
-
} }
|
|
6647
|
+
}) }
|
|
6628
6648
|
});
|
|
6629
6649
|
function startPendingReplacement(options) {
|
|
6630
6650
|
return (state, dispatch) => {
|
|
@@ -6728,27 +6748,29 @@ function definePendingReplacementHandler(handler) {
|
|
|
6728
6748
|
const prev = pendingReplacementKey.getState(prevState);
|
|
6729
6749
|
const next = pendingReplacementKey.getState(view.state);
|
|
6730
6750
|
if (!next || prev === next) return;
|
|
6731
|
-
|
|
6732
|
-
if (next.pending
|
|
6733
|
-
|
|
6734
|
-
|
|
6751
|
+
try {
|
|
6752
|
+
if (next.pending) {
|
|
6753
|
+
if (next.pending !== prev?.pending) handler({
|
|
6754
|
+
type: "update",
|
|
6755
|
+
pending: next.pending
|
|
6756
|
+
});
|
|
6757
|
+
} else if (next.ended && next.ended !== prev?.ended) handler({
|
|
6758
|
+
type: "ended",
|
|
6759
|
+
pending: next.ended.pending,
|
|
6760
|
+
outcome: next.ended.outcome
|
|
6735
6761
|
});
|
|
6736
|
-
}
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
outcome: next.ended.outcome
|
|
6740
|
-
});
|
|
6762
|
+
} catch (error) {
|
|
6763
|
+
reportError(error);
|
|
6764
|
+
}
|
|
6741
6765
|
} }) }));
|
|
6742
6766
|
}
|
|
6743
6767
|
|
|
6744
|
-
|
|
6745
|
-
//#region src/extensions/readonly.ts
|
|
6768
|
+
// src/extensions/readonly.ts
|
|
6746
6769
|
function defineReadonly(getReadonly = () => true) {
|
|
6747
6770
|
return definePlugin(new Plugin({ props: { editable: (state) => !getReadonly(state) } }));
|
|
6748
6771
|
}
|
|
6749
6772
|
|
|
6750
|
-
|
|
6751
|
-
//#region src/utils/caret-coords.ts
|
|
6773
|
+
// src/utils/caret-coords.ts
|
|
6752
6774
|
/**
|
|
6753
6775
|
* A dimensionless point: the fallback measurement of a hidden (font-size: 0)
|
|
6754
6776
|
* syntax run. A real caret rect always has line height, and a block-context
|
|
@@ -6776,15 +6798,13 @@ function tryCoordsAtPos(view, pos, side) {
|
|
|
6776
6798
|
return isPointRect(coords) ? void 0 : coords;
|
|
6777
6799
|
}
|
|
6778
6800
|
|
|
6779
|
-
|
|
6780
|
-
//#region src/utils/line-break.ts
|
|
6801
|
+
// src/utils/line-break.ts
|
|
6781
6802
|
function isAfterLineBreak($pos) {
|
|
6782
6803
|
const { parentOffset, parent } = $pos;
|
|
6783
6804
|
return parentOffset > 0 && parent.textBetween(parentOffset - 1, parentOffset) === "\n";
|
|
6784
6805
|
}
|
|
6785
6806
|
|
|
6786
|
-
|
|
6787
|
-
//#region src/extensions/caret-rect.ts
|
|
6807
|
+
// src/extensions/caret-rect.ts
|
|
6788
6808
|
function findNativeCaretRect(view) {
|
|
6789
6809
|
const selection = view.dom.ownerDocument.getSelection();
|
|
6790
6810
|
if (selection == null || selection.rangeCount === 0) return void 0;
|
|
@@ -6890,8 +6910,7 @@ function measureCaretScrollRect(view) {
|
|
|
6890
6910
|
return findCoordsCaretRect(view) ?? findAtomCaretRect(view);
|
|
6891
6911
|
}
|
|
6892
6912
|
|
|
6893
|
-
|
|
6894
|
-
//#region src/extensions/scroll-to-selection.ts
|
|
6913
|
+
// src/extensions/scroll-to-selection.ts
|
|
6895
6914
|
const key$1 = new PluginKey("meowdown-scroll-to-selection");
|
|
6896
6915
|
function handleScrollToSelection(view) {
|
|
6897
6916
|
const selection = view.state.selection;
|
|
@@ -6993,8 +7012,7 @@ function defineScrollToSelection() {
|
|
|
6993
7012
|
}));
|
|
6994
7013
|
}
|
|
6995
7014
|
|
|
6996
|
-
|
|
6997
|
-
//#region src/extensions/select-doc-boundary.ts
|
|
7015
|
+
// src/extensions/select-doc-boundary.ts
|
|
6998
7016
|
function selectDocBoundary(direction, extend) {
|
|
6999
7017
|
return (state, dispatch) => {
|
|
7000
7018
|
const boundary = direction < 0 ? Selection.atStart(state.doc) : Selection.atEnd(state.doc);
|
|
@@ -7021,8 +7039,7 @@ function defineSelectDocBoundary() {
|
|
|
7021
7039
|
});
|
|
7022
7040
|
}
|
|
7023
7041
|
|
|
7024
|
-
|
|
7025
|
-
//#region src/extensions/soft-break.ts
|
|
7042
|
+
// src/extensions/soft-break.ts
|
|
7026
7043
|
function canHoldSoftBreak($pos) {
|
|
7027
7044
|
if (!isNodeOfType($pos.parent, "paragraph")) return false;
|
|
7028
7045
|
const container = $pos.depth > 0 ? $pos.node($pos.depth - 1) : void 0;
|
|
@@ -7070,8 +7087,7 @@ function defineSoftBreak() {
|
|
|
7070
7087
|
return union(defineCommands({ insertSoftBreak }), defineKeymap({ "Shift-Enter": chainCommands(exitCodeBlockAtEnd, softBreakCommand) }));
|
|
7071
7088
|
}
|
|
7072
7089
|
|
|
7073
|
-
|
|
7074
|
-
//#region src/extensions/substitution.ts
|
|
7090
|
+
// src/extensions/substitution.ts
|
|
7075
7091
|
const SUBSTITUTION_RULES = [
|
|
7076
7092
|
[/<-/, "←"],
|
|
7077
7093
|
[new RegExp((canUseRegexLookbehind() ? "(?<!-)" : "") + "->"), "→"],
|
|
@@ -7159,8 +7175,7 @@ function defineSubstitution(enabled) {
|
|
|
7159
7175
|
return union(defineSubstitutionInputRules(enabled), defineSubstitutionUndo(), defineSubstitutionEnterRules(enabled));
|
|
7160
7176
|
}
|
|
7161
7177
|
|
|
7162
|
-
|
|
7163
|
-
//#region src/extensions/system-substitution-guard.ts
|
|
7178
|
+
// src/extensions/system-substitution-guard.ts
|
|
7164
7179
|
const EM_DASH = "—";
|
|
7165
7180
|
/**
|
|
7166
7181
|
* Block the macOS "smart dashes" rewrite. With the `spellcheck` attribute on,
|
|
@@ -7186,8 +7201,7 @@ function defineSystemSubstitutionGuard() {
|
|
|
7186
7201
|
return withPriority$1(definePlugin(plugin), Priority$1.highest);
|
|
7187
7202
|
}
|
|
7188
7203
|
|
|
7189
|
-
|
|
7190
|
-
//#region src/extensions/view-attributes.ts
|
|
7204
|
+
// src/extensions/view-attributes.ts
|
|
7191
7205
|
/**
|
|
7192
7206
|
* Add DOM attributes to the editable root. `class` and `style` values from
|
|
7193
7207
|
* every such extension are combined, so applying this more than once adds
|
|
@@ -7197,8 +7211,7 @@ function defineViewAttributes(attributes) {
|
|
|
7197
7211
|
return definePlugin(new Plugin({ props: { attributes } }));
|
|
7198
7212
|
}
|
|
7199
7213
|
|
|
7200
|
-
|
|
7201
|
-
//#region src/utils/clean-text.ts
|
|
7214
|
+
// src/utils/clean-text.ts
|
|
7202
7215
|
/**
|
|
7203
7216
|
* Projects a document slice to syntax-clean text, omitting inline markers and
|
|
7204
7217
|
* hidden link destinations. Set `preserveMathSource` when the result must keep
|
|
@@ -7219,8 +7232,7 @@ function cleanTextFromSlice(slice, options = {}) {
|
|
|
7219
7232
|
return blocks.join("\n");
|
|
7220
7233
|
}
|
|
7221
7234
|
|
|
7222
|
-
|
|
7223
|
-
//#region src/extensions/wikilink-trigger.ts
|
|
7235
|
+
// src/extensions/wikilink-trigger.ts
|
|
7224
7236
|
const WIKILINK_OPEN = "[[";
|
|
7225
7237
|
/**
|
|
7226
7238
|
* Inserts the `[[` wikilink trigger at the cursor and opens the wikilink menu.
|
|
@@ -7265,8 +7277,7 @@ function defineWikilinkTrigger(enabled) {
|
|
|
7265
7277
|
});
|
|
7266
7278
|
}
|
|
7267
7279
|
|
|
7268
|
-
|
|
7269
|
-
//#region src/extensions/wikilink.ts
|
|
7280
|
+
// src/extensions/wikilink.ts
|
|
7270
7281
|
/**
|
|
7271
7282
|
* Render `mdWikilink` as a non-editable label standing in for the raw source.
|
|
7272
7283
|
* The source stays in `contentDOM` after the label, hidden by `style.css`
|
|
@@ -7307,12 +7318,11 @@ function createWikilinkMarkView() {
|
|
|
7307
7318
|
function defineWikilink() {
|
|
7308
7319
|
return defineMarkView({
|
|
7309
7320
|
name: "mdWikilink",
|
|
7310
|
-
constructor: createWikilinkMarkView()
|
|
7321
|
+
constructor: guardMarkView(createWikilinkMarkView())
|
|
7311
7322
|
});
|
|
7312
7323
|
}
|
|
7313
7324
|
|
|
7314
|
-
|
|
7315
|
-
//#region src/extensions/x-post-media-click.ts
|
|
7325
|
+
// src/extensions/x-post-media-click.ts
|
|
7316
7326
|
const xPostMediaClickKey = new PluginKey("meowdown-x-post-media-click");
|
|
7317
7327
|
/**
|
|
7318
7328
|
* Call `onClick` when the user activates a photo or video inside an X post
|
|
@@ -7330,8 +7340,7 @@ function defineXPostMediaClickHandler(getOnClick) {
|
|
|
7330
7340
|
}));
|
|
7331
7341
|
}
|
|
7332
7342
|
|
|
7333
|
-
|
|
7334
|
-
//#region src/extensions/youtube-video-click.ts
|
|
7343
|
+
// src/extensions/youtube-video-click.ts
|
|
7335
7344
|
const youTubeVideoClickKey = new PluginKey("meowdown-youtube-video-click");
|
|
7336
7345
|
/**
|
|
7337
7346
|
* Call `onClick` when the user activates the poster of a YouTube card.
|
|
@@ -7348,8 +7357,7 @@ function defineYouTubeVideoClickHandler(getOnClick) {
|
|
|
7348
7357
|
}));
|
|
7349
7358
|
}
|
|
7350
7359
|
|
|
7351
|
-
|
|
7352
|
-
//#region src/extensions/extension.ts
|
|
7360
|
+
// src/extensions/extension.ts
|
|
7353
7361
|
function defineEditorExtensionImpl(options) {
|
|
7354
7362
|
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({
|
|
7355
7363
|
placeholder: (state) => {
|
|
@@ -7383,8 +7391,7 @@ function defineEditorExtension(options = {}) {
|
|
|
7383
7391
|
return defineEditorExtensionImpl(options);
|
|
7384
7392
|
}
|
|
7385
7393
|
|
|
7386
|
-
|
|
7387
|
-
//#region src/extensions/schema.ts
|
|
7394
|
+
// src/extensions/schema.ts
|
|
7388
7395
|
/**
|
|
7389
7396
|
* The schema shared by every parser and serializer, built once and cached.
|
|
7390
7397
|
*/
|
|
@@ -7428,15 +7435,17 @@ function getNodeBuildersForSchema(schema) {
|
|
|
7428
7435
|
return builders;
|
|
7429
7436
|
}
|
|
7430
7437
|
|
|
7431
|
-
|
|
7432
|
-
//#region src/converters/ast-to-pm.ts
|
|
7438
|
+
// src/converters/ast-to-pm.ts
|
|
7433
7439
|
/**
|
|
7434
7440
|
* Build nodes with the caller's schema; Markdown inline syntax remains literal text.
|
|
7435
7441
|
*/
|
|
7436
7442
|
function astToDoc(node, nodes = getNodeBuilders()) {
|
|
7437
7443
|
const children = node.children?.map((child) => astToDoc(child, nodes)) || [];
|
|
7438
7444
|
switch (node.type) {
|
|
7439
|
-
case "document": return nodes.doc(
|
|
7445
|
+
case "document": return nodes.doc({
|
|
7446
|
+
frontmatter: node.frontmatter ?? null,
|
|
7447
|
+
frontmatterTight: !!node.frontmatterTight
|
|
7448
|
+
}, children);
|
|
7440
7449
|
case "paragraph": return nodes.paragraph(node.value);
|
|
7441
7450
|
case "heading": return nodes.heading({
|
|
7442
7451
|
level: node.level,
|
|
@@ -7468,8 +7477,7 @@ function astToDoc(node, nodes = getNodeBuilders()) {
|
|
|
7468
7477
|
}
|
|
7469
7478
|
}
|
|
7470
7479
|
|
|
7471
|
-
|
|
7472
|
-
//#region src/converters/md-to-pm.ts
|
|
7480
|
+
// src/converters/md-to-pm.ts
|
|
7473
7481
|
/**
|
|
7474
7482
|
* Convert a markdown string into a ProseMirror document node.
|
|
7475
7483
|
*
|
|
@@ -7488,8 +7496,7 @@ function markdownToDoc(markdown, options = {}) {
|
|
|
7488
7496
|
return astToDoc(parseMarkdownAst(markdown, options), options.nodes);
|
|
7489
7497
|
}
|
|
7490
7498
|
|
|
7491
|
-
|
|
7492
|
-
//#region src/extensions/code-block-languages.ts
|
|
7499
|
+
// src/extensions/code-block-languages.ts
|
|
7493
7500
|
const excludeLanguages = /* @__PURE__ */ new Set([
|
|
7494
7501
|
"MscGen",
|
|
7495
7502
|
"Xù",
|
|
@@ -7532,8 +7539,7 @@ const codeBlockLanguages = languages.map((language) => ({
|
|
|
7532
7539
|
value: language.name.toLowerCase()
|
|
7533
7540
|
})).filter((language) => !excludeLanguages.has(language.label)).concat(extraLanguages).sort((a, b) => a.label.localeCompare(b.label));
|
|
7534
7541
|
|
|
7535
|
-
|
|
7536
|
-
//#region src/extensions/key-bindings.ts
|
|
7542
|
+
// src/extensions/key-bindings.ts
|
|
7537
7543
|
/**
|
|
7538
7544
|
* Human-readable descriptions of the editor's formatting and heading shortcuts.
|
|
7539
7545
|
*/
|
|
@@ -7567,8 +7573,7 @@ const EDITOR_KEY_BINDINGS = {
|
|
|
7567
7573
|
Escape: "Collapse the selection"
|
|
7568
7574
|
};
|
|
7569
7575
|
|
|
7570
|
-
|
|
7571
|
-
//#region src/extensions/mark-hover.ts
|
|
7576
|
+
// src/extensions/mark-hover.ts
|
|
7572
7577
|
const IDLE = { kind: "idle" };
|
|
7573
7578
|
function getHit(phase) {
|
|
7574
7579
|
return phase.kind === "active" || phase.kind === "leaving" ? phase.hit : void 0;
|
|
@@ -7800,8 +7805,7 @@ function defineMarkHoverHandler(config) {
|
|
|
7800
7805
|
}));
|
|
7801
7806
|
}
|
|
7802
7807
|
|
|
7803
|
-
|
|
7804
|
-
//#region src/extensions/link-hover.ts
|
|
7808
|
+
// src/extensions/link-hover.ts
|
|
7805
7809
|
const linkHoverKey = new PluginKey("meowdown-link-hover");
|
|
7806
7810
|
/**
|
|
7807
7811
|
* Delay before a cold hover enters, in ms.
|
|
@@ -7845,14 +7849,12 @@ function dismissLinkHover(state) {
|
|
|
7845
7849
|
linkHoverKey.getState(state)?.dismiss();
|
|
7846
7850
|
}
|
|
7847
7851
|
|
|
7848
|
-
|
|
7849
|
-
//#region src/utils/force-reflow.ts
|
|
7852
|
+
// src/utils/force-reflow.ts
|
|
7850
7853
|
function forceReflow(element) {
|
|
7851
7854
|
element.offsetWidth;
|
|
7852
7855
|
}
|
|
7853
7856
|
|
|
7854
|
-
|
|
7855
|
-
//#region src/extensions/virtual-caret.ts
|
|
7857
|
+
// src/extensions/virtual-caret.ts
|
|
7856
7858
|
const key = new PluginKey("meowdown-virtual-caret");
|
|
7857
7859
|
const BLINK_ANIMATIONS = ["md-virtual-caret-blink", "md-virtual-caret-blink2"];
|
|
7858
7860
|
const DATA_ATTRIBUTE = "data-meowdown-virtual-caret";
|
|
@@ -8017,8 +8019,7 @@ function defineVirtualCaret(layer) {
|
|
|
8017
8019
|
}));
|
|
8018
8020
|
}
|
|
8019
8021
|
|
|
8020
|
-
|
|
8021
|
-
//#region src/extensions/wikilink-hover.ts
|
|
8022
|
+
// src/extensions/wikilink-hover.ts
|
|
8022
8023
|
const wikilinkHoverKey = new PluginKey("meowdown-wikilink-hover");
|
|
8023
8024
|
/**
|
|
8024
8025
|
* Delay before a cold hover enters, in ms.
|
|
@@ -8058,8 +8059,7 @@ function defineWikilinkHoverHandler(onHoverChange, openDelay = OPEN_DELAY, close
|
|
|
8058
8059
|
});
|
|
8059
8060
|
}
|
|
8060
8061
|
|
|
8061
|
-
|
|
8062
|
-
//#region src/utils/display-text.ts
|
|
8062
|
+
// src/utils/display-text.ts
|
|
8063
8063
|
function getAtomDisplayText(atom) {
|
|
8064
8064
|
switch (atom.type.name) {
|
|
8065
8065
|
case "mdWikilink": {
|
|
@@ -8088,8 +8088,7 @@ function getTextblockDisplayText(textblock) {
|
|
|
8088
8088
|
return output;
|
|
8089
8089
|
}
|
|
8090
8090
|
|
|
8091
|
-
|
|
8092
|
-
//#region src/utils/selected-text.ts
|
|
8091
|
+
// src/utils/selected-text.ts
|
|
8093
8092
|
/**
|
|
8094
8093
|
* The current selection as Markdown: block structure (list markers, headings,
|
|
8095
8094
|
* blockquotes) is serialized, and inline Markdown syntax is already literal
|
|
@@ -8109,8 +8108,7 @@ function getSelectedText(state) {
|
|
|
8109
8108
|
}
|
|
8110
8109
|
}
|
|
8111
8110
|
|
|
8112
|
-
|
|
8113
|
-
//#region src/utils/virtual-element.ts
|
|
8111
|
+
// src/utils/virtual-element.ts
|
|
8114
8112
|
function tryHiddenRunCoords(view, pos, side) {
|
|
8115
8113
|
if (side === 1) {
|
|
8116
8114
|
const run = getHiddenRunAfter(view.state, pos);
|
|
@@ -8149,5 +8147,4 @@ function getVirtualElementFromRange(view, range) {
|
|
|
8149
8147
|
};
|
|
8150
8148
|
}
|
|
8151
8149
|
|
|
8152
|
-
//#endregion
|
|
8153
8150
|
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 };
|