Skip to content

Commit 99bd4e5

Browse files
authored
fix(document-api): add mutation-ready cell addresses to tables.getCells (#2461)
* fix(document-api): add mutation-ready cell addresses to tables.getCells * chore: fix lint
1 parent 57b3ecc commit 99bd4e5

9 files changed

Lines changed: 57 additions & 5 deletions

File tree

apps/docs/document-api/reference/_generated-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -976,5 +976,5 @@
976976
}
977977
],
978978
"marker": "{/* GENERATED FILE: DO NOT EDIT. Regenerate via `pnpm run docapi:sync`. */}",
979-
"sourceHash": "3bca09dc183fa828d25a2349a4f780e5ef7bfcad2e9ddf21e552a88c97b9fa97"
979+
"sourceHash": "0ac9ab9c8f464a719722f89f32d725cc3c2079d126fa09d487a90eb7170d474d"
980980
}

apps/docs/document-api/reference/tables/get-cells.mdx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ Returns a TablesGetCellsOutput with cell information for the requested rows and
8181
},
8282
"cells": [
8383
{
84+
"address": {
85+
"kind": "block",
86+
"nodeId": "node-def456",
87+
"nodeType": "tableCell"
88+
},
8489
"colspan": 1,
8590
"columnIndex": 1,
8691
"nodeId": "node-def456",
@@ -151,6 +156,9 @@ Returns a TablesGetCellsOutput with cell information for the requested rows and
151156
"items": {
152157
"additionalProperties": false,
153158
"properties": {
159+
"address": {
160+
"$ref": "#/$defs/TableCellAddress"
161+
},
154162
"colspan": {
155163
"minimum": 1,
156164
"type": "integer"
@@ -173,6 +181,7 @@ Returns a TablesGetCellsOutput with cell information for the requested rows and
173181
},
174182
"required": [
175183
"nodeId",
184+
"address",
176185
"rowIndex",
177186
"columnIndex",
178187
"colspan",

packages/document-api/src/contract/schemas.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5212,12 +5212,13 @@ const operationSchemas: Record<OperationId, OperationSchemaSet> = {
52125212
items: objectSchema(
52135213
{
52145214
nodeId: { type: 'string' },
5215+
address: tableCellAddressSchema,
52155216
rowIndex: { type: 'integer', minimum: 0 },
52165217
columnIndex: { type: 'integer', minimum: 0 },
52175218
colspan: { type: 'integer', minimum: 1 },
52185219
rowspan: { type: 'integer', minimum: 1 },
52195220
},
5220-
['nodeId', 'rowIndex', 'columnIndex', 'colspan', 'rowspan'],
5221+
['nodeId', 'address', 'rowIndex', 'columnIndex', 'colspan', 'rowspan'],
52215222
),
52225223
},
52235224
},

packages/document-api/src/index.test.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,16 @@ function makeTablesAdapter(): TablesAdapter {
310310
getCells: vi.fn(() => ({
311311
nodeId: 't1',
312312
address: { kind: 'block' as const, nodeType: 'table' as const, nodeId: 't1' },
313-
cells: [{ nodeId: 'c1', rowIndex: 0, columnIndex: 0, colspan: 1, rowspan: 1 }],
313+
cells: [
314+
{
315+
nodeId: 'c1',
316+
address: { kind: 'block' as const, nodeType: 'tableCell' as const, nodeId: 'c1' },
317+
rowIndex: 0,
318+
columnIndex: 0,
319+
colspan: 1,
320+
rowspan: 1,
321+
},
322+
],
314323
})),
315324
getProperties: vi.fn(() => ({
316325
nodeId: 't1',

packages/document-api/src/types/table-operations.types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,10 @@ export interface TablesGetCellsInput extends TableLocator {
471471

472472
/** Per-cell info with stable ref for write handoff. */
473473
export interface TableCellInfo {
474+
/** Shorthand cell identifier — convenient for logging, Map keys, and display. */
474475
nodeId: string;
476+
/** Mutation-ready address — pass directly as `target` in follow-up cell operations. */
477+
address: TableCellAddress;
475478
rowIndex: number;
476479
columnIndex: number;
477480
colspan: number;

packages/super-editor/src/document-api-adapters/__conformance__/contract-conformance.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10467,7 +10467,7 @@ describe('document-api adapter conformance', () => {
1046710467
).toThrow(/rowIndex must not be provided when target is a row node/);
1046810468
});
1046910469

10470-
it('returns stable cell ids from tables.getCells using table-map resolved absolute positions', () => {
10470+
it('returns stable cell ids and mutation-ready addresses from tables.getCells', () => {
1047110471
const editor = makeTableEditor();
1047210472
const result = tablesGetCellsAdapter(editor, { nodeId: 'table-1' });
1047310473

@@ -10478,6 +10478,14 @@ describe('document-api adapter conformance', () => {
1047810478

1047910479
const topLeft = result.cells.find((cell) => cell.rowIndex === 0 && cell.columnIndex === 0);
1048010480
expect(topLeft?.nodeId).toBe('cell-1');
10481+
10482+
// Each cell address mirrors nodeId and is ready for mutation handoff.
10483+
expect(topLeft?.address).toEqual({ kind: 'block', nodeType: 'tableCell', nodeId: 'cell-1' });
10484+
10485+
// All cells carry a well-formed address.
10486+
for (const cell of result.cells) {
10487+
expect(cell.address).toEqual({ kind: 'block', nodeType: 'tableCell', nodeId: cell.nodeId });
10488+
}
1048110489
});
1048210490

1048310491
it('reads tables.getProperties from nested tableProperties', () => {

packages/super-editor/src/document-api-adapters/tables-adapter.ref-handoff.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,24 @@ describe('SD-2126: post-mutation table ref handoff', () => {
138138
expect(table?.nodeType).toBe('table');
139139
});
140140

141+
it('cell address from getCells is accepted as target in a follow-up mutation', () => {
142+
const ed = createEditor();
143+
144+
const createResult = createTableAdapter(ed, { rows: 2, columns: 2, at: { kind: 'documentEnd' } }, DIRECT);
145+
const tableNodeId = requireTableNodeId(createResult, 'create.table');
146+
const cellsResult = tablesGetCellsAdapter(ed, { nodeId: tableNodeId });
147+
const firstCell = cellsResult.cells[0]!;
148+
149+
// Use the cell's address (not its flat nodeId) as the mutation target.
150+
const borderResult = tablesSetBorderAdapter(
151+
ed,
152+
{ target: firstCell.address, edge: 'top', lineStyle: 'single', lineWeightPt: 1, color: '000000' },
153+
DIRECT,
154+
);
155+
156+
expect(borderResult.success).toBe(true);
157+
});
158+
141159
it('tables.move returns a chainable ref after relocating the table', () => {
142160
const ed = createEditor();
143161

packages/super-editor/src/document-api-adapters/tables-adapter.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3632,8 +3632,10 @@ export function tablesGetCellsAdapter(editor: Editor, input: TablesGetCellsInput
36323632
if (input.columnIndex != null && col !== input.columnIndex) continue;
36333633

36343634
const attrs = candidate.node.attrs as Record<string, unknown>;
3635+
const cellNodeId = candidate.nodeId || resolveCellNodeId(attrs);
36353636
cells.push({
3636-
nodeId: candidate.nodeId || resolveCellNodeId(attrs),
3637+
nodeId: cellNodeId,
3638+
address: { kind: 'block', nodeType: 'tableCell', nodeId: cellNodeId },
36373639
rowIndex: row,
36383640
columnIndex: col,
36393641
colspan: typeof attrs.colspan === 'number' ? attrs.colspan : 1,

tests/doc-api-stories/tests/tables/all-commands.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ describe('document-api story: all table commands', () => {
142142
expect(Array.isArray(result?.cells)).toBe(true);
143143
expect(result.cells.length).toBeGreaterThan(0);
144144
expect(typeof result.cells[0]?.nodeId).toBe('string');
145+
expect(result.cells[0]?.address?.nodeId).toBe(result.cells[0]?.nodeId);
146+
expect(result.cells[0]?.address?.nodeType).toBe('tableCell');
145147
return;
146148
}
147149

0 commit comments

Comments
 (0)