Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,5 +287,6 @@ function cellUnderMouse(
top: event.clientY,
});
if (!mousePos) return null;
return mousePos ? cellAround(view.state.doc.resolve(mousePos.pos)) : null;
const $pos = view.state.doc.resolve(mousePos.pos);
return cellAround($pos);
}
29 changes: 29 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,35 @@ export function cellAround($pos: ResolvedPos): ResolvedPos | null {
for (let d = $pos.depth - 1; d > 0; d--)
if ($pos.node(d).type.spec.tableRole == 'row')
return $pos.node(0).resolve($pos.before(d + 1));

// search the entire mergeCells
for (let d = $pos.depth; d > 0; d--) {
const node = $pos.node(d);
if (node.type.spec.tableRole === 'table') {
const table = TableMap.get(node);
for (let i = 0; i < table.map.length; i++) {
const cellPos = table.map[i];
try {
const cellRect = table.findCell(cellPos);
const row = Math.floor(i / table.width);
const col = i % table.width;

if (
row >= cellRect.top &&
row < cellRect.bottom &&
col >= cellRect.left &&
col < cellRect.right
) {
return $pos.node(0).resolve($pos.start(d) + cellPos);
}
} catch (e) {
continue;
}
}
break;
}
}

return null;
}

Expand Down
58 changes: 58 additions & 0 deletions test/cellAround.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { EditorState } from 'prosemirror-state';
import { describe, expect, it } from 'vitest';
import { cellAround } from '../src/util';
import { c, c11, cCursor, table, tr, selectionFor } from './build';

describe('cellAround', () => {
it('cursor is in text', () => {
const doc = table(
tr(cCursor, c11, c11),
);
const state = EditorState.create({ doc, selection: selectionFor(doc) });

expect(cellAround(state.doc.resolve(state.selection.anchor))).not.toBeNull();
expect(cellAround(state.doc.resolve(doc.content.size))).toBeNull();
});
// Test finding a cell in a regular cell
it('finds a regular cell', () => {
// Create a simple table with cursor in the middle cell
const doc = table(
tr(c11, c11, c11),
tr(c11, cCursor, c11),
tr(c11, c11, c11),
);
const state = EditorState.create({ doc, selection: selectionFor(doc) });
const $pos = state.doc.resolve(state.selection.anchor);
const $cell = cellAround($pos);

// Verify that the cell was found
expect($cell).not.toBeNull();
// Verify that the found cell is the expected merged cell
const cellNode = $cell!.nodeAfter;
expect(cellNode!.attrs.colspan).toBe(1);
expect(cellNode!.attrs.rowspan).toBe(1);
});

// Test finding a cell when cursor is inside a merged cell
it('finds a merged cell when cursor is inside', () => {
// Create a table with a merged cell, cursor inside the merged cell
const doc = table(
tr(c11, c(2, 2, 'x<cursor>'), c11),
tr(c11, c11),
tr(c11, c11, c11),
);

const state = EditorState.create({ doc, selection: selectionFor(doc) });
const $pos = state.doc.resolve(state.selection.anchor);
const $cell = cellAround($pos);

// Verify that the cell was found
expect($cell).not.toBeNull();
// Verify that the found cell is a merged cell
const cellNode = $cell!.nodeAfter;
expect(cellNode!.attrs.colspan).toBe(2);
expect(cellNode!.attrs.rowspan).toBe(2);
});


});