mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-05 03:25:10 +08:00
07a08e6d4d
fix #15080 fix #15085 fix #15031 fix #15094 #### PR Dependency Tree * **PR #15098** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved code-block paste behavior for plain-text insertion * Fixed block selection ordering to reflect document model * Made table cell formatting resilient to conversion errors * Ensured user feature list is consistently returned as an array * **Refactor** * Streamlined authentication session fetch and profile enrichment flow * **Tests** * Added tests for markdown blockquote list preservation * Added authentication session validation tests <!-- end of auto-generated comment: release notes by coderabbit.ai -->
114 lines
2.6 KiB
TypeScript
114 lines
2.6 KiB
TypeScript
import type { ColumnDataType, SerializedCells } from '@blocksuite/affine-model';
|
|
import type { BlockSnapshot, DeltaInsert } from '@blocksuite/store';
|
|
|
|
import { databaseBlockModels } from '../properties/model';
|
|
|
|
function calculateColumnWidths(rows: string[][]): number[] {
|
|
return (
|
|
rows[0]?.map((_, colIndex) =>
|
|
Math.max(...rows.map(row => (row[colIndex] || '').length))
|
|
) ?? []
|
|
);
|
|
}
|
|
|
|
function formatRow(
|
|
row: string[],
|
|
columnWidths: number[],
|
|
isHeader: boolean
|
|
): string {
|
|
const cells = row.map((cell, colIndex) =>
|
|
cell?.padEnd(columnWidths[colIndex] ?? 0, ' ')
|
|
);
|
|
const rowString = `| ${cells.join(' | ')} |`;
|
|
return isHeader
|
|
? `${rowString}\n${formatSeparator(columnWidths)}`
|
|
: rowString;
|
|
}
|
|
|
|
function formatSeparator(columnWidths: number[]): string {
|
|
const separator = columnWidths.map(width => '-'.repeat(width)).join(' | ');
|
|
return `| ${separator} |`;
|
|
}
|
|
|
|
export function formatTable(rows: string[][]): string {
|
|
const columnWidths = calculateColumnWidths(rows);
|
|
const formattedRows = rows.map((row, index) =>
|
|
formatRow(row, columnWidths, index === 0)
|
|
);
|
|
return formattedRows.join('\n');
|
|
}
|
|
export const isDelta = (value: unknown): value is { delta: DeltaInsert[] } => {
|
|
if (typeof value === 'object' && value !== null) {
|
|
return '$blocksuite:internal:text$' in value;
|
|
}
|
|
return false;
|
|
};
|
|
type Table = {
|
|
headers: ColumnDataType[];
|
|
rows: Row[];
|
|
};
|
|
type Row = {
|
|
cells: Cell[];
|
|
};
|
|
type Cell = {
|
|
value: string | { delta: DeltaInsert[] };
|
|
};
|
|
export const processTable = (
|
|
columns: ColumnDataType[] = [],
|
|
children: BlockSnapshot[] = [],
|
|
cells: SerializedCells = {}
|
|
): Table => {
|
|
const table: Table = {
|
|
headers: columns,
|
|
rows: [],
|
|
};
|
|
children.forEach(v => {
|
|
const row: Row = {
|
|
cells: [],
|
|
};
|
|
const title = v.props.text;
|
|
if (isDelta(title)) {
|
|
row.cells.push({
|
|
value: title,
|
|
});
|
|
} else {
|
|
row.cells.push({
|
|
value: '',
|
|
});
|
|
}
|
|
|
|
columns.forEach(col => {
|
|
const property = databaseBlockModels[col.type];
|
|
const cell = cells[v.id]?.[col.id];
|
|
if (col.type === 'title') {
|
|
return;
|
|
}
|
|
if (!cell || !property) {
|
|
row.cells.push({
|
|
value: '',
|
|
});
|
|
return;
|
|
}
|
|
let value: string | { delta: DeltaInsert[] };
|
|
try {
|
|
if (isDelta(cell.value)) {
|
|
value = cell.value;
|
|
} else {
|
|
value = property.config.rawValue.toString({
|
|
value: cell.value,
|
|
data: col.data,
|
|
});
|
|
}
|
|
} catch {
|
|
value = '';
|
|
}
|
|
row.cells.push({
|
|
value,
|
|
});
|
|
});
|
|
table.rows.push(row);
|
|
});
|
|
|
|
return table;
|
|
};
|