@codemirror/view 0.19.45 → 0.19.46
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 +10 -0
- package/dist/index.cjs +83 -20
- package/dist/index.js +83 -20
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## 0.19.46 (2022-03-03)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix a bug where block widgets on the edges of viewports could cause the positioning of content to misalign with the gutter and height computations.
|
|
6
|
+
|
|
7
|
+
Improve cursor height next to widgets.
|
|
8
|
+
|
|
9
|
+
Fix a bug where mapping positions to screen coordinates could return incorred coordinates during composition.
|
|
10
|
+
|
|
1
11
|
## 0.19.45 (2022-02-23)
|
|
2
12
|
|
|
3
13
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -22,7 +22,7 @@ function getSelection(root) {
|
|
|
22
22
|
return target.getSelection();
|
|
23
23
|
}
|
|
24
24
|
function contains(dom, node) {
|
|
25
|
-
return node ? dom.contains(node.nodeType != 1 ? node.parentNode : node) : false;
|
|
25
|
+
return node ? dom == node || dom.contains(node.nodeType != 1 ? node.parentNode : node) : false;
|
|
26
26
|
}
|
|
27
27
|
function deepActiveElement() {
|
|
28
28
|
let elt = document.activeElement;
|
|
@@ -856,18 +856,26 @@ class WidgetView extends ContentView {
|
|
|
856
856
|
}
|
|
857
857
|
class CompositionView extends WidgetView {
|
|
858
858
|
domAtPos(pos) {
|
|
859
|
-
let { topView } = this.widget;
|
|
859
|
+
let { topView, text } = this.widget;
|
|
860
860
|
if (!topView)
|
|
861
|
-
return new DOMPos(
|
|
862
|
-
return
|
|
861
|
+
return new DOMPos(text, Math.min(pos, text.nodeValue.length));
|
|
862
|
+
return scanCompositionTree(pos, 0, topView, text, (v, p) => v.domAtPos(p), p => new DOMPos(text, Math.min(p, text.nodeValue.length)));
|
|
863
863
|
}
|
|
864
864
|
sync() { this.setDOM(this.widget.toDOM()); }
|
|
865
865
|
localPosFromDOM(node, offset) {
|
|
866
|
-
|
|
866
|
+
let { topView, text } = this.widget;
|
|
867
|
+
if (!topView)
|
|
868
|
+
return Math.min(offset, this.length);
|
|
869
|
+
return posFromDOMInCompositionTree(node, offset, topView, text);
|
|
867
870
|
}
|
|
868
871
|
ignoreMutation() { return false; }
|
|
869
872
|
get overrideDOMText() { return null; }
|
|
870
|
-
coordsAt(pos, side) {
|
|
873
|
+
coordsAt(pos, side) {
|
|
874
|
+
let { topView, text } = this.widget;
|
|
875
|
+
if (!topView)
|
|
876
|
+
return textCoords(text, pos, side);
|
|
877
|
+
return scanCompositionTree(pos, side, topView, text, (v, pos, side) => v.coordsAt(pos, side), (pos, side) => textCoords(text, pos, side));
|
|
878
|
+
}
|
|
871
879
|
destroy() {
|
|
872
880
|
var _a;
|
|
873
881
|
super.destroy();
|
|
@@ -878,23 +886,37 @@ class CompositionView extends WidgetView {
|
|
|
878
886
|
// Uses the old structure of a chunk of content view frozen for
|
|
879
887
|
// composition to try and find a reasonable DOM location for the given
|
|
880
888
|
// offset.
|
|
881
|
-
function
|
|
889
|
+
function scanCompositionTree(pos, side, view, text, enterView, fromText) {
|
|
882
890
|
if (view instanceof MarkView) {
|
|
883
891
|
for (let child of view.children) {
|
|
884
|
-
let hasComp = child.dom
|
|
892
|
+
let hasComp = contains(child.dom, text);
|
|
885
893
|
let len = hasComp ? text.nodeValue.length : child.length;
|
|
886
894
|
if (pos < len || pos == len && child.getSide() <= 0)
|
|
887
|
-
return hasComp ?
|
|
895
|
+
return hasComp ? scanCompositionTree(pos, side, child, text, enterView, fromText) : enterView(child, pos, side);
|
|
888
896
|
pos -= len;
|
|
889
897
|
}
|
|
890
|
-
return
|
|
898
|
+
return enterView(view, view.length, -1);
|
|
891
899
|
}
|
|
892
900
|
else if (view.dom == text) {
|
|
893
|
-
return
|
|
901
|
+
return fromText(pos, side);
|
|
894
902
|
}
|
|
895
903
|
else {
|
|
896
|
-
return view
|
|
904
|
+
return enterView(view, pos, side);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
function posFromDOMInCompositionTree(node, offset, view, text) {
|
|
908
|
+
if (view instanceof MarkView) {
|
|
909
|
+
for (let child of view.children) {
|
|
910
|
+
let pos = 0, hasComp = contains(child.dom, text);
|
|
911
|
+
if (contains(child.dom, node))
|
|
912
|
+
return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, child, text) : child.localPosFromDOM(node, offset));
|
|
913
|
+
pos += hasComp ? text.nodeValue.length : child.length;
|
|
914
|
+
}
|
|
897
915
|
}
|
|
916
|
+
else if (view.dom == text) {
|
|
917
|
+
return Math.min(offset, text.nodeValue.length);
|
|
918
|
+
}
|
|
919
|
+
return view.localPosFromDOM(node, offset);
|
|
898
920
|
}
|
|
899
921
|
// These are drawn around uneditable widgets to avoid a number of
|
|
900
922
|
// browser bugs that show up when the cursor is directly next to
|
|
@@ -922,13 +944,43 @@ class WidgetBufferView extends ContentView {
|
|
|
922
944
|
localPosFromDOM() { return 0; }
|
|
923
945
|
domBoundsAround() { return null; }
|
|
924
946
|
coordsAt(pos) {
|
|
925
|
-
|
|
947
|
+
let imgRect = this.dom.getBoundingClientRect();
|
|
948
|
+
// Since the <img> height doesn't correspond to text height, try
|
|
949
|
+
// to borrow the height from some sibling node.
|
|
950
|
+
let siblingRect = inlineSiblingRect(this, this.side > 0 ? -1 : 1);
|
|
951
|
+
return siblingRect && siblingRect.top < imgRect.bottom && siblingRect.bottom > imgRect.top
|
|
952
|
+
? { left: imgRect.left, right: imgRect.right, top: siblingRect.top, bottom: siblingRect.bottom } : imgRect;
|
|
926
953
|
}
|
|
927
954
|
get overrideDOMText() {
|
|
928
955
|
return text.Text.empty;
|
|
929
956
|
}
|
|
930
957
|
}
|
|
931
958
|
TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
|
|
959
|
+
function inlineSiblingRect(view, side) {
|
|
960
|
+
let parent = view.parent, index = parent ? parent.children.indexOf(view) : -1;
|
|
961
|
+
while (parent && index >= 0) {
|
|
962
|
+
if (side < 0 ? index > 0 : index < parent.children.length) {
|
|
963
|
+
let next = parent.children[index + side];
|
|
964
|
+
if (next instanceof TextView) {
|
|
965
|
+
let nextRect = next.coordsAt(side < 0 ? next.length : 0, side);
|
|
966
|
+
if (nextRect)
|
|
967
|
+
return nextRect;
|
|
968
|
+
}
|
|
969
|
+
index += side;
|
|
970
|
+
}
|
|
971
|
+
else if (parent instanceof MarkView && parent.parent) {
|
|
972
|
+
index = parent.parent.children.indexOf(parent) + (side < 0 ? 0 : 1);
|
|
973
|
+
parent = parent.parent;
|
|
974
|
+
}
|
|
975
|
+
else {
|
|
976
|
+
let last = parent.dom.lastChild;
|
|
977
|
+
if (last && last.nodeName == "BR")
|
|
978
|
+
return last.getClientRects()[0];
|
|
979
|
+
break;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
return undefined;
|
|
983
|
+
}
|
|
932
984
|
function inlineDOMAtPos(dom, children, pos) {
|
|
933
985
|
let i = 0;
|
|
934
986
|
for (let off = 0; i < children.length; i++) {
|
|
@@ -1154,7 +1206,7 @@ class Decoration extends rangeset.RangeValue {
|
|
|
1154
1206
|
*/
|
|
1155
1207
|
static widget(spec) {
|
|
1156
1208
|
let side = spec.side || 0, block = !!spec.block;
|
|
1157
|
-
side += block ? (side > 0 ?
|
|
1209
|
+
side += block ? (side > 0 ? 400000000 /* BlockAfter */ : -500000000 /* BlockBefore */) : (side > 0 ? 100000000 /* InlineAfter */ : -100000000 /* InlineBefore */);
|
|
1158
1210
|
return new PointDecoration(spec, side, side, block, spec.widget || null, false);
|
|
1159
1211
|
}
|
|
1160
1212
|
/**
|
|
@@ -1162,10 +1214,16 @@ class Decoration extends rangeset.RangeValue {
|
|
|
1162
1214
|
a widget, or simply hides it.
|
|
1163
1215
|
*/
|
|
1164
1216
|
static replace(spec) {
|
|
1165
|
-
let block = !!spec.block;
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1217
|
+
let block = !!spec.block, startSide, endSide;
|
|
1218
|
+
if (spec.isBlockGap) {
|
|
1219
|
+
startSide = -400000000 /* GapStart */;
|
|
1220
|
+
endSide = 300000000 /* GapEnd */;
|
|
1221
|
+
}
|
|
1222
|
+
else {
|
|
1223
|
+
let { start, end } = getInclusive(spec, block);
|
|
1224
|
+
startSide = (start ? (block ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 500000000 /* NonIncStart */) - 1;
|
|
1225
|
+
endSide = (end ? (block ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -600000000 /* NonIncEnd */) + 1;
|
|
1226
|
+
}
|
|
1169
1227
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1170
1228
|
}
|
|
1171
1229
|
/**
|
|
@@ -1195,7 +1253,7 @@ Decoration.none = rangeset.RangeSet.empty;
|
|
|
1195
1253
|
class MarkDecoration extends Decoration {
|
|
1196
1254
|
constructor(spec) {
|
|
1197
1255
|
let { start, end } = getInclusive(spec);
|
|
1198
|
-
super(start ? -1 /* InlineIncStart */ :
|
|
1256
|
+
super(start ? -1 /* InlineIncStart */ : 500000000 /* NonIncStart */, end ? 1 /* InlineIncEnd */ : -600000000 /* NonIncEnd */, null, spec);
|
|
1199
1257
|
this.tagName = spec.tagName || "span";
|
|
1200
1258
|
this.class = spec.class || "";
|
|
1201
1259
|
this.attrs = spec.attributes || null;
|
|
@@ -2774,7 +2832,12 @@ class DocView extends ContentView {
|
|
|
2774
2832
|
let end = next ? next.from - 1 : this.length;
|
|
2775
2833
|
if (end > pos) {
|
|
2776
2834
|
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
2777
|
-
deco.push(Decoration.replace({
|
|
2835
|
+
deco.push(Decoration.replace({
|
|
2836
|
+
widget: new BlockGapWidget(height),
|
|
2837
|
+
block: true,
|
|
2838
|
+
inclusive: true,
|
|
2839
|
+
isBlockGap: true,
|
|
2840
|
+
}).range(pos, end));
|
|
2778
2841
|
}
|
|
2779
2842
|
if (!next)
|
|
2780
2843
|
break;
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ function getSelection(root) {
|
|
|
19
19
|
return target.getSelection();
|
|
20
20
|
}
|
|
21
21
|
function contains(dom, node) {
|
|
22
|
-
return node ? dom.contains(node.nodeType != 1 ? node.parentNode : node) : false;
|
|
22
|
+
return node ? dom == node || dom.contains(node.nodeType != 1 ? node.parentNode : node) : false;
|
|
23
23
|
}
|
|
24
24
|
function deepActiveElement() {
|
|
25
25
|
let elt = document.activeElement;
|
|
@@ -853,18 +853,26 @@ class WidgetView extends ContentView {
|
|
|
853
853
|
}
|
|
854
854
|
class CompositionView extends WidgetView {
|
|
855
855
|
domAtPos(pos) {
|
|
856
|
-
let { topView } = this.widget;
|
|
856
|
+
let { topView, text } = this.widget;
|
|
857
857
|
if (!topView)
|
|
858
|
-
return new DOMPos(
|
|
859
|
-
return
|
|
858
|
+
return new DOMPos(text, Math.min(pos, text.nodeValue.length));
|
|
859
|
+
return scanCompositionTree(pos, 0, topView, text, (v, p) => v.domAtPos(p), p => new DOMPos(text, Math.min(p, text.nodeValue.length)));
|
|
860
860
|
}
|
|
861
861
|
sync() { this.setDOM(this.widget.toDOM()); }
|
|
862
862
|
localPosFromDOM(node, offset) {
|
|
863
|
-
|
|
863
|
+
let { topView, text } = this.widget;
|
|
864
|
+
if (!topView)
|
|
865
|
+
return Math.min(offset, this.length);
|
|
866
|
+
return posFromDOMInCompositionTree(node, offset, topView, text);
|
|
864
867
|
}
|
|
865
868
|
ignoreMutation() { return false; }
|
|
866
869
|
get overrideDOMText() { return null; }
|
|
867
|
-
coordsAt(pos, side) {
|
|
870
|
+
coordsAt(pos, side) {
|
|
871
|
+
let { topView, text } = this.widget;
|
|
872
|
+
if (!topView)
|
|
873
|
+
return textCoords(text, pos, side);
|
|
874
|
+
return scanCompositionTree(pos, side, topView, text, (v, pos, side) => v.coordsAt(pos, side), (pos, side) => textCoords(text, pos, side));
|
|
875
|
+
}
|
|
868
876
|
destroy() {
|
|
869
877
|
var _a;
|
|
870
878
|
super.destroy();
|
|
@@ -875,23 +883,37 @@ class CompositionView extends WidgetView {
|
|
|
875
883
|
// Uses the old structure of a chunk of content view frozen for
|
|
876
884
|
// composition to try and find a reasonable DOM location for the given
|
|
877
885
|
// offset.
|
|
878
|
-
function
|
|
886
|
+
function scanCompositionTree(pos, side, view, text, enterView, fromText) {
|
|
879
887
|
if (view instanceof MarkView) {
|
|
880
888
|
for (let child of view.children) {
|
|
881
|
-
let hasComp = child.dom
|
|
889
|
+
let hasComp = contains(child.dom, text);
|
|
882
890
|
let len = hasComp ? text.nodeValue.length : child.length;
|
|
883
891
|
if (pos < len || pos == len && child.getSide() <= 0)
|
|
884
|
-
return hasComp ?
|
|
892
|
+
return hasComp ? scanCompositionTree(pos, side, child, text, enterView, fromText) : enterView(child, pos, side);
|
|
885
893
|
pos -= len;
|
|
886
894
|
}
|
|
887
|
-
return
|
|
895
|
+
return enterView(view, view.length, -1);
|
|
888
896
|
}
|
|
889
897
|
else if (view.dom == text) {
|
|
890
|
-
return
|
|
898
|
+
return fromText(pos, side);
|
|
891
899
|
}
|
|
892
900
|
else {
|
|
893
|
-
return view
|
|
901
|
+
return enterView(view, pos, side);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
function posFromDOMInCompositionTree(node, offset, view, text) {
|
|
905
|
+
if (view instanceof MarkView) {
|
|
906
|
+
for (let child of view.children) {
|
|
907
|
+
let pos = 0, hasComp = contains(child.dom, text);
|
|
908
|
+
if (contains(child.dom, node))
|
|
909
|
+
return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, child, text) : child.localPosFromDOM(node, offset));
|
|
910
|
+
pos += hasComp ? text.nodeValue.length : child.length;
|
|
911
|
+
}
|
|
894
912
|
}
|
|
913
|
+
else if (view.dom == text) {
|
|
914
|
+
return Math.min(offset, text.nodeValue.length);
|
|
915
|
+
}
|
|
916
|
+
return view.localPosFromDOM(node, offset);
|
|
895
917
|
}
|
|
896
918
|
// These are drawn around uneditable widgets to avoid a number of
|
|
897
919
|
// browser bugs that show up when the cursor is directly next to
|
|
@@ -919,13 +941,43 @@ class WidgetBufferView extends ContentView {
|
|
|
919
941
|
localPosFromDOM() { return 0; }
|
|
920
942
|
domBoundsAround() { return null; }
|
|
921
943
|
coordsAt(pos) {
|
|
922
|
-
|
|
944
|
+
let imgRect = this.dom.getBoundingClientRect();
|
|
945
|
+
// Since the <img> height doesn't correspond to text height, try
|
|
946
|
+
// to borrow the height from some sibling node.
|
|
947
|
+
let siblingRect = inlineSiblingRect(this, this.side > 0 ? -1 : 1);
|
|
948
|
+
return siblingRect && siblingRect.top < imgRect.bottom && siblingRect.bottom > imgRect.top
|
|
949
|
+
? { left: imgRect.left, right: imgRect.right, top: siblingRect.top, bottom: siblingRect.bottom } : imgRect;
|
|
923
950
|
}
|
|
924
951
|
get overrideDOMText() {
|
|
925
952
|
return Text.empty;
|
|
926
953
|
}
|
|
927
954
|
}
|
|
928
955
|
TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
|
|
956
|
+
function inlineSiblingRect(view, side) {
|
|
957
|
+
let parent = view.parent, index = parent ? parent.children.indexOf(view) : -1;
|
|
958
|
+
while (parent && index >= 0) {
|
|
959
|
+
if (side < 0 ? index > 0 : index < parent.children.length) {
|
|
960
|
+
let next = parent.children[index + side];
|
|
961
|
+
if (next instanceof TextView) {
|
|
962
|
+
let nextRect = next.coordsAt(side < 0 ? next.length : 0, side);
|
|
963
|
+
if (nextRect)
|
|
964
|
+
return nextRect;
|
|
965
|
+
}
|
|
966
|
+
index += side;
|
|
967
|
+
}
|
|
968
|
+
else if (parent instanceof MarkView && parent.parent) {
|
|
969
|
+
index = parent.parent.children.indexOf(parent) + (side < 0 ? 0 : 1);
|
|
970
|
+
parent = parent.parent;
|
|
971
|
+
}
|
|
972
|
+
else {
|
|
973
|
+
let last = parent.dom.lastChild;
|
|
974
|
+
if (last && last.nodeName == "BR")
|
|
975
|
+
return last.getClientRects()[0];
|
|
976
|
+
break;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
return undefined;
|
|
980
|
+
}
|
|
929
981
|
function inlineDOMAtPos(dom, children, pos) {
|
|
930
982
|
let i = 0;
|
|
931
983
|
for (let off = 0; i < children.length; i++) {
|
|
@@ -1150,7 +1202,7 @@ class Decoration extends RangeValue {
|
|
|
1150
1202
|
*/
|
|
1151
1203
|
static widget(spec) {
|
|
1152
1204
|
let side = spec.side || 0, block = !!spec.block;
|
|
1153
|
-
side += block ? (side > 0 ?
|
|
1205
|
+
side += block ? (side > 0 ? 400000000 /* BlockAfter */ : -500000000 /* BlockBefore */) : (side > 0 ? 100000000 /* InlineAfter */ : -100000000 /* InlineBefore */);
|
|
1154
1206
|
return new PointDecoration(spec, side, side, block, spec.widget || null, false);
|
|
1155
1207
|
}
|
|
1156
1208
|
/**
|
|
@@ -1158,10 +1210,16 @@ class Decoration extends RangeValue {
|
|
|
1158
1210
|
a widget, or simply hides it.
|
|
1159
1211
|
*/
|
|
1160
1212
|
static replace(spec) {
|
|
1161
|
-
let block = !!spec.block;
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1213
|
+
let block = !!spec.block, startSide, endSide;
|
|
1214
|
+
if (spec.isBlockGap) {
|
|
1215
|
+
startSide = -400000000 /* GapStart */;
|
|
1216
|
+
endSide = 300000000 /* GapEnd */;
|
|
1217
|
+
}
|
|
1218
|
+
else {
|
|
1219
|
+
let { start, end } = getInclusive(spec, block);
|
|
1220
|
+
startSide = (start ? (block ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 500000000 /* NonIncStart */) - 1;
|
|
1221
|
+
endSide = (end ? (block ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -600000000 /* NonIncEnd */) + 1;
|
|
1222
|
+
}
|
|
1165
1223
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1166
1224
|
}
|
|
1167
1225
|
/**
|
|
@@ -1191,7 +1249,7 @@ Decoration.none = RangeSet.empty;
|
|
|
1191
1249
|
class MarkDecoration extends Decoration {
|
|
1192
1250
|
constructor(spec) {
|
|
1193
1251
|
let { start, end } = getInclusive(spec);
|
|
1194
|
-
super(start ? -1 /* InlineIncStart */ :
|
|
1252
|
+
super(start ? -1 /* InlineIncStart */ : 500000000 /* NonIncStart */, end ? 1 /* InlineIncEnd */ : -600000000 /* NonIncEnd */, null, spec);
|
|
1195
1253
|
this.tagName = spec.tagName || "span";
|
|
1196
1254
|
this.class = spec.class || "";
|
|
1197
1255
|
this.attrs = spec.attributes || null;
|
|
@@ -2769,7 +2827,12 @@ class DocView extends ContentView {
|
|
|
2769
2827
|
let end = next ? next.from - 1 : this.length;
|
|
2770
2828
|
if (end > pos) {
|
|
2771
2829
|
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
2772
|
-
deco.push(Decoration.replace({
|
|
2830
|
+
deco.push(Decoration.replace({
|
|
2831
|
+
widget: new BlockGapWidget(height),
|
|
2832
|
+
block: true,
|
|
2833
|
+
inclusive: true,
|
|
2834
|
+
isBlockGap: true,
|
|
2835
|
+
}).range(pos, end));
|
|
2773
2836
|
}
|
|
2774
2837
|
if (!next)
|
|
2775
2838
|
break;
|