@inkandswitch/patchwork-pkg-base 0.0.124 → 0.0.125

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:Wh4456nTsRj7WssD8ChKeeRFqa9
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.125",
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 EditorView6, 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,154 @@ 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/zoom.ts
2645
+ import { Prec as Prec3 } from "@codemirror/state";
2646
+ import { keymap as keymap2 } from "@codemirror/view";
2471
2647
  var MIN_FONT_SIZE = 6;
2472
2648
  var FALLBACK_FONT_SIZE = 16;
2473
2649
  var px = (value) => parseFloat(value) || FALLBACK_FONT_SIZE;
@@ -2496,8 +2672,8 @@ function step(view, by) {
2496
2672
  var zoomIn = (view) => step(view, 1);
2497
2673
  var zoomOut = (view) => step(view, -1);
2498
2674
  var zoomReset = (view) => step(view, 0);
2499
- var markdownZoom = Prec2.high(
2500
- keymap.of([
2675
+ var markdownZoom = Prec3.high(
2676
+ keymap2.of([
2501
2677
  // `+` and `_` are the shifted keys, for keyboards that need Shift.
2502
2678
  { key: "Mod-=", run: zoomIn, preventDefault: true },
2503
2679
  { key: "Mod-+", run: zoomIn, preventDefault: true },
@@ -2734,7 +2910,7 @@ function markdownExtensions() {
2734
2910
  ...theme("sans"),
2735
2911
  indentOnInput(),
2736
2912
  markdownZoom,
2737
- keymap2.of([
2913
+ keymap3.of([
2738
2914
  ...markdownFormattingKeymap,
2739
2915
  ...defaultKeymap,
2740
2916
  ...searchKeymap,
@@ -2751,6 +2927,7 @@ function markdownExtensions() {
2751
2927
  }),
2752
2928
  taskCheckboxes,
2753
2929
  margin,
2930
+ headings,
2754
2931
  indentUnit.of(" ")
2755
2932
  ];
2756
2933
  }