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
|
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";
export async function run(config: Config) {
const posts = await generatePosts(config);
await generateTags(posts, config);
await generatePostList(posts, 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",
);
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");
ensureDir(dirname(destFilePath));
await writeHtmlFile(postList, 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.revisions[0].date;
const tb = b.revisions[0].date;
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");
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);
}
}
|