-
Notifications
You must be signed in to change notification settings - Fork 90
Expand file tree
/
Copy pathbuild-static.ts
More file actions
174 lines (145 loc) · 4.71 KB
/
build-static.ts
File metadata and controls
174 lines (145 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
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';
import { downloadFavicon } from './utils/downloadFavicon.js';
import { buildPageBreadcrumbs } from './utils/breadcrumbs.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);
});
});
}
if (config.overwrite) {
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();
try {
console.log('Create dist folder');
await mkdirp(distPath);
} catch (e) {
console.log('Error while creating dist folder', e);
return;
}
console.log('Copy public directory');
const publicDir = path.resolve(dirname, '../../public');
console.log(`Copy from ${publicDir} to ${distPath}`);
try {
await fse.copy(publicDir, distPath);
console.log('Public directory copied');
} catch (e) {
console.log('Error while copying public directory');
console.error(e);
}
const favicon = appConfig.favicon ? await downloadFavicon(appConfig.favicon, distPath, '') : {
destination: '/favicon.png',
type: 'image/png',
};
/**
* 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 pageUri = page.uri;
if (!pageUri) {
throw new Error('Page uri is not defined');
}
const breadcrumbItems = await buildPageBreadcrumbs(page);
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);
const result = await renderTemplate('./views/pages/page.twig', {
page,
breadcrumbItems,
previousPage,
nextPage,
menu,
favicon,
config: appConfig.frontend,
});
let filename: string;
if (isIndex) {
filename = 'index.html';
} else if (config?.pagesInsideFolders) { // create folder for each page if pagesInsideFolders is true
const pagePath = path.resolve(distPath, pageUri);
await mkdirp(pagePath);
filename = path.resolve(pagePath, 'index.html');
} else {
filename = `${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');
if (appConfig.uploads.driver === 'local') {
console.log('Copy uploads directory');
await fse.copy(path.resolve(cwd, appConfig.uploads.local.path), path.resolve(distPath, 'uploads'));
console.log('Uploads directory copied');
}
}