-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathstaticLoader.ts
More file actions
139 lines (118 loc) · 4.43 KB
/
staticLoader.ts
File metadata and controls
139 lines (118 loc) · 4.43 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
import { extname, resolve } from './deps/path.ts'
import { walk } from './deps/walk.ts'
import loadBlogPosts from "./loadBlogPosts.ts";
// pages
import fourOhFour from './render/404.html.ts'
import about from './render/about.html.ts'
import contact from './render/contact.html.ts'
import index from './render/index.html.ts'
import feed from './render/feed.xml.ts'
import blogPost from './render/blog-post.html.ts'
import CleanCSS from "./deps/clean-css.ts";
import { ONE_HOUR, ONE_MINUTE } from './utils/misc.ts';
const SIMPLE_PAGES = {
'404': fourOhFour,
'about': about,
'contact': contact,
'index': index,
'feed.xml': feed
} as const
const ONE_MINUTE_S = ONE_MINUTE / 1000
const ONE_HOUR_S = ONE_HOUR / 1000
export const createFileMap = async () => {
const fileMap = new Map<string, { content: Uint8Array, headers: HeadersInit }>()
const encoder = new TextEncoder()
// build CSS bundle
{
const CSS_BUNDLE_NAME = '_all.css';
const cssFiles = await Promise.all(['article.css', 'base.css', 'utils.css', 'variables.css', 'fragments/bio.css',
'fragments/home-link.css', 'fragments/icons.css',
'fragments/post-preview.css', 'fragments/prism.css', 'pages/about.css',
'pages/index.css'].map(async file => {
if (file !== CSS_BUNDLE_NAME) {
const fullPath = resolve(`./static/css`, file)
return await Deno.readTextFile(fullPath)
} else {
return ''
}
}))
const allCSS = new CleanCSS().minify(cssFiles.reduce((all, file) => all + '\n' + file, '')).styles
const allCSSArray = encoder.encode(allCSS)
fileMap.set('/css/_all.css', {
content: allCSSArray,
headers: {
'Content-Type': CONTENT_TYPES.css,
'Cache-Control': `max-age=${ONE_HOUR_S}`
}
})
}
// other static content
for await (const file of walk('static')) {
if (file.isFile) {
const content = await Deno.readFile(file.path)
const fileExtension = extname(file.name).substring(1) as keyof typeof CONTENT_TYPES
fileMap.set(file.path.substring('static'.length), {
content,
headers: {
'Content-Type': CONTENT_TYPES[fileExtension],
'Cache-Control': `max-age=${ONE_HOUR_S}`
}
})
}
}
const posts = await loadBlogPosts()
const allTags = posts
.filter(p => !p.meta.test)
.map(post => post.meta.tags)
.flat()
.filter((el, index, arr) => arr.indexOf(el) === index);
// generate plain pages
for (const [pageName, render] of Object.entries(SIMPLE_PAGES)) {
const fileEntry = {
content: encoder.encode(render({ allTags, posts })),
headers: {
'Content-Type': CONTENT_TYPES.html,
'Cache-Control': `max-age=${ONE_MINUTE_S}`
}
}
fileMap.set(`/${pageName}`, fileEntry)
fileMap.set(`/${pageName}.html`, fileEntry)
if (pageName === 'index') {
fileMap.set(`/`, fileEntry)
}
}
// generate tags pages
for (const tag of allTags) {
const file = {
content: encoder.encode(index({ allTags, posts, tag })),
headers: {
'Content-Type': CONTENT_TYPES.html,
'Cache-Control': `max-age=${ONE_MINUTE_S}`
}
}
fileMap.set(`/tags/${tag}`, file)
fileMap.set(`/tags/${tag}.html`, file)
}
// generate blog post pages
for (const post of posts) {
const file = {
content: encoder.encode(blogPost({ post })),
headers: {
'Content-Type': CONTENT_TYPES.html,
'Cache-Control': `max-age=${ONE_MINUTE_S}`
}
}
fileMap.set(`/blog/${post.slug}`, file)
fileMap.set(`/blog/${post.slug}.html`, file)
}
return fileMap
}
const CONTENT_TYPES = {
'html': 'text/html; charset=utf-8',
'css': 'text/css; charset=utf-8',
'js': 'application/javascript; charset=utf-8',
'xml': 'application/rss+xml; charset=utf-8',
'png': 'image/png',
'jpg': 'image/jpg',
'jpeg': 'image/jpeg',
} as const