@prismicio/types-internal
Version:
Prismic types for Custom Types and Prismic Data
176 lines (159 loc) • 3.69 kB
text/typescript
import { either } from "fp-ts"
import { pipe } from "fp-ts/lib/function"
import * as t from "io-ts"
import {
type NestableWidget,
TableCell as TableCellModel,
} from "../../../customtypes"
import type { LegacyContentCtx, WithTypes } from "../../LegacyContentCtx"
import {
ContentPath,
hasContentType,
TraverseWidgetContentFn,
withKey,
} from "../../utils"
import { RichTextContent, RichTextLegacyContent } from "./RichTextContent"
export const TableContentType = "TableContent"
export const isTableContent = (u: unknown): u is TableContent =>
hasContentType(u) && u.__TYPE__ === TableContentType
const TableCell = withKey(
t.intersection([
t.strict({
type: t.union([t.literal("tableHeader"), t.literal("tableCell")]),
content: RichTextContent,
}),
t.exact(
t.partial({
columnWidth: t.number,
}),
),
]),
)
const TableRow = withKey(
t.strict({
type: t.literal("tableRow"),
content: t.array(TableCell),
}),
)
export const TableContent = t.strict({
__TYPE__: t.literal(TableContentType),
content: t.array(TableRow),
})
export type TableContent = t.TypeOf<typeof TableContent>
// Legacy.
const TableCellLegacy = withKey(
t.intersection([
t.strict({
type: t.union([t.literal("tableHeader"), t.literal("tableCell")]),
content: RichTextLegacyContent,
}),
t.exact(
t.partial({
columnWidth: t.number,
}),
),
]),
)
const TableRowLegacy = withKey(
t.strict({
type: t.literal("tableRow"),
content: t.array(TableCellLegacy),
}),
)
const TableLegacyContent = t.strict({
content: t.array(TableRowLegacy),
})
type TableLegacyContent = t.TypeOf<typeof TableLegacyContent>
export const TableLegacy = (ctx: LegacyContentCtx) =>
new t.Type<TableContent, WithTypes<TableLegacyContent>>(
"TableLegacy",
isTableContent,
(u) => {
return pipe(
TableLegacyContent.decode(u),
either.map((content) => ({
__TYPE__: "TableContent",
content: content.content.map((row) => ({
...row,
content: row.content.map((cell) => ({
...cell,
content: {
__TYPE__: "StructuredTextContent",
value: cell.content,
},
})),
})),
})),
)
},
(t: TableContent) => {
return {
content: TableLegacyContent.encode({
content: t.content.map((row) => ({
...row,
content: row.content.map((cell) => ({
...cell,
content: cell.content.value,
})),
})),
}),
types: { [ctx.keyOfType]: "Table" },
keys: {},
}
},
)
// Traverse.
export function traverseTableContent({
path,
key,
apiId,
model,
content,
}: {
path: ContentPath
key: string
apiId: string
content: TableContent
model?: NestableWidget | undefined
}) {
return (transform: TraverseWidgetContentFn): TableContent | undefined => {
const tableContent = content.content.map((row, rowIndex) => ({
...row,
content: row.content.map((cell, cellIndex) => {
const itemPath = path.concat([
{
key: [rowIndex.toString(), cellIndex.toString()].join(","),
type: "Widget",
},
])
const cellContent = transform({
path: itemPath,
key,
apiId,
model: TableCellModel, // Table cell content config is fixed.
content: {
__TYPE__: cell.content.__TYPE__,
value: cell.content.value,
},
}) || {
__TYPE__: "StructuredTextContent",
value: [],
} // Return an empty table cell if the transform function filters out rich text (returns undefined)
return {
...cell,
content: cellContent,
}
}),
}))
return transform({
path,
key,
apiId,
model,
content: {
__TYPE__: content.__TYPE__,
content: tableContent,
},
})
}
}