From a39209058bba5aa7a5da356842677c58408fa983 Mon Sep 17 00:00:00 2001 From: Arjun Gadhia Date: Fri, 5 Sep 2025 16:44:57 +0100 Subject: [PATCH] feat: support TableHeader and make sortType optional Some old content has been published with a Table Header, so make that an optional child type for tables. --- SPEC.md | 14 ++- content-tree.d.ts | 36 ++++++-- schemas/body-tree.schema.json | 145 +++++++++++++++++++------------ schemas/content-tree.schema.json | 145 +++++++++++++++++++------------ schemas/transit-tree.schema.json | 145 +++++++++++++++++++------------ 5 files changed, 310 insertions(+), 175 deletions(-) diff --git a/SPEC.md b/SPEC.md index b9aef8d..89b09f1 100644 --- a/SPEC.md +++ b/SPEC.md @@ -782,7 +782,7 @@ interface LayoutImage extends Node { type TableColumnSettings = { hideOnMobile: boolean sortable: boolean - sortType: 'text' | 'number' | 'date' | 'currency' | 'percent' + sortType?: 'text' | 'number' | 'date' | 'currency' | 'percent' } type TableLayoutWidth = Extract +type TableChildren = + | [TableCaption, TableBody, TableFooter?] + | [TableBody, TableFooter?] + | [TableCaption, TableHeader, TableBody, TableFooter?] + | [TableHeader, TableBody, TableFooter?] interface TableCaption extends Parent { type: 'table-caption' @@ -806,6 +811,11 @@ interface TableCell extends Parent { children: Phrasing[] } +interface TableHeader extends Parent { + type: 'table-header' + children: TableRow[] +} + interface TableRow extends Parent { type: 'table-row' children: TableCell[] @@ -828,8 +838,8 @@ interface Table extends Parent { layoutWidth: TableLayoutWidth collapseAfterHowManyRows?: number responsiveStyle: 'overflow' | 'flat' | 'scroll' - children: [TableCaption, TableBody, TableFooter] | [TableCaption, TableBody] | [TableBody, TableFooter] | [TableBody] columnSettings: TableColumnSettings[] + children: TableChildren } ``` diff --git a/content-tree.d.ts b/content-tree.d.ts index 3834d4e..29c19ac 100644 --- a/content-tree.d.ts +++ b/content-tree.d.ts @@ -297,9 +297,10 @@ export declare namespace ContentTree { type TableColumnSettings = { hideOnMobile: boolean; sortable: boolean; - sortType: 'text' | 'number' | 'date' | 'currency' | 'percent'; + sortType?: 'text' | 'number' | 'date' | 'currency' | 'percent'; }; type TableLayoutWidth = Extract; + type TableChildren = [TableCaption, TableBody, TableFooter?] | [TableBody, TableFooter?] | [TableCaption, TableHeader, TableBody, TableFooter?] | [TableHeader, TableBody, TableFooter?]; interface TableCaption extends Parent { type: 'table-caption'; children: Phrasing[]; @@ -311,6 +312,10 @@ export declare namespace ContentTree { rowSpan?: number; children: Phrasing[]; } + interface TableHeader extends Parent { + type: 'table-header'; + children: TableRow[]; + } interface TableRow extends Parent { type: 'table-row'; children: TableCell[]; @@ -330,8 +335,8 @@ export declare namespace ContentTree { layoutWidth: TableLayoutWidth; collapseAfterHowManyRows?: number; responsiveStyle: 'overflow' | 'flat' | 'scroll'; - children: [TableCaption, TableBody, TableFooter] | [TableCaption, TableBody] | [TableBody, TableFooter] | [TableBody]; columnSettings: TableColumnSettings[]; + children: TableChildren; } type CustomCodeComponentAttributes = { [key: string]: string | boolean | undefined; @@ -725,9 +730,10 @@ export declare namespace ContentTree { type TableColumnSettings = { hideOnMobile: boolean; sortable: boolean; - sortType: 'text' | 'number' | 'date' | 'currency' | 'percent'; + sortType?: 'text' | 'number' | 'date' | 'currency' | 'percent'; }; type TableLayoutWidth = Extract; + type TableChildren = [TableCaption, TableBody, TableFooter?] | [TableBody, TableFooter?] | [TableCaption, TableHeader, TableBody, TableFooter?] | [TableHeader, TableBody, TableFooter?]; interface TableCaption extends Parent { type: 'table-caption'; children: Phrasing[]; @@ -739,6 +745,10 @@ export declare namespace ContentTree { rowSpan?: number; children: Phrasing[]; } + interface TableHeader extends Parent { + type: 'table-header'; + children: TableRow[]; + } interface TableRow extends Parent { type: 'table-row'; children: TableCell[]; @@ -758,8 +768,8 @@ export declare namespace ContentTree { layoutWidth: TableLayoutWidth; collapseAfterHowManyRows?: number; responsiveStyle: 'overflow' | 'flat' | 'scroll'; - children: [TableCaption, TableBody, TableFooter] | [TableCaption, TableBody] | [TableBody, TableFooter] | [TableBody]; columnSettings: TableColumnSettings[]; + children: TableChildren; } type CustomCodeComponentAttributes = { [key: string]: string | boolean | undefined; @@ -1135,9 +1145,10 @@ export declare namespace ContentTree { type TableColumnSettings = { hideOnMobile: boolean; sortable: boolean; - sortType: 'text' | 'number' | 'date' | 'currency' | 'percent'; + sortType?: 'text' | 'number' | 'date' | 'currency' | 'percent'; }; type TableLayoutWidth = Extract; + type TableChildren = [TableCaption, TableBody, TableFooter?] | [TableBody, TableFooter?] | [TableCaption, TableHeader, TableBody, TableFooter?] | [TableHeader, TableBody, TableFooter?]; interface TableCaption extends Parent { type: 'table-caption'; children: Phrasing[]; @@ -1149,6 +1160,10 @@ export declare namespace ContentTree { rowSpan?: number; children: Phrasing[]; } + interface TableHeader extends Parent { + type: 'table-header'; + children: TableRow[]; + } interface TableRow extends Parent { type: 'table-row'; children: TableCell[]; @@ -1168,8 +1183,8 @@ export declare namespace ContentTree { layoutWidth: TableLayoutWidth; collapseAfterHowManyRows?: number; responsiveStyle: 'overflow' | 'flat' | 'scroll'; - children: [TableCaption, TableBody, TableFooter] | [TableCaption, TableBody] | [TableBody, TableFooter] | [TableBody]; columnSettings: TableColumnSettings[]; + children: TableChildren; } type CustomCodeComponentAttributes = { [key: string]: string | boolean | undefined; @@ -1556,9 +1571,10 @@ export declare namespace ContentTree { type TableColumnSettings = { hideOnMobile: boolean; sortable: boolean; - sortType: 'text' | 'number' | 'date' | 'currency' | 'percent'; + sortType?: 'text' | 'number' | 'date' | 'currency' | 'percent'; }; type TableLayoutWidth = Extract; + type TableChildren = [TableCaption, TableBody, TableFooter?] | [TableBody, TableFooter?] | [TableCaption, TableHeader, TableBody, TableFooter?] | [TableHeader, TableBody, TableFooter?]; interface TableCaption extends Parent { type: 'table-caption'; children: Phrasing[]; @@ -1570,6 +1586,10 @@ export declare namespace ContentTree { rowSpan?: number; children: Phrasing[]; } + interface TableHeader extends Parent { + type: 'table-header'; + children: TableRow[]; + } interface TableRow extends Parent { type: 'table-row'; children: TableCell[]; @@ -1589,8 +1609,8 @@ export declare namespace ContentTree { layoutWidth: TableLayoutWidth; collapseAfterHowManyRows?: number; responsiveStyle: 'overflow' | 'flat' | 'scroll'; - children: [TableCaption, TableBody, TableFooter] | [TableCaption, TableBody] | [TableBody, TableFooter] | [TableBody]; columnSettings: TableColumnSettings[]; + children: TableChildren; } type CustomCodeComponentAttributes = { [key: string]: string | boolean | undefined; diff --git a/schemas/body-tree.schema.json b/schemas/body-tree.schema.json index ad26b36..c12fd11 100644 --- a/schemas/body-tree.schema.json +++ b/schemas/body-tree.schema.json @@ -1182,60 +1182,7 @@ "additionalProperties": false, "properties": { "children": { - "anyOf": [ - { - "items": [ - { - "$ref": "#/definitions/ContentTree.transit.TableCaption" - }, - { - "$ref": "#/definitions/ContentTree.transit.TableBody" - }, - { - "$ref": "#/definitions/ContentTree.transit.TableFooter" - } - ], - "maxItems": 3, - "minItems": 3, - "type": "array" - }, - { - "items": [ - { - "$ref": "#/definitions/ContentTree.transit.TableCaption" - }, - { - "$ref": "#/definitions/ContentTree.transit.TableBody" - } - ], - "maxItems": 2, - "minItems": 2, - "type": "array" - }, - { - "items": [ - { - "$ref": "#/definitions/ContentTree.transit.TableBody" - }, - { - "$ref": "#/definitions/ContentTree.transit.TableFooter" - } - ], - "maxItems": 2, - "minItems": 2, - "type": "array" - }, - { - "items": [ - { - "$ref": "#/definitions/ContentTree.transit.TableBody" - } - ], - "maxItems": 1, - "minItems": 1, - "type": "array" - } - ] + "$ref": "#/definitions/ContentTree.transit.TableChildren" }, "collapseAfterHowManyRows": { "type": "number" @@ -1263,7 +1210,6 @@ }, "required": [ "hideOnMobile", - "sortType", "sortable" ], "type": "object" @@ -1376,6 +1322,74 @@ ], "type": "object" }, + "ContentTree.transit.TableChildren": { + "anyOf": [ + { + "items": [ + { + "$ref": "#/definitions/ContentTree.transit.TableCaption" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableFooter" + } + ], + "maxItems": 3, + "minItems": 2, + "type": "array" + }, + { + "items": [ + { + "$ref": "#/definitions/ContentTree.transit.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableFooter" + } + ], + "maxItems": 2, + "minItems": 1, + "type": "array" + }, + { + "items": [ + { + "$ref": "#/definitions/ContentTree.transit.TableCaption" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableHeader" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableFooter" + } + ], + "maxItems": 4, + "minItems": 3, + "type": "array" + }, + { + "items": [ + { + "$ref": "#/definitions/ContentTree.transit.TableHeader" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableFooter" + } + ], + "maxItems": 3, + "minItems": 2, + "type": "array" + } + ] + }, "ContentTree.transit.TableFooter": { "additionalProperties": false, "properties": { @@ -1397,6 +1411,27 @@ ], "type": "object" }, + "ContentTree.transit.TableHeader": { + "additionalProperties": false, + "properties": { + "children": { + "items": { + "$ref": "#/definitions/ContentTree.transit.TableRow" + }, + "type": "array" + }, + "data": {}, + "type": { + "const": "table-header", + "type": "string" + } + }, + "required": [ + "children", + "type" + ], + "type": "object" + }, "ContentTree.transit.TableLayoutWidth": { "enum": [ "auto", diff --git a/schemas/content-tree.schema.json b/schemas/content-tree.schema.json index 2e69b18..2aa85de 100644 --- a/schemas/content-tree.schema.json +++ b/schemas/content-tree.schema.json @@ -2002,60 +2002,7 @@ "additionalProperties": false, "properties": { "children": { - "anyOf": [ - { - "items": [ - { - "$ref": "#/definitions/ContentTree.full.TableCaption" - }, - { - "$ref": "#/definitions/ContentTree.full.TableBody" - }, - { - "$ref": "#/definitions/ContentTree.full.TableFooter" - } - ], - "maxItems": 3, - "minItems": 3, - "type": "array" - }, - { - "items": [ - { - "$ref": "#/definitions/ContentTree.full.TableCaption" - }, - { - "$ref": "#/definitions/ContentTree.full.TableBody" - } - ], - "maxItems": 2, - "minItems": 2, - "type": "array" - }, - { - "items": [ - { - "$ref": "#/definitions/ContentTree.full.TableBody" - }, - { - "$ref": "#/definitions/ContentTree.full.TableFooter" - } - ], - "maxItems": 2, - "minItems": 2, - "type": "array" - }, - { - "items": [ - { - "$ref": "#/definitions/ContentTree.full.TableBody" - } - ], - "maxItems": 1, - "minItems": 1, - "type": "array" - } - ] + "$ref": "#/definitions/ContentTree.full.TableChildren" }, "collapseAfterHowManyRows": { "type": "number" @@ -2083,7 +2030,6 @@ }, "required": [ "hideOnMobile", - "sortType", "sortable" ], "type": "object" @@ -2196,6 +2142,74 @@ ], "type": "object" }, + "ContentTree.full.TableChildren": { + "anyOf": [ + { + "items": [ + { + "$ref": "#/definitions/ContentTree.full.TableCaption" + }, + { + "$ref": "#/definitions/ContentTree.full.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.full.TableFooter" + } + ], + "maxItems": 3, + "minItems": 2, + "type": "array" + }, + { + "items": [ + { + "$ref": "#/definitions/ContentTree.full.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.full.TableFooter" + } + ], + "maxItems": 2, + "minItems": 1, + "type": "array" + }, + { + "items": [ + { + "$ref": "#/definitions/ContentTree.full.TableCaption" + }, + { + "$ref": "#/definitions/ContentTree.full.TableHeader" + }, + { + "$ref": "#/definitions/ContentTree.full.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.full.TableFooter" + } + ], + "maxItems": 4, + "minItems": 3, + "type": "array" + }, + { + "items": [ + { + "$ref": "#/definitions/ContentTree.full.TableHeader" + }, + { + "$ref": "#/definitions/ContentTree.full.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.full.TableFooter" + } + ], + "maxItems": 3, + "minItems": 2, + "type": "array" + } + ] + }, "ContentTree.full.TableFooter": { "additionalProperties": false, "properties": { @@ -2217,6 +2231,27 @@ ], "type": "object" }, + "ContentTree.full.TableHeader": { + "additionalProperties": false, + "properties": { + "children": { + "items": { + "$ref": "#/definitions/ContentTree.full.TableRow" + }, + "type": "array" + }, + "data": {}, + "type": { + "const": "table-header", + "type": "string" + } + }, + "required": [ + "children", + "type" + ], + "type": "object" + }, "ContentTree.full.TableLayoutWidth": { "enum": [ "auto", diff --git a/schemas/transit-tree.schema.json b/schemas/transit-tree.schema.json index ba02551..ef0856c 100644 --- a/schemas/transit-tree.schema.json +++ b/schemas/transit-tree.schema.json @@ -1207,60 +1207,7 @@ "additionalProperties": false, "properties": { "children": { - "anyOf": [ - { - "items": [ - { - "$ref": "#/definitions/ContentTree.transit.TableCaption" - }, - { - "$ref": "#/definitions/ContentTree.transit.TableBody" - }, - { - "$ref": "#/definitions/ContentTree.transit.TableFooter" - } - ], - "maxItems": 3, - "minItems": 3, - "type": "array" - }, - { - "items": [ - { - "$ref": "#/definitions/ContentTree.transit.TableCaption" - }, - { - "$ref": "#/definitions/ContentTree.transit.TableBody" - } - ], - "maxItems": 2, - "minItems": 2, - "type": "array" - }, - { - "items": [ - { - "$ref": "#/definitions/ContentTree.transit.TableBody" - }, - { - "$ref": "#/definitions/ContentTree.transit.TableFooter" - } - ], - "maxItems": 2, - "minItems": 2, - "type": "array" - }, - { - "items": [ - { - "$ref": "#/definitions/ContentTree.transit.TableBody" - } - ], - "maxItems": 1, - "minItems": 1, - "type": "array" - } - ] + "$ref": "#/definitions/ContentTree.transit.TableChildren" }, "collapseAfterHowManyRows": { "type": "number" @@ -1288,7 +1235,6 @@ }, "required": [ "hideOnMobile", - "sortType", "sortable" ], "type": "object" @@ -1401,6 +1347,74 @@ ], "type": "object" }, + "ContentTree.transit.TableChildren": { + "anyOf": [ + { + "items": [ + { + "$ref": "#/definitions/ContentTree.transit.TableCaption" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableFooter" + } + ], + "maxItems": 3, + "minItems": 2, + "type": "array" + }, + { + "items": [ + { + "$ref": "#/definitions/ContentTree.transit.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableFooter" + } + ], + "maxItems": 2, + "minItems": 1, + "type": "array" + }, + { + "items": [ + { + "$ref": "#/definitions/ContentTree.transit.TableCaption" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableHeader" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableFooter" + } + ], + "maxItems": 4, + "minItems": 3, + "type": "array" + }, + { + "items": [ + { + "$ref": "#/definitions/ContentTree.transit.TableHeader" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableBody" + }, + { + "$ref": "#/definitions/ContentTree.transit.TableFooter" + } + ], + "maxItems": 3, + "minItems": 2, + "type": "array" + } + ] + }, "ContentTree.transit.TableFooter": { "additionalProperties": false, "properties": { @@ -1422,6 +1436,27 @@ ], "type": "object" }, + "ContentTree.transit.TableHeader": { + "additionalProperties": false, + "properties": { + "children": { + "items": { + "$ref": "#/definitions/ContentTree.transit.TableRow" + }, + "type": "array" + }, + "data": {}, + "type": { + "const": "table-header", + "type": "string" + } + }, + "required": [ + "children", + "type" + ], + "type": "object" + }, "ContentTree.transit.TableLayoutWidth": { "enum": [ "auto",