Repository
Current version released
3 years ago
Dependencies
deno.land/x
std
Jikji: small static site generator toolkit
Jikji is a small toolkit for building your own static site generators on Deno.
Currently, it provides the below composable building blocks:
- Parallel generation
- Partial generation
- Flexible permalinks
- Watch changes & reload
- First-class support for content negotiation on type & language
- Markdown (powered by markdown-it)
- EJS/ETS template engine (powered by dejs)
- Sass/SCSS stylesheet preprocessor (through subprocess)
Example
import {
intoDirectory,
scanFiles,
rebase,
writeFiles
} from "https://deno.land/x/jikji/mod.ts";
import { markdown } from "https://deno.land/x/jikji/markdown.ts";
const baseUrl = new URL("http://localhost:8000/");
const outDir = "public_html";
// Scans for Markdown files in the posts/ directory:
await scanFiles(["posts/**/*.md"])
// Renders posts written in Markdown to HTML:
.transform(markdown(), { type: "text/markdown" })
// Makes permalinks like posts/foobar/ instead of posts/foobar.md
.move(intoDirectory())
// Maps the current directory to the target URL <https://example.com/>:
// E.g., ./posts/foobar.md -> https://example.com/posts/foobar/
.move(rebase("posts/", baseUrl))
// Writes the files to the output directory (public_html/):
.forEach(writeFiles(outDir, baseUrl));
// If you want watch mode, use forEachWithReloading() instead:
// .forEachWithReloading(writeFiles(outDir, baseUrl));
More realistic examples are placed in the examples/ directory.
Key concepts
Building blocks that Jikji provides are based on the following concepts:
Pipeline
represents the entire steps from the input to the output. It’s like a stream of zero or moreResource
s. Its whole process is lazy so that if some parts don’t need to be generated again they are even not loaded at all. (In the above example, a newPipeline
is acquired usingscanFiles()
function, butscanFiles()
does not immediately list files nor load their contents.)Resource
represents an abstract resource which is mapped to a uniquepath
. Itspath
is a rather URL than a filesystem path, which means it has a scheme likehttps
orfile
and can end with a slash. (Note thatintoDirectory()
function turns posts/foobar.md into posts/foobar/ in the above example.)Resource
also can has multiple representations for content negotiation on type and language.Content
represents an actual content which can belong toResource
s as a representation. TheContentBody
can be lazily loaded and either a Unicode text or binary data. They are typed through IANAMediaType
s (formerly known as MIME types). Optionally, they can have their RFC 5656LanguageTag
to describe their natural language. If you want you can put additionalmetadata
liketitle
orpublished
as well.ResourceTransformer
transforms aResource
into a modifiedResource
. It purposes to change multipleResources
into new ones in immutable style by being passed toPipeline#map()
method.PathTransformer
transforms aURL
into a modifiedURL
. It purposes to change multipleResource
spath
s into new ones in immutable style by being passed toPipeline#move()
method. (In the above example,intoDirectory()
andrebase()
functions returnPathTransformer
s.)ContentTransformer
transforms aContent
into a modifiedContent
. It purposes to change multiple representations ofResource
s into new ones in immutable style by being passed toPipeline#transform()
method. (In the above example,markdown()
function returns aContentTransformer
.)