import type { SliceItemContent, SlicesContent } from "@prismicio/types-internal/lib/content" import { EmptyContentType } from "@prismicio/types-internal/lib/content" import type { StaticSlice, StaticSlices } from "@prismicio/types-internal/lib/customtypes" import { pipe } from "fp-ts/function" import { compact } from "fp-ts/lib/Array" import * as O from "fp-ts/Option" import { v4 as uuid } from "uuid" import type { RenderContext } from "../../models" import type { Renderer } from "../../models" import type { GroupOrField, Slice, SliceZone } from "../../models/fetch" import { renderIfNoFetchOrFetchDefined } from "../../utils" import SliceWidgetRenderer from "./SliceWidgetRenderer" function sliceId(sliceKey: string, sliceName: string): string { const IdRegexp = new RegExp(`^(${sliceName})\\$\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12}$`) if (sliceKey.match(IdRegexp)) return sliceKey return `${sliceName}$${uuid()}` } function renderItemAndFilterOutEmptyOne( slicesContent: SlicesContent, sliceFetch: SliceZone | undefined, ctx: RenderContext, ): [SliceItemContent, object][] { const fetchRecord = sliceFetch?.slices return compact( slicesContent.value.map((item) => { return pipe( renderIfNoFetchOrFetchDefined( fetchRecord, item.key, (f) => SliceWidgetRenderer(ctx).renderV1(item.widget, f) as O.Option, ), //TODO: add fetch O.map((renderedItem) => [item, renderedItem] as [SliceItemContent, object]), ) }), ) } function renderContent( slice: SliceItemContent, sliceFetch: GroupOrField | Slice | undefined, ctx: RenderContext, slicesDefs: Record, ): O.Option { if ("__TYPE__" in slice.widget && slice.widget.__TYPE__ === EmptyContentType) { return O.none } else if (!(slice.name in slicesDefs)) { return O.none } else { const def = slicesDefs[slice.name] if (!def) return O.none return pipe( SliceWidgetRenderer(ctx).renderV2(def, slice.widget, sliceFetch) as O.Option, O.map((render) => ({ //TODO: clean type here, must case because of unknown coming from the renderer ...(render as object), id: sliceId(slice.key, slice.name), slice_type: slice.name, slice_label: slice.maybeLabel ?? null, })), ) } } const SlicesRenderer: (ctx: RenderContext) => Renderer = (ctx) => ({ renderV1(content: SlicesContent, fetch: SliceZone | undefined): unknown { return { type: "SliceZone", value: renderItemAndFilterOutEmptyOne(content, fetch, ctx).map(([item, renderedItem]) => { return { ...renderedItem, id: sliceId(item.key, item.name), slice_type: item.name, slice_label: item.maybeLabel ?? null, type: "Slice", } }), } }, renderV2(def: StaticSlices, content: SlicesContent, fetch: SliceZone | undefined): unknown { const keyToSliceDef = Object.fromEntries( Object.entries(def.config?.choices || {}).map(([name, slice]) => [name, slice]), ) const fetchRecord = fetch?.slices return compact( content.value.map((contentValue) => { return renderIfNoFetchOrFetchDefined(fetchRecord, contentValue.name, (f) => renderContent(contentValue, f, ctx, keyToSliceDef), ) }), ) }, renderDefault(_def: StaticSlices): unknown { return [] }, renderMocks(def: StaticSlices, content: SlicesContent): unknown { return this.renderV2(def, content) }, }) export default SlicesRenderer