@paroicms/site-generator-plugin
Version:
ParoiCMS Site Generator Plugin
139 lines (136 loc) • 4.87 kB
JavaScript
import { isObj } from "@paroicms/public-anywhere-lib";
import { mkdir, writeFile } from "node:fs/promises";
import { dirname, join } from "node:path";
import { camelToKebabCase } from "../lib/utils.js";
import { templateOfSiteFooter, templateOfSiteHeader } from "./common-template-creator.js";
import { templateOfDocumentType } from "./document-template-creator.js";
import { isMultilingual } from "./jt-site-schema-helpers.js";
import { createSchemaWithAuthors } from "./schema-with-authors.js";
import { createThemeCreatorContext } from "./theme-creator-context.js";
import { getThemeCssContent } from "./theme-css.js";
export async function createTheme(ctx, siteDir, siteSchema) {
const schemaWithAuthors = createSchemaWithAuthors(siteSchema);
const themeContext = createThemeCreatorContext(schemaWithAuthors);
for (const nodeType of schemaWithAuthors.nodeTypes ?? []) {
if (nodeType.kind === "site")
continue;
if (nodeType.kind === "part")
continue;
if (nodeType.documentKind === "routing" && nodeType.redirectTo)
continue;
themeContext.addLiquidFile("root", `${camelToKebabCase(nodeType.typeName)}.liquid`, templateOfDocumentType(themeContext, nodeType));
}
themeContext.addFile("theme.json", getThemeJsonContent());
themeContext.addFile(".theme-check.yml", getLiquidLinterCheckContent());
themeContext.addFile("assets/css/index.css", getThemeCssContent());
themeContext.addFile("assets/bundle.css", getThemeCssContent());
themeContext.addLiquidFile("layouts", "main-layout.liquid", templateOfLayout(themeContext));
themeContext.addLiquidFile("root", "404.liquid", templateOf404(themeContext));
if (isMultilingual(siteSchema)) {
themeContext.addLiquidFile("root", "index.liquid", templateOfIndex());
}
const themeDir = join(siteDir, "theme");
await mkdir(themeDir);
const { files, issues } = themeContext.toFiles();
for (const file of files) {
const filePath = join(themeDir, file.path);
const dirPath = dirname(filePath);
await ensureDirectory(dirPath, { recursive: true });
await writeFile(filePath, file.content, "utf-8");
}
if (issues) {
ctx.logger.warn(`Issues in "${siteDir}":`, issues);
}
}
function templateOf404(ctx) {
const { siteSchema } = ctx;
const rawParam = isMultilingual(siteSchema) ? " raw: true" : "";
return `{% layout "layouts/main-layout.liquid" doc: doc site: site${rawParam} %}
{% block %}
<div class="Container">
<div class="Page">
<div class="TextWidth Text">
<h1>404</h1>
<p>This page doesn't exist. Please <a href='/'>return to home page</a>.</p>
</div>
</div>
</div>
{% endblock %}`;
}
function templateOfIndex() {
return `{% layout "layouts/main-layout.liquid" doc: doc site: site raw: true %}
{% block %}
<div class="Container">
<div class="Page">
{% for translation in doc.translations %}
<a href="{{ translation.url }}">{{ translation.languageLabel }}</a>
{% endfor %}
</div>
</div>
{% endblock %}`;
}
function templateOfLayout(ctx) {
const { siteSchema } = ctx;
const multilingual = isMultilingual(siteSchema);
ctx.addLiquidFile("partials", "site-header.liquid", templateOfSiteHeader(ctx));
ctx.addLiquidFile("partials", "site-footer.liquid", templateOfSiteFooter(ctx));
const renderHeader = `{% render "partials/site-header" doc: doc %}`;
const headerTemplate = multilingual
? `{% unless raw %}
${renderHeader}
{% endunless %}`
: renderHeader;
const renderFooter = `{% render "partials/site-footer" doc: doc %}`;
const footerTemplate = multilingual
? `{% unless raw %}
${renderFooter}
{% endunless %}`
: renderFooter;
return `<!doctype html>
<html lang="{{ doc.language }}">
<head>
<meta name="viewport" content="width=device-width,initial-scale=1">
{{ doc | headTags }}
<title>
{% if doc.type != "home" and doc.title %}
{{ doc.title }} -{% endif %}
{{ site.field.title }}</title>
<link rel="stylesheet" href="{{ site.assetsUrl }}/bundle.css">
</head>
<body>
${headerTemplate}
{% block -%}
{%- endblock %}
${footerTemplate}
</body>
</html>`;
}
function getThemeJsonContent() {
return JSON.stringify({
fTextImages: ["700x", "x400x", "700x350"],
pixelRatio: 1.5,
}, null, 2);
}
function getLiquidLinterCheckContent() {
return `UndefinedObject:
enabled: false
TranslationKeyExists:
enabled: false
MissingTemplate:
enabled: false
RemoteAsset:
enabled: false
UnknownFilter:
enabled: false
VariableName:
enabled: false`;
}
async function ensureDirectory(dirPath, { recursive = false } = {}) {
try {
await mkdir(dirPath, { recursive });
}
catch (e) {
if (!isObj(e) || e.code !== "EEXIST")
throw e;
}
}