174 lines
5.0 KiB
TypeScript
174 lines
5.0 KiB
TypeScript
import {
|
|
BreakBlockType,
|
|
Collections,
|
|
PageType,
|
|
RichTextBreakBlock,
|
|
RichTextContent,
|
|
RichTextSectionBlock,
|
|
isBlockNodeBreakBlock,
|
|
isBlockNodeSectionBlock,
|
|
isNodeBlockNode,
|
|
} from "../../../constants";
|
|
import { createGetByEndpoint } from "../../../endpoints/createGetByEndpoint";
|
|
import { EndpointPage, EndpointPagePreview, TableOfContentEntry } from "../../../sdk";
|
|
import { Page } from "../../../types/collections";
|
|
import {
|
|
isNotEmpty,
|
|
isPayloadArrayType,
|
|
isPayloadType,
|
|
isValidPayloadImage,
|
|
} from "../../../utils/asserts";
|
|
import { convertTagsToGroups, handleParentPages, handleRecorder } from "../../../utils/endpoints";
|
|
|
|
export const getBySlugEndpoint = createGetByEndpoint({
|
|
collection: Collections.Pages,
|
|
attribute: "slug",
|
|
handler: (page: Page): EndpointPage => {
|
|
const { translations, collectibles, folders, backgroundImage } = page;
|
|
|
|
return {
|
|
...convertPageToPreview(page),
|
|
...(isValidPayloadImage(backgroundImage) ? { backgroundImage } : {}),
|
|
translations: translations.map(
|
|
({
|
|
content,
|
|
language,
|
|
sourceLanguage,
|
|
title,
|
|
pretitle,
|
|
subtitle,
|
|
proofreaders,
|
|
summary,
|
|
transcribers,
|
|
translators,
|
|
}) => ({
|
|
language: isPayloadType(language) ? language.id : language,
|
|
sourceLanguage: isPayloadType(sourceLanguage) ? sourceLanguage.id : sourceLanguage,
|
|
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
|
title,
|
|
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
|
...(isNotEmpty(summary) ? { summary } : {}),
|
|
content: handleContent(content),
|
|
toc: handleToc(content),
|
|
translators: isPayloadArrayType(translators) ? translators.map(handleRecorder) : [],
|
|
transcribers: isPayloadArrayType(transcribers) ? transcribers.map(handleRecorder) : [],
|
|
proofreaders: isPayloadArrayType(proofreaders) ? proofreaders.map(handleRecorder) : [],
|
|
})
|
|
),
|
|
parentPages: handleParentPages({ collectibles, folders }),
|
|
};
|
|
},
|
|
});
|
|
|
|
const handleContent = (
|
|
{ root: { children, ...others } }: RichTextContent,
|
|
parentPrefix = ""
|
|
): RichTextContent => {
|
|
let index = 0;
|
|
return {
|
|
root: {
|
|
...others,
|
|
children: children.map((node) => {
|
|
if (isNodeBlockNode(node)) {
|
|
if (isBlockNodeSectionBlock(node)) {
|
|
index++;
|
|
const anchorHash = `${parentPrefix}${index}.`;
|
|
const newNode: RichTextSectionBlock = {
|
|
...node,
|
|
fields: {
|
|
...node.fields,
|
|
content: handleContent(node.fields.content, anchorHash),
|
|
},
|
|
anchorHash,
|
|
};
|
|
return newNode;
|
|
} else if (isBlockNodeBreakBlock(node)) {
|
|
index++;
|
|
const anchorHash = `${parentPrefix}${index}.`;
|
|
const newNode: RichTextBreakBlock = {
|
|
...node,
|
|
anchorHash,
|
|
};
|
|
return newNode;
|
|
}
|
|
}
|
|
return node;
|
|
}),
|
|
},
|
|
};
|
|
};
|
|
|
|
const handleToc = (content: RichTextContent, parentPrefix = ""): TableOfContentEntry[] => {
|
|
let index = 0;
|
|
|
|
return content.root.children.filter(isNodeBlockNode).flatMap<TableOfContentEntry>((node) => {
|
|
if (isBlockNodeSectionBlock(node)) {
|
|
index++;
|
|
return [
|
|
{
|
|
index,
|
|
prefix: `${parentPrefix}${index}.`,
|
|
title: node.fields.blockName ?? "",
|
|
type: "section",
|
|
children: handleToc(node.fields.content, `${index}.`),
|
|
},
|
|
];
|
|
} else if (isBlockNodeBreakBlock(node)) {
|
|
switch (node.fields.type) {
|
|
case BreakBlockType.dottedLine:
|
|
case BreakBlockType.solidLine: {
|
|
index++;
|
|
return [
|
|
{
|
|
index,
|
|
prefix: `${parentPrefix}${index}.`,
|
|
title: node.fields.blockName ?? "",
|
|
type: "break",
|
|
children: [],
|
|
},
|
|
];
|
|
}
|
|
|
|
case BreakBlockType.sceneBreak: {
|
|
index++;
|
|
return [
|
|
{
|
|
index,
|
|
prefix: `${parentPrefix}${index}.`,
|
|
title: node.fields.blockName ?? "",
|
|
type: "sceneBreak",
|
|
children: [],
|
|
},
|
|
];
|
|
}
|
|
|
|
case BreakBlockType.space:
|
|
default:
|
|
return [];
|
|
}
|
|
}
|
|
return [];
|
|
});
|
|
};
|
|
|
|
export const convertPageToPreview = ({
|
|
authors,
|
|
slug,
|
|
translations,
|
|
tags,
|
|
thumbnail,
|
|
type,
|
|
}: Page): EndpointPagePreview => ({
|
|
slug,
|
|
type: type as PageType,
|
|
...(isValidPayloadImage(thumbnail) ? { thumbnail } : {}),
|
|
tagGroups: convertTagsToGroups(tags),
|
|
translations: translations.map(({ language, title, pretitle, subtitle }) => ({
|
|
language: isPayloadType(language) ? language.id : language,
|
|
...(isNotEmpty(pretitle) ? { pretitle } : {}),
|
|
title,
|
|
...(isNotEmpty(subtitle) ? { subtitle } : {}),
|
|
})),
|
|
authors: isPayloadArrayType(authors) ? authors.map(handleRecorder) : [],
|
|
});
|