@inkandswitch/patchwork-pkg-base 0.0.124 → 0.0.126
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/module-settings-url
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
automerge:
|
|
1
|
+
automerge:3LxJsuExcL8S2E8j8758gWkK1Hdp
|
package/package.json
CHANGED
|
@@ -2066,7 +2066,7 @@ var searchExtensions = [
|
|
|
2066
2066
|
];
|
|
2067
2067
|
|
|
2068
2068
|
// src/extensions/markdown.ts
|
|
2069
|
-
import { EditorView as
|
|
2069
|
+
import { EditorView as EditorView7, keymap as keymap3 } from "@codemirror/view";
|
|
2070
2070
|
|
|
2071
2071
|
// src/extensions/formatting.ts
|
|
2072
2072
|
import { EditorSelection as EditorSelection2 } from "@codemirror/state";
|
|
@@ -2234,7 +2234,6 @@ import {
|
|
|
2234
2234
|
ViewPlugin as ViewPlugin3,
|
|
2235
2235
|
WidgetType as WidgetType2
|
|
2236
2236
|
} from "@codemirror/view";
|
|
2237
|
-
var hangMark = Decoration3.mark({ class: "cm-md-hang" });
|
|
2238
2237
|
var numberMark = Decoration3.mark({ class: "cm-md-hang cm-md-hang-number" });
|
|
2239
2238
|
var quoteMark = Decoration3.mark({ class: "cm-md-hang cm-md-hang-quote" });
|
|
2240
2239
|
var hidden = Decoration3.replace({});
|
|
@@ -2271,6 +2270,37 @@ var Bullet = class extends WidgetType2 {
|
|
|
2271
2270
|
return span;
|
|
2272
2271
|
}
|
|
2273
2272
|
};
|
|
2273
|
+
var NumberLabel = class extends WidgetType2 {
|
|
2274
|
+
constructor(text) {
|
|
2275
|
+
super();
|
|
2276
|
+
this.text = text;
|
|
2277
|
+
}
|
|
2278
|
+
eq(other) {
|
|
2279
|
+
return other.text === this.text;
|
|
2280
|
+
}
|
|
2281
|
+
toDOM() {
|
|
2282
|
+
const span = document.createElement("span");
|
|
2283
|
+
span.className = "cm-md-hang cm-md-hang-number";
|
|
2284
|
+
span.textContent = this.text;
|
|
2285
|
+
return span;
|
|
2286
|
+
}
|
|
2287
|
+
};
|
|
2288
|
+
function renderedNumber(state, mark) {
|
|
2289
|
+
const text = state.doc.sliceString(mark.from, mark.to);
|
|
2290
|
+
const delimiter = text.slice(-1);
|
|
2291
|
+
let item = mark.parent;
|
|
2292
|
+
if (!item || item.name !== "ListItem") return text;
|
|
2293
|
+
let index = 0;
|
|
2294
|
+
let first = item;
|
|
2295
|
+
for (let prev = item.prevSibling; prev; prev = prev.prevSibling) {
|
|
2296
|
+
if (prev.name !== "ListItem") continue;
|
|
2297
|
+
index++;
|
|
2298
|
+
first = prev;
|
|
2299
|
+
}
|
|
2300
|
+
const firstMark = first.getChild("ListMark");
|
|
2301
|
+
const start = firstMark ? parseInt(state.doc.sliceString(firstMark.from, firstMark.to), 10) : 1;
|
|
2302
|
+
return `${(Number.isNaN(start) ? 1 : start) + index}${delimiter}`;
|
|
2303
|
+
}
|
|
2274
2304
|
function caretLines(state) {
|
|
2275
2305
|
const lines = /* @__PURE__ */ new Set();
|
|
2276
2306
|
for (const r of state.selection.ranges) {
|
|
@@ -2301,16 +2331,11 @@ function build2(view) {
|
|
|
2301
2331
|
const mark = node.node.firstChild;
|
|
2302
2332
|
if (!mark || mark.name !== "HeaderMark" || mark.from !== node.from)
|
|
2303
2333
|
return;
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
Decoration3.replace({
|
|
2310
|
-
widget: new HeadingLabel(Number(heading[1]))
|
|
2311
|
-
}).range(mark.from, end)
|
|
2312
|
-
);
|
|
2313
|
-
}
|
|
2334
|
+
decos.push(
|
|
2335
|
+
Decoration3.replace({
|
|
2336
|
+
widget: new HeadingLabel(Number(heading[1]))
|
|
2337
|
+
}).range(mark.from, skipSpaces(state, mark.to))
|
|
2338
|
+
);
|
|
2314
2339
|
return;
|
|
2315
2340
|
}
|
|
2316
2341
|
if (name === "ListMark") {
|
|
@@ -2328,8 +2353,14 @@ function build2(view) {
|
|
|
2328
2353
|
decos.push(
|
|
2329
2354
|
Decoration3.replace({ widget: new Bullet() }).range(node.from, end)
|
|
2330
2355
|
);
|
|
2331
|
-
} else {
|
|
2356
|
+
} else if (editing.has(doc.lineAt(node.from).number)) {
|
|
2332
2357
|
decos.push(numberMark.range(node.from, end));
|
|
2358
|
+
} else {
|
|
2359
|
+
decos.push(
|
|
2360
|
+
Decoration3.replace({
|
|
2361
|
+
widget: new NumberLabel(renderedNumber(state, node.node))
|
|
2362
|
+
}).range(node.from, end)
|
|
2363
|
+
);
|
|
2333
2364
|
}
|
|
2334
2365
|
return;
|
|
2335
2366
|
}
|
|
@@ -2465,9 +2496,473 @@ var marginTheme = EditorView3.baseTheme({
|
|
|
2465
2496
|
});
|
|
2466
2497
|
var margin = [marginPlugin, marginTheme];
|
|
2467
2498
|
|
|
2468
|
-
// src/extensions/
|
|
2469
|
-
import {
|
|
2499
|
+
// src/extensions/headings.ts
|
|
2500
|
+
import { syntaxTree as syntaxTree3 } from "@codemirror/language";
|
|
2501
|
+
import {
|
|
2502
|
+
EditorSelection as EditorSelection3,
|
|
2503
|
+
EditorState as EditorState2,
|
|
2504
|
+
Prec as Prec2
|
|
2505
|
+
} from "@codemirror/state";
|
|
2470
2506
|
import { keymap } from "@codemirror/view";
|
|
2507
|
+
function headingPrefix(state, line) {
|
|
2508
|
+
for (let node = syntaxTree3(state).resolveInner(line.from, 1); node; node = node.parent) {
|
|
2509
|
+
const m = /^ATXHeading(\d)$/.exec(node.name);
|
|
2510
|
+
if (!m) continue;
|
|
2511
|
+
if (state.doc.lineAt(node.from).number !== line.number) return null;
|
|
2512
|
+
const mark = node.firstChild;
|
|
2513
|
+
if (!mark || mark.name !== "HeaderMark") return null;
|
|
2514
|
+
let to = mark.to;
|
|
2515
|
+
while (to < line.to && state.doc.sliceString(to, to + 1) === " ") to++;
|
|
2516
|
+
return { from: line.from, to, level: Number(m[1]) };
|
|
2517
|
+
}
|
|
2518
|
+
return null;
|
|
2519
|
+
}
|
|
2520
|
+
var keepOutOfPrefix = EditorState2.transactionFilter.of((tr) => {
|
|
2521
|
+
if (!tr.selection) return tr;
|
|
2522
|
+
const { state } = tr;
|
|
2523
|
+
const before = tr.startState.selection;
|
|
2524
|
+
let moved = false;
|
|
2525
|
+
const ranges = tr.selection.ranges.map((r, i) => {
|
|
2526
|
+
if (!r.empty) return r;
|
|
2527
|
+
const line = state.doc.lineAt(r.head);
|
|
2528
|
+
if (r.head >= line.to && line.length > 0) return r;
|
|
2529
|
+
const prefix = headingPrefix(state, line);
|
|
2530
|
+
if (!prefix || r.head >= prefix.to) return r;
|
|
2531
|
+
const old = before.ranges[i] ?? before.main;
|
|
2532
|
+
const leaving = !tr.docChanged && old.empty && old.head === prefix.to && line.from > 0;
|
|
2533
|
+
moved = true;
|
|
2534
|
+
return EditorSelection3.cursor(leaving ? line.from - 1 : prefix.to);
|
|
2535
|
+
});
|
|
2536
|
+
if (!moved) return tr;
|
|
2537
|
+
return [
|
|
2538
|
+
tr,
|
|
2539
|
+
{
|
|
2540
|
+
selection: EditorSelection3.create(ranges, tr.selection.mainIndex),
|
|
2541
|
+
sequential: true
|
|
2542
|
+
}
|
|
2543
|
+
];
|
|
2544
|
+
});
|
|
2545
|
+
function selectedLines(state) {
|
|
2546
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2547
|
+
const lines = [];
|
|
2548
|
+
for (const r of state.selection.ranges) {
|
|
2549
|
+
for (let n = state.doc.lineAt(r.from).number; n <= state.doc.lineAt(r.to).number; n++) {
|
|
2550
|
+
if (seen.has(n)) continue;
|
|
2551
|
+
seen.add(n);
|
|
2552
|
+
lines.push(state.doc.line(n));
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
return lines;
|
|
2556
|
+
}
|
|
2557
|
+
var setHeading = (level) => ({ state, dispatch }) => {
|
|
2558
|
+
const lines = selectedLines(state);
|
|
2559
|
+
const prefixes = lines.map((line) => headingPrefix(state, line));
|
|
2560
|
+
const already = level > 0 && prefixes.every((p) => p && p.level === level);
|
|
2561
|
+
const target = already ? 0 : level;
|
|
2562
|
+
const insert = target ? "#".repeat(target) + " " : "";
|
|
2563
|
+
const changes = lines.map((line, i) => {
|
|
2564
|
+
const p = prefixes[i];
|
|
2565
|
+
return { from: line.from, to: p ? p.to : line.from, insert };
|
|
2566
|
+
});
|
|
2567
|
+
dispatch(
|
|
2568
|
+
state.update({
|
|
2569
|
+
changes,
|
|
2570
|
+
scrollIntoView: true,
|
|
2571
|
+
userEvent: "input.format"
|
|
2572
|
+
})
|
|
2573
|
+
);
|
|
2574
|
+
return true;
|
|
2575
|
+
};
|
|
2576
|
+
function atHeadingStart(state) {
|
|
2577
|
+
const sel = state.selection;
|
|
2578
|
+
if (sel.ranges.length !== 1 || !sel.main.empty) return null;
|
|
2579
|
+
const line = state.doc.lineAt(sel.main.head);
|
|
2580
|
+
const prefix = headingPrefix(state, line);
|
|
2581
|
+
return prefix && sel.main.head === prefix.to ? prefix : null;
|
|
2582
|
+
}
|
|
2583
|
+
var backspace = ({ state, dispatch }) => {
|
|
2584
|
+
const prefix = atHeadingStart(state);
|
|
2585
|
+
if (!prefix) return false;
|
|
2586
|
+
dispatch(
|
|
2587
|
+
state.update({
|
|
2588
|
+
changes: { from: prefix.from, to: prefix.to },
|
|
2589
|
+
selection: EditorSelection3.cursor(prefix.from),
|
|
2590
|
+
userEvent: "delete.backward"
|
|
2591
|
+
})
|
|
2592
|
+
);
|
|
2593
|
+
return true;
|
|
2594
|
+
};
|
|
2595
|
+
var enter = ({ state, dispatch }) => {
|
|
2596
|
+
const prefix = atHeadingStart(state);
|
|
2597
|
+
if (!prefix) return false;
|
|
2598
|
+
const line = state.doc.lineAt(prefix.from);
|
|
2599
|
+
if (prefix.to >= line.to) return false;
|
|
2600
|
+
dispatch(
|
|
2601
|
+
state.update({
|
|
2602
|
+
changes: { from: line.from, insert: "\n" },
|
|
2603
|
+
selection: EditorSelection3.cursor(prefix.to + 1),
|
|
2604
|
+
scrollIntoView: true,
|
|
2605
|
+
userEvent: "input"
|
|
2606
|
+
})
|
|
2607
|
+
);
|
|
2608
|
+
return true;
|
|
2609
|
+
};
|
|
2610
|
+
var deleteForward = ({ state, dispatch }) => {
|
|
2611
|
+
const sel = state.selection;
|
|
2612
|
+
if (sel.ranges.length !== 1 || !sel.main.empty) return false;
|
|
2613
|
+
const line = state.doc.lineAt(sel.main.head);
|
|
2614
|
+
if (sel.main.head !== line.to || line.number >= state.doc.lines) return false;
|
|
2615
|
+
const prefix = headingPrefix(state, state.doc.line(line.number + 1));
|
|
2616
|
+
if (!prefix) return false;
|
|
2617
|
+
dispatch(
|
|
2618
|
+
state.update({
|
|
2619
|
+
changes: { from: line.to, to: prefix.to },
|
|
2620
|
+
userEvent: "delete.forward"
|
|
2621
|
+
})
|
|
2622
|
+
);
|
|
2623
|
+
return true;
|
|
2624
|
+
};
|
|
2625
|
+
var headings = [
|
|
2626
|
+
keepOutOfPrefix,
|
|
2627
|
+
// above lang-markdown's own (Prec.high) Enter and Backspace.
|
|
2628
|
+
Prec2.highest(
|
|
2629
|
+
keymap.of([
|
|
2630
|
+
{ key: "Backspace", run: backspace },
|
|
2631
|
+
{ key: "Enter", run: enter },
|
|
2632
|
+
{ key: "Delete", run: deleteForward },
|
|
2633
|
+
{ key: "Mod-Shift-h", run: setHeading(2), preventDefault: true },
|
|
2634
|
+
{ key: "Mod-Shift-j", run: setHeading(3), preventDefault: true },
|
|
2635
|
+
{ key: "Mod-Shift-b", run: setHeading(0), preventDefault: true },
|
|
2636
|
+
{ key: "Mod-Alt-1", run: setHeading(1), preventDefault: true },
|
|
2637
|
+
{ key: "Mod-Alt-2", run: setHeading(2), preventDefault: true },
|
|
2638
|
+
{ key: "Mod-Alt-3", run: setHeading(3), preventDefault: true },
|
|
2639
|
+
{ key: "Mod-Alt-0", run: setHeading(0), preventDefault: true }
|
|
2640
|
+
])
|
|
2641
|
+
)
|
|
2642
|
+
];
|
|
2643
|
+
|
|
2644
|
+
// src/extensions/lists.ts
|
|
2645
|
+
import { syntaxTree as syntaxTree4 } from "@codemirror/language";
|
|
2646
|
+
import {
|
|
2647
|
+
StateEffect as StateEffect2,
|
|
2648
|
+
StateField as StateField2
|
|
2649
|
+
} from "@codemirror/state";
|
|
2650
|
+
import {
|
|
2651
|
+
Decoration as Decoration4,
|
|
2652
|
+
EditorView as EditorView4,
|
|
2653
|
+
ViewPlugin as ViewPlugin4,
|
|
2654
|
+
WidgetType as WidgetType3
|
|
2655
|
+
} from "@codemirror/view";
|
|
2656
|
+
function listAt(state, pos) {
|
|
2657
|
+
for (let n = syntaxTree4(state).resolveInner(pos, 1); n; n = n.parent) {
|
|
2658
|
+
if (n.name === "BulletList" || n.name === "OrderedList") return n;
|
|
2659
|
+
}
|
|
2660
|
+
return null;
|
|
2661
|
+
}
|
|
2662
|
+
var items = (list) => list.getChildren("ListItem");
|
|
2663
|
+
function done(state, item) {
|
|
2664
|
+
const marker = item.getChild("Task")?.getChild("TaskMarker");
|
|
2665
|
+
if (!marker) return null;
|
|
2666
|
+
return state.doc.sliceString(marker.from + 1, marker.to - 1).trim() !== "";
|
|
2667
|
+
}
|
|
2668
|
+
var startOf = (state, item) => state.doc.lineAt(item.from).from;
|
|
2669
|
+
var textOf = (state, item) => state.doc.sliceString(startOf(state, item), item.to);
|
|
2670
|
+
function deleteItems(state, all, gone) {
|
|
2671
|
+
const changes = [];
|
|
2672
|
+
for (let i = 0; i < all.length; ) {
|
|
2673
|
+
if (!gone.has(i)) {
|
|
2674
|
+
i++;
|
|
2675
|
+
continue;
|
|
2676
|
+
}
|
|
2677
|
+
let j = i;
|
|
2678
|
+
while (j + 1 < all.length && gone.has(j + 1)) j++;
|
|
2679
|
+
if (j + 1 < all.length) {
|
|
2680
|
+
changes.push({ from: startOf(state, all[i]), to: startOf(state, all[j + 1]) });
|
|
2681
|
+
} else if (i > 0) {
|
|
2682
|
+
changes.push({ from: all[i - 1].to, to: all[j].to });
|
|
2683
|
+
} else {
|
|
2684
|
+
changes.push({ from: startOf(state, all[i]), to: all[j].to });
|
|
2685
|
+
}
|
|
2686
|
+
i = j + 1;
|
|
2687
|
+
}
|
|
2688
|
+
return changes;
|
|
2689
|
+
}
|
|
2690
|
+
function renumber(state, list) {
|
|
2691
|
+
const changes = [];
|
|
2692
|
+
const all = items(list);
|
|
2693
|
+
const firstMark = all[0]?.getChild("ListMark");
|
|
2694
|
+
if (!firstMark) return changes;
|
|
2695
|
+
const start = parseInt(state.doc.sliceString(firstMark.from, firstMark.to), 10) || 0;
|
|
2696
|
+
all.forEach((item, i) => {
|
|
2697
|
+
const mark = item.getChild("ListMark");
|
|
2698
|
+
if (!mark) return;
|
|
2699
|
+
const text = state.doc.sliceString(mark.from, mark.to);
|
|
2700
|
+
const want = `${start + i}${text.slice(-1)}`;
|
|
2701
|
+
if (want === text) return;
|
|
2702
|
+
changes.push({ from: mark.from, to: mark.to, insert: want });
|
|
2703
|
+
const shift = want.length - text.length;
|
|
2704
|
+
const first = state.doc.lineAt(item.from).number;
|
|
2705
|
+
const last = state.doc.lineAt(item.to).number;
|
|
2706
|
+
for (let n = first + 1; n <= last; n++) {
|
|
2707
|
+
const line = state.doc.line(n);
|
|
2708
|
+
if (shift > 0) {
|
|
2709
|
+
if (line.length) changes.push({ from: line.from, insert: " ".repeat(shift) });
|
|
2710
|
+
} else {
|
|
2711
|
+
const spaces = /^ */.exec(line.text)[0].length;
|
|
2712
|
+
const cut = Math.min(spaces, -shift);
|
|
2713
|
+
if (cut) changes.push({ from: line.from, to: line.from + cut });
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
});
|
|
2717
|
+
return changes;
|
|
2718
|
+
}
|
|
2719
|
+
function needsRenumber(state, list) {
|
|
2720
|
+
return list.name === "OrderedList" && renumber(state, list).length > 0;
|
|
2721
|
+
}
|
|
2722
|
+
function clearDone(state, list) {
|
|
2723
|
+
const all = items(list);
|
|
2724
|
+
const gone = new Set(all.flatMap((it, i) => done(state, it) ? [i] : []));
|
|
2725
|
+
return deleteItems(state, all, gone);
|
|
2726
|
+
}
|
|
2727
|
+
function moveDoneDown(state, list) {
|
|
2728
|
+
const all = items(list);
|
|
2729
|
+
let lastOpen = -1;
|
|
2730
|
+
all.forEach((it, i) => {
|
|
2731
|
+
if (done(state, it) === false || done(state, it) === null) lastOpen = i;
|
|
2732
|
+
});
|
|
2733
|
+
const moving = /* @__PURE__ */ new Set();
|
|
2734
|
+
for (let i = 0; i < lastOpen; i++) if (done(state, all[i])) moving.add(i);
|
|
2735
|
+
if (!moving.size) return [];
|
|
2736
|
+
const texts = [...moving].map((i) => textOf(state, all[i]));
|
|
2737
|
+
return [
|
|
2738
|
+
...deleteItems(state, all, moving),
|
|
2739
|
+
{ from: all[lastOpen].to, insert: "\n" + texts.join("\n") }
|
|
2740
|
+
];
|
|
2741
|
+
}
|
|
2742
|
+
var countDone = (state, list) => items(list).filter((it) => done(state, it)).length;
|
|
2743
|
+
var setHideDone = StateEffect2.define();
|
|
2744
|
+
var HiddenDone = class extends WidgetType3 {
|
|
2745
|
+
constructor(count) {
|
|
2746
|
+
super();
|
|
2747
|
+
this.count = count;
|
|
2748
|
+
}
|
|
2749
|
+
eq(other) {
|
|
2750
|
+
return other.count === this.count;
|
|
2751
|
+
}
|
|
2752
|
+
toDOM(view) {
|
|
2753
|
+
const button = document.createElement("button");
|
|
2754
|
+
button.type = "button";
|
|
2755
|
+
button.className = "cm-md-hidden-done";
|
|
2756
|
+
button.textContent = `${this.count} done`;
|
|
2757
|
+
button.title = "Show done tasks";
|
|
2758
|
+
button.addEventListener("mousedown", (event) => {
|
|
2759
|
+
event.preventDefault();
|
|
2760
|
+
view.dispatch({ effects: setHideDone.of(false) });
|
|
2761
|
+
});
|
|
2762
|
+
return button;
|
|
2763
|
+
}
|
|
2764
|
+
ignoreEvent() {
|
|
2765
|
+
return true;
|
|
2766
|
+
}
|
|
2767
|
+
};
|
|
2768
|
+
function hiddenDone(state) {
|
|
2769
|
+
const decos = [];
|
|
2770
|
+
const hide = Decoration4.replace({ block: true });
|
|
2771
|
+
let hiddenTo = -1;
|
|
2772
|
+
syntaxTree4(state).iterate({
|
|
2773
|
+
enter: (node) => {
|
|
2774
|
+
if (node.from < hiddenTo) return false;
|
|
2775
|
+
if (node.name !== "BulletList" && node.name !== "OrderedList") return;
|
|
2776
|
+
const all = items(node.node);
|
|
2777
|
+
const total = all.filter((it) => done(state, it)).length;
|
|
2778
|
+
if (!total) return;
|
|
2779
|
+
const button = new HiddenDone(total);
|
|
2780
|
+
for (let i = 0; i < all.length; ) {
|
|
2781
|
+
if (!done(state, all[i])) {
|
|
2782
|
+
i++;
|
|
2783
|
+
continue;
|
|
2784
|
+
}
|
|
2785
|
+
let j = i;
|
|
2786
|
+
while (j + 1 < all.length && done(state, all[j + 1])) j++;
|
|
2787
|
+
const last = j === all.length - 1;
|
|
2788
|
+
decos.push(
|
|
2789
|
+
(last ? Decoration4.replace({ block: true, widget: button }) : hide).range(
|
|
2790
|
+
startOf(state, all[i]),
|
|
2791
|
+
all[j].to
|
|
2792
|
+
)
|
|
2793
|
+
);
|
|
2794
|
+
hiddenTo = Math.max(hiddenTo, all[j].to);
|
|
2795
|
+
i = j + 1;
|
|
2796
|
+
}
|
|
2797
|
+
const end = all[all.length - 1];
|
|
2798
|
+
if (!done(state, end)) {
|
|
2799
|
+
decos.push(
|
|
2800
|
+
Decoration4.widget({ block: true, side: 1, widget: button }).range(end.to)
|
|
2801
|
+
);
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
});
|
|
2805
|
+
return Decoration4.set(decos, true);
|
|
2806
|
+
}
|
|
2807
|
+
var hideDoneField = StateField2.define({
|
|
2808
|
+
create: () => ({ on: false, decos: Decoration4.none }),
|
|
2809
|
+
update(value, tr) {
|
|
2810
|
+
let on = value.on;
|
|
2811
|
+
for (const e of tr.effects) if (e.is(setHideDone)) on = e.value;
|
|
2812
|
+
if (!on) return { on, decos: Decoration4.none };
|
|
2813
|
+
if (on === value.on && !tr.docChanged && syntaxTree4(tr.startState) === syntaxTree4(tr.state))
|
|
2814
|
+
return value;
|
|
2815
|
+
return { on, decos: hiddenDone(tr.state) };
|
|
2816
|
+
},
|
|
2817
|
+
provide: (f) => [
|
|
2818
|
+
EditorView4.decorations.from(f, (v) => v.decos),
|
|
2819
|
+
EditorView4.atomicRanges.from(f, (v) => () => v.decos)
|
|
2820
|
+
]
|
|
2821
|
+
});
|
|
2822
|
+
var isHidingDone = (state) => state.field(hideDoneField, false)?.on ?? false;
|
|
2823
|
+
function menuItems(view, pos) {
|
|
2824
|
+
const { state } = view;
|
|
2825
|
+
const list = listAt(state, pos);
|
|
2826
|
+
if (!list) return [];
|
|
2827
|
+
const apply = (changes, userEvent) => () => view.dispatch({ changes, userEvent });
|
|
2828
|
+
const out = [];
|
|
2829
|
+
if (needsRenumber(state, list)) {
|
|
2830
|
+
out.push({ label: "Fix numbering", run: apply(renumber(state, list), "input.renumber") });
|
|
2831
|
+
}
|
|
2832
|
+
const hasTasks = items(list).some((it) => done(state, it) !== null);
|
|
2833
|
+
if (hasTasks) {
|
|
2834
|
+
const n = countDone(state, list);
|
|
2835
|
+
if (moveDoneDown(state, list).length)
|
|
2836
|
+
out.push({ label: "Move done to bottom", run: apply(moveDoneDown(state, list), "input.move") });
|
|
2837
|
+
if (n)
|
|
2838
|
+
out.push({ label: `Clear done (${n})`, run: apply(clearDone(state, list), "delete.clear-done") });
|
|
2839
|
+
const hiding = isHidingDone(state);
|
|
2840
|
+
out.push({
|
|
2841
|
+
label: hiding ? "Show done" : "Hide done",
|
|
2842
|
+
run: () => view.dispatch({ effects: setHideDone.of(!hiding) })
|
|
2843
|
+
});
|
|
2844
|
+
}
|
|
2845
|
+
return out;
|
|
2846
|
+
}
|
|
2847
|
+
function openMenu(view, x, y, entries) {
|
|
2848
|
+
const menu = document.createElement("div");
|
|
2849
|
+
menu.className = "cm-md-menu";
|
|
2850
|
+
menu.setAttribute("role", "menu");
|
|
2851
|
+
menu.style.left = `${x}px`;
|
|
2852
|
+
menu.style.top = `${y}px`;
|
|
2853
|
+
const buttons = entries.map(({ label, run }) => {
|
|
2854
|
+
const b = document.createElement("button");
|
|
2855
|
+
b.type = "button";
|
|
2856
|
+
b.className = "cm-md-menu-item";
|
|
2857
|
+
b.setAttribute("role", "menuitem");
|
|
2858
|
+
b.textContent = label;
|
|
2859
|
+
b.addEventListener("click", () => {
|
|
2860
|
+
close();
|
|
2861
|
+
run();
|
|
2862
|
+
view.focus();
|
|
2863
|
+
});
|
|
2864
|
+
return b;
|
|
2865
|
+
});
|
|
2866
|
+
menu.append(...buttons);
|
|
2867
|
+
const outside = (e) => {
|
|
2868
|
+
if (!menu.contains(e.target)) close();
|
|
2869
|
+
};
|
|
2870
|
+
const keys = (e) => {
|
|
2871
|
+
const i = buttons.indexOf(document.activeElement);
|
|
2872
|
+
if (e.key === "Escape") {
|
|
2873
|
+
e.preventDefault();
|
|
2874
|
+
close();
|
|
2875
|
+
view.focus();
|
|
2876
|
+
} else if (e.key === "ArrowDown" || e.key === "ArrowUp") {
|
|
2877
|
+
e.preventDefault();
|
|
2878
|
+
const step2 = e.key === "ArrowDown" ? 1 : -1;
|
|
2879
|
+
buttons[(i + step2 + buttons.length) % buttons.length]?.focus();
|
|
2880
|
+
}
|
|
2881
|
+
};
|
|
2882
|
+
function close() {
|
|
2883
|
+
menu.remove();
|
|
2884
|
+
window.removeEventListener("pointerdown", outside, true);
|
|
2885
|
+
window.removeEventListener("scroll", close, true);
|
|
2886
|
+
window.removeEventListener("blur", close);
|
|
2887
|
+
menu.removeEventListener("keydown", keys);
|
|
2888
|
+
}
|
|
2889
|
+
window.addEventListener("pointerdown", outside, true);
|
|
2890
|
+
window.addEventListener("scroll", close, true);
|
|
2891
|
+
window.addEventListener("blur", close);
|
|
2892
|
+
menu.addEventListener("keydown", keys);
|
|
2893
|
+
view.dom.appendChild(menu);
|
|
2894
|
+
const r = menu.getBoundingClientRect();
|
|
2895
|
+
if (r.right > window.innerWidth) menu.style.left = `${Math.max(0, x - r.width)}px`;
|
|
2896
|
+
if (r.bottom > window.innerHeight) menu.style.top = `${Math.max(0, y - r.height)}px`;
|
|
2897
|
+
buttons[0]?.focus();
|
|
2898
|
+
return close;
|
|
2899
|
+
}
|
|
2900
|
+
var menuPlugin = ViewPlugin4.fromClass(
|
|
2901
|
+
class {
|
|
2902
|
+
constructor(view) {
|
|
2903
|
+
this.view = view;
|
|
2904
|
+
view.contentDOM.addEventListener("contextmenu", this.open);
|
|
2905
|
+
}
|
|
2906
|
+
close = null;
|
|
2907
|
+
open = (event) => {
|
|
2908
|
+
const { view } = this;
|
|
2909
|
+
const target = event.target;
|
|
2910
|
+
const marker = target?.closest(".cm-md-hang, .cm-md-hidden-done");
|
|
2911
|
+
if (!marker || !view.contentDOM.contains(marker)) return;
|
|
2912
|
+
const entries = menuItems(view, view.posAtDOM(marker));
|
|
2913
|
+
if (!entries.length) return;
|
|
2914
|
+
event.preventDefault();
|
|
2915
|
+
this.close?.();
|
|
2916
|
+
this.close = openMenu(view, event.clientX, event.clientY, entries);
|
|
2917
|
+
};
|
|
2918
|
+
destroy() {
|
|
2919
|
+
this.view.contentDOM.removeEventListener("contextmenu", this.open);
|
|
2920
|
+
this.close?.();
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
);
|
|
2924
|
+
var listsTheme = EditorView4.baseTheme({
|
|
2925
|
+
".cm-md-menu": {
|
|
2926
|
+
position: "fixed",
|
|
2927
|
+
zIndex: "var(--studio-layer-popover, 4000)",
|
|
2928
|
+
display: "flex",
|
|
2929
|
+
flexDirection: "column",
|
|
2930
|
+
minWidth: "12rem",
|
|
2931
|
+
padding: "4px",
|
|
2932
|
+
borderRadius: "6px",
|
|
2933
|
+
background: "var(--studio-fill, white)",
|
|
2934
|
+
color: "var(--studio-line, black)",
|
|
2935
|
+
border: "var(--studio-border-width, 1px) var(--studio-border-style, solid) var(--studio-fill-offset-30, #ddd)",
|
|
2936
|
+
boxShadow: "var(--studio-shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1))",
|
|
2937
|
+
fontFamily: "var(--studio-family-ui, system-ui, sans-serif)",
|
|
2938
|
+
fontSize: "0.8rem"
|
|
2939
|
+
},
|
|
2940
|
+
".cm-md-menu-item": {
|
|
2941
|
+
all: "unset",
|
|
2942
|
+
padding: "8px 12px",
|
|
2943
|
+
borderRadius: "4px",
|
|
2944
|
+
cursor: "var(--studio-cursor-default, default)"
|
|
2945
|
+
},
|
|
2946
|
+
".cm-md-menu-item:hover, .cm-md-menu-item:focus-visible": {
|
|
2947
|
+
background: "var(--studio-fill-offset-20, #eee)"
|
|
2948
|
+
},
|
|
2949
|
+
".cm-md-hidden-done": {
|
|
2950
|
+
all: "unset",
|
|
2951
|
+
display: "block",
|
|
2952
|
+
paddingInline: "6px 2px",
|
|
2953
|
+
fontSize: "0.8rem",
|
|
2954
|
+
color: "var(--text-editor-line-offset-40, #999)",
|
|
2955
|
+
cursor: "var(--studio-cursor-pointer, pointer)"
|
|
2956
|
+
},
|
|
2957
|
+
".cm-md-hidden-done:hover": {
|
|
2958
|
+
textDecoration: "underline"
|
|
2959
|
+
}
|
|
2960
|
+
});
|
|
2961
|
+
var lists = [hideDoneField, menuPlugin, listsTheme];
|
|
2962
|
+
|
|
2963
|
+
// src/extensions/zoom.ts
|
|
2964
|
+
import { Prec as Prec3 } from "@codemirror/state";
|
|
2965
|
+
import { keymap as keymap2 } from "@codemirror/view";
|
|
2471
2966
|
var MIN_FONT_SIZE = 6;
|
|
2472
2967
|
var FALLBACK_FONT_SIZE = 16;
|
|
2473
2968
|
var px = (value) => parseFloat(value) || FALLBACK_FONT_SIZE;
|
|
@@ -2496,8 +2991,8 @@ function step(view, by) {
|
|
|
2496
2991
|
var zoomIn = (view) => step(view, 1);
|
|
2497
2992
|
var zoomOut = (view) => step(view, -1);
|
|
2498
2993
|
var zoomReset = (view) => step(view, 0);
|
|
2499
|
-
var markdownZoom =
|
|
2500
|
-
|
|
2994
|
+
var markdownZoom = Prec3.high(
|
|
2995
|
+
keymap2.of([
|
|
2501
2996
|
// `+` and `_` are the shifted keys, for keyboards that need Shift.
|
|
2502
2997
|
{ key: "Mod-=", run: zoomIn, preventDefault: true },
|
|
2503
2998
|
{ key: "Mod-+", run: zoomIn, preventDefault: true },
|
|
@@ -2509,7 +3004,7 @@ var markdownZoom = Prec2.high(
|
|
|
2509
3004
|
|
|
2510
3005
|
// src/themes/markdown.ts
|
|
2511
3006
|
import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
2512
|
-
import { EditorView as
|
|
3007
|
+
import { EditorView as EditorView6 } from "@codemirror/view";
|
|
2513
3008
|
var bodyFont = (style) => style == "serif" ? 'var(--text-editor-family-serif, "Merriweather", serif)' : "var(--text-editor-family-sans)";
|
|
2514
3009
|
var zoomed2 = (length) => `calc(${length} * var(--markdown-zoom, 1))`;
|
|
2515
3010
|
var markdownStyles = (style) => ({
|
|
@@ -2724,7 +3219,7 @@ var markdownSyntaxHighlighting = (style) => HighlightStyle.define([
|
|
|
2724
3219
|
{ tag: tags.monospace, ...baseCodeStyles }
|
|
2725
3220
|
]);
|
|
2726
3221
|
var theme = (style) => [
|
|
2727
|
-
|
|
3222
|
+
EditorView6.theme(markdownStyles(style)),
|
|
2728
3223
|
syntaxHighlighting(markdownSyntaxHighlighting(style))
|
|
2729
3224
|
];
|
|
2730
3225
|
|
|
@@ -2734,7 +3229,7 @@ function markdownExtensions() {
|
|
|
2734
3229
|
...theme("sans"),
|
|
2735
3230
|
indentOnInput(),
|
|
2736
3231
|
markdownZoom,
|
|
2737
|
-
|
|
3232
|
+
keymap3.of([
|
|
2738
3233
|
...markdownFormattingKeymap,
|
|
2739
3234
|
...defaultKeymap,
|
|
2740
3235
|
...searchKeymap,
|
|
@@ -2742,7 +3237,7 @@ function markdownExtensions() {
|
|
|
2742
3237
|
...completionKeymap,
|
|
2743
3238
|
indentWithTab
|
|
2744
3239
|
]),
|
|
2745
|
-
|
|
3240
|
+
EditorView7.lineWrapping,
|
|
2746
3241
|
// GFM base: task lists, tables, strikethrough, autolinks.
|
|
2747
3242
|
markdown({
|
|
2748
3243
|
base: markdownLanguage,
|
|
@@ -2751,6 +3246,8 @@ function markdownExtensions() {
|
|
|
2751
3246
|
}),
|
|
2752
3247
|
taskCheckboxes,
|
|
2753
3248
|
margin,
|
|
3249
|
+
headings,
|
|
3250
|
+
lists,
|
|
2754
3251
|
indentUnit.of(" ")
|
|
2755
3252
|
];
|
|
2756
3253
|
}
|