Skip to content

Commit 2ff6583

Browse files
Fixes for drag and drop at the end of the document (#1039)
* Fix for DND highlight when no line break at EOF. Closes #823 * Analogous fix for end of document indent level.
1 parent ed6b16b commit 2ff6583

File tree

4 files changed

+49
-2
lines changed

4 files changed

+49
-2
lines changed

src/editor/codemirror/dnd-decorations.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,34 @@ describe("dndDecorations", () => {
131131

132132
expect(plugin.decorations.size).toEqual(0);
133133
});
134+
135+
it("handles inserting at end of doc with no blank line", () => {
136+
const view = createView(Text.of(["#1"]));
137+
const plugin = new DndDecorationsViewPlugin(view, 0);
138+
139+
const viewUpdate = createViewUpdate(
140+
view,
141+
true,
142+
view.state.update({
143+
userEvent: "dnd.preview",
144+
changes: [
145+
{
146+
insert: "\n#2\n",
147+
from: 2,
148+
},
149+
],
150+
})
151+
);
152+
plugin.update(viewUpdate);
153+
expect(viewUpdate.state.doc.sliceString(0)).toEqual("#1\n#2\n");
154+
155+
expect(decorationDetails(plugin)).toEqual([
156+
{
157+
class: "cm-preview",
158+
from: 3,
159+
},
160+
]);
161+
});
134162
});
135163

136164
interface DecorationDetails {

src/editor/codemirror/dnd-decorations.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ export class DndDecorationsViewPlugin {
3535
const isDrop = transactions.some((t) => t.isUserEvent("dnd.drop"));
3636
if (isPreview || isDrop) {
3737
changes.iterChangedRanges((_fromA, _toA, fromB, toB) => {
38-
const start = state.doc.lineAt(fromB);
38+
let start = state.doc.lineAt(fromB);
39+
// If there was no blank line at the end then the insertion will have
40+
// started from the EOL but doesn't make sense to highlight that line.
41+
if (start.to === fromB) {
42+
start = state.doc.lineAt(fromB + 1);
43+
}
3944
const end = state.doc.lineAt(toB);
4045
for (let l = start.number; l < end.number; ++l) {
4146
const line = state.doc.line(l);

src/editor/codemirror/edits.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,4 +493,13 @@ describe("edits", () => {
493493
indentLevelHint: 0,
494494
});
495495
});
496+
it("uses correct preceding line for indent at end of document", () => {
497+
check({
498+
line: 2,
499+
initial: "if True:",
500+
additional: "pass",
501+
expected: "if True:\n\tpass\n",
502+
type: "example",
503+
});
504+
});
496505
});

src/editor/codemirror/edits.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,12 @@ const indentLevel = (text: string): number => {
201201
};
202202

203203
const preceedingLinesExclusive = function* (state: EditorState, from: number) {
204-
const initial = state.doc.lineAt(from).number - 1;
204+
const initialLine = state.doc.lineAt(from);
205+
// Special case: if there was no line break on the previous line then
206+
// we're inserting one. So we need to use the current line as the preceding
207+
// line.
208+
let initial =
209+
initialLine.to === from ? initialLine.number : initialLine.number - 1;
205210
for (let line = initial; line >= 1; --line) {
206211
yield state.doc.line(line);
207212
}

0 commit comments

Comments
 (0)