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
|
import { dirname, join, joinGlobs } from "std/path/mod.ts";
import { ensureDir } from "std/fs/mod.ts";
import { expandGlob } from "std/fs/expand_glob.ts";
import { Config } from "../config.ts";
import { parseDocBookFile } from "../docbook/parse.ts";
import { writeHtmlFile } from "../html.ts";
import { Document } from "../docbook/document.ts";
import convertPost from "../templates/post.ts";
import convertPostList from "../templates/post_list.ts";
import convertTag from "../templates/tag.ts";
import generateAbout from "../templates/about.ts";
export async function runBuildCommand(config: Config) {
const posts = await generatePosts(config);
await generateTags(posts, config);
await generatePostList(posts, config);
await generateAboutPage(config);
await copyStaticFiles(config);
}
async function generatePosts(config: Config) {
const sourceDir = join(Deno.cwd(), config.locations.contentDir, "posts");
const postFiles = await collectPostFiles(sourceDir);
const posts = await parsePosts(postFiles, config);
await outputPosts(posts, config);
return posts;
}
async function collectPostFiles(sourceDir: string): Promise<string[]> {
const filePaths = [];
const globPattern = joinGlobs([sourceDir, "**", "*.xml"]);
for await (const entry of expandGlob(globPattern)) {
filePaths.push(entry.path);
}
return filePaths;
}
async function parsePosts(
postFiles: string[],
config: Config,
): Promise<Document[]> {
const posts = [];
for (const postFile of postFiles) {
posts.push(
await convertPost(await parseDocBookFile(postFile, config), config),
);
}
return posts;
}
async function outputPosts(posts: Document[], config: Config) {
const cwd = Deno.cwd();
const contentDir = join(cwd, config.locations.contentDir);
const destDir = join(cwd, config.locations.destDir);
for (const post of posts) {
const destFilePath = join(
post.sourceFilePath.replace(contentDir, destDir).replace(".xml", ""),
"index.html",
);
await ensureDir(dirname(destFilePath));
await writeHtmlFile(post, destFilePath);
}
}
async function generatePostList(posts: Document[], config: Config) {
const postList = await buildPostListDoc(posts, config);
await outputPostList(postList, config);
}
async function buildPostListDoc(
posts: Document[],
config: Config,
): Promise<Document> {
return await convertPostList(posts, config);
}
async function outputPostList(postList: Document, config: Config) {
const cwd = Deno.cwd();
const destDir = join(cwd, config.locations.destDir);
const destFilePath = join(destDir, "posts", "index.html");
await ensureDir(dirname(destFilePath));
await writeHtmlFile(postList, destFilePath);
}
async function generateAboutPage(config: Config) {
const aboutDoc = await generateAbout(config);
await outputAboutPage(aboutDoc, config);
}
async function outputAboutPage(about: Document, config: Config) {
const cwd = Deno.cwd();
const destDir = join(cwd, config.locations.destDir);
const destFilePath = join(destDir, "about", "index.html");
await ensureDir(dirname(destFilePath));
await writeHtmlFile(about, destFilePath);
}
async function generateTags(posts: Document[], config: Config) {
const tagsAndPosts = collectTags(posts);
const tagDocs = await buildTagDocs(tagsAndPosts, config);
await outputTags(tagDocs, config);
}
function collectTags(posts: Document[]): [string, Document[]][] {
const tagsAndPosts = new Map();
for (const post of posts) {
for (const tag of post.tags) {
if (!tagsAndPosts.has(tag)) {
tagsAndPosts.set(tag, []);
}
tagsAndPosts.get(tag).push(post);
}
}
const result: [string, Document[]][] = [];
for (const tag of Array.from(tagsAndPosts.keys()).sort()) {
result.push([
tag,
tagsAndPosts.get(tag).sort((a: Document, b: Document) => {
const ta = a.getCreatedDate();
const tb = b.getCreatedDate();
if (ta > tb) return -1;
if (ta < tb) return 1;
return 0;
}),
]);
}
return result;
}
async function buildTagDocs(
tagsAndPosts: [string, Document[]][],
config: Config,
): Promise<[string, Document][]> {
const docs: [string, Document][] = [];
for (const [tag, posts] of tagsAndPosts) {
docs.push([tag, await buildTagDoc(tag, posts, config)]);
}
return docs;
}
async function buildTagDoc(
tag: string,
posts: Document[],
config: Config,
): Promise<Document> {
return await convertTag(tag, posts, config);
}
async function outputTags(tagDocs: [string, Document][], config: Config) {
const cwd = Deno.cwd();
const destDir = join(cwd, config.locations.destDir);
for (const [tag, tagDoc] of tagDocs) {
const destFilePath = join(destDir, "tags", tag, "index.html");
await ensureDir(dirname(destFilePath));
await writeHtmlFile(tagDoc, destFilePath);
}
}
async function copyStaticFiles(config: Config) {
const globPattern = joinGlobs([Deno.cwd(), config.locations.staticDir, "*"]);
for await (const entry of expandGlob(globPattern)) {
const src = entry.path;
const dst = src.replace(
config.locations.staticDir,
config.locations.destDir,
);
await Deno.copyFile(src, dst);
}
}
|