1
0
Fork 0
mirror of https://github.com/codex-team/codex.docs.git synced 2025-07-19 21:29:41 +02:00
codex.docs/src/backend/build-static.ts

129 lines
3.6 KiB
TypeScript
Raw Normal View History

import twig from 'twig';
import Page from './models/page.js';
import PagesFlatArray from './models/pagesFlatArray.js';
import path from 'path';
import { fileURLToPath } from 'url';
import('./utils/twig.js');
import fs from 'fs/promises';
import mkdirp from 'mkdirp';
import { createMenuTree } from './utils/menu.js';
import { EntityId } from './database/types.js';
import PagesOrder from './controllers/pagesOrder.js';
import fse from 'fs-extra';
import appConfig from './utils/appConfig.js';
import Aliases from './controllers/aliases.js';
import Pages from './controllers/pages.js';
/**
* Build static pages from database
*/
export default async function buildStatic(): Promise<void> {
const config = appConfig.staticBuild;
if (!config) {
throw new Error('Static build config not found');
}
const dirname = path.dirname(fileURLToPath(import.meta.url));
const cwd = process.cwd();
const distPath = path.resolve(cwd, config.outputDir);
/**
* Render template with twig by path
*
* @param filePath - path to template
* @param data - data to render template
*/
function renderTemplate(filePath: string, data: Record<string, unknown>): Promise<string> {
return new Promise((resolve, reject) => {
twig.renderFile(path.resolve(dirname, filePath), data, (err, html) => {
if (err) {
reject(err);
}
resolve(html);
});
});
}
console.log('Removing old static files');
await fse.remove(distPath);
console.log('Building static files');
const pagesOrder = await PagesOrder.getAll();
const allPages = await Page.getAll();
await mkdirp(distPath);
/**
* Renders single page
*
* @param page - page to render
* @param isIndex - is this page index page
*/
async function renderPage(page: Page, isIndex?: boolean): Promise<void> {
console.log(`Rendering page ${page.uri}`);
const pageParent = await page.getParent();
const pageId = page._id;
if (!pageId) {
throw new Error('Page id is not defined');
}
const parentIdOfRootPages = '0' as EntityId;
const previousPage = await PagesFlatArray.getPageBefore(pageId);
const nextPage = await PagesFlatArray.getPageAfter(pageId);
const menu = createMenuTree(parentIdOfRootPages, allPages, pagesOrder, 2);
const result = await renderTemplate('./views/pages/page.twig', {
page,
pageParent,
previousPage,
nextPage,
menu,
config: appConfig.frontend,
});
const filename = (isIndex || page.uri === '') ? 'index.html' : `${page.uri}.html`;
await fs.writeFile(path.resolve(distPath, filename), result);
console.log(`Page ${page.uri} rendered`);
}
/**
* Render index page
*
* @param indexPageUri - uri of index page
*/
async function renderIndexPage(indexPageUri: string): Promise<void> {
const alias = await Aliases.get(indexPageUri);
if (!alias.id) {
throw new Error(`Alias ${indexPageUri} not found`);
}
const page = await Pages.get(alias.id);
await renderPage(page, true);
}
/**
* Render all pages
*/
for (const page of allPages) {
await renderPage(page);
}
// Check if index page is enabled
if (config.indexPage.enabled) {
await renderIndexPage(config.indexPage.uri);
}
console.log('Static files built');
console.log('Copy public directory');
await fse.copy(path.resolve(dirname, '../../public'), distPath);
if (appConfig.uploads.driver === 'local') {
console.log('Copy uploads directory');
await fse.copy(path.resolve(cwd, appConfig.uploads.local.path), path.resolve(distPath, 'uploads'));
}
}