UNPKG

@paroicms/site-generator-plugin

Version:

ParoiCMS Site Generator Plugin

139 lines (136 loc) 4.87 kB
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; } }