import { GroupContent, isGroupContent, isLinkContent, isNestableContent, isRepeatableContent, NestableContent, RepeatableContent, } from "@prismicio/types-internal/lib/content" import type { Group as GroupField, Link, NestableWidget } from "@prismicio/types-internal/lib/customtypes" import type { RenderContext } from "../models" import { Field, Group, GroupOrField, GroupType, Simple } from "../models/fetch" import { withObjectRenderers } from "../object" import GroupRenderer from "./GroupRenderer" import RepeatableRenderer from "./RepeatableRenderer" import SimpleWidgetRenderer from "./SimpleWidgetRenderer" function extractFetchGroupIfAny(fetch: GroupOrField | undefined): Group | undefined { if (fetch !== undefined && fetch.TYPE === GroupType) { return fetch } else { return undefined } } function extractFetchFieldIfAny(fetch: GroupOrField | undefined): Field | undefined { if (fetch !== undefined && fetch.TYPE !== GroupType) { return fetch } else { return undefined } } function extractSimpleFieldIfAny(field: Field | undefined): Simple | undefined { if (field !== undefined && (field.TYPE === "SimpleField" || field.TYPE === "DocRelation")) { return field } else { return undefined } } function renderContent( def: NestableWidget | GroupField, content: NestableContent | GroupContent, fetch: GroupOrField | Simple | undefined, renderer: { group: (def: GroupField, content: GroupContent, fetch?: Group) => unknown repeatable: (def: Link, content: RepeatableContent, fetch?: Simple) => unknown simple: (def: NestableWidget, content: NestableContent, fetch?: Field) => unknown default: (def: NestableWidget | GroupField) => unknown }, ) { // When def is a Link, there is a special management with the fact it can be repeated or not. // The custom type is always the one deciding the return type of the content. // If repeat is true, it will always return an array, and if repeat is false, it will always return an object. if (def.type === "Link") { // When repeat is true and existing content is repeatable, render the content as is if (def.config?.repeat && isRepeatableContent(content)) { return renderer.repeatable(def, content, extractSimpleFieldIfAny(fetch)) } // When repeat is true and existing content is not repeatable, render as repeatable if (def.config?.repeat && isLinkContent(content)) { return renderer.repeatable( def, { __TYPE__: "RepeatableContent", type: def.type, value: [content], }, extractSimpleFieldIfAny(fetch), ) } // When repeat is false and existing content is repeatable with data, render the first item if (!def.config?.repeat && isRepeatableContent(content) && content.value[0]) { return renderer.simple(def, content.value[0], extractFetchFieldIfAny(fetch)) } // When repeat is false and existing content is repeatable but empty, render the default widget if (!def.config?.repeat && isRepeatableContent(content)) { return renderer.default(def) } // When repeat is false and existing content is not repeatable, render the content as is, // using the normal nestable content renderer condition bellow } if (def.type !== "Group" && isNestableContent(content)) { return renderer.simple(def, content, extractFetchFieldIfAny(fetch)) } if (def.type === "Group" && isGroupContent(content)) { return renderer.group(def, content, extractFetchGroupIfAny(fetch)) } return renderer.default(def) } const StaticWidgetRenderer = (ctx: RenderContext) => withObjectRenderers({ renderV1(content, fetch) { if (isGroupContent(content)) { return GroupRenderer(ctx).renderV1(content, extractFetchGroupIfAny(fetch)) } else if (isRepeatableContent(content)) { return RepeatableRenderer(ctx).renderV1(content, extractSimpleFieldIfAny(fetch)) } else { return SimpleWidgetRenderer(ctx).renderV1(content, extractFetchFieldIfAny(fetch)) } }, renderV2(def, content, fetch) { return renderContent(def, content, fetch, { group: (def: GroupField, content: GroupContent, fetch?: Group) => GroupRenderer(ctx).renderV2(def, content, fetch), repeatable: (def: Link, content: RepeatableContent, fetch?: Simple) => RepeatableRenderer(ctx).renderV2(def, content, fetch), simple: (def: NestableWidget, content: NestableContent, fetch?: Field) => SimpleWidgetRenderer(ctx).renderV2(def, content, fetch), default: (def: NestableWidget | GroupField) => this.renderDefault(def), }) }, renderDefault(def) { if (def.type === "Link" && def.config?.repeat) { return RepeatableRenderer(ctx).renderDefault(def) } else if (def.type === "Group") { return GroupRenderer(ctx).renderDefault(def) } else { return SimpleWidgetRenderer(ctx).renderDefault(def) } }, renderMocks(def, content) { return renderContent(def, content, undefined, { group: (def: GroupField, content: GroupContent) => GroupRenderer(ctx).renderMocks(def, content), repeatable: (def: Link, content: RepeatableContent) => RepeatableRenderer(ctx).renderMocks(def, content), simple: (def: NestableWidget, content: NestableContent) => SimpleWidgetRenderer(ctx).renderMocks(def, content), default: (def: NestableWidget | GroupField) => this.renderDefault(def), }) }, }) export default StaticWidgetRenderer