@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.
@@ -1 +1 @@
1
- automerge:26QrzDPdwUkvv4fzdBx1Md6JmTCc
1
+ automerge:3LxJsuExcL8S2E8j8758gWkK1Hdp
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkandswitch/patchwork-pkg-base",
3
- "version": "0.0.124",
3
+ "version": "0.0.126",
4
4
  "type": "module",
5
5
  "description": "Base packages for the Patchwork system",
6
6
  "repository": {
@@ -2066,7 +2066,7 @@ var searchExtensions = [
2066
2066
  ];
2067
2067
 
2068
2068
  // src/extensions/markdown.ts
2069
- import { EditorView as EditorView6, keymap as keymap2 } from "@codemirror/view";
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
- const end = skipSpaces(state, mark.to);
2305
- if (editing.has(doc.lineAt(node.from).number)) {
2306
- decos.push(hangMark.range(mark.from, end));
2307
- } else {
2308
- decos.push(
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/zoom.ts
2469
- import { Prec as Prec2 } from "@codemirror/state";
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 = Prec2.high(
2500
- keymap.of([
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 EditorView5 } from "@codemirror/view";
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
- EditorView5.theme(markdownStyles(style)),
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
- keymap2.of([
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
- EditorView6.lineWrapping,
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
  }