@agentshouse/mdruntime 0.1.0-cb9c79aee537a → 0.1.0-cc294e382554d

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.
Files changed (65) hide show
  1. package/dist/adapter.d.ts +13 -0
  2. package/dist/adapter.d.ts.map +1 -1
  3. package/dist/change-set.d.ts +5 -2
  4. package/dist/change-set.d.ts.map +1 -1
  5. package/dist/change-set.js +6 -1
  6. package/dist/chat/list.d.ts +2 -1
  7. package/dist/chat/list.d.ts.map +1 -1
  8. package/dist/chat/list.js +7 -3
  9. package/dist/chat/message.d.ts +1 -0
  10. package/dist/chat/message.d.ts.map +1 -1
  11. package/dist/chat/message.js +12 -2
  12. package/dist/chat/messages.d.ts +2 -0
  13. package/dist/chat/messages.d.ts.map +1 -1
  14. package/dist/chat/messages.js +52 -20
  15. package/dist/chat/overlay.d.ts +1 -0
  16. package/dist/chat/overlay.d.ts.map +1 -1
  17. package/dist/chat/overlay.js +10 -0
  18. package/dist/chat/pieces.d.ts +13 -2
  19. package/dist/chat/pieces.d.ts.map +1 -1
  20. package/dist/chat/pieces.js +397 -84
  21. package/dist/chat/provider.d.ts +1 -0
  22. package/dist/chat/provider.d.ts.map +1 -1
  23. package/dist/chat/provider.js +13 -3
  24. package/dist/chat/ready.d.ts +1 -1
  25. package/dist/chat/ready.d.ts.map +1 -1
  26. package/dist/chat/ready.js +1 -1
  27. package/dist/chat/steady.d.ts +3 -0
  28. package/dist/chat/steady.d.ts.map +1 -0
  29. package/dist/chat/steady.js +26 -0
  30. package/dist/chat.d.ts +1 -1
  31. package/dist/chat.d.ts.map +1 -1
  32. package/dist/chat.js +1 -1
  33. package/dist/connection.d.ts.map +1 -1
  34. package/dist/connection.js +45 -30
  35. package/dist/conversation.d.ts +6 -0
  36. package/dist/conversation.d.ts.map +1 -1
  37. package/dist/conversation.js +36 -1
  38. package/dist/host.d.ts +1 -1
  39. package/dist/host.d.ts.map +1 -1
  40. package/dist/host.js +1 -1
  41. package/dist/overlay.d.ts +3 -4
  42. package/dist/overlay.d.ts.map +1 -1
  43. package/dist/overlay.js +178 -141
  44. package/dist/read-side.d.ts.map +1 -1
  45. package/dist/read-side.js +4 -2
  46. package/dist/refresh.d.ts.map +1 -1
  47. package/dist/refresh.js +34 -15
  48. package/dist/replica.d.ts +2 -1
  49. package/dist/replica.d.ts.map +1 -1
  50. package/dist/replica.js +18 -15
  51. package/dist/room-draft.d.ts.map +1 -1
  52. package/dist/room-draft.js +8 -9
  53. package/dist/save.d.ts +1 -1
  54. package/dist/save.d.ts.map +1 -1
  55. package/dist/save.js +154 -92
  56. package/dist/shared.d.ts +1 -0
  57. package/dist/shared.d.ts.map +1 -1
  58. package/dist/shared.js +5 -1
  59. package/dist/store.d.ts +2 -0
  60. package/dist/store.d.ts.map +1 -1
  61. package/dist/store.js +387 -339
  62. package/dist/turn.d.ts +1 -1
  63. package/dist/turn.d.ts.map +1 -1
  64. package/dist/turn.js +4 -4
  65. package/package.json +2 -2
@@ -36,6 +36,11 @@ const PUNCTUATION = /[\p{P}\p{S}]/u;
36
36
  const ESCAPABLE = /[!-/:-@[-`{-~]/;
37
37
  const TAG_START = /[A-Za-z!?/]/;
38
38
  const LINE_ENDING = /\r\n?|\n/g;
39
+ const QUOTE_MARKER = /^ {0,3}> ?/;
40
+ const MARKER = /^(?:[-+*]|\d{1,9}[.)])/;
41
+ const TASK = /^\[[ \txX]\]/;
42
+ const NOTE = /^\[\^(?:[^\\\]]|\\.){1,999}\]:/;
43
+ const SPACES = /^[ \t]*$/;
39
44
  const START = {
40
45
  fence: null,
41
46
  list: null,
@@ -288,11 +293,12 @@ export function longOf(text) {
288
293
  anchors,
289
294
  candidates,
290
295
  pieces: [],
291
- next: { start: 0, path: [], join: '', carry: '' },
296
+ next: { start: 0, path: [], join: '', carry: '', levels: [] },
292
297
  urls: new Map(),
293
298
  spans: new Map(),
294
299
  discoveries: new Map(),
295
300
  regions: new Map(),
301
+ spreads: new Map(),
296
302
  };
297
303
  }
298
304
  function offsetOf(node) {
@@ -328,6 +334,7 @@ function windowOf(long, from, end, prefix) {
328
334
  lead,
329
335
  prefix,
330
336
  carry: from.carry,
337
+ levels: from.levels,
331
338
  nodes,
332
339
  defined: definedIn(nodes, from.start - lead),
333
340
  };
@@ -344,16 +351,15 @@ function spanned(long, anchor, stop) {
344
351
  function discovered(long, anchor, stop) {
345
352
  let discovery = long.discoveries.get(anchor);
346
353
  if (discovery === undefined) {
347
- discovery = { found: [], next: { start: anchor, path: [], join: '', carry: '' } };
354
+ discovery = { found: [], next: { start: anchor, path: [], join: '', carry: '', levels: [] } };
348
355
  long.discoveries.set(anchor, discovery);
349
356
  }
350
357
  while (discovery.next !== null && discovery.next.start < stop) {
351
358
  const from = discovery.next;
352
- const { window, cut } = cutWindow(long, from, 'discover', (end) => windowOf(long, from, end, ''));
359
+ const { pane, cut } = cutWindow(long, from, 'discover', (end) => windowOf(long, from, end, ''));
353
360
  const end = cut?.at ?? long.text.length;
354
- discovery.found.push(...window.defined.filter((one) => one.at < end));
355
- discovery.next =
356
- cut === null ? null : { start: cut.at, path: cut.path, join: cut.join, carry: cut.carry };
361
+ discovery.found.push(...pane.defined.filter((one) => one.at < end));
362
+ discovery.next = cut === null ? null : nextOf(cut);
357
363
  }
358
364
  return discovery.found;
359
365
  }
@@ -420,10 +426,10 @@ function renderWindow(long, from, end) {
420
426
  long.urls.set(key, url);
421
427
  known.push(key);
422
428
  }
423
- const window = windowOf(long, from, end, prefixOf(known));
429
+ const pane = windowOf(long, from, end, prefixOf(known));
424
430
  const later = [];
425
431
  for (const key of deferred) {
426
- const native = window.defined.find((one) => one.key === key);
432
+ const native = pane.defined.find((one) => one.key === key);
427
433
  if (native !== undefined) {
428
434
  long.urls.set(key, native.url);
429
435
  continue;
@@ -434,7 +440,7 @@ function renderWindow(long, from, end) {
434
440
  long.urls.set(key, url);
435
441
  later.push(key);
436
442
  }
437
- return later.length === 0 ? window : windowOf(long, from, end, prefixOf([...known, ...later]));
443
+ return later.length === 0 ? pane : windowOf(long, from, end, prefixOf([...known, ...later]));
438
444
  }
439
445
  function windowEnd(long, start, size) {
440
446
  const at = start + size;
@@ -443,19 +449,209 @@ function windowEnd(long, start, size) {
443
449
  const end = lineEnd(long.starts, long.text, lineOf(long, at));
444
450
  return end - at <= VIEW_CHARS ? Math.min(end + 1, long.text.length) : at;
445
451
  }
446
- function regionOf(long, line, depth) {
447
- const stop = (depth > 0 ? long.quoteBreaks : long.breaks)[line];
448
- const markers = markersOf(depth);
449
- const name = `${depth}:${stop}`;
450
- const held = long.regions.get(name);
452
+ function nextOf(cut) {
453
+ return { start: cut.at, path: cut.path, join: cut.join, carry: cut.carry, levels: cut.levels };
454
+ }
455
+ function quotesOf(levels) {
456
+ return levels.filter((level) => level.kind === 'quote').length;
457
+ }
458
+ function itemed(levels) {
459
+ return levels.some((level) => level.kind !== 'quote');
460
+ }
461
+ function stepsOf(levels) {
462
+ return levels.flatMap((level) => level.kind === 'quote'
463
+ ? ['blockquote']
464
+ : level.kind === 'item'
465
+ ? ['list', 'item']
466
+ : ['footnote']);
467
+ }
468
+ function carryOf(levels) {
469
+ return levels.map((level) => level.carry).join('');
470
+ }
471
+ function columnOn(long, index, levels) {
472
+ const raw = lineText(long.starts, long.text, index);
473
+ let at = 0;
474
+ for (const level of levels) {
475
+ if (level.line === index) {
476
+ at = level.column;
477
+ if (at < 0)
478
+ return -1;
479
+ }
480
+ else if (level.kind === 'quote') {
481
+ const marker = QUOTE_MARKER.exec(raw.slice(at));
482
+ if (marker === null)
483
+ return -1;
484
+ at += marker[0].length;
485
+ }
486
+ else {
487
+ for (let column = 0; column < level.size; column += 1) {
488
+ if (raw[at + column] !== ' ')
489
+ return -1;
490
+ }
491
+ at += level.size;
492
+ }
493
+ }
494
+ return at;
495
+ }
496
+ function withinOf(raw, levels) {
497
+ let rest = raw;
498
+ for (const [index, level] of levels.entries()) {
499
+ if (level.kind === 'quote') {
500
+ const marker = QUOTE_MARKER.exec(rest);
501
+ if (marker === null)
502
+ return SPACES.test(rest) ? 'gone' : 'line';
503
+ rest = rest.slice(marker[0].length);
504
+ continue;
505
+ }
506
+ if (SPACES.test(rest))
507
+ return quotesOf(levels.slice(index)) > 0 ? 'gone' : 'blank';
508
+ if (!rest.startsWith(' '.repeat(level.size)))
509
+ return 'line';
510
+ rest = rest.slice(level.size);
511
+ }
512
+ return SPACES.test(rest) ? 'blank' : 'line';
513
+ }
514
+ function plain(facts) {
515
+ return (!opens(facts) &&
516
+ !TAG.test(facts.content) &&
517
+ !DELIMITER_ROW.test(facts.content) &&
518
+ !UNDERLINE.test(facts.content));
519
+ }
520
+ function spreadScan(long, line, column, size, parents) {
521
+ const { text, starts } = long;
522
+ const lines = starts.length - 1;
523
+ const quotes = quotesOf(parents);
524
+ const breaks = quotes > 0 ? long.quoteBreaks : long.breaks;
525
+ const kind = (index) => withinOf(lineText(starts, text, index), parents);
526
+ let blank = breaks[line + 1];
527
+ while (blank < lines && kind(blank) === 'line')
528
+ blank = breaks[blank + 1];
529
+ if (blank >= lines || kind(blank) === 'gone')
530
+ return false;
531
+ let next = blank + 1;
532
+ while (next < lines && kind(next) === 'blank')
533
+ next += 1;
534
+ if (next >= lines || kind(next) === 'gone')
535
+ return false;
536
+ const at = columnOn(long, next, parents);
537
+ if (at < 0)
538
+ return false;
539
+ const lead = /^[ \t]*/.exec(lineText(starts, text, next).slice(at))[0];
540
+ if (lead.includes('\t'))
541
+ return null;
542
+ if (lead.length < size)
543
+ return false;
544
+ const leads = new RegExp(`^(?: {0,3}> ?){0,${quotes}}`);
545
+ if (!plain(lineFacts(lineText(starts, text, line).slice(column))))
546
+ return null;
547
+ for (let index = line + 1; index < blank; index += 1) {
548
+ const raw = lineText(starts, text, index);
549
+ const held = columnOn(long, index, parents);
550
+ const rest = held < 0 ? raw.replace(leads, '') : raw.slice(held);
551
+ const indent = /^[ \t]*/.exec(rest)[0];
552
+ if (indent.includes('\t'))
553
+ return null;
554
+ const inner = indent.length >= size ? lineFacts(rest.slice(size)) : lineFacts(rest);
555
+ if (indent.length >= size && inner.indent >= 4)
556
+ return null;
557
+ if (!plain(inner))
558
+ return null;
559
+ }
560
+ return true;
561
+ }
562
+ function spreadOf(long, line, column, size, parents) {
563
+ const key = long.starts[line] + column;
564
+ const held = long.spreads.get(key);
451
565
  if (held !== undefined)
452
566
  return held;
567
+ const spread = spreadScan(long, line, column, size, parents);
568
+ long.spreads.set(key, spread);
569
+ return spread;
570
+ }
571
+ function itemLevel(long, pane, item, outer) {
572
+ const { text, starts } = long;
573
+ const marker = offsetOf(item) + pane.start - pane.lead;
574
+ const line = lineOf(long, marker);
575
+ const start = starts[line];
576
+ const base = columnOn(long, line, outer);
577
+ if (base < 0 || marker < start + base || !/^ *$/.test(text.slice(start + base, marker))) {
578
+ return null;
579
+ }
580
+ const sign = MARKER.exec(text.slice(marker, marker + 11))?.[0];
581
+ if (sign === undefined)
582
+ return null;
583
+ let after = marker + sign.length;
584
+ while (text[after] === ' ')
585
+ after += 1;
586
+ const spaces = after - marker - sign.length;
587
+ if (spaces < 1 || spaces > 4 || after >= lineEnd(starts, text, line))
588
+ return null;
589
+ if (/[\t\r\n]/.test(text[after]))
590
+ return null;
591
+ const column = after - start;
592
+ const size = column - base;
593
+ const spread = item.spread === true
594
+ ? true
595
+ : spreadOf(long, line, column, size, outer);
596
+ if (spread === null)
597
+ return null;
598
+ long.spreads.set(start + column, spread);
599
+ const carry = `${' '.repeat(marker - start - base)}${sign}${' '.repeat(spaces)}`;
600
+ return { kind: 'item', line, column, size, carry, spread };
601
+ }
602
+ function noteLevel(long, pane, note, outer) {
603
+ const { text, starts } = long;
604
+ const marker = offsetOf(note) + pane.start - pane.lead;
605
+ const line = lineOf(long, marker);
606
+ const start = starts[line];
607
+ const base = columnOn(long, line, outer);
608
+ if (base < 0 || marker < start + base || !/^ *$/.test(text.slice(start + base, marker))) {
609
+ return null;
610
+ }
611
+ const label = NOTE.exec(text.slice(marker, marker + 1_004))?.[0];
612
+ if (label === undefined)
613
+ return null;
614
+ let after = marker + label.length;
615
+ while (text[after] === ' ')
616
+ after += 1;
617
+ if (text[after] === '\t')
618
+ return null;
619
+ const column = after - start;
620
+ return { kind: 'note', line, column, size: 4, carry: `${label} `, spread: false };
621
+ }
622
+ function quoteLevel(long, pane, quote) {
623
+ const { text, starts } = long;
624
+ const marker = offsetOf(quote) + pane.start - pane.lead;
625
+ const line = lineOf(long, marker);
626
+ const known = text[marker] === '>' && text[marker + 1] !== '\t';
627
+ const after = text[marker + 1] === ' ' ? marker + 2 : marker + 1;
628
+ return {
629
+ kind: 'quote',
630
+ line,
631
+ column: known ? after - starts[line] : -1,
632
+ size: 0,
633
+ carry: '> ',
634
+ spread: false,
635
+ };
636
+ }
637
+ function regionOf(long, line, levels) {
638
+ const quotes = quotesOf(levels);
639
+ const lined = !itemed(levels);
640
+ const stop = (quotes > 0 ? long.quoteBreaks : long.breaks)[line];
641
+ const markers = markersOf(quotes);
642
+ const leads = new RegExp(`^(?: {0,3}> ?){0,${quotes}}`);
643
+ const name = `${levels.map((level) => (level.kind === 'quote' ? '>' : level.size)).join(' ')}:${stop}`;
644
+ const held = long.regions.get(name);
645
+ if (held !== undefined && held.from <= line + 1)
646
+ return held;
453
647
  const { text, starts } = long;
454
- let setext = false;
455
- for (let index = line + 1; index < stop && !setext; index += 1) {
648
+ const looks = [];
649
+ for (let index = line + 1; index < stop; index += 1) {
456
650
  const raw = lineText(starts, text, index);
457
- const facts = lineFacts(raw.replace(markers, ''));
458
- setext = facts.indent <= 3 && UNDERLINE.test(facts.content);
651
+ const column = lined ? (markers.exec(raw)?.[0].length ?? -1) : columnOn(long, index, levels);
652
+ const facts = lineFacts(column < 0 ? raw.replace(lined ? markers : leads, '') : raw.slice(column));
653
+ if (facts.indent <= 3 && UNDERLINE.test(facts.content))
654
+ looks.push(index);
459
655
  }
460
656
  const from = starts[line];
461
657
  const to = Math.min(starts[stop], text.length);
@@ -470,10 +666,22 @@ function regionOf(long, line, depth) {
470
666
  runs.set(end - at, at);
471
667
  at = text.indexOf('`', end);
472
668
  }
473
- const region = { setext, last, runs };
669
+ const region = { from: line + 1, looks, last, runs };
474
670
  long.regions.set(name, region);
475
671
  return region;
476
672
  }
673
+ function after(lines, line) {
674
+ let low = 0;
675
+ let high = lines.length;
676
+ while (low < high) {
677
+ const middle = (low + high) >> 1;
678
+ if (lines[middle] <= line)
679
+ low = middle + 1;
680
+ else
681
+ high = middle;
682
+ }
683
+ return lines[low] ?? Infinity;
684
+ }
477
685
  const CODE = 1;
478
686
  const LINKED = 2;
479
687
  const EMPHASIZED = 4;
@@ -513,12 +721,12 @@ function opener(text, from, to, paragraph) {
513
721
  const right = !space(before) && (!mark(before) || space(after) || mark(after));
514
722
  return left && (!right || mark(before));
515
723
  }
516
- function pendingAt(long, window, paragraph, start, region) {
724
+ function pendingAt(long, pane, paragraph, start, region) {
517
725
  const { text } = long;
518
- const shift = window.start - window.lead;
519
- const flags = new Uint8Array(window.end - start);
726
+ const shift = pane.start - pane.lead;
727
+ const flags = new Uint8Array(pane.end - start);
520
728
  marked(paragraph, flags, shift, start, text);
521
- for (let at = start; at < window.end; at += 1) {
729
+ for (let at = start; at < pane.end; at += 1) {
522
730
  if ((flags[at - start] & CODE) !== 0)
523
731
  continue;
524
732
  const one = text[at];
@@ -565,61 +773,102 @@ function inside(spans, at) {
565
773
  function markersOf(depth) {
566
774
  return new RegExp(`^(?: {0,3}> ?){${depth}}`);
567
775
  }
568
- function paragraphCuts(long, window, paragraph, depth, mode) {
776
+ function spreadAlong(nodes, levels) {
777
+ let node = nodes.at(-1);
778
+ for (const level of levels) {
779
+ if (node === undefined || !('children' in node))
780
+ break;
781
+ if (level.kind !== 'item') {
782
+ node = node.children.at(-1);
783
+ continue;
784
+ }
785
+ const item = node.children.at(-1);
786
+ if (node.type !== 'list' || item?.type !== 'listItem')
787
+ break;
788
+ item.spread = level.spread;
789
+ node = item.children.at(-1);
790
+ }
791
+ return nodes;
792
+ }
793
+ function openable(long, line, cut, begun, frame) {
569
794
  const { text, starts } = long;
570
- const markers = markersOf(depth);
571
- const leads = new RegExp(`^(?: {0,3}> ?){0,${depth}}`);
572
- const carry = '> '.repeat(depth);
573
- const shift = window.start - window.lead;
574
- const start = Math.max(offsetOf(paragraph) + shift, window.start);
795
+ if (!/^ *$/.test(text.slice(cut, begun)))
796
+ return false;
797
+ const content = lineText(starts, text, line).slice(cut - starts[line]);
798
+ const inner = frame.at(-1).kind;
799
+ if (inner !== 'quote' && cut !== begun)
800
+ return false;
801
+ if (inner === 'item' && TASK.test(content))
802
+ return false;
803
+ return frame.every((_, index) => {
804
+ const facts = lineFacts(`${carryOf(frame.slice(index))}${content}`);
805
+ return facts.indent > 3 || !THEMATIC.test(facts.content);
806
+ });
807
+ }
808
+ function paragraphCuts(long, pane, paragraph, levels, mode) {
809
+ const { text, starts } = long;
810
+ const quotes = quotesOf(levels);
811
+ const lined = !itemed(levels);
812
+ const markers = markersOf(quotes);
813
+ const leads = new RegExp(`^(?: {0,3}> ?){0,${quotes}}`);
814
+ const carry = carryOf(levels);
815
+ const shift = pane.start - pane.lead;
816
+ const start = Math.max(offsetOf(paragraph) + shift, pane.start);
575
817
  const first = lineOf(long, start);
576
- const region = regionOf(long, first, depth);
577
- if (region.setext)
818
+ const region = regionOf(long, first, levels);
819
+ if (after(region.looks, first) !== Infinity)
578
820
  return [];
579
- const pending = mode === 'render' ? pendingAt(long, window, paragraph, start, region) : Infinity;
821
+ const pending = mode === 'render' ? pendingAt(long, pane, paragraph, start, region) : Infinity;
580
822
  const spans = mode === 'render'
581
823
  ? paragraph.children
582
824
  .filter((child) => child.type !== 'text')
583
825
  .map((child) => [offsetOf(child) + shift, endOf(child) + shift])
584
826
  : [];
585
- const last = lineOf(long, window.end - 1);
827
+ const last = lineOf(long, pane.end - 1);
586
828
  const lines = starts.length - 1;
587
- const path = [...Array(depth).fill('blockquote'), 'paragraph'];
588
- const reparsed = (at) => () => windowOf(long, { start: window.start, path: [], join: '', carry: window.carry }, at, window.prefix).nodes;
829
+ const path = [...stepsOf(levels), 'paragraph'];
830
+ const reparsed = (at) => () => spreadAlong(windowOf(long, { start: pane.start, path: [], join: '', carry: pane.carry, levels: pane.levels }, at, pane.prefix).nodes, levels);
589
831
  const cuts = [];
590
832
  const settled = (at) => at > start && at < pending && !inside(spans, at);
591
- const unbroken = (index) => {
592
- if (index >= lines)
593
- return true;
594
- const next = lineText(starts, text, index);
595
- return !DELIMITER_ROW.test(lineFacts(next.replace(markers, '')).content);
833
+ const restOf = (index) => {
834
+ const raw = lineText(starts, text, index);
835
+ const column = lined ? -1 : columnOn(long, index, levels);
836
+ return column < 0 ? raw.replace(lined ? markers : leads, '') : raw.slice(column);
596
837
  };
597
- const contentOf = (index) => starts[index] + leads.exec(lineText(starts, text, index))[0].length;
838
+ const unbroken = (index) => index >= lines || !DELIMITER_ROW.test(lineFacts(restOf(index)).content);
839
+ const contentOf = (index) => {
840
+ const raw = lineText(starts, text, index);
841
+ const column = lined ? -1 : columnOn(long, index, levels);
842
+ return starts[index] + (column < 0 ? leads.exec(raw)[0].length : column);
843
+ };
844
+ const fresh = (at) => levels.at(-1)?.kind !== 'item' || !TASK.test(text.slice(at, at + 3));
598
845
  for (let index = first + 1; index <= last; index += 1) {
599
846
  const line = starts[index];
600
847
  if (line >= pending)
601
848
  break;
602
- const whole = markers.test(lineText(starts, text, index));
849
+ const whole = lined && markers.test(lineText(starts, text, index));
603
850
  const content = contentOf(index);
604
851
  const at = whole ? line : content;
605
852
  const previous = lineText(starts, text, index - 1);
606
- if (!restartable(text, content) || /[ \t\\]$/.test(previous))
853
+ if (!restartable(text, content) || !fresh(content) || /[ \t\\]$/.test(previous))
607
854
  continue;
608
855
  if (!settled(at) || !unbroken(index + 1))
609
856
  continue;
610
857
  const join = text.slice(starts[index - 1] + previous.length, line);
611
- cuts.push({ at, path, join, carry: whole ? '' : carry, nodes: reparsed(at) });
858
+ cuts.push({ at, path, join, carry: whole ? '' : carry, levels, nodes: reparsed(at) });
612
859
  }
613
860
  if (cuts.length > 0)
614
861
  return cuts;
615
862
  for (let index = first; index <= last; index += 1) {
616
863
  const content = contentOf(index);
617
- const end = Math.min(lineEnd(starts, text, index), window.end);
864
+ const end = Math.min(lineEnd(starts, text, index), pane.end);
618
865
  for (let at = Math.max(content + 1, start + 1); at < end; at += 1) {
619
866
  if (at >= pending)
620
867
  return cuts;
621
868
  if (!/[ \t]/.test(text[at - 1]) || !restartable(text, at) || !settled(at))
622
869
  continue;
870
+ if (!fresh(at))
871
+ continue;
623
872
  if (!unbroken(index + 1))
624
873
  break;
625
874
  let from = at - 1;
@@ -627,21 +876,21 @@ function paragraphCuts(long, window, paragraph, depth, mode) {
627
876
  from -= 1;
628
877
  if (from === content)
629
878
  continue;
630
- cuts.push({ at, path, join: text.slice(from, at), carry, nodes: reparsed(at) });
879
+ cuts.push({ at, path, join: text.slice(from, at), carry, levels, nodes: reparsed(at) });
631
880
  }
632
881
  }
633
882
  return cuts;
634
883
  }
635
- function cutsOf(long, window, mode) {
636
- const { nodes } = window;
637
- const shift = window.start - window.lead;
884
+ function cutsOf(long, pane, mode) {
885
+ const { nodes } = pane;
886
+ const shift = pane.start - pane.lead;
638
887
  const at = (node) => lineStartOf(long, offsetOf(node) + shift);
639
888
  const cuts = [];
640
889
  for (let index = 1; index < nodes.length; index += 1) {
641
890
  const start = at(nodes[index]);
642
- if (start > window.start) {
891
+ if (start > pane.start) {
643
892
  const taken = nodes.slice(0, index);
644
- cuts.push({ at: start, path: [], join: '', carry: '', nodes: () => taken });
893
+ cuts.push({ at: start, path: [], join: '', carry: '', levels: [], nodes: () => taken });
645
894
  }
646
895
  }
647
896
  const last = nodes.at(-1);
@@ -649,46 +898,111 @@ function cutsOf(long, window, mode) {
649
898
  return cuts;
650
899
  const before = nodes.slice(0, -1);
651
900
  const chain = [];
652
- const within = (parent, step, carry) => {
901
+ const levels = [];
902
+ const spreads = new Map();
903
+ const within = (parent, path, frame, header) => {
653
904
  const held = [...chain, parent];
654
- const path = [...Array(chain.length).fill('blockquote'), step];
655
- const marked = markersOf(path.filter((one) => one === 'blockquote').length);
905
+ const lined = !itemed(frame);
906
+ const marked = markersOf(quotesOf(frame));
656
907
  for (let index = 1; index < parent.children.length; index += 1) {
657
- const start = at(parent.children[index]);
658
- if (start <= window.start)
908
+ const begun = offsetOf(parent.children[index]) + shift;
909
+ const line = lineOf(long, begun);
910
+ let cut = long.starts[line];
911
+ if (lined) {
912
+ if (!marked.test(lineText(long.starts, long.text, line)))
913
+ continue;
914
+ }
915
+ else {
916
+ const column = columnOn(long, line, frame);
917
+ if (column < 0)
918
+ continue;
919
+ if (header === null) {
920
+ cut += column;
921
+ if (!openable(long, line, cut, begun, frame))
922
+ continue;
923
+ }
924
+ }
925
+ if (cut <= pane.start)
659
926
  continue;
660
- if (!marked.test(lineText(long.starts, long.text, lineOf(long, start))))
661
- continue;
662
- const taken = [...before, truncated(held, index)];
663
- cuts.push({ at: start, path, join: '', carry, nodes: () => taken });
927
+ const taken = [...before, truncated(held, index, spreads)];
928
+ const carry = header ?? (lined ? '' : carryOf(frame));
929
+ cuts.push({ at: cut, path, join: '', carry, levels: frame, nodes: () => taken });
664
930
  }
665
931
  };
932
+ const carried = (node) => offsetOf(node) < pane.lead;
666
933
  let node = last;
667
934
  while (node !== undefined) {
668
935
  if (node.type === 'paragraph') {
669
- cuts.push(...paragraphCuts(long, window, node, chain.length, mode));
936
+ cuts.push(...paragraphCuts(long, pane, node, levels, mode));
670
937
  }
671
- if (node.type === 'list')
672
- within(node, 'list', '');
673
938
  if (node.type === 'table' && node.children.length > 1) {
674
- const begun = offsetOf(node) + shift < window.start;
675
- const carry = begun ? window.carry : long.text.slice(at(node), at(node.children[1]));
676
- within(node, 'table', carry);
939
+ const begun = offsetOf(node) + shift;
940
+ const lined = !itemed(levels);
941
+ const header = begun < pane.start
942
+ ? pane.carry
943
+ : lined
944
+ ? long.text.slice(at(node), at(node.children[1]))
945
+ : long.text[begun] === ' '
946
+ ? null
947
+ : `${carryOf(levels)}${long.text.slice(begun, at(node.children[1]))}`;
948
+ if (header !== null)
949
+ within(node, [...stepsOf(levels), 'table'], levels, header);
950
+ }
951
+ if (node.type === 'list') {
952
+ within(node, [...stepsOf(levels), 'list'], levels, null);
953
+ const item = node.children.at(-1);
954
+ if (item === undefined)
955
+ break;
956
+ const level = carried(item)
957
+ ? pane.levels[levels.length]
958
+ : itemLevel(long, pane, item, levels);
959
+ if (level === undefined || level === null || level.kind !== 'item')
960
+ break;
961
+ chain.push(node);
962
+ levels.push(level);
963
+ spreads.set(item, level.spread);
964
+ within(item, stepsOf(levels), levels, null);
965
+ chain.push(item);
966
+ node = item.children.at(-1);
967
+ continue;
968
+ }
969
+ if (node.type === 'footnoteDefinition') {
970
+ const level = carried(node)
971
+ ? pane.levels[levels.length]
972
+ : noteLevel(long, pane, node, levels);
973
+ if (level === undefined || level === null || level.kind !== 'note')
974
+ break;
975
+ levels.push(level);
976
+ within(node, stepsOf(levels), levels, null);
977
+ chain.push(node);
978
+ node = node.children.at(-1);
979
+ continue;
677
980
  }
678
981
  if (node.type !== 'blockquote')
679
982
  break;
680
- within(node, 'blockquote', '');
983
+ const level = carried(node) ? pane.levels[levels.length] : quoteLevel(long, pane, node);
984
+ if (level === undefined || level.kind !== 'quote')
985
+ break;
986
+ levels.push(level);
987
+ within(node, stepsOf(levels), levels, null);
681
988
  chain.push(node);
682
989
  node = node.children.at(-1);
683
990
  }
684
991
  return cuts;
685
992
  }
686
- function truncated(chain, index) {
993
+ function truncated(chain, index, spreads) {
687
994
  const [outer, ...inner] = chain;
688
- if (inner.length === 0)
689
- return { ...outer, children: outer.children.slice(0, index) };
995
+ const spread = spreads.get(outer);
996
+ const kept = spread === undefined ? {} : { spread };
997
+ if (inner.length === 0) {
998
+ return { ...outer, ...kept, children: outer.children.slice(0, index) };
999
+ }
690
1000
  const children = outer.children.slice(0, -1);
691
- return { ...outer, children: [...children, truncated(inner, index)] };
1001
+ return {
1002
+ ...outer,
1003
+ ...kept,
1004
+ children: [...children, truncated(inner, index, spreads)],
1005
+ };
692
1006
  }
693
1007
  function chosen(cuts, target) {
694
1008
  let best = null;
@@ -704,12 +1018,12 @@ function chosen(cuts, target) {
704
1018
  }
705
1019
  return best;
706
1020
  }
707
- function closingOf(long, window) {
708
- const last = window.nodes.at(-1);
1021
+ function closingOf(long, pane) {
1022
+ const last = pane.nodes.at(-1);
709
1023
  if (last?.type !== 'code')
710
1024
  return 0;
711
1025
  const { text, starts } = long;
712
- const line = lineOf(long, offsetOf(last) + window.start - window.lead);
1026
+ const line = lineOf(long, offsetOf(last) + pane.start - pane.lead);
713
1027
  const fence = fenceOf(lineFacts(lineText(starts, text, line)));
714
1028
  if (fence === null)
715
1029
  return 0;
@@ -725,30 +1039,29 @@ function cutWindow(long, from, mode, open) {
725
1039
  const line = Math.min(lineOf(long, from.start) + WINDOW_LINES, long.starts.length - 1);
726
1040
  let end = windowEnd(long, from.start, Math.min(WINDOW_CHARS, long.starts[line] - from.start));
727
1041
  for (;;) {
728
- const window = open(end);
1042
+ const pane = open(end);
729
1043
  if (end >= long.text.length)
730
- return { window, cut: null };
731
- const cut = chosen(cutsOf(long, window, mode), from.start + VIEW_CHARS);
1044
+ return { pane, cut: null };
1045
+ const cut = chosen(cutsOf(long, pane, mode), from.start + VIEW_CHARS);
732
1046
  if (cut !== null)
733
- return { window, cut };
1047
+ return { pane, cut };
734
1048
  const grown = windowEnd(long, from.start, 2 * (end - from.start));
735
1049
  const whole = 2 * grown - from.start >= long.text.length;
736
- end = Math.max(whole ? long.text.length : grown, closingOf(long, window));
1050
+ end = Math.max(whole ? long.text.length : grown, closingOf(long, pane));
737
1051
  }
738
1052
  }
739
1053
  export function pieceAt(long, index) {
740
1054
  while (long.pieces.length <= index && long.next !== null) {
741
1055
  const from = long.next;
742
- const { window, cut } = cutWindow(long, from, 'render', (end) => renderWindow(long, from, end));
1056
+ const { pane, cut } = cutWindow(long, from, 'render', (end) => renderWindow(long, from, end));
743
1057
  const end = cut?.at ?? long.text.length;
744
- for (const one of window.defined) {
1058
+ for (const one of pane.defined) {
745
1059
  if (one.at < end && !long.urls.has(one.key))
746
1060
  long.urls.set(one.key, one.url);
747
1061
  }
748
- const nodes = cut === null ? window.nodes : cut.nodes();
1062
+ const nodes = cut === null ? pane.nodes : cut.nodes();
749
1063
  long.pieces.push({ nodes, path: from.path, join: from.join });
750
- long.next =
751
- cut === null ? null : { start: cut.at, path: cut.path, join: cut.join, carry: cut.carry };
1064
+ long.next = cut === null ? null : nextOf(cut);
752
1065
  }
753
1066
  return long.pieces[index] ?? null;
754
1067
  }