@meowdown/core 0.83.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.js +112 -32
- package/dist/style.css +4 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -72,6 +72,39 @@ function getIsComposing() {
|
|
|
72
72
|
return isComposing || compositionEndedAt > 0 && Date.now() - compositionEndedAt <= COMPOSITION_TAIL_MS;
|
|
73
73
|
}
|
|
74
74
|
|
|
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
|
+
|
|
75
108
|
// src/utils/input-modality.ts
|
|
76
109
|
const KEYBOARD_MODALITY_KEYS = /* @__PURE__ */ new Set([
|
|
77
110
|
"ArrowLeft",
|
|
@@ -555,7 +588,7 @@ function getUnitEdge(range, oldPos, newPos, isPointer) {
|
|
|
555
588
|
function createCaretSnapPlugin(marks) {
|
|
556
589
|
return new Plugin({
|
|
557
590
|
key: new PluginKey("atom-mark-caret-snap"),
|
|
558
|
-
appendTransaction: (transactions, oldState, newState) => {
|
|
591
|
+
appendTransaction: guardAppendTransaction((transactions, oldState, newState) => {
|
|
559
592
|
if (getIsComposing()) return null;
|
|
560
593
|
const markNames = getActiveMarkNames(marks, newState);
|
|
561
594
|
if (markNames.length === 0) return null;
|
|
@@ -575,14 +608,14 @@ function createCaretSnapPlugin(marks) {
|
|
|
575
608
|
const isPointer = hasPointerSelectionTransaction(transactions);
|
|
576
609
|
const head = getUnitEdge(range, oldState.selection.head, selection.head, isPointer);
|
|
577
610
|
return newState.tr.setSelection(TextSelection.create(newState.doc, head));
|
|
578
|
-
}
|
|
611
|
+
})
|
|
579
612
|
});
|
|
580
613
|
}
|
|
581
614
|
const SELECTED_CLASS = "md-atom-selected";
|
|
582
615
|
function createSelectionPlugin(marks) {
|
|
583
616
|
return new Plugin({
|
|
584
617
|
key: new PluginKey("atom-mark-selection"),
|
|
585
|
-
props: { decorations: (state) => {
|
|
618
|
+
props: { decorations: guardDecorations((state) => {
|
|
586
619
|
const markNames = getActiveMarkNames(marks, state);
|
|
587
620
|
if (markNames.length === 0) return;
|
|
588
621
|
if (isNodeSelection(state.selection)) return;
|
|
@@ -595,7 +628,7 @@ function createSelectionPlugin(marks) {
|
|
|
595
628
|
if (node.marks.some((mark) => markNames.includes(mark.type.name))) decorations.push(Decoration.inline(pos, pos + node.nodeSize, { class: SELECTED_CLASS }));
|
|
596
629
|
});
|
|
597
630
|
return DecorationSet.create(state.doc, decorations);
|
|
598
|
-
} }
|
|
631
|
+
}) }
|
|
599
632
|
});
|
|
600
633
|
}
|
|
601
634
|
/**
|
|
@@ -696,7 +729,7 @@ function isSingleParagraph(state) {
|
|
|
696
729
|
function defineSingleParagraph() {
|
|
697
730
|
return withPriority$1(definePlugin(new Plugin({
|
|
698
731
|
key: singleParagraphPluginKey,
|
|
699
|
-
appendTransaction(transactions, _oldState, state) {
|
|
732
|
+
appendTransaction: guardAppendTransaction((transactions, _oldState, state) => {
|
|
700
733
|
if (!isSingleParagraph(state)) return;
|
|
701
734
|
if (!transactions.some((transaction) => transaction.docChanged)) return;
|
|
702
735
|
const markdown = docToParagraphMarkdown(state.doc);
|
|
@@ -705,7 +738,7 @@ function defineSingleParagraph() {
|
|
|
705
738
|
const position = Math.min(state.selection.head, doc.content.size - 1);
|
|
706
739
|
const transaction = state.tr.replaceWith(0, state.doc.content.size, doc.content);
|
|
707
740
|
return transaction.setSelection(TextSelection.create(transaction.doc, Math.max(1, position)));
|
|
708
|
-
}
|
|
741
|
+
})
|
|
709
742
|
})), Priority$1.highest);
|
|
710
743
|
}
|
|
711
744
|
|
|
@@ -2424,6 +2457,45 @@ function formatFileSize(bytes) {
|
|
|
2424
2457
|
return `${value < 9.95 ? Math.round(value * 10) / 10 : Math.round(value)} ${unit}`;
|
|
2425
2458
|
}
|
|
2426
2459
|
|
|
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
|
+
|
|
2427
2499
|
// src/extensions/file-view.ts
|
|
2428
2500
|
/**
|
|
2429
2501
|
* `data-file-kind` values by file extension, for host CSS theming.
|
|
@@ -2574,16 +2646,16 @@ var FileMarkView = class {
|
|
|
2574
2646
|
function defineFileView(getOptions) {
|
|
2575
2647
|
return defineMarkView({
|
|
2576
2648
|
name: "mdFile",
|
|
2577
|
-
constructor: (mark, view) => new FileMarkView(mark, getOptions?.(view.state))
|
|
2649
|
+
constructor: guardMarkView((mark, view) => new FileMarkView(mark, getOptions?.(view.state)))
|
|
2578
2650
|
});
|
|
2579
2651
|
}
|
|
2580
2652
|
|
|
2581
2653
|
// src/extensions/find.ts
|
|
2582
|
-
const revealActiveMatch = new Plugin({ props: { decorations: (state) => {
|
|
2654
|
+
const revealActiveMatch = new Plugin({ props: { decorations: guardDecorations((state) => {
|
|
2583
2655
|
const { from, to, empty } = state.selection;
|
|
2584
2656
|
if (empty || getSearchStatus$1(state).active === 0) return;
|
|
2585
2657
|
return DecorationSet.create(state.doc, [Decoration.inline(from, to, { class: "show" })]);
|
|
2586
|
-
} } });
|
|
2658
|
+
}) } });
|
|
2587
2659
|
/**
|
|
2588
2660
|
* Find over the editor's text. `setSearchQuery` highlights every match and
|
|
2589
2661
|
* selects the first one at or after the caret; `findNext` and `findPrev` walk
|
|
@@ -3058,7 +3130,7 @@ const beforeInputKey = new PluginKey("meowdown-hidden-run-beforeinput");
|
|
|
3058
3130
|
function createSnapPlugin() {
|
|
3059
3131
|
return new Plugin({
|
|
3060
3132
|
key: snapKey,
|
|
3061
|
-
appendTransaction: (transactions, oldState, newState) => {
|
|
3133
|
+
appendTransaction: guardAppendTransaction((transactions, oldState, newState) => {
|
|
3062
3134
|
if (getIsComposing()) return null;
|
|
3063
3135
|
if (getMarkMode(newState) !== "hide") return null;
|
|
3064
3136
|
const selection = newState.selection;
|
|
@@ -3075,7 +3147,7 @@ function createSnapPlugin() {
|
|
|
3075
3147
|
const anchor = selection.anchor === selection.from ? from : to;
|
|
3076
3148
|
const head = selection.head === selection.from ? from : to;
|
|
3077
3149
|
return newState.tr.setSelection(TextSelection.create(newState.doc, anchor, head));
|
|
3078
|
-
}
|
|
3150
|
+
})
|
|
3079
3151
|
});
|
|
3080
3152
|
}
|
|
3081
3153
|
const relocateEnterSplit = (state, dispatch) => {
|
|
@@ -3727,7 +3799,7 @@ var ImageMarkView = class {
|
|
|
3727
3799
|
function defineImage(getOptions) {
|
|
3728
3800
|
return defineMarkView({
|
|
3729
3801
|
name: "mdImage",
|
|
3730
|
-
constructor: (mark, view) => new ImageMarkView(mark, view, getOptions?.(view.state) ?? {})
|
|
3802
|
+
constructor: guardMarkView((mark, view) => new ImageMarkView(mark, view, getOptions?.(view.state) ?? {}))
|
|
3731
3803
|
});
|
|
3732
3804
|
}
|
|
3733
3805
|
|
|
@@ -4769,7 +4841,7 @@ function createInlineMarkPlugin(getOptions) {
|
|
|
4769
4841
|
};
|
|
4770
4842
|
}
|
|
4771
4843
|
},
|
|
4772
|
-
appendTransaction(transactions, oldState, newState) {
|
|
4844
|
+
appendTransaction: guardAppendTransaction((transactions, oldState, newState) => {
|
|
4773
4845
|
for (const tr of transactions) if (tr.getMeta(META_KEY)) return null;
|
|
4774
4846
|
const restyle = transactions.some((transaction) => transaction.getMeta(RESTYLE_KEY));
|
|
4775
4847
|
if (!(restyle || transactions.some((transaction) => {
|
|
@@ -4790,9 +4862,13 @@ function createInlineMarkPlugin(getOptions) {
|
|
|
4790
4862
|
tr.setMeta(META_KEY, true);
|
|
4791
4863
|
tr.setMeta("addToHistory", false);
|
|
4792
4864
|
return tr;
|
|
4793
|
-
},
|
|
4865
|
+
}),
|
|
4794
4866
|
view(view) {
|
|
4795
|
-
|
|
4867
|
+
try {
|
|
4868
|
+
view.dispatch(triggerInlineMarks(view.state));
|
|
4869
|
+
} catch (error) {
|
|
4870
|
+
reportError(error);
|
|
4871
|
+
}
|
|
4796
4872
|
const controller = new AbortController();
|
|
4797
4873
|
const flush = (currentView) => {
|
|
4798
4874
|
if (currentView.isDestroyed) return;
|
|
@@ -6047,10 +6123,10 @@ function defineMeowdownList() {
|
|
|
6047
6123
|
function createMarkModePlugin(getMode) {
|
|
6048
6124
|
return new Plugin({ props: {
|
|
6049
6125
|
attributes: (state) => ({ "data-mark-mode": getMode(state) }),
|
|
6050
|
-
decorations: (state) => {
|
|
6126
|
+
decorations: guardDecorations((state) => {
|
|
6051
6127
|
const mode = getMode(state);
|
|
6052
6128
|
return mode === "focus" || mode === "hide" ? computeRevealDecorations(state, mode) : void 0;
|
|
6053
|
-
}
|
|
6129
|
+
})
|
|
6054
6130
|
} });
|
|
6055
6131
|
}
|
|
6056
6132
|
function findRevealablePack($pos, mode, direction) {
|
|
@@ -6195,7 +6271,7 @@ var MathMarkView = class {
|
|
|
6195
6271
|
function defineMath() {
|
|
6196
6272
|
return defineMarkView({
|
|
6197
6273
|
name: "mdMath",
|
|
6198
|
-
constructor: (mark, view) => new MathMarkView(mark, view)
|
|
6274
|
+
constructor: guardMarkView((mark, view) => new MathMarkView(mark, view))
|
|
6199
6275
|
});
|
|
6200
6276
|
}
|
|
6201
6277
|
|
|
@@ -6292,7 +6368,7 @@ function unionOfChangedRanges(transactions) {
|
|
|
6292
6368
|
function createTableAlignSyncPlugin() {
|
|
6293
6369
|
return new Plugin({
|
|
6294
6370
|
key: new PluginKey("table-align-sync"),
|
|
6295
|
-
appendTransaction(transactions, _oldState, newState) {
|
|
6371
|
+
appendTransaction: guardAppendTransaction((transactions, _oldState, newState) => {
|
|
6296
6372
|
if (!transactions.some((transaction) => transaction.docChanged)) return;
|
|
6297
6373
|
const range = unionOfChangedRanges(transactions);
|
|
6298
6374
|
if (!range) return;
|
|
@@ -6307,7 +6383,7 @@ function createTableAlignSyncPlugin() {
|
|
|
6307
6383
|
return false;
|
|
6308
6384
|
});
|
|
6309
6385
|
return tr?.docChanged ? tr : void 0;
|
|
6310
|
-
}
|
|
6386
|
+
})
|
|
6311
6387
|
});
|
|
6312
6388
|
}
|
|
6313
6389
|
function defineTableAlignSync() {
|
|
@@ -6564,11 +6640,11 @@ const pendingReplacementPlugin = new Plugin({
|
|
|
6564
6640
|
return value;
|
|
6565
6641
|
}
|
|
6566
6642
|
},
|
|
6567
|
-
props: { decorations: (state) => {
|
|
6643
|
+
props: { decorations: guardDecorations((state) => {
|
|
6568
6644
|
const pending = getPendingReplacement(state);
|
|
6569
6645
|
if (!pending || pending.from >= pending.to) return null;
|
|
6570
6646
|
return DecorationSet.create(state.doc, [Decoration.inline(pending.from, pending.to, { class: "md-pending-replacement" })]);
|
|
6571
|
-
} }
|
|
6647
|
+
}) }
|
|
6572
6648
|
});
|
|
6573
6649
|
function startPendingReplacement(options) {
|
|
6574
6650
|
return (state, dispatch) => {
|
|
@@ -6672,16 +6748,20 @@ function definePendingReplacementHandler(handler) {
|
|
|
6672
6748
|
const prev = pendingReplacementKey.getState(prevState);
|
|
6673
6749
|
const next = pendingReplacementKey.getState(view.state);
|
|
6674
6750
|
if (!next || prev === next) return;
|
|
6675
|
-
|
|
6676
|
-
if (next.pending
|
|
6677
|
-
|
|
6678
|
-
|
|
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
|
|
6679
6761
|
});
|
|
6680
|
-
}
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
outcome: next.ended.outcome
|
|
6684
|
-
});
|
|
6762
|
+
} catch (error) {
|
|
6763
|
+
reportError(error);
|
|
6764
|
+
}
|
|
6685
6765
|
} }) }));
|
|
6686
6766
|
}
|
|
6687
6767
|
|
|
@@ -7238,7 +7318,7 @@ function createWikilinkMarkView() {
|
|
|
7238
7318
|
function defineWikilink() {
|
|
7239
7319
|
return defineMarkView({
|
|
7240
7320
|
name: "mdWikilink",
|
|
7241
|
-
constructor: createWikilinkMarkView()
|
|
7321
|
+
constructor: guardMarkView(createWikilinkMarkView())
|
|
7242
7322
|
});
|
|
7243
7323
|
}
|
|
7244
7324
|
|
package/dist/style.css
CHANGED
|
@@ -894,9 +894,13 @@
|
|
|
894
894
|
--meowdown-mermaid-surface: color-mix(in srgb,
|
|
895
895
|
var(--meowdown-mermaid-fg) 3%,
|
|
896
896
|
var(--meowdown-mermaid-bg));
|
|
897
|
+
--meowdown-mermaid-surface-alt: color-mix(in srgb,
|
|
898
|
+
var(--meowdown-mermaid-fg) 8%,
|
|
899
|
+
var(--meowdown-mermaid-bg));
|
|
897
900
|
--meowdown-mermaid-border: color-mix(in srgb,
|
|
898
901
|
var(--meowdown-mermaid-fg) 20%,
|
|
899
902
|
var(--meowdown-mermaid-bg));
|
|
903
|
+
--meowdown-mermaid-critical: var(--meowdown-danger);
|
|
900
904
|
--meowdown-mermaid-error: var(--meowdown-danger);
|
|
901
905
|
--meowdown-image-loading-bg: light-dark(oklch(96.7% 0 0), oklch(27.4% .005 286));
|
|
902
906
|
--meowdown-image-radius: .5rem;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meowdown/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.83.
|
|
4
|
+
"version": "0.83.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"@lezer/highlight": "^1.2.5",
|
|
28
28
|
"@meowdown/embed": "0.3.1",
|
|
29
29
|
"@meowdown/markdown": "0.78.0",
|
|
30
|
-
"@ocavue/utils": "^1.
|
|
30
|
+
"@ocavue/utils": "^1.11.0",
|
|
31
31
|
"@post-embed/exporter": "^0.5.0",
|
|
32
32
|
"@post-embed/schema": "^0.5.2",
|
|
33
33
|
"@post-embed/types": "^0.5.0",
|