- TypeScript 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .vscode | ||
| src | ||
| .gitignore | ||
| bun.lock | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
ssg
A static site generator made for my blog (eventually). It is relativly generic and can probably be used for your own static site generator needs. It works by providing a very basic post type and then calling template on it. Template wraps the file and uses js string interpolation to generate the final output data. This means it can do lots of complex things. There also is a very basic asset copy step, which moves static assets into the output directory.
Disclaimer: It does sadly currently use bun. This is something I want to remove in the future. Currently bun is used because it can execute ts without a external compiler step. Im open for pr's to move it away from that if someone wants to help me
Setup
- Install bun
- Setup a .env file with the relevant parameters (see:
src/settings.ts) - Setup your templates, static assets, post.ts files
- Run
src/index.ts - Copy the output where you need it
GetPostEnumerator(posts, tagPosts)
Is expected to return either a post or null. When it returns a post it will simply template the post. This function will continue to be called until it returns null. The reasoning is, that it enables one post class to be used for several output files. One way this can be used is to create a page for each tag that is used by any blogpost. A default implementation is also provided, which simply returns the post once and then null.
Template accessible data
| object | description |
|---|---|
| post | Information about the current post |
| arg | Data that can be passed through states of the templating |
| arg.current | Data about the current object in the content array |
| arg.time | The timestamp, where the processing for this post started |
| posts | An array of all posts |
| tagPosts | A map of all posts with their tag being the key |
read(file, arg)
Inserts the content of templateDir + file in the current location, while passing arg into the template, to be used by it
rel(path)
Get a path to path relative to the page root, regardless of which file/template you are currently in.
content(arg)
Helper function for blogposts. Loops through all of the objects in the content field of the post and calls their template. Also stores the rest of the object in arg.current
Example file
import { Post } from "../../../ssg/src/post";
export default class TagList extends Post {
public override outputFile: string = "";
public override baseTemplate: string = "postList.html";
public override type = "other";
public override title: string = "Alle Posts";
private static counter = 0;
public override GetPostEnumerator(posts: Post[], tagPosts: Map<string, Post[]>): Post | null {
const keys: string[] = [];
for(const k of tagPosts.keys()) {
keys.push(k);
}
if(TagList.counter < keys.length) {
const toReturn = new TagList();
toReturn.title = keys[TagList.counter].toUpperCase();
toReturn.outputFile = "tags/" + keys[TagList.counter] + ".html";
for(const post of tagPosts.get(keys[TagList.counter])!.filter((p) => p.type != "other")) {
toReturn.content.push({
type: "parts/postPreview.html",
content: post.title,
path: post.outputFile,
description: "description" in post ? post["description"] : "Default post description",
});
}
TagList.counter += 1;
return toReturn;
}
return null;
}
}
<!DOCTYPE html>
<html>
<head>
<title>${post.title}</title>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<!--Stylesheets & Scripts-->
<link rel="stylesheet" href="${rel('/styles/style.css')}" />
</head>
<body>
${read('header.html')}
<div style="display:block">
<div class="content">
<h1>#${post.title}</h1>
${content(arg)}
</div>
</div>
${read('footer.html', arg)}
</body>
</html>