@codemirror/state 6.4.1 → 6.5.0

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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 6.5.0 (2024-12-09)
2
+
3
+ ### New features
4
+
5
+ `RangeSet.compare` now supports a `boundChange` callback that is called when there's a change in the way ranges are split.
6
+
1
7
  ## 6.4.1 (2024-02-19)
2
8
 
3
9
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var findClusterBreak$1 = require('@marijn/find-cluster-break');
4
+
3
5
  /**
4
6
  The data structure for documents. @nonabstract
5
7
  */
@@ -562,26 +564,6 @@ function clip(text, from, to) {
562
564
  return [from, Math.max(from, Math.min(text.length, to))];
563
565
  }
564
566
 
565
- // Compressed representation of the Grapheme_Cluster_Break=Extend
566
- // information from
567
- // http://www.unicode.org/Public/13.0.0/ucd/auxiliary/GraphemeBreakProperty.txt.
568
- // Each pair of elements represents a range, as an offet from the
569
- // previous range and a length. Numbers are in base-36, with the empty
570
- // string being a shorthand for 1.
571
- let extend = "lc,34,7n,7,7b,19,,,,2,,2,,,20,b,1c,l,g,,2t,7,2,6,2,2,,4,z,,u,r,2j,b,1m,9,9,,o,4,,9,,3,,5,17,3,3b,f,,w,1j,,,,4,8,4,,3,7,a,2,t,,1m,,,,2,4,8,,9,,a,2,q,,2,2,1l,,4,2,4,2,2,3,3,,u,2,3,,b,2,1l,,4,5,,2,4,,k,2,m,6,,,1m,,,2,,4,8,,7,3,a,2,u,,1n,,,,c,,9,,14,,3,,1l,3,5,3,,4,7,2,b,2,t,,1m,,2,,2,,3,,5,2,7,2,b,2,s,2,1l,2,,,2,4,8,,9,,a,2,t,,20,,4,,2,3,,,8,,29,,2,7,c,8,2q,,2,9,b,6,22,2,r,,,,,,1j,e,,5,,2,5,b,,10,9,,2u,4,,6,,2,2,2,p,2,4,3,g,4,d,,2,2,6,,f,,jj,3,qa,3,t,3,t,2,u,2,1s,2,,7,8,,2,b,9,,19,3,3b,2,y,,3a,3,4,2,9,,6,3,63,2,2,,1m,,,7,,,,,2,8,6,a,2,,1c,h,1r,4,1c,7,,,5,,14,9,c,2,w,4,2,2,,3,1k,,,2,3,,,3,1m,8,2,2,48,3,,d,,7,4,,6,,3,2,5i,1m,,5,ek,,5f,x,2da,3,3x,,2o,w,fe,6,2x,2,n9w,4,,a,w,2,28,2,7k,,3,,4,,p,2,5,,47,2,q,i,d,,12,8,p,b,1a,3,1c,,2,4,2,2,13,,1v,6,2,2,2,2,c,,8,,1b,,1f,,,3,2,2,5,2,,,16,2,8,,6m,,2,,4,,fn4,,kh,g,g,g,a6,2,gt,,6a,,45,5,1ae,3,,2,5,4,14,3,4,,4l,2,fx,4,ar,2,49,b,4w,,1i,f,1k,3,1d,4,2,2,1x,3,10,5,,8,1q,,c,2,1g,9,a,4,2,,2n,3,2,,,2,6,,4g,,3,8,l,2,1l,2,,,,,m,,e,7,3,5,5f,8,2,3,,,n,,29,,2,6,,,2,,,2,,2,6j,,2,4,6,2,,2,r,2,2d,8,2,,,2,2y,,,,2,6,,,2t,3,2,4,,5,77,9,,2,6t,,a,2,,,4,,40,4,2,2,4,,w,a,14,6,2,4,8,,9,6,2,3,1a,d,,2,ba,7,,6,,,2a,m,2,7,,2,,2,3e,6,3,,,2,,7,,,20,2,3,,,,9n,2,f0b,5,1n,7,t4,,1r,4,29,,f5k,2,43q,,,3,4,5,8,8,2,7,u,4,44,3,1iz,1j,4,1e,8,,e,,m,5,,f,11s,7,,h,2,7,,2,,5,79,7,c5,4,15s,7,31,7,240,5,gx7k,2o,3k,6o".split(",").map(s => s ? parseInt(s, 36) : 1);
572
- // Convert offsets into absolute values
573
- for (let i = 1; i < extend.length; i++)
574
- extend[i] += extend[i - 1];
575
- function isExtendingChar(code) {
576
- for (let i = 1; i < extend.length; i += 2)
577
- if (extend[i] > code)
578
- return extend[i - 1] <= code;
579
- return false;
580
- }
581
- function isRegionalIndicator(code) {
582
- return code >= 0x1F1E6 && code <= 0x1F1FF;
583
- }
584
- const ZWJ = 0x200d;
585
567
  /**
586
568
  Returns a next grapheme cluster break _after_ (not equal to)
587
569
  `pos`, if `forward` is true, or before otherwise. Returns `pos`
@@ -591,47 +573,7 @@ Moves across surrogate pairs, extending characters (when
591
573
  joiners, and flag emoji.
592
574
  */
593
575
  function findClusterBreak(str, pos, forward = true, includeExtending = true) {
594
- return (forward ? nextClusterBreak : prevClusterBreak)(str, pos, includeExtending);
595
- }
596
- function nextClusterBreak(str, pos, includeExtending) {
597
- if (pos == str.length)
598
- return pos;
599
- // If pos is in the middle of a surrogate pair, move to its start
600
- if (pos && surrogateLow(str.charCodeAt(pos)) && surrogateHigh(str.charCodeAt(pos - 1)))
601
- pos--;
602
- let prev = codePointAt(str, pos);
603
- pos += codePointSize(prev);
604
- while (pos < str.length) {
605
- let next = codePointAt(str, pos);
606
- if (prev == ZWJ || next == ZWJ || includeExtending && isExtendingChar(next)) {
607
- pos += codePointSize(next);
608
- prev = next;
609
- }
610
- else if (isRegionalIndicator(next)) {
611
- let countBefore = 0, i = pos - 2;
612
- while (i >= 0 && isRegionalIndicator(codePointAt(str, i))) {
613
- countBefore++;
614
- i -= 2;
615
- }
616
- if (countBefore % 2 == 0)
617
- break;
618
- else
619
- pos += 2;
620
- }
621
- else {
622
- break;
623
- }
624
- }
625
- return pos;
626
- }
627
- function prevClusterBreak(str, pos, includeExtending) {
628
- while (pos > 0) {
629
- let found = nextClusterBreak(str, pos - 2, includeExtending);
630
- if (found < pos)
631
- return found;
632
- pos--;
633
- }
634
- return 0;
576
+ return findClusterBreak$1.findClusterBreak(str, pos, forward, includeExtending);
635
577
  }
636
578
  function surrogateLow(ch) { return ch >= 0xDC00 && ch < 0xE000; }
637
579
  function surrogateHigh(ch) { return ch >= 0xD800 && ch < 0xDC00; }
@@ -661,7 +603,7 @@ function fromCodePoint(code) {
661
603
  return String.fromCharCode((code >> 10) + 0xd800, (code & 1023) + 0xdc00);
662
604
  }
663
605
  /**
664
- The amount of positions a character takes up a JavaScript string.
606
+ The amount of positions a character takes up in a JavaScript string.
665
607
  */
666
608
  function codePointSize(code) { return code < 0x10000 ? 1 : 2; }
667
609
 
@@ -791,7 +733,7 @@ class ChangeDesc {
791
733
  Map this description, which should start with the same document
792
734
  as `other`, over another set of changes, so that it can be
793
735
  applied after it. When `before` is true, map as if the changes
794
- in `other` happened before the ones in `this`.
736
+ in `this` happened before the ones in `other`.
795
737
  */
796
738
  mapDesc(other, before = false) { return other.empty ? this : mapSet(this, other, before); }
797
739
  mapPos(pos, assoc = -1, mode = exports.MapMode.Simple) {
@@ -1094,7 +1036,7 @@ function addSection(sections, len, ins, forceJoin = false) {
1094
1036
  let last = sections.length - 2;
1095
1037
  if (last >= 0 && ins <= 0 && ins == sections[last + 1])
1096
1038
  sections[last] += len;
1097
- else if (len == 0 && sections[last] == 0)
1039
+ else if (last >= 0 && len == 0 && sections[last] == 0)
1098
1040
  sections[last + 1] += ins;
1099
1041
  else if (forceJoin) {
1100
1042
  sections[last] += len;
@@ -1152,7 +1094,10 @@ function mapSet(setA, setB, before, mkSet = false) {
1152
1094
  // content has been inserted already, and refers to the section
1153
1095
  // index.
1154
1096
  for (let inserted = -1;;) {
1155
- if (a.ins == -1 && b.ins == -1) {
1097
+ if (a.done && b.len || b.done && a.len) {
1098
+ throw new Error("Mismatched change set lengths");
1099
+ }
1100
+ else if (a.ins == -1 && b.ins == -1) {
1156
1101
  // Move across ranges skipped by both sets.
1157
1102
  let len = Math.min(a.len, b.len);
1158
1103
  addSection(sections, len, -1);
@@ -3845,7 +3790,7 @@ function compare(a, startA, b, startB, length, comparator) {
3845
3790
  let endB = startB + length;
3846
3791
  let pos = startB, dPos = startB - startA;
3847
3792
  for (;;) {
3848
- let diff = (a.to + dPos) - b.to || a.endSide - b.endSide;
3793
+ let dEnd = (a.to + dPos) - b.to, diff = dEnd || a.endSide - b.endSide;
3849
3794
  let end = diff < 0 ? a.to + dPos : b.to, clipEnd = Math.min(end, endB);
3850
3795
  if (a.point || b.point) {
3851
3796
  if (!(a.point && b.point && (a.point == b.point || a.point.eq(b.point)) &&
@@ -3858,6 +3803,8 @@ function compare(a, startA, b, startB, length, comparator) {
3858
3803
  }
3859
3804
  if (end > endB)
3860
3805
  break;
3806
+ if ((dEnd || a.openEnd != b.openEnd) && comparator.boundChange)
3807
+ comparator.boundChange(end);
3861
3808
  pos = end;
3862
3809
  if (diff <= 0)
3863
3810
  a.next();
package/dist/index.d.cts CHANGED
@@ -210,7 +210,7 @@ declare class ChangeDesc {
210
210
  Map this description, which should start with the same document
211
211
  as `other`, over another set of changes, so that it can be
212
212
  applied after it. When `before` is true, map as if the changes
213
- in `other` happened before the ones in `this`.
213
+ in `this` happened before the ones in `other`.
214
214
  */
215
215
  mapDesc(other: ChangeDesc, before?: boolean): ChangeDesc;
216
216
  /**
@@ -1444,6 +1444,13 @@ interface RangeComparator<T extends RangeValue> {
1444
1444
  Notification for a changed (or inserted, or deleted) point range.
1445
1445
  */
1446
1446
  comparePoint(from: number, to: number, pointA: T | null, pointB: T | null): void;
1447
+ /**
1448
+ Notification for a changed boundary between ranges. For example,
1449
+ if the same span is covered by two partial ranges before and one
1450
+ bigger range after, this is called at the point where the ranges
1451
+ used to be split.
1452
+ */
1453
+ boundChange?(pos: number): void;
1447
1454
  }
1448
1455
  /**
1449
1456
  Methods used when iterating over the spans created by a set of
@@ -1672,7 +1679,7 @@ respresents it (like
1672
1679
  */
1673
1680
  declare function fromCodePoint(code: number): string;
1674
1681
  /**
1675
- The amount of positions a character takes up a JavaScript string.
1682
+ The amount of positions a character takes up in a JavaScript string.
1676
1683
  */
1677
1684
  declare function codePointSize(code: number): 1 | 2;
1678
1685
 
package/dist/index.d.ts CHANGED
@@ -210,7 +210,7 @@ declare class ChangeDesc {
210
210
  Map this description, which should start with the same document
211
211
  as `other`, over another set of changes, so that it can be
212
212
  applied after it. When `before` is true, map as if the changes
213
- in `other` happened before the ones in `this`.
213
+ in `this` happened before the ones in `other`.
214
214
  */
215
215
  mapDesc(other: ChangeDesc, before?: boolean): ChangeDesc;
216
216
  /**
@@ -1444,6 +1444,13 @@ interface RangeComparator<T extends RangeValue> {
1444
1444
  Notification for a changed (or inserted, or deleted) point range.
1445
1445
  */
1446
1446
  comparePoint(from: number, to: number, pointA: T | null, pointB: T | null): void;
1447
+ /**
1448
+ Notification for a changed boundary between ranges. For example,
1449
+ if the same span is covered by two partial ranges before and one
1450
+ bigger range after, this is called at the point where the ranges
1451
+ used to be split.
1452
+ */
1453
+ boundChange?(pos: number): void;
1447
1454
  }
1448
1455
  /**
1449
1456
  Methods used when iterating over the spans created by a set of
@@ -1672,7 +1679,7 @@ respresents it (like
1672
1679
  */
1673
1680
  declare function fromCodePoint(code: number): string;
1674
1681
  /**
1675
- The amount of positions a character takes up a JavaScript string.
1682
+ The amount of positions a character takes up in a JavaScript string.
1676
1683
  */
1677
1684
  declare function codePointSize(code: number): 1 | 2;
1678
1685
 
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { findClusterBreak as findClusterBreak$1 } from '@marijn/find-cluster-break';
2
+
1
3
  /**
2
4
  The data structure for documents. @nonabstract
3
5
  */
@@ -560,26 +562,6 @@ function clip(text, from, to) {
560
562
  return [from, Math.max(from, Math.min(text.length, to))];
561
563
  }
562
564
 
563
- // Compressed representation of the Grapheme_Cluster_Break=Extend
564
- // information from
565
- // http://www.unicode.org/Public/13.0.0/ucd/auxiliary/GraphemeBreakProperty.txt.
566
- // Each pair of elements represents a range, as an offet from the
567
- // previous range and a length. Numbers are in base-36, with the empty
568
- // string being a shorthand for 1.
569
- let extend = /*@__PURE__*/"lc,34,7n,7,7b,19,,,,2,,2,,,20,b,1c,l,g,,2t,7,2,6,2,2,,4,z,,u,r,2j,b,1m,9,9,,o,4,,9,,3,,5,17,3,3b,f,,w,1j,,,,4,8,4,,3,7,a,2,t,,1m,,,,2,4,8,,9,,a,2,q,,2,2,1l,,4,2,4,2,2,3,3,,u,2,3,,b,2,1l,,4,5,,2,4,,k,2,m,6,,,1m,,,2,,4,8,,7,3,a,2,u,,1n,,,,c,,9,,14,,3,,1l,3,5,3,,4,7,2,b,2,t,,1m,,2,,2,,3,,5,2,7,2,b,2,s,2,1l,2,,,2,4,8,,9,,a,2,t,,20,,4,,2,3,,,8,,29,,2,7,c,8,2q,,2,9,b,6,22,2,r,,,,,,1j,e,,5,,2,5,b,,10,9,,2u,4,,6,,2,2,2,p,2,4,3,g,4,d,,2,2,6,,f,,jj,3,qa,3,t,3,t,2,u,2,1s,2,,7,8,,2,b,9,,19,3,3b,2,y,,3a,3,4,2,9,,6,3,63,2,2,,1m,,,7,,,,,2,8,6,a,2,,1c,h,1r,4,1c,7,,,5,,14,9,c,2,w,4,2,2,,3,1k,,,2,3,,,3,1m,8,2,2,48,3,,d,,7,4,,6,,3,2,5i,1m,,5,ek,,5f,x,2da,3,3x,,2o,w,fe,6,2x,2,n9w,4,,a,w,2,28,2,7k,,3,,4,,p,2,5,,47,2,q,i,d,,12,8,p,b,1a,3,1c,,2,4,2,2,13,,1v,6,2,2,2,2,c,,8,,1b,,1f,,,3,2,2,5,2,,,16,2,8,,6m,,2,,4,,fn4,,kh,g,g,g,a6,2,gt,,6a,,45,5,1ae,3,,2,5,4,14,3,4,,4l,2,fx,4,ar,2,49,b,4w,,1i,f,1k,3,1d,4,2,2,1x,3,10,5,,8,1q,,c,2,1g,9,a,4,2,,2n,3,2,,,2,6,,4g,,3,8,l,2,1l,2,,,,,m,,e,7,3,5,5f,8,2,3,,,n,,29,,2,6,,,2,,,2,,2,6j,,2,4,6,2,,2,r,2,2d,8,2,,,2,2y,,,,2,6,,,2t,3,2,4,,5,77,9,,2,6t,,a,2,,,4,,40,4,2,2,4,,w,a,14,6,2,4,8,,9,6,2,3,1a,d,,2,ba,7,,6,,,2a,m,2,7,,2,,2,3e,6,3,,,2,,7,,,20,2,3,,,,9n,2,f0b,5,1n,7,t4,,1r,4,29,,f5k,2,43q,,,3,4,5,8,8,2,7,u,4,44,3,1iz,1j,4,1e,8,,e,,m,5,,f,11s,7,,h,2,7,,2,,5,79,7,c5,4,15s,7,31,7,240,5,gx7k,2o,3k,6o".split(",").map(s => s ? parseInt(s, 36) : 1);
570
- // Convert offsets into absolute values
571
- for (let i = 1; i < extend.length; i++)
572
- extend[i] += extend[i - 1];
573
- function isExtendingChar(code) {
574
- for (let i = 1; i < extend.length; i += 2)
575
- if (extend[i] > code)
576
- return extend[i - 1] <= code;
577
- return false;
578
- }
579
- function isRegionalIndicator(code) {
580
- return code >= 0x1F1E6 && code <= 0x1F1FF;
581
- }
582
- const ZWJ = 0x200d;
583
565
  /**
584
566
  Returns a next grapheme cluster break _after_ (not equal to)
585
567
  `pos`, if `forward` is true, or before otherwise. Returns `pos`
@@ -589,47 +571,7 @@ Moves across surrogate pairs, extending characters (when
589
571
  joiners, and flag emoji.
590
572
  */
591
573
  function findClusterBreak(str, pos, forward = true, includeExtending = true) {
592
- return (forward ? nextClusterBreak : prevClusterBreak)(str, pos, includeExtending);
593
- }
594
- function nextClusterBreak(str, pos, includeExtending) {
595
- if (pos == str.length)
596
- return pos;
597
- // If pos is in the middle of a surrogate pair, move to its start
598
- if (pos && surrogateLow(str.charCodeAt(pos)) && surrogateHigh(str.charCodeAt(pos - 1)))
599
- pos--;
600
- let prev = codePointAt(str, pos);
601
- pos += codePointSize(prev);
602
- while (pos < str.length) {
603
- let next = codePointAt(str, pos);
604
- if (prev == ZWJ || next == ZWJ || includeExtending && isExtendingChar(next)) {
605
- pos += codePointSize(next);
606
- prev = next;
607
- }
608
- else if (isRegionalIndicator(next)) {
609
- let countBefore = 0, i = pos - 2;
610
- while (i >= 0 && isRegionalIndicator(codePointAt(str, i))) {
611
- countBefore++;
612
- i -= 2;
613
- }
614
- if (countBefore % 2 == 0)
615
- break;
616
- else
617
- pos += 2;
618
- }
619
- else {
620
- break;
621
- }
622
- }
623
- return pos;
624
- }
625
- function prevClusterBreak(str, pos, includeExtending) {
626
- while (pos > 0) {
627
- let found = nextClusterBreak(str, pos - 2, includeExtending);
628
- if (found < pos)
629
- return found;
630
- pos--;
631
- }
632
- return 0;
574
+ return findClusterBreak$1(str, pos, forward, includeExtending);
633
575
  }
634
576
  function surrogateLow(ch) { return ch >= 0xDC00 && ch < 0xE000; }
635
577
  function surrogateHigh(ch) { return ch >= 0xD800 && ch < 0xDC00; }
@@ -659,7 +601,7 @@ function fromCodePoint(code) {
659
601
  return String.fromCharCode((code >> 10) + 0xd800, (code & 1023) + 0xdc00);
660
602
  }
661
603
  /**
662
- The amount of positions a character takes up a JavaScript string.
604
+ The amount of positions a character takes up in a JavaScript string.
663
605
  */
664
606
  function codePointSize(code) { return code < 0x10000 ? 1 : 2; }
665
607
 
@@ -788,7 +730,7 @@ class ChangeDesc {
788
730
  Map this description, which should start with the same document
789
731
  as `other`, over another set of changes, so that it can be
790
732
  applied after it. When `before` is true, map as if the changes
791
- in `other` happened before the ones in `this`.
733
+ in `this` happened before the ones in `other`.
792
734
  */
793
735
  mapDesc(other, before = false) { return other.empty ? this : mapSet(this, other, before); }
794
736
  mapPos(pos, assoc = -1, mode = MapMode.Simple) {
@@ -1091,7 +1033,7 @@ function addSection(sections, len, ins, forceJoin = false) {
1091
1033
  let last = sections.length - 2;
1092
1034
  if (last >= 0 && ins <= 0 && ins == sections[last + 1])
1093
1035
  sections[last] += len;
1094
- else if (len == 0 && sections[last] == 0)
1036
+ else if (last >= 0 && len == 0 && sections[last] == 0)
1095
1037
  sections[last + 1] += ins;
1096
1038
  else if (forceJoin) {
1097
1039
  sections[last] += len;
@@ -1149,7 +1091,10 @@ function mapSet(setA, setB, before, mkSet = false) {
1149
1091
  // content has been inserted already, and refers to the section
1150
1092
  // index.
1151
1093
  for (let inserted = -1;;) {
1152
- if (a.ins == -1 && b.ins == -1) {
1094
+ if (a.done && b.len || b.done && a.len) {
1095
+ throw new Error("Mismatched change set lengths");
1096
+ }
1097
+ else if (a.ins == -1 && b.ins == -1) {
1153
1098
  // Move across ranges skipped by both sets.
1154
1099
  let len = Math.min(a.len, b.len);
1155
1100
  addSection(sections, len, -1);
@@ -3841,7 +3786,7 @@ function compare(a, startA, b, startB, length, comparator) {
3841
3786
  let endB = startB + length;
3842
3787
  let pos = startB, dPos = startB - startA;
3843
3788
  for (;;) {
3844
- let diff = (a.to + dPos) - b.to || a.endSide - b.endSide;
3789
+ let dEnd = (a.to + dPos) - b.to, diff = dEnd || a.endSide - b.endSide;
3845
3790
  let end = diff < 0 ? a.to + dPos : b.to, clipEnd = Math.min(end, endB);
3846
3791
  if (a.point || b.point) {
3847
3792
  if (!(a.point && b.point && (a.point == b.point || a.point.eq(b.point)) &&
@@ -3854,6 +3799,8 @@ function compare(a, startA, b, startB, length, comparator) {
3854
3799
  }
3855
3800
  if (end > endB)
3856
3801
  break;
3802
+ if ((dEnd || a.openEnd != b.openEnd) && comparator.boundChange)
3803
+ comparator.boundChange(end);
3857
3804
  pos = end;
3858
3805
  if (diff <= 0)
3859
3806
  a.next();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/state",
3
- "version": "6.4.1",
3
+ "version": "6.5.0",
4
4
  "description": "Editor state data structures for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",
@@ -25,6 +25,9 @@
25
25
  "module": "dist/index.js",
26
26
  "sideEffects": false,
27
27
  "license": "MIT",
28
+ "dependencies": {
29
+ "@marijn/find-cluster-break": "^1.0.0"
30
+ },
28
31
  "devDependencies": {
29
32
  "@codemirror/buildhelper": "^1.0.0"
30
33
  },