Skip to content

Table updates RFC #1425

@nperez0111

Description

@nperez0111

Is your feature request related to a problem? Please describe.

Tables are missing a number of features, but to implement them, we must modify the block schema for tables to allow for additional complexity to support features like:

  • merging / splitting cells
  • cell background color
  • cell alignment?
  • table headers

Describe the solution you'd like

Given that a table's contents is just a multi-dimensional array of InlineContent, there is not a good place to capture things like colspan, rowspan and background-color per cell.

So, the proposal is to change TableContents representation from this:

export type TableContent<
  I extends InlineContentSchema,
  S extends StyleSchema = StyleSchema
> = {
  type: "tableContent";
  columnWidths: (number | undefined)[];
  rows: {
    cells: InlineContent<I, S>[][];
  }[];
};

into this:

export type TableItemProps = {
  colspan?: number;
  rowspan?: number;
  backgroundColor?: string;
  alignment?: "left" | "right" | "center" | "justify";
};

export type TableHeader<
  I extends InlineContentSchema,
  S extends StyleSchema = StyleSchema
> = {
  type: "tableHeader";
  props: TableItemProps;
  content: InlineContent<I, S>[];
};

export type TableCell<
  I extends InlineContentSchema,
  S extends StyleSchema = StyleSchema
> = {
  type: "tableCell";
  props: TableItemProps;
  content: InlineContent<I, S>[];
};

export type TableContent<
  I extends InlineContentSchema,
  S extends StyleSchema = StyleSchema
> = {
  type: "tableContent";
  columnWidths: (number | undefined)[];
  rows: {
    cells: (InlineContent<I, S>[] | (TableCell<I, S> | TableHeader<I, S>)[])[];
  }[];
};

This would be backwards-compatible by still allowing InlineContent as an input type, but the output would be as either tableCells or tableHeaders. This would follow the principle of being liberal in what you accept, but strict in what you output. This would mean that a document's output between the two versions would be different and since existing versions cannot be forwards-compatible, it would be a 1 way door to a migration of a document.

Describe alternatives you've considered

In order to store these values, they need to be stored on a cell-by-cell basis, so there is not an opportunity to do something like what was done for columnWidths that could be added separately to the schema.

Another possibility would be to store metadata adjacent to the rows in a separate multidimensional array of the same size as the rows.cells like so:

export type TableItemProps = {
  colspan?: number;
  rowspan?: number;
  backgroundColor?: string;
  alignment?: "left" | "right" | "center" | "justify";
};

export type TableContent<
  I extends InlineContentSchema,
  S extends StyleSchema = StyleSchema
> = {
  type: "tableContent";
  columnWidths: (number | undefined)[];
  rows: {
    cells: InlineContent<I, S>[][];
    cellMetadata: TableItemProps[][];
  }[];
};

This has a couple of drawbacks though, it is unclear what should happen if the array lengths are not the same. And, feels like an oversight of the data-model to be having to keep track of the cell's position across the arrays. Though, this does have the benefit of being fully-backwards compatible, as old clients will just simply ignore the additional properties.

Additional context
Add any other context or screenshots about the feature request here.

Bonus
[ ] I'm a sponsor and would appreciate if you could look into this sooner than later 💖

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions