@codemirror/view 0.19.35 → 0.19.39

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,39 @@
1
+ ## 0.19.39 (2022-01-06)
2
+
3
+ ### Bug fixes
4
+
5
+ Make sure the editor signals a `geometryChanged` update when its width changes.
6
+
7
+ ### New features
8
+
9
+ `EditorView.darkTheme` can now be queried to figure out whether the editor is using a dark theme.
10
+
11
+ ## 0.19.38 (2022-01-05)
12
+
13
+ ### Bug fixes
14
+
15
+ Fix a bug that caused line decorations with a `class` property to suppress all other line decorations for that line.
16
+
17
+ Fix a bug that caused scroll effects to be corrupted when further updates came in before they were applied.
18
+
19
+ Fix an issue where, depending on which way a floating point rounding error fell, `posAtCoords` (and thus vertical cursor motion) for positions outside of the vertical range of the document might or might not return the start/end of the document.
20
+
21
+ ## 0.19.37 (2021-12-22)
22
+
23
+ ### Bug fixes
24
+
25
+ Fix regression where plugin replacing decorations that span to the end of the line are ignored.
26
+
27
+ ## 0.19.36 (2021-12-22)
28
+
29
+ ### Bug fixes
30
+
31
+ Fix a crash in `posAtCoords` when the position lies in a block widget that is rendered but scrolled out of view.
32
+
33
+ Adding block decorations from a plugin now raises an error. Replacing decorations that cross lines are ignored, when provided by a plugin.
34
+
35
+ Fix inverted interpretation of the `precise` argument to `posAtCoords`.
36
+
1
37
  ## 0.19.35 (2021-12-20)
2
38
 
3
39
  ### Bug fixes
package/dist/index.cjs CHANGED
@@ -1311,7 +1311,7 @@ class LineView extends ContentView {
1311
1311
  if (attrs)
1312
1312
  this.attrs = combineAttrs(attrs, this.attrs || {});
1313
1313
  if (cls)
1314
- this.attrs = combineAttrs(attrs, { class: cls });
1314
+ this.attrs = combineAttrs({ class: cls }, this.attrs || {});
1315
1315
  }
1316
1316
  domAtPos(pos) {
1317
1317
  return inlineDOMAtPos(this.dom, this.children, pos);
@@ -1372,16 +1372,17 @@ class LineView extends ContentView {
1372
1372
  become(_other) { return false; }
1373
1373
  get type() { return exports.BlockType.Text; }
1374
1374
  static find(docView, pos) {
1375
- for (let i = 0, off = 0;; i++) {
1375
+ for (let i = 0, off = 0; i < docView.children.length; i++) {
1376
1376
  let block = docView.children[i], end = off + block.length;
1377
1377
  if (end >= pos) {
1378
1378
  if (block instanceof LineView)
1379
1379
  return block;
1380
- if (block.length)
1381
- return null;
1380
+ if (end > pos)
1381
+ break;
1382
1382
  }
1383
1383
  off = end + block.breakAfter;
1384
1384
  }
1385
+ return null;
1385
1386
  }
1386
1387
  }
1387
1388
  class BlockWidgetView extends ContentView {
@@ -1442,10 +1443,11 @@ class BlockWidgetView extends ContentView {
1442
1443
  }
1443
1444
 
1444
1445
  class ContentBuilder {
1445
- constructor(doc, pos, end) {
1446
+ constructor(doc, pos, end, disallowBlockEffectsBelow) {
1446
1447
  this.doc = doc;
1447
1448
  this.pos = pos;
1448
1449
  this.end = end;
1450
+ this.disallowBlockEffectsBelow = disallowBlockEffectsBelow;
1449
1451
  this.content = [];
1450
1452
  this.curLine = null;
1451
1453
  this.breakAtStart = 0;
@@ -1574,8 +1576,15 @@ class ContentBuilder {
1574
1576
  if (this.openStart < 0)
1575
1577
  this.openStart = openStart;
1576
1578
  }
1577
- static build(text, from, to, decorations) {
1578
- let builder = new ContentBuilder(text, from, to);
1579
+ filterPoint(from, to, value, index) {
1580
+ if (index >= this.disallowBlockEffectsBelow || !(value instanceof PointDecoration))
1581
+ return true;
1582
+ if (value.block)
1583
+ throw new RangeError("Block decorations may not be specified via plugins");
1584
+ return to <= this.doc.lineAt(this.pos).to;
1585
+ }
1586
+ static build(text, from, to, decorations, pluginDecorationLength) {
1587
+ let builder = new ContentBuilder(text, from, to, pluginDecorationLength);
1579
1588
  builder.openEnd = rangeset.RangeSet.spans(decorations, from, to, builder);
1580
1589
  if (builder.openStart < 0)
1581
1590
  builder.openStart = builder.openEnd;
@@ -1698,11 +1707,13 @@ This field can be used by plugins to provide
1698
1707
  **Note**: For reasons of data flow (plugins are only updated
1699
1708
  after the viewport is computed), decorations produced by plugins
1700
1709
  are _not_ taken into account when predicting the vertical layout
1701
- structure of the editor. Thus, things like large widgets or big
1702
- replacements (i.e. code folding) should be provided through the
1703
- state-level [`decorations` facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations),
1704
- not this plugin field. Specifically, replacing decorations that
1705
- cross line boundaries will break if provided through a plugin.
1710
+ structure of the editor. They **must not** introduce block
1711
+ widgets (that will raise an error) or replacing decorations that
1712
+ cover line breaks (these will be ignored if they occur). Such
1713
+ decorations, or others that cause a large amount of vertical
1714
+ size shift compared to the undecorated content, should be
1715
+ provided through the state-level [`decorations`
1716
+ facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations) instead.
1706
1717
  */
1707
1718
  PluginField.decorations = PluginField.define();
1708
1719
  /**
@@ -1935,8 +1946,6 @@ class ViewUpdate {
1935
1946
  view.inputState.notifiedFocused = focus;
1936
1947
  this.flags |= 1 /* Focus */;
1937
1948
  }
1938
- if (this.docChanged)
1939
- this.flags |= 2 /* Height */;
1940
1949
  }
1941
1950
  /**
1942
1951
  Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
@@ -1947,14 +1956,15 @@ class ViewUpdate {
1947
1956
  return (this.flags & 4 /* Viewport */) > 0;
1948
1957
  }
1949
1958
  /**
1950
- Indicates whether the line height in the editor changed in this update.
1959
+ Indicates whether the height of an element in the editor changed
1960
+ in this update.
1951
1961
  */
1952
1962
  get heightChanged() {
1953
1963
  return (this.flags & 2 /* Height */) > 0;
1954
1964
  }
1955
1965
  /**
1956
- Returns true when the document changed or the size of the editor
1957
- or the lines or characters within it has changed.
1966
+ Returns true when the document was modified or the size of the
1967
+ editor, or elements within the editor, changed.
1958
1968
  */
1959
1969
  get geometryChanged() {
1960
1970
  return this.docChanged || (this.flags & (8 /* Geometry */ | 2 /* Height */)) > 0;
@@ -2373,6 +2383,7 @@ class DocView extends ContentView {
2373
2383
  this.view = view;
2374
2384
  this.compositionDeco = Decoration.none;
2375
2385
  this.decorations = [];
2386
+ this.pluginDecorationLength = 0;
2376
2387
  // Track a minimum width for the editor. When measuring sizes in
2377
2388
  // measureVisibleLineHeights, this is updated to point at the width
2378
2389
  // of a given element and its extent in the document. When a change
@@ -2394,7 +2405,8 @@ class DocView extends ContentView {
2394
2405
  this.setDOM(view.contentDOM);
2395
2406
  this.children = [new LineView];
2396
2407
  this.children[0].setParent(this);
2397
- this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], this.updateDeco(), 0);
2408
+ this.updateDeco();
2409
+ this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
2398
2410
  }
2399
2411
  get root() { return this.view.root; }
2400
2412
  get editorView() { return this.view; }
@@ -2433,7 +2445,7 @@ class DocView extends ContentView {
2433
2445
  return false;
2434
2446
  }
2435
2447
  else {
2436
- this.updateInner(changedRanges, deco, update.startState.doc.length);
2448
+ this.updateInner(changedRanges, update.startState.doc.length);
2437
2449
  if (update.transactions.length)
2438
2450
  this.lastUpdate = Date.now();
2439
2451
  return true;
@@ -2441,9 +2453,9 @@ class DocView extends ContentView {
2441
2453
  }
2442
2454
  // Used by update and the constructor do perform the actual DOM
2443
2455
  // update
2444
- updateInner(changes, deco, oldLength) {
2456
+ updateInner(changes, oldLength) {
2445
2457
  this.view.viewState.mustMeasureContent = true;
2446
- this.updateChildren(changes, deco, oldLength);
2458
+ this.updateChildren(changes, oldLength);
2447
2459
  let { observer } = this.view;
2448
2460
  observer.ignore(() => {
2449
2461
  // Lock the height during redrawing, since Chrome sometimes
@@ -2470,14 +2482,14 @@ class DocView extends ContentView {
2470
2482
  gaps.push(child.dom);
2471
2483
  observer.updateGaps(gaps);
2472
2484
  }
2473
- updateChildren(changes, deco, oldLength) {
2485
+ updateChildren(changes, oldLength) {
2474
2486
  let cursor = this.childCursor(oldLength);
2475
2487
  for (let i = changes.length - 1;; i--) {
2476
2488
  let next = i >= 0 ? changes[i] : null;
2477
2489
  if (!next)
2478
2490
  break;
2479
2491
  let { fromA, toA, fromB, toB } = next;
2480
- let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, deco);
2492
+ let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, this.decorations, this.pluginDecorationLength);
2481
2493
  let { i: toI, off: toOff } = cursor.findPos(toA, 1);
2482
2494
  let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
2483
2495
  replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
@@ -2696,8 +2708,10 @@ class DocView extends ContentView {
2696
2708
  return Decoration.set(deco);
2697
2709
  }
2698
2710
  updateDeco() {
2711
+ let pluginDecorations = this.view.pluginField(PluginField.decorations);
2712
+ this.pluginDecorationLength = pluginDecorations.length;
2699
2713
  return this.decorations = [
2700
- ...this.view.pluginField(PluginField.decorations),
2714
+ ...pluginDecorations,
2701
2715
  ...this.view.state.facet(decorations),
2702
2716
  this.compositionDeco,
2703
2717
  this.computeBlockGapDeco(),
@@ -2991,7 +3005,11 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
2991
3005
  var _a;
2992
3006
  let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
2993
3007
  let block, { docHeight } = view.viewState;
2994
- let yOffset = Math.max(0, Math.min(y - docTop, docHeight));
3008
+ let yOffset = y - docTop;
3009
+ if (yOffset < 0)
3010
+ return 0;
3011
+ if (yOffset > docHeight)
3012
+ return view.state.doc.length;
2995
3013
  // Scan for a text block near the queried y position
2996
3014
  for (let halfLine = view.defaultLineHeight / 2, bounced = false;;) {
2997
3015
  block = view.elementAtHeight(yOffset);
@@ -3014,10 +3032,10 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
3014
3032
  let lineStart = block.from;
3015
3033
  // If this is outside of the rendered viewport, we can't determine a position
3016
3034
  if (lineStart < view.viewport.from)
3017
- return view.viewport.from == 0 ? 0 : precise ? posAtCoordsImprecise(view, content, block, x, y) : null;
3035
+ return view.viewport.from == 0 ? 0 : precise ? null : posAtCoordsImprecise(view, content, block, x, y);
3018
3036
  if (lineStart > view.viewport.to)
3019
3037
  return view.viewport.to == view.state.doc.length ? view.state.doc.length :
3020
- precise ? posAtCoordsImprecise(view, content, block, x, y) : null;
3038
+ precise ? null : posAtCoordsImprecise(view, content, block, x, y);
3021
3039
  // Prefer ShadowRootOrDocument.elementFromPoint if present, fall back to document if not
3022
3040
  let doc = view.dom.ownerDocument;
3023
3041
  let root = view.root.elementFromPoint ? view.root : doc;
@@ -3052,6 +3070,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
3052
3070
  // No luck, do our own (potentially expensive) search
3053
3071
  if (!node || !view.docView.dom.contains(node)) {
3054
3072
  let line = LineView.find(view.docView, lineStart);
3073
+ if (!line)
3074
+ return yOffset > block.top + block.height / 2 ? block.to : block.from;
3055
3075
  ({ node, offset } = domPosAtCoords(line.dom, x, y));
3056
3076
  }
3057
3077
  return view.docView.posFromDOM(node, offset);
@@ -4579,6 +4599,7 @@ class ViewState {
4579
4599
  this.contentDOMWidth = 0;
4580
4600
  this.contentDOMHeight = 0;
4581
4601
  this.editorHeight = 0;
4602
+ this.editorWidth = 0;
4582
4603
  this.heightOracle = new HeightOracle;
4583
4604
  // See VP.MaxDOMHeight
4584
4605
  this.scaler = IdScaler;
@@ -4684,11 +4705,18 @@ class ViewState {
4684
4705
  }
4685
4706
  if (!this.inView)
4686
4707
  return 0;
4708
+ let contentWidth = dom.clientWidth;
4709
+ if (this.contentDOMWidth != contentWidth || this.editorHeight != view.scrollDOM.clientHeight ||
4710
+ this.editorWidth != view.scrollDOM.clientWidth) {
4711
+ this.contentDOMWidth = contentWidth;
4712
+ this.editorHeight = view.scrollDOM.clientHeight;
4713
+ this.editorWidth = view.scrollDOM.clientWidth;
4714
+ result |= 8 /* Geometry */;
4715
+ }
4687
4716
  if (measureContent) {
4688
4717
  let lineHeights = view.docView.measureVisibleLineHeights();
4689
4718
  if (oracle.mustRefreshForHeights(lineHeights))
4690
4719
  refresh = true;
4691
- let contentWidth = dom.clientWidth;
4692
4720
  if (refresh || oracle.lineWrapping && Math.abs(contentWidth - this.contentDOMWidth) > oracle.charWidth) {
4693
4721
  let { lineHeight, charWidth } = view.docView.measureTextSize();
4694
4722
  refresh = oracle.refresh(whiteSpace, direction, lineHeight, charWidth, contentWidth / charWidth, lineHeights);
@@ -4697,14 +4725,6 @@ class ViewState {
4697
4725
  result |= 8 /* Geometry */;
4698
4726
  }
4699
4727
  }
4700
- if (this.contentDOMWidth != contentWidth) {
4701
- this.contentDOMWidth = contentWidth;
4702
- result |= 8 /* Geometry */;
4703
- }
4704
- if (this.editorHeight != view.scrollDOM.clientHeight) {
4705
- this.editorHeight = view.scrollDOM.clientHeight;
4706
- result |= 8 /* Geometry */;
4707
- }
4708
4728
  if (dTop > 0 && dBottom > 0)
4709
4729
  bias = Math.max(dTop, dBottom);
4710
4730
  else if (dTop < 0 && dBottom < 0)
@@ -5844,7 +5864,7 @@ class EditorView {
5844
5864
  if (state$1.facet(state.EditorState.phrases) != this.state.facet(state.EditorState.phrases))
5845
5865
  return this.setState(state$1);
5846
5866
  update = new ViewUpdate(this, state$1, transactions);
5847
- let scrollTarget = null;
5867
+ let scrollTarget = this.viewState.scrollTarget;
5848
5868
  try {
5849
5869
  this.updateState = 2 /* Updating */;
5850
5870
  for (let tr of transactions) {
@@ -6565,6 +6585,13 @@ mechanism for providing decorations.
6565
6585
  */
6566
6586
  EditorView.decorations = decorations;
6567
6587
  /**
6588
+ This facet records whether a dark theme is active. The extension
6589
+ returned by [`theme`](https://codemirror.net/6/docs/ref/#view.EditorView^theme) automatically
6590
+ includes an instance of this when the `dark` option is set to
6591
+ true.
6592
+ */
6593
+ EditorView.darkTheme = darkTheme;
6594
+ /**
6568
6595
  Facet that provides additional DOM attributes for the editor's
6569
6596
  editable DOM element.
6570
6597
  */
package/dist/index.d.ts CHANGED
@@ -340,11 +340,13 @@ declare class PluginField<T> {
340
340
  **Note**: For reasons of data flow (plugins are only updated
341
341
  after the viewport is computed), decorations produced by plugins
342
342
  are _not_ taken into account when predicting the vertical layout
343
- structure of the editor. Thus, things like large widgets or big
344
- replacements (i.e. code folding) should be provided through the
345
- state-level [`decorations` facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations),
346
- not this plugin field. Specifically, replacing decorations that
347
- cross line boundaries will break if provided through a plugin.
343
+ structure of the editor. They **must not** introduce block
344
+ widgets (that will raise an error) or replacing decorations that
345
+ cover line breaks (these will be ignored if they occur). Such
346
+ decorations, or others that cause a large amount of vertical
347
+ size shift compared to the undecorated content, should be
348
+ provided through the state-level [`decorations`
349
+ facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations) instead.
348
350
  */
349
351
  static decorations: PluginField<DecorationSet>;
350
352
  /**
@@ -470,12 +472,13 @@ declare class ViewUpdate {
470
472
  */
471
473
  get viewportChanged(): boolean;
472
474
  /**
473
- Indicates whether the line height in the editor changed in this update.
475
+ Indicates whether the height of an element in the editor changed
476
+ in this update.
474
477
  */
475
478
  get heightChanged(): boolean;
476
479
  /**
477
- Returns true when the document changed or the size of the editor
478
- or the lines or characters within it has changed.
480
+ Returns true when the document was modified or the size of the
481
+ editor, or elements within the editor, changed.
479
482
  */
480
483
  get geometryChanged(): boolean;
481
484
  /**
@@ -1153,6 +1156,13 @@ declare class EditorView {
1153
1156
  dark?: boolean;
1154
1157
  }): Extension;
1155
1158
  /**
1159
+ This facet records whether a dark theme is active. The extension
1160
+ returned by [`theme`](https://codemirror.net/6/docs/ref/#view.EditorView^theme) automatically
1161
+ includes an instance of this when the `dark` option is set to
1162
+ true.
1163
+ */
1164
+ static darkTheme: Facet<boolean, boolean>;
1165
+ /**
1156
1166
  Create an extension that adds styles to the base theme. Like
1157
1167
  with [`theme`](https://codemirror.net/6/docs/ref/#view.EditorView^theme), use `&` to indicate the
1158
1168
  place of the editor wrapper element when directly targeting
package/dist/index.js CHANGED
@@ -1307,7 +1307,7 @@ class LineView extends ContentView {
1307
1307
  if (attrs)
1308
1308
  this.attrs = combineAttrs(attrs, this.attrs || {});
1309
1309
  if (cls)
1310
- this.attrs = combineAttrs(attrs, { class: cls });
1310
+ this.attrs = combineAttrs({ class: cls }, this.attrs || {});
1311
1311
  }
1312
1312
  domAtPos(pos) {
1313
1313
  return inlineDOMAtPos(this.dom, this.children, pos);
@@ -1368,16 +1368,17 @@ class LineView extends ContentView {
1368
1368
  become(_other) { return false; }
1369
1369
  get type() { return BlockType.Text; }
1370
1370
  static find(docView, pos) {
1371
- for (let i = 0, off = 0;; i++) {
1371
+ for (let i = 0, off = 0; i < docView.children.length; i++) {
1372
1372
  let block = docView.children[i], end = off + block.length;
1373
1373
  if (end >= pos) {
1374
1374
  if (block instanceof LineView)
1375
1375
  return block;
1376
- if (block.length)
1377
- return null;
1376
+ if (end > pos)
1377
+ break;
1378
1378
  }
1379
1379
  off = end + block.breakAfter;
1380
1380
  }
1381
+ return null;
1381
1382
  }
1382
1383
  }
1383
1384
  class BlockWidgetView extends ContentView {
@@ -1438,10 +1439,11 @@ class BlockWidgetView extends ContentView {
1438
1439
  }
1439
1440
 
1440
1441
  class ContentBuilder {
1441
- constructor(doc, pos, end) {
1442
+ constructor(doc, pos, end, disallowBlockEffectsBelow) {
1442
1443
  this.doc = doc;
1443
1444
  this.pos = pos;
1444
1445
  this.end = end;
1446
+ this.disallowBlockEffectsBelow = disallowBlockEffectsBelow;
1445
1447
  this.content = [];
1446
1448
  this.curLine = null;
1447
1449
  this.breakAtStart = 0;
@@ -1570,8 +1572,15 @@ class ContentBuilder {
1570
1572
  if (this.openStart < 0)
1571
1573
  this.openStart = openStart;
1572
1574
  }
1573
- static build(text, from, to, decorations) {
1574
- let builder = new ContentBuilder(text, from, to);
1575
+ filterPoint(from, to, value, index) {
1576
+ if (index >= this.disallowBlockEffectsBelow || !(value instanceof PointDecoration))
1577
+ return true;
1578
+ if (value.block)
1579
+ throw new RangeError("Block decorations may not be specified via plugins");
1580
+ return to <= this.doc.lineAt(this.pos).to;
1581
+ }
1582
+ static build(text, from, to, decorations, pluginDecorationLength) {
1583
+ let builder = new ContentBuilder(text, from, to, pluginDecorationLength);
1575
1584
  builder.openEnd = RangeSet.spans(decorations, from, to, builder);
1576
1585
  if (builder.openStart < 0)
1577
1586
  builder.openStart = builder.openEnd;
@@ -1694,11 +1703,13 @@ This field can be used by plugins to provide
1694
1703
  **Note**: For reasons of data flow (plugins are only updated
1695
1704
  after the viewport is computed), decorations produced by plugins
1696
1705
  are _not_ taken into account when predicting the vertical layout
1697
- structure of the editor. Thus, things like large widgets or big
1698
- replacements (i.e. code folding) should be provided through the
1699
- state-level [`decorations` facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations),
1700
- not this plugin field. Specifically, replacing decorations that
1701
- cross line boundaries will break if provided through a plugin.
1706
+ structure of the editor. They **must not** introduce block
1707
+ widgets (that will raise an error) or replacing decorations that
1708
+ cover line breaks (these will be ignored if they occur). Such
1709
+ decorations, or others that cause a large amount of vertical
1710
+ size shift compared to the undecorated content, should be
1711
+ provided through the state-level [`decorations`
1712
+ facet](https://codemirror.net/6/docs/ref/#view.EditorView^decorations) instead.
1702
1713
  */
1703
1714
  PluginField.decorations = /*@__PURE__*/PluginField.define();
1704
1715
  /**
@@ -1931,8 +1942,6 @@ class ViewUpdate {
1931
1942
  view.inputState.notifiedFocused = focus;
1932
1943
  this.flags |= 1 /* Focus */;
1933
1944
  }
1934
- if (this.docChanged)
1935
- this.flags |= 2 /* Height */;
1936
1945
  }
1937
1946
  /**
1938
1947
  Tells you whether the [viewport](https://codemirror.net/6/docs/ref/#view.EditorView.viewport) or
@@ -1943,14 +1952,15 @@ class ViewUpdate {
1943
1952
  return (this.flags & 4 /* Viewport */) > 0;
1944
1953
  }
1945
1954
  /**
1946
- Indicates whether the line height in the editor changed in this update.
1955
+ Indicates whether the height of an element in the editor changed
1956
+ in this update.
1947
1957
  */
1948
1958
  get heightChanged() {
1949
1959
  return (this.flags & 2 /* Height */) > 0;
1950
1960
  }
1951
1961
  /**
1952
- Returns true when the document changed or the size of the editor
1953
- or the lines or characters within it has changed.
1962
+ Returns true when the document was modified or the size of the
1963
+ editor, or elements within the editor, changed.
1954
1964
  */
1955
1965
  get geometryChanged() {
1956
1966
  return this.docChanged || (this.flags & (8 /* Geometry */ | 2 /* Height */)) > 0;
@@ -2368,6 +2378,7 @@ class DocView extends ContentView {
2368
2378
  this.view = view;
2369
2379
  this.compositionDeco = Decoration.none;
2370
2380
  this.decorations = [];
2381
+ this.pluginDecorationLength = 0;
2371
2382
  // Track a minimum width for the editor. When measuring sizes in
2372
2383
  // measureVisibleLineHeights, this is updated to point at the width
2373
2384
  // of a given element and its extent in the document. When a change
@@ -2389,7 +2400,8 @@ class DocView extends ContentView {
2389
2400
  this.setDOM(view.contentDOM);
2390
2401
  this.children = [new LineView];
2391
2402
  this.children[0].setParent(this);
2392
- this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], this.updateDeco(), 0);
2403
+ this.updateDeco();
2404
+ this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
2393
2405
  }
2394
2406
  get root() { return this.view.root; }
2395
2407
  get editorView() { return this.view; }
@@ -2428,7 +2440,7 @@ class DocView extends ContentView {
2428
2440
  return false;
2429
2441
  }
2430
2442
  else {
2431
- this.updateInner(changedRanges, deco, update.startState.doc.length);
2443
+ this.updateInner(changedRanges, update.startState.doc.length);
2432
2444
  if (update.transactions.length)
2433
2445
  this.lastUpdate = Date.now();
2434
2446
  return true;
@@ -2436,9 +2448,9 @@ class DocView extends ContentView {
2436
2448
  }
2437
2449
  // Used by update and the constructor do perform the actual DOM
2438
2450
  // update
2439
- updateInner(changes, deco, oldLength) {
2451
+ updateInner(changes, oldLength) {
2440
2452
  this.view.viewState.mustMeasureContent = true;
2441
- this.updateChildren(changes, deco, oldLength);
2453
+ this.updateChildren(changes, oldLength);
2442
2454
  let { observer } = this.view;
2443
2455
  observer.ignore(() => {
2444
2456
  // Lock the height during redrawing, since Chrome sometimes
@@ -2465,14 +2477,14 @@ class DocView extends ContentView {
2465
2477
  gaps.push(child.dom);
2466
2478
  observer.updateGaps(gaps);
2467
2479
  }
2468
- updateChildren(changes, deco, oldLength) {
2480
+ updateChildren(changes, oldLength) {
2469
2481
  let cursor = this.childCursor(oldLength);
2470
2482
  for (let i = changes.length - 1;; i--) {
2471
2483
  let next = i >= 0 ? changes[i] : null;
2472
2484
  if (!next)
2473
2485
  break;
2474
2486
  let { fromA, toA, fromB, toB } = next;
2475
- let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, deco);
2487
+ let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, this.decorations, this.pluginDecorationLength);
2476
2488
  let { i: toI, off: toOff } = cursor.findPos(toA, 1);
2477
2489
  let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
2478
2490
  replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
@@ -2691,8 +2703,10 @@ class DocView extends ContentView {
2691
2703
  return Decoration.set(deco);
2692
2704
  }
2693
2705
  updateDeco() {
2706
+ let pluginDecorations = this.view.pluginField(PluginField.decorations);
2707
+ this.pluginDecorationLength = pluginDecorations.length;
2694
2708
  return this.decorations = [
2695
- ...this.view.pluginField(PluginField.decorations),
2709
+ ...pluginDecorations,
2696
2710
  ...this.view.state.facet(decorations),
2697
2711
  this.compositionDeco,
2698
2712
  this.computeBlockGapDeco(),
@@ -2986,7 +3000,11 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
2986
3000
  var _a;
2987
3001
  let content = view.contentDOM.getBoundingClientRect(), docTop = content.top + view.viewState.paddingTop;
2988
3002
  let block, { docHeight } = view.viewState;
2989
- let yOffset = Math.max(0, Math.min(y - docTop, docHeight));
3003
+ let yOffset = y - docTop;
3004
+ if (yOffset < 0)
3005
+ return 0;
3006
+ if (yOffset > docHeight)
3007
+ return view.state.doc.length;
2990
3008
  // Scan for a text block near the queried y position
2991
3009
  for (let halfLine = view.defaultLineHeight / 2, bounced = false;;) {
2992
3010
  block = view.elementAtHeight(yOffset);
@@ -3009,10 +3027,10 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
3009
3027
  let lineStart = block.from;
3010
3028
  // If this is outside of the rendered viewport, we can't determine a position
3011
3029
  if (lineStart < view.viewport.from)
3012
- return view.viewport.from == 0 ? 0 : precise ? posAtCoordsImprecise(view, content, block, x, y) : null;
3030
+ return view.viewport.from == 0 ? 0 : precise ? null : posAtCoordsImprecise(view, content, block, x, y);
3013
3031
  if (lineStart > view.viewport.to)
3014
3032
  return view.viewport.to == view.state.doc.length ? view.state.doc.length :
3015
- precise ? posAtCoordsImprecise(view, content, block, x, y) : null;
3033
+ precise ? null : posAtCoordsImprecise(view, content, block, x, y);
3016
3034
  // Prefer ShadowRootOrDocument.elementFromPoint if present, fall back to document if not
3017
3035
  let doc = view.dom.ownerDocument;
3018
3036
  let root = view.root.elementFromPoint ? view.root : doc;
@@ -3047,6 +3065,8 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
3047
3065
  // No luck, do our own (potentially expensive) search
3048
3066
  if (!node || !view.docView.dom.contains(node)) {
3049
3067
  let line = LineView.find(view.docView, lineStart);
3068
+ if (!line)
3069
+ return yOffset > block.top + block.height / 2 ? block.to : block.from;
3050
3070
  ({ node, offset } = domPosAtCoords(line.dom, x, y));
3051
3071
  }
3052
3072
  return view.docView.posFromDOM(node, offset);
@@ -4573,6 +4593,7 @@ class ViewState {
4573
4593
  this.contentDOMWidth = 0;
4574
4594
  this.contentDOMHeight = 0;
4575
4595
  this.editorHeight = 0;
4596
+ this.editorWidth = 0;
4576
4597
  this.heightOracle = new HeightOracle;
4577
4598
  // See VP.MaxDOMHeight
4578
4599
  this.scaler = IdScaler;
@@ -4678,11 +4699,18 @@ class ViewState {
4678
4699
  }
4679
4700
  if (!this.inView)
4680
4701
  return 0;
4702
+ let contentWidth = dom.clientWidth;
4703
+ if (this.contentDOMWidth != contentWidth || this.editorHeight != view.scrollDOM.clientHeight ||
4704
+ this.editorWidth != view.scrollDOM.clientWidth) {
4705
+ this.contentDOMWidth = contentWidth;
4706
+ this.editorHeight = view.scrollDOM.clientHeight;
4707
+ this.editorWidth = view.scrollDOM.clientWidth;
4708
+ result |= 8 /* Geometry */;
4709
+ }
4681
4710
  if (measureContent) {
4682
4711
  let lineHeights = view.docView.measureVisibleLineHeights();
4683
4712
  if (oracle.mustRefreshForHeights(lineHeights))
4684
4713
  refresh = true;
4685
- let contentWidth = dom.clientWidth;
4686
4714
  if (refresh || oracle.lineWrapping && Math.abs(contentWidth - this.contentDOMWidth) > oracle.charWidth) {
4687
4715
  let { lineHeight, charWidth } = view.docView.measureTextSize();
4688
4716
  refresh = oracle.refresh(whiteSpace, direction, lineHeight, charWidth, contentWidth / charWidth, lineHeights);
@@ -4691,14 +4719,6 @@ class ViewState {
4691
4719
  result |= 8 /* Geometry */;
4692
4720
  }
4693
4721
  }
4694
- if (this.contentDOMWidth != contentWidth) {
4695
- this.contentDOMWidth = contentWidth;
4696
- result |= 8 /* Geometry */;
4697
- }
4698
- if (this.editorHeight != view.scrollDOM.clientHeight) {
4699
- this.editorHeight = view.scrollDOM.clientHeight;
4700
- result |= 8 /* Geometry */;
4701
- }
4702
4722
  if (dTop > 0 && dBottom > 0)
4703
4723
  bias = Math.max(dTop, dBottom);
4704
4724
  else if (dTop < 0 && dBottom < 0)
@@ -5838,7 +5858,7 @@ class EditorView {
5838
5858
  if (state.facet(EditorState.phrases) != this.state.facet(EditorState.phrases))
5839
5859
  return this.setState(state);
5840
5860
  update = new ViewUpdate(this, state, transactions);
5841
- let scrollTarget = null;
5861
+ let scrollTarget = this.viewState.scrollTarget;
5842
5862
  try {
5843
5863
  this.updateState = 2 /* Updating */;
5844
5864
  for (let tr of transactions) {
@@ -6559,6 +6579,13 @@ mechanism for providing decorations.
6559
6579
  */
6560
6580
  EditorView.decorations = decorations;
6561
6581
  /**
6582
+ This facet records whether a dark theme is active. The extension
6583
+ returned by [`theme`](https://codemirror.net/6/docs/ref/#view.EditorView^theme) automatically
6584
+ includes an instance of this when the `dark` option is set to
6585
+ true.
6586
+ */
6587
+ EditorView.darkTheme = darkTheme;
6588
+ /**
6562
6589
  Facet that provides additional DOM attributes for the editor's
6563
6590
  editable DOM element.
6564
6591
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemirror/view",
3
- "version": "0.19.35",
3
+ "version": "0.19.39",
4
4
  "description": "DOM view component for the CodeMirror code editor",
5
5
  "scripts": {
6
6
  "test": "cm-runtests",
@@ -26,7 +26,7 @@
26
26
  "sideEffects": false,
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
- "@codemirror/rangeset": "^0.19.4",
29
+ "@codemirror/rangeset": "^0.19.5",
30
30
  "@codemirror/state": "^0.19.3",
31
31
  "@codemirror/text": "^0.19.0",
32
32
  "style-mod": "^4.0.0",