@paroicms/site-generator-plugin
Version:
ParoiCMS Site Generator Plugin
147 lines (146 loc) • 5.19 kB
JavaScript
import { isDef, } from "@paroicms/public-anywhere-lib";
import { camelToKebabCase, camelToTitleCase } from "../lib/utils.js";
import { createNodeContents } from "./create-node-contents.js";
import { invokeGenerateFakeContent, } from "./invoke-generate-fake-content.js";
export async function generateFieldSetContent(ctx, options, report) {
const list = await generateMultipleFieldSetContents(ctx, {
...options,
count: 1,
}, report);
if (list.length !== 1)
throw new Error(`Expected one item, got ${list.length}`);
return list[0];
}
export async function generateMultipleFieldSetContents(ctx, options, report) {
const { siteSchema, nodeType, documentType, schemaI18n, count, withTitle, tolerateErrors, llmTaskName, } = options;
if (nodeType.kind === "site")
throw new Error("Cannot generate content for site node type");
// for a document, the LLM is best at generating the title, so we ask for it and remove it later
const skipTitle = nodeType.kind === "document" && !withTitle;
const outputTags = withTitle || skipTitle
? [{ tagName: "title", key: "title", format: "text", tagDescription: "Write the title here" }]
: [];
if (nodeType.fields) {
outputTags.push(...nodeType.fields.map(toFakeContentOutputTag).filter(isDef));
}
const defaultLanguage = siteSchema.languages?.[0];
const typeLabel = translateText(schemaI18n, `nodeTypes.${nodeType.typeName}.label`, {
defaultValue: camelToTitleCase(nodeType.typeName),
defaultLanguage,
});
const typeDescription = translateText(schemaI18n, `nodeTypes.${nodeType.typeName}.description`, {
defaultValue: "",
defaultLanguage,
});
const documentDescription = translateText(schemaI18n, `nodeTypes.${documentType.typeName}.description`, {
defaultValue: "",
defaultLanguage,
});
const siteTheme = translateText(schemaI18n, "siteTheme", {
defaultValue: "",
defaultLanguage,
});
const language = defaultLanguage ?? "en";
let output = outputTags.length > 0
? await invokeGenerateFakeContent(ctx, {
count,
typeKind: nodeType.kind,
typeLabel,
typeDescription,
documentDescription,
siteTheme,
language,
}, outputTags, { tolerateErrors, llmTaskName })
: undefined;
if (skipTitle && output) {
output = {
contents: output.contents.map((content) => {
const { title, ...rest } = content;
return rest;
}),
llmReport: output.llmReport,
};
}
report.add(count, output?.llmReport);
return createNodeContents({
nodeType,
count,
generatedContents: output?.contents,
outputTags,
language,
});
}
function translateText(schemaI18n, key, options) {
const defaultValue = options.defaultValue ?? key;
const val = schemaI18n.translate({
key,
language: "en",
defaultValue,
});
if (val !== defaultValue || !options.defaultLanguage)
return val;
return schemaI18n.translate({
key,
language: options.defaultLanguage,
defaultValue,
});
}
function toFakeContentOutputTag(fieldNameOrType) {
const key = typeof fieldNameOrType === "string" ? fieldNameOrType : fieldNameOrType.name;
if (key === "leadParagraph") {
return {
tagName: `${camelToKebabCase(key)}-md`,
key,
format: "markdown",
tagDescription: "Write one lead paragraph here (15-30 words) in markdown format",
};
}
if (key === "htmlContent") {
return {
tagName: `${camelToKebabCase(key)}-md`,
key,
format: "markdown",
tagDescription: "Write document content here (150-200 words) in markdown format. It MUST NOT include the title.",
};
}
if (key === "introduction") {
return {
tagName: `${camelToKebabCase(key)}-md`,
key,
format: "markdown",
tagDescription: "Write a short introduction here (15-30 words) in markdown format",
};
}
if (key === "footerMention") {
return {
tagName: `${camelToKebabCase(key)}-md`,
key,
format: "markdown",
tagDescription: "Write a very short footer mention here in markdown format",
};
}
if (key === "slogan") {
return {
tagName: camelToKebabCase(key),
key,
format: "text",
tagDescription: "Write a slogan here in plain text",
};
}
if (key === "title") {
return {
tagName: camelToKebabCase(key),
key,
format: "text",
tagDescription: "Write a title here in plain text",
};
}
if (key === "buttonLabel") {
return {
tagName: camelToKebabCase(key),
key,
format: "text",
tagDescription: "Rewrite the title as a short button label (1 or 2 words) here",
};
}
}