-
Notifications
You must be signed in to change notification settings - Fork 6
/
build.ts
153 lines (136 loc) · 3.74 KB
/
build.ts
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
import { basename, dirname, join } from "./deps.ts";
import { compile, configure, render, templates } from "./deps.ts";
import { Page } from "./pages.ts";
import { SiteConfig } from "./config.ts";
import { hasKey } from "./attributes.ts";
configure({ autotrim: true });
interface Breadcrumb {
slug: string;
url: string;
current: boolean;
isTag?: boolean;
}
interface PageOpts {
headInclude: string;
includeRefresh: boolean;
childPages: Array<Page>;
backlinkPages: Array<Page>;
taggedPages: { [tag: string]: Array<Page> };
childTags: Array<string>;
view: string;
siteConf: SiteConfig;
style: string;
}
interface TagPageOpts {
headInclude: string;
includeRefresh: boolean;
taggedPages: Array<Page>;
view: string;
siteConf: SiteConfig;
style: string;
}
const sortPages = (pages: Page[]): Page[] =>
pages
.sort((a, b) => {
if (a.date && b.date) return b.date.valueOf() - a.date.valueOf();
else return 0;
})
.sort((page) => page.isIndex ? -1 : 0)
.sort((page) => hasKey(page.attrs, ["pinned"]) ? -1 : 0);
function generateBreadcrumbs(
currentPage: Page,
homeSlug?: string,
): Array<Breadcrumb> {
const dir = dirname(currentPage.url.pathname);
const chunks: string[] = dir.split("/").filter((ch: string) => !!ch);
const slug = basename(currentPage.url.pathname);
let breadcrumbs: Array<Breadcrumb> = chunks.map((chunk, i) => {
const slug = chunk;
const url = join("/", ...chunks.slice(0, i + 1));
return {
slug,
url,
current: false,
};
});
if (currentPage.url.pathname !== "/") {
breadcrumbs = [
{ slug: homeSlug ?? "index", url: "/", current: false },
...breadcrumbs,
];
}
if (slug !== "") {
breadcrumbs = [
...breadcrumbs,
{ slug, url: "", current: true },
];
}
return breadcrumbs;
}
export async function buildPage(
page: Page,
opts: PageOpts,
): Promise<string | void> {
const breadcrumbs = generateBreadcrumbs(page, opts.siteConf.rootName);
const backlinkPages = sortPages(opts.backlinkPages);
const childPages = sortPages(opts.childPages);
const useLogLayout = hasKey(page.attrs, ["log"]) && page.attrs?.log === true;
const showToc = hasKey(page.attrs, ["toc"]) && page.attrs?.toc === true;
const taggedPages: { [tag: string]: Array<Page> } = {};
for (const tag of Object.keys(opts.taggedPages)) {
const tagIndex = sortPages(
opts.taggedPages[tag].filter((taggedPage) => taggedPage !== page),
);
if (tagIndex.length !== 0) {
taggedPages[tag] = tagIndex;
}
}
templates.define("head", compile(opts.headInclude));
return await render(opts.view, {
page,
indexLayout: useLogLayout ? "log" : "default",
toc: showToc,
breadcrumbs,
childPages,
backlinkPages,
pagesByTag: taggedPages,
childTags: opts.childTags,
site: opts.siteConf,
style: opts.style,
includeRefresh: opts.includeRefresh,
});
}
export async function buildTagPage(
tagName: string,
opts: TagPageOpts,
): Promise<string | void> {
templates.define("head", compile(opts.headInclude));
const breadcrumbs: Array<Breadcrumb> = [
{ slug: "index", url: "/", current: false },
{ slug: `#${tagName}`, url: "", current: true, isTag: true },
];
const result = await render(opts.view, {
page: {
title: `#${tagName}`,
description: `Pages tagged #${tagName}`,
},
tagName,
breadcrumbs,
childPages: sortPages(opts.taggedPages),
site: opts.siteConf,
style: opts.style,
includeRefresh: opts.includeRefresh,
});
return result;
}
export async function buildFeed(
pages: Array<Page>,
view: string,
siteConf: SiteConfig,
): Promise<string | void> {
const result = await render(view, {
pages,
site: siteConf,
});
return result;
}