format
This commit is contained in:
parent
f1b1c650ce
commit
ea5f2bc325
48 changed files with 5217 additions and 5177 deletions
|
@ -16,7 +16,10 @@
|
||||||
pkgs.nodejs_24 # runtime
|
pkgs.nodejs_24 # runtime
|
||||||
pkgs.deno # formatter
|
pkgs.deno # formatter
|
||||||
(pkgs.ffmpeg.override {
|
(pkgs.ffmpeg.override {
|
||||||
|
withOpus = true;
|
||||||
withSvtav1 = true;
|
withSvtav1 = true;
|
||||||
|
withJxl = true;
|
||||||
|
withWebp = true;
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
@ -96,7 +96,9 @@ Module._resolveFilename = (...args) => {
|
||||||
try {
|
try {
|
||||||
return require.resolve(replacedPath, { paths: [projectSrc] });
|
return require.resolve(replacedPath, { paths: [projectSrc] });
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.code === "MODULE_NOT_FOUND" && (err?.requireStack?.length ?? 0) <= 1) {
|
if (
|
||||||
|
err.code === "MODULE_NOT_FOUND" && (err?.requireStack?.length ?? 0) <= 1
|
||||||
|
) {
|
||||||
err.message.replace(replacedPath, args[0]);
|
err.message.replace(replacedPath, args[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ export class Queue<T, R> {
|
||||||
try {
|
try {
|
||||||
active.unshift(spinner);
|
active.unshift(spinner);
|
||||||
bar.props = { active };
|
bar.props = { active };
|
||||||
console.log(this.#name + ": " + itemText);
|
// console.log(this.#name + ": " + itemText);
|
||||||
const result = await this.#fn(args, spinner);
|
const result = await this.#fn(args, spinner);
|
||||||
this.#done++;
|
this.#done++;
|
||||||
return result;
|
return result;
|
||||||
|
@ -116,6 +116,7 @@ export class Queue<T, R> {
|
||||||
(err as any).job = itemText;
|
(err as any).job = itemText;
|
||||||
}
|
}
|
||||||
this.#errors.push(err);
|
this.#errors.push(err);
|
||||||
|
console.error(util.inspect(err, false, Infinity, true));
|
||||||
throw err;
|
throw err;
|
||||||
} finally {
|
} finally {
|
||||||
active.splice(active.indexOf(spinner), 1);
|
active.splice(active.indexOf(spinner), 1);
|
||||||
|
@ -295,3 +296,4 @@ import { Progress } from "@paperclover/console/Progress";
|
||||||
import { Spinner } from "@paperclover/console/Spinner";
|
import { Spinner } from "@paperclover/console/Spinner";
|
||||||
import * as path from "node:path";
|
import * as path from "node:path";
|
||||||
import process from "node:process";
|
import process from "node:process";
|
||||||
|
import * as util from "node:util";
|
||||||
|
|
40
readme.md
40
readme.md
|
@ -4,27 +4,27 @@ this repository contains clover's "sitegen" framework, which is a set of tools
|
||||||
that assist building websites. these tools power https://paperclover.net.
|
that assist building websites. these tools power https://paperclover.net.
|
||||||
|
|
||||||
- **HTML "Server Side Rendering") engine written from scratch.** (~500 lines)
|
- **HTML "Server Side Rendering") engine written from scratch.** (~500 lines)
|
||||||
- A more practical JSX runtime (`class` instead of `className`, built-in
|
- A more practical JSX runtime (`class` instead of `className`, built-in
|
||||||
`clsx`, `html()` helper over `dangerouslySetInnerHTML` prop, etc).
|
`clsx`, `html()` helper over `dangerouslySetInnerHTML` prop, etc).
|
||||||
- Integration with [Marko][1] for concisely written components.
|
- Integration with [Marko][1] for concisely written components.
|
||||||
- TODO: MDX-like compiler for content-heavy pages like blogs.
|
- TODO: MDX-like compiler for content-heavy pages like blogs.
|
||||||
- Different languages can be used at the same time. Supports
|
- Different languages can be used at the same time. Supports `async function`
|
||||||
`async function` components, `<Suspense />`, and custom extensions.
|
components, `<Suspense />`, and custom extensions.
|
||||||
- **Incremental static site generator and build system.**
|
- **Incremental static site generator and build system.**
|
||||||
- Build entire production site at start, incremental updates when pages
|
- Build entire production site at start, incremental updates when pages
|
||||||
change; Build system state survives coding sessions.
|
change; Build system state survives coding sessions.
|
||||||
- The only difference in development and production mode is hidden
|
- The only difference in development and production mode is hidden source-maps
|
||||||
source-maps and stripped `console.debug` calls. The site you
|
and stripped `console.debug` calls. The site you see locally is the same
|
||||||
see locally is the same site you see deployed.
|
site you see deployed.
|
||||||
- (TODO) Tests, Lints, and Type-checking is run alongside, and only re-runs
|
- (TODO) Tests, Lints, and Type-checking is run alongside, and only re-runs
|
||||||
checks when the files change. For example, changing a component re-tests
|
checks when the files change. For example, changing a component re-tests
|
||||||
only pages that use that component and re-lints only the changed file.
|
only pages that use that component and re-lints only the changed file.
|
||||||
- **Integrated libraries for building complex, content heavy web sites.**
|
- **Integrated libraries for building complex, content heavy web sites.**
|
||||||
- Static asset serving with ETag and build-time compression.
|
- Static asset serving with ETag and build-time compression.
|
||||||
- Dynamicly rendered pages with static client. (`#import "#sitegen/view"`)
|
- Dynamicly rendered pages with static client. (`#import "#sitegen/view"`)
|
||||||
- Databases with a typed SQLite wrapper. (`import "#sitegen/sqlite"`)
|
- Databases with a typed SQLite wrapper. (`import "#sitegen/sqlite"`)
|
||||||
- TODO: Meta and Open Graph generation. (`export const meta`)
|
- TODO: Meta and Open Graph generation. (`export const meta`)
|
||||||
- TODO: Font subsetting tools to reduce bytes downloaded by fonts.
|
- TODO: Font subsetting tools to reduce bytes downloaded by fonts.
|
||||||
- **Built on the battle-tested Node.js runtime.**
|
- **Built on the battle-tested Node.js runtime.**
|
||||||
|
|
||||||
[1]: https://next.markojs.com
|
[1]: https://next.markojs.com
|
||||||
|
@ -42,6 +42,7 @@ Included is `src`, which contains `paperclover.net`. Website highlights:
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
minimum system requirements:
|
minimum system requirements:
|
||||||
|
|
||||||
- a cpu with at least 1 core.
|
- a cpu with at least 1 core.
|
||||||
- random access memory.
|
- random access memory.
|
||||||
- windows 7 or later, macos, or other operating system.
|
- windows 7 or later, macos, or other operating system.
|
||||||
|
@ -73,4 +74,3 @@ open a shell with all needed system dependencies.
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
No contributions to `src` accepted, only `framework`.
|
No contributions to `src` accepted, only `framework`.
|
||||||
|
|
||||||
|
|
2
run.js
2
run.js
|
@ -12,7 +12,7 @@ if (!zlib.zstdCompress) {
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
globalThis.console.error(
|
globalThis.console.error(
|
||||||
`sitegen depends on a node.js-compatibile runtime that supports zstd compression\n` +
|
`sitegen depends on a node.js-compatibile runtime\n` +
|
||||||
`this is node.js version ${process.version}${
|
`this is node.js version ${process.version}${
|
||||||
brand ? ` (${brand})` : ""
|
brand ? ` (${brand})` : ""
|
||||||
}\n\n` +
|
}\n\n` +
|
||||||
|
|
|
@ -252,6 +252,7 @@ interface Process {
|
||||||
enable?: boolean;
|
enable?: boolean;
|
||||||
include: Set<string>;
|
include: Set<string>;
|
||||||
depends?: string[];
|
depends?: string[];
|
||||||
|
version?: number;
|
||||||
/* Perform an action. */
|
/* Perform an action. */
|
||||||
run(args: ProcessFileArgs): Promise<void>;
|
run(args: ProcessFileArgs): Promise<void>;
|
||||||
/* Should detect if `run` was never even run before before undoing state */
|
/* Should detect if `run` was never even run before before undoing state */
|
||||||
|
@ -384,6 +385,7 @@ const procImageSubsets: Process = {
|
||||||
name: "encode image subsets",
|
name: "encode image subsets",
|
||||||
include: rules.extsImage,
|
include: rules.extsImage,
|
||||||
depends: ["calculate dimensions"],
|
depends: ["calculate dimensions"],
|
||||||
|
version: 2,
|
||||||
async run({ absPath, mediaFile, spin }) {
|
async run({ absPath, mediaFile, spin }) {
|
||||||
const { width, height } = UNWRAP(mediaFile.parseDimensions());
|
const { width, height } = UNWRAP(mediaFile.parseDimensions());
|
||||||
const targetSizes = transcodeRules.imageSizes.filter((w) => w < width);
|
const targetSizes = transcodeRules.imageSizes.filter((w) => w < width);
|
||||||
|
@ -485,6 +487,7 @@ const procVideos = transcodeRules.videoFormats.map<Process>((preset) => ({
|
||||||
title: fakeProgress.text,
|
title: fakeProgress.text,
|
||||||
progress: fakeProgress,
|
progress: fakeProgress,
|
||||||
args,
|
args,
|
||||||
|
cwd: base,
|
||||||
});
|
});
|
||||||
return await collectFiles();
|
return await collectFiles();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -522,7 +525,10 @@ const processors = [
|
||||||
// Create a unique key.
|
// Create a unique key.
|
||||||
hash: new Uint16Array(
|
hash: new Uint16Array(
|
||||||
crypto.createHash("sha1")
|
crypto.createHash("sha1")
|
||||||
.update(process.run.toString())
|
.update(
|
||||||
|
process.run.toString() +
|
||||||
|
(process.version ? String(process.version) : ""),
|
||||||
|
)
|
||||||
.digest().buffer,
|
.digest().buffer,
|
||||||
).reduce((a, b) => a ^ b),
|
).reduce((a, b) => a ^ b),
|
||||||
depends: (process.depends ?? []).map((depend) => {
|
depends: (process.depends ?? []).map((depend) => {
|
||||||
|
|
|
@ -135,10 +135,7 @@ function highlightLines({
|
||||||
|
|
||||||
export const getRegistry = async.once(async () => {
|
export const getRegistry = async.once(async () => {
|
||||||
const wasmBin = await fs.readFile(
|
const wasmBin = await fs.readFile(
|
||||||
path.join(
|
require.resolve("vscode-oniguruma/release/onig.wasm"),
|
||||||
import.meta.dirname,
|
|
||||||
"../node_modules/vscode-oniguruma/release/onig.wasm",
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
await oniguruma.loadWASM(wasmBin);
|
await oniguruma.loadWASM(wasmBin);
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ db.table(
|
||||||
create table if not exists asset_ref_files (
|
create table if not exists asset_ref_files (
|
||||||
file text not null,
|
file text not null,
|
||||||
id integer not null,
|
id integer not null,
|
||||||
foreign key (id) references asset_refs(id)
|
foreign key (id) references asset_refs(id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
create index asset_ref_files_id on asset_ref_files(id);
|
create index asset_ref_files_id on asset_ref_files(id);
|
||||||
`,
|
`,
|
||||||
|
|
|
@ -56,11 +56,15 @@ export const extsImage = new Set([
|
||||||
".jpg",
|
".jpg",
|
||||||
".jpeg",
|
".jpeg",
|
||||||
".png",
|
".png",
|
||||||
".gif",
|
|
||||||
".webp",
|
".webp",
|
||||||
".avif",
|
".avif",
|
||||||
".heic",
|
".heic",
|
||||||
|
]);
|
||||||
|
/** These files show an image embed, but aren't optimized */
|
||||||
|
export const extsImageLike = new Set([
|
||||||
|
...extsImage,
|
||||||
".svg",
|
".svg",
|
||||||
|
".gif",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/** These files populate `duration` using `ffprobe` */
|
/** These files populate `duration` using `ffprobe` */
|
||||||
|
|
|
@ -99,14 +99,38 @@ export const imagePresets = [
|
||||||
"6",
|
"6",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// TODO: avif
|
{
|
||||||
|
ext: ".avif",
|
||||||
|
args: [
|
||||||
|
"-c:v",
|
||||||
|
"libaom-av1",
|
||||||
|
"-crf",
|
||||||
|
"30",
|
||||||
|
"-pix_fmt",
|
||||||
|
"yuv420p10le",
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ext: ".jxl",
|
ext: ".jxl",
|
||||||
args: ["-c:v", "libjxl", "-distance", "0.8", "-effort", "9"],
|
args: [
|
||||||
|
"-c:v",
|
||||||
|
"libjxl",
|
||||||
|
"-distance",
|
||||||
|
"0.8",
|
||||||
|
"-effort",
|
||||||
|
"9",
|
||||||
|
"-update",
|
||||||
|
"-frames:v",
|
||||||
|
"1",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function getVideoArgs(preset: VideoEncodePreset, outbase: string, input: string[]) {
|
export function getVideoArgs(
|
||||||
|
preset: VideoEncodePreset,
|
||||||
|
outbase: string,
|
||||||
|
input: string[],
|
||||||
|
) {
|
||||||
const cmd = [...input];
|
const cmd = [...input];
|
||||||
|
|
||||||
if (preset.codec === "av1") {
|
if (preset.codec === "av1") {
|
||||||
|
|
|
@ -27,12 +27,12 @@ li a {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
li a:hover {
|
li a:hover {
|
||||||
background-color: rgba(255,255,255,0.2);
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-decoration: none!important;
|
text-decoration: none !important;
|
||||||
}
|
}
|
||||||
.dir a {
|
.dir a {
|
||||||
color: #99eeFF
|
color: #99eeff;
|
||||||
}
|
}
|
||||||
.ext {
|
.ext {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
|
|
|
@ -118,4 +118,3 @@ code {
|
||||||
font-family: "rmo", monospace;
|
font-family: "rmo", monospace;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
body,html {
|
body, html {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
|
@ -41,7 +41,7 @@ footer h2 {
|
||||||
header h2, header em, footer h2, footer em {
|
header h2, header em, footer h2, footer em {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
header em, footer em {
|
header em, footer em {
|
||||||
margin-left: 16px!important;
|
margin-left: 16px !important;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
<title>paper clover</title>
|
<title>paper clover</title>
|
||||||
</head>
|
</head>
|
||||||
<body bgcolor="black" style="word-wrap: initial">
|
<body bgcolor="black" style="word-wrap: initial">
|
||||||
<main style="display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh">
|
<main
|
||||||
|
style="display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100vh"
|
||||||
|
>
|
||||||
<div>
|
<div>
|
||||||
<p style="margin: 0.5rem 0">
|
<p style="margin: 0.5rem 0">
|
||||||
<a
|
<a
|
||||||
|
@ -56,7 +58,9 @@
|
||||||
<font color="#FF8147">feed</font>
|
<font color="#FF8147">feed</font>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<h1 style="margin: -1.5rem 0 3rem 0; font-size: 7rem; font-weight: 400; font-family: times">
|
<h1
|
||||||
|
style="margin: -1.5rem 0 3rem 0; font-size: 7rem; font-weight: 400; font-family: times"
|
||||||
|
>
|
||||||
<font color="#B8E1FF">paper</font>
|
<font color="#B8E1FF">paper</font>
|
||||||
<font color="#E8F4FF">clover</font>
|
<font color="#E8F4FF">clover</font>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
|
@ -22,4 +22,3 @@
|
||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue