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
|
import { render } from './renderPage.js';
import { Page, PageDirectory } from './pageDirectory.js';
import fs from 'fs';
import path from 'path';
import { logger } from '../logger.js';
import glob from 'glob';
import { process as processCss } from './processCss.js';
import { discoverFeed } from './discoverFeed.js';
export async function buildPages(verbose: boolean = true): Promise<{ success: boolean, errors: number, pageDirectory: PageDirectory}> {
// Recreate output directory
if (process.env.SKIP_OUTPUT_DIR_CREATION !== 'true') {
try {
if (fs.existsSync(process.env.OUTPUT_DIR)) {
fs.rmSync(process.env.OUTPUT_DIR, { recursive: true });
}
fs.mkdirSync(process.env.OUTPUT_DIR);
} catch (e) {
logger.error(`Failed to create output directory: ${e.message}`);
return { success: false, errors: 0, pageDirectory: null };
}
}
// Load pages
if (verbose) logger.info(`Reading pages from disk...`);
const pageDirectory = new PageDirectory(process.env.PAGES_DIR);
await pageDirectory.init();
let pagesCount = Object.keys(pageDirectory.getPages()).length;
if (verbose) logger.info(`Found ${pagesCount} pages.`);
// Render pages
if (verbose) logger.info(`Rendering pages...`);
let pagesRendered = 0;
let pagesFailed = 0;
for (const page of pageDirectory.getPages()) {
if (await renderPage(page, pageDirectory)) {
pagesRendered++;
} else {
pagesFailed++;
}
}
if (verbose) logger.info(`Rendered ${pagesRendered} of ${pagesCount} pages.`);
// Discover feeds
if (verbose) logger.info(`Discovering feeds...`);
const feeds = pageDirectory.getFeeds();
for (const feed of feeds) {
try {
await discoverFeed(feed, pageDirectory);
} catch (e) {
logger.error(`Failed to discover feed ${feed.title}: ${e.message}`);
}
}
//TODO move to util
const ensureParentDirExists = (file: string) => {
const joinedOutputPath = path.join(process.env.OUTPUT_DIR, 'static', file);
const dir = path.dirname(joinedOutputPath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
return joinedOutputPath;
};
// Copy static files
if (verbose) logger.info(`Copying static files...`);
try {
const files = glob.sync(`**/*`, {
cwd: process.env.STATIC_DIR,
nodir: true,
ignore: ['**/*.scss', '**/*.css']
})
for (const file of files) {
const outputPath = ensureParentDirExists(file);
const joinedPath = path.join(process.env.STATIC_DIR, file);
fs.copyFileSync(joinedPath, outputPath);
}
if (verbose) logger.info(`Done.`);
} catch (e) {
logger.error(`Failed to copy static files: ${e.message}`);
logger.error(e);
}
// Process CSS files
const cssFiles = glob.sync(`**/*.{css,scss}`, {
cwd: process.env.STATIC_DIR,
nodir: true,
});
if (cssFiles.length > 0) {
if (verbose) logger.info(`Processing CSS files...`);
for (const file of cssFiles) {
const outputPath = ensureParentDirExists(file);
const joinedPath = path.join(process.env.STATIC_DIR, file);
let processedCss: string;
try {
processedCss = await processCss(joinedPath);
} catch (e) {
logger.error(`Failed to process CSS file ${joinedPath}`);
logger.error(e.message);
continue;
}
const newOutputPath = outputPath.replace(/\.scss$/, '.css');
fs.writeFileSync(newOutputPath, processedCss);
}
if (verbose) logger.info(`Done.`);
}
return { success: pagesFailed == 0, errors: pagesFailed, pageDirectory: pageDirectory};
}
async function renderPage(page: Page, pageDirectory: PageDirectory): Promise<boolean> {
let html;
try {
html = await render(page, pageDirectory);
} catch (e) {
logger.error(`Failed to render page ${page.originalPath}: ${e.message}`);
return false;
}
try {
const file = page.buildPath;
const dir = path.dirname(file);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
fs.writeFileSync(file, html);
} catch (e) {
logger.error(`Failed to write page ${page.buildPath}: ${e.message}`);
return false;
}
return true;
}
export async function rebuildSinglePage(path: string, pageDirectory: PageDirectory): Promise<boolean> {
const page = await pageDirectory.loadPage(path);
if (!page) {
return false;
}
return await renderPage(page, pageDirectory);
}
|