@codemirror/view 6.42.1 → 6.43.1

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,19 @@
1
+ ## 6.43.1 (2026-06-09)
2
+
3
+ ### Bug fixes
4
+
5
+ Work around an issue in with some IMEs (like Tibetan) in MacOS Chrome where composition could get interrupted needlessly.
6
+
7
+ Fix a crash when calling on a line with only `display: none` content.
8
+
9
+ Improve reuse of widgets near composition, which in some cases prevents Safari from doing odd thing with the selection.
10
+
11
+ ## 6.43.0 (2026-05-14)
12
+
13
+ ### New features
14
+
15
+ Block wrappers can now be given a rank to set a specific nesting order for wrappers coming from the same source.
16
+
1
17
  ## 6.42.1 (2026-05-07)
2
18
 
3
19
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -395,10 +395,23 @@ widget that starts inside its range, including blocks starting
395
395
  directly at `from` but not including `to`.
396
396
  */
397
397
  class BlockWrapper extends state.RangeValue {
398
- constructor(tagName, attributes) {
398
+ constructor(
399
+ /**
400
+ @internal
401
+ */
402
+ tagName,
403
+ /**
404
+ @internal
405
+ */
406
+ attributes,
407
+ /**
408
+ @internal
409
+ */
410
+ rank) {
399
411
  super();
400
412
  this.tagName = tagName;
401
413
  this.attributes = attributes;
414
+ this.rank = rank;
402
415
  }
403
416
  eq(other) {
404
417
  return other == this ||
@@ -409,7 +422,7 @@ class BlockWrapper extends state.RangeValue {
409
422
  attributes.
410
423
  */
411
424
  static create(spec) {
412
- return new BlockWrapper(spec.tagName, spec.attributes || noAttrs);
425
+ return new BlockWrapper(spec.tagName, spec.attributes || noAttrs, spec.rank == null ? 50 : Math.max(0, Math.min(spec.rank, 100)));
413
426
  }
414
427
  /**
415
428
  Create a range set from the given block wrapper ranges.
@@ -2410,7 +2423,8 @@ class TileBuilder {
2410
2423
  this.wrappers.splice(i, 1);
2411
2424
  for (let cur = this.blockWrappers; cur.value && cur.from <= this.pos; cur.next())
2412
2425
  if (cur.to >= this.pos) {
2413
- let wrap = new OpenWrapper(cur.from, cur.to, cur.value, cur.rank), i = this.wrappers.length;
2426
+ let rank = (cur.rank * 102) + cur.value.rank;
2427
+ let wrap = new OpenWrapper(cur.from, cur.to, cur.value, rank), i = this.wrappers.length;
2414
2428
  while (i > 0 && (this.wrappers[i - 1].rank - wrap.rank || this.wrappers[i - 1].to - wrap.to) < 0)
2415
2429
  i--;
2416
2430
  this.wrappers.splice(i, 0, wrap);
@@ -2617,6 +2631,7 @@ class TileUpdate {
2617
2631
  if (composition && next.fromA <= composition.range.fromA && next.toA >= composition.range.toA) {
2618
2632
  this.forward(next.fromA, composition.range.fromA, composition.range.fromA < composition.range.toA ? 1 : -1);
2619
2633
  this.emit(posB, composition.range.fromB);
2634
+ this.builder.flushBuffer();
2620
2635
  this.cache.clear(); // Must not reuse DOM across composition
2621
2636
  this.builder.addComposition(composition, compositionContext);
2622
2637
  this.text.skip(composition.range.toB - composition.range.fromB);
@@ -3830,12 +3845,11 @@ class InlineCoordsScan {
3830
3845
  }
3831
3846
  // Scan through the rectangles for the content of a tile with inline
3832
3847
  // content, looking for one that overlaps the queried position
3833
- // vertically andis
3834
- // closest horizontally. The caller is responsible for dividing its
3835
- // content into N pieces, and pass an array with N+1 positions
3836
- // (including the position after the last piece). For a text tile,
3837
- // these will be character clusters, for a composite tile, these
3838
- // will be child tiles.
3848
+ // vertically and is closest horizontally. The caller is responsible
3849
+ // for dividing its content into N pieces, and pass an array with
3850
+ // N+1 positions (including the position after the last piece). For
3851
+ // a text tile, these will be character clusters, for a composite
3852
+ // tile, these will be child tiles.
3839
3853
  scan(positions, getRects, recursed = false) {
3840
3854
  let lo = 0, hi = positions.length - 1, seen = new Set();
3841
3855
  let bidi = this.bidiIn(positions[0], positions[hi]);
@@ -3907,6 +3921,8 @@ class InlineCoordsScan {
3907
3921
  // If no element with y overlap is found, find the nearest element
3908
3922
  // on the y axis, move this.y into it, and retry the scan.
3909
3923
  if (!closestRect) {
3924
+ if (!below && !above)
3925
+ return { i: positions[0], after: false };
3910
3926
  let side = above && (!below || (this.y - above.bottom < below.top - this.y)) ? above : below;
3911
3927
  this.y = (side.top + side.bottom) / 2;
3912
3928
  return this.scan(positions, getRects, true);
@@ -6800,6 +6816,7 @@ const baseTheme$1 = buildTheme("." + baseThemeID, {
6800
6816
  padding: "0 2px 0 6px"
6801
6817
  },
6802
6818
  ".cm-layer": {
6819
+ userSelect: "none", // #1708
6803
6820
  position: "absolute",
6804
6821
  left: 0,
6805
6822
  top: 0,
package/dist/index.d.cts CHANGED
@@ -366,6 +366,13 @@ interface BlockWrapperSpec {
366
366
  attributes?: {
367
367
  [key: string]: string;
368
368
  };
369
+ /**
370
+ When multiple overlapping block wrappers are produced by the
371
+ same source, this determines their relative precedence. Lower
372
+ rank wrappers are nested inside higher-rank ones. Should be
373
+ a number between 0 and 100.
374
+ */
375
+ rank?: number;
369
376
  }
370
377
  /**
371
378
  A block wrapper defines a DOM node that wraps lines or other block
@@ -374,8 +381,6 @@ widget that starts inside its range, including blocks starting
374
381
  directly at `from` but not including `to`.
375
382
  */
376
383
  declare class BlockWrapper extends RangeValue {
377
- readonly tagName: string;
378
- readonly attributes: Attrs;
379
384
  private constructor();
380
385
  eq(other: RangeValue): boolean;
381
386
  /**
package/dist/index.d.ts CHANGED
@@ -366,6 +366,13 @@ interface BlockWrapperSpec {
366
366
  attributes?: {
367
367
  [key: string]: string;
368
368
  };
369
+ /**
370
+ When multiple overlapping block wrappers are produced by the
371
+ same source, this determines their relative precedence. Lower
372
+ rank wrappers are nested inside higher-rank ones. Should be
373
+ a number between 0 and 100.
374
+ */
375
+ rank?: number;
369
376
  }
370
377
  /**
371
378
  A block wrapper defines a DOM node that wraps lines or other block
@@ -374,8 +381,6 @@ widget that starts inside its range, including blocks starting
374
381
  directly at `from` but not including `to`.
375
382
  */
376
383
  declare class BlockWrapper extends RangeValue {
377
- readonly tagName: string;
378
- readonly attributes: Attrs;
379
384
  private constructor();
380
385
  eq(other: RangeValue): boolean;
381
386
  /**
package/dist/index.js CHANGED
@@ -392,10 +392,23 @@ widget that starts inside its range, including blocks starting
392
392
  directly at `from` but not including `to`.
393
393
  */
394
394
  class BlockWrapper extends RangeValue {
395
- constructor(tagName, attributes) {
395
+ constructor(
396
+ /**
397
+ @internal
398
+ */
399
+ tagName,
400
+ /**
401
+ @internal
402
+ */
403
+ attributes,
404
+ /**
405
+ @internal
406
+ */
407
+ rank) {
396
408
  super();
397
409
  this.tagName = tagName;
398
410
  this.attributes = attributes;
411
+ this.rank = rank;
399
412
  }
400
413
  eq(other) {
401
414
  return other == this ||
@@ -406,7 +419,7 @@ class BlockWrapper extends RangeValue {
406
419
  attributes.
407
420
  */
408
421
  static create(spec) {
409
- return new BlockWrapper(spec.tagName, spec.attributes || noAttrs);
422
+ return new BlockWrapper(spec.tagName, spec.attributes || noAttrs, spec.rank == null ? 50 : Math.max(0, Math.min(spec.rank, 100)));
410
423
  }
411
424
  /**
412
425
  Create a range set from the given block wrapper ranges.
@@ -2406,7 +2419,8 @@ class TileBuilder {
2406
2419
  this.wrappers.splice(i, 1);
2407
2420
  for (let cur = this.blockWrappers; cur.value && cur.from <= this.pos; cur.next())
2408
2421
  if (cur.to >= this.pos) {
2409
- let wrap = new OpenWrapper(cur.from, cur.to, cur.value, cur.rank), i = this.wrappers.length;
2422
+ let rank = (cur.rank * 102) + cur.value.rank;
2423
+ let wrap = new OpenWrapper(cur.from, cur.to, cur.value, rank), i = this.wrappers.length;
2410
2424
  while (i > 0 && (this.wrappers[i - 1].rank - wrap.rank || this.wrappers[i - 1].to - wrap.to) < 0)
2411
2425
  i--;
2412
2426
  this.wrappers.splice(i, 0, wrap);
@@ -2613,6 +2627,7 @@ class TileUpdate {
2613
2627
  if (composition && next.fromA <= composition.range.fromA && next.toA >= composition.range.toA) {
2614
2628
  this.forward(next.fromA, composition.range.fromA, composition.range.fromA < composition.range.toA ? 1 : -1);
2615
2629
  this.emit(posB, composition.range.fromB);
2630
+ this.builder.flushBuffer();
2616
2631
  this.cache.clear(); // Must not reuse DOM across composition
2617
2632
  this.builder.addComposition(composition, compositionContext);
2618
2633
  this.text.skip(composition.range.toB - composition.range.fromB);
@@ -3826,12 +3841,11 @@ class InlineCoordsScan {
3826
3841
  }
3827
3842
  // Scan through the rectangles for the content of a tile with inline
3828
3843
  // content, looking for one that overlaps the queried position
3829
- // vertically andis
3830
- // closest horizontally. The caller is responsible for dividing its
3831
- // content into N pieces, and pass an array with N+1 positions
3832
- // (including the position after the last piece). For a text tile,
3833
- // these will be character clusters, for a composite tile, these
3834
- // will be child tiles.
3844
+ // vertically and is closest horizontally. The caller is responsible
3845
+ // for dividing its content into N pieces, and pass an array with
3846
+ // N+1 positions (including the position after the last piece). For
3847
+ // a text tile, these will be character clusters, for a composite
3848
+ // tile, these will be child tiles.
3835
3849
  scan(positions, getRects, recursed = false) {
3836
3850
  let lo = 0, hi = positions.length - 1, seen = new Set();
3837
3851
  let bidi = this.bidiIn(positions[0], positions[hi]);
@@ -3903,6 +3917,8 @@ class InlineCoordsScan {
3903
3917
  // If no element with y overlap is found, find the nearest element
3904
3918
  // on the y axis, move this.y into it, and retry the scan.
3905
3919
  if (!closestRect) {
3920
+ if (!below && !above)
3921
+ return { i: positions[0], after: false };
3906
3922
  let side = above && (!below || (this.y - above.bottom < below.top - this.y)) ? above : below;
3907
3923
  this.y = (side.top + side.bottom) / 2;
3908
3924
  return this.scan(positions, getRects, true);
@@ -6795,6 +6811,7 @@ const baseTheme$1 = /*@__PURE__*/buildTheme("." + baseThemeID, {
6795
6811
  padding: "0 2px 0 6px"
6796
6812
  },
6797
6813
  ".cm-layer": {
6814
+ userSelect: "none", // #1708
6798
6815
  position: "absolute",
6799
6816
  left: 0,
6800
6817
  top: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "6.42.1",
3
+ "version": "6.43.1",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",