Skip to content

Commit 7ddac6d

Browse files
committed
chore: separate the source content from the processed content
Feels cleaner doesn't it? I really wish the public directory wasn't called "docs" though.
1 parent 868dd67 commit 7ddac6d

File tree

7 files changed

+213
-18
lines changed

7 files changed

+213
-18
lines changed

README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
1-
# chrisnewtn.github.io
1+
# [chrisnewtn.com](https://chrisnewtn.com)
2+
23
Chris Newton's personal website.
4+
5+
### Methodology
6+
7+
One of my goals with this site is to attempt to keep its content as raw as possible, unminifed and previewable without a web server.
8+
9+
Over time, the idea is the tooling and the content will serve as a representative sample of the kind of work I produce, the way I think, etc.

docs-raw/index.html

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Chris Newton</title>
7+
<link rel="stylesheet" href="style.css">
8+
</head>
9+
<body>
10+
<header>
11+
<h1>Chris Newton</h1>
12+
</header>
13+
<main>
14+
<p>Programming for the web since 1873.</p>
15+
<div class="under-construction">Under Construction</div>
16+
</main>
17+
<footer>
18+
<p><small>© Copyright 2024 Chris Newton. Hosted using <a href="https://pages.github.com/">GitHub Pages</a> (<a href="https://github.com/chrisnewtn/chrisnewtn.github.io/">repo</a>).</small></p>
19+
</footer>
20+
</body>
21+
</html>

docs/style.css docs-raw/style.css

File renamed without changes.

docs/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>Chris Newton</title>
7-
<link rel="stylesheet" href="style.css?sha256=c2f6e97789262b456bf386861cc82b9c16f7a31e286ab70291f45b03fc9e014f">
7+
<link rel="stylesheet" href="style-c2f6e97.css">
88
</head>
99
<body>
1010
<header>

docs/style-c2f6e97.css

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
* {
2+
box-sizing: border-box;
3+
}
4+
5+
html,
6+
body {
7+
height: 100%;
8+
}
9+
10+
a {
11+
color: var(--link);
12+
}
13+
a:visited {
14+
color: var(--link-visited);
15+
}
16+
17+
body {
18+
/* https://tailwindcss.com/docs/customizing-colors#default-color-palette */
19+
--neutral-50: #fafafa;
20+
--neutral-950: #0a0a0a;
21+
--blue-500: #3b82f6;
22+
--blue-600: #2563eb;
23+
--purple-500: #a855f7;
24+
--purple-600: #9333ea;
25+
--amber-400: #fbbf24;
26+
27+
font-family: Helvetica, Arial, sans-serif;
28+
29+
color: var(--primary-text);
30+
background-color: var(--bg-color);
31+
32+
margin: 0;
33+
34+
display: grid;
35+
grid-template-columns: auto auto auto;
36+
grid-template-rows: max-content auto max-content;
37+
grid-template-areas:
38+
". header ."
39+
". main ."
40+
". footer .";
41+
}
42+
43+
body > header {
44+
text-align: center;
45+
grid-area: header;
46+
}
47+
48+
body > main {
49+
text-align: center;
50+
grid-area: main;
51+
}
52+
53+
body > footer {
54+
text-align: center;
55+
grid-area: footer;
56+
}
57+
58+
.under-construction {
59+
background-color: var(--amber-400);
60+
border: dashed var(--neutral-950);
61+
padding: 1rem;
62+
color: var(--neutral-950);
63+
}
64+
65+
/** Colours **/
66+
67+
/** Light **/
68+
body {
69+
--primary-text: var(--neutral-950);
70+
--bg-color: var(--neutral-50);
71+
--link: var(--blue-600);
72+
--link-visited: var(--purple-600);
73+
}
74+
75+
/** Dark **/
76+
@media (prefers-color-scheme: dark) {
77+
body {
78+
--primary-text: var(--neutral-50);
79+
--bg-color: var(--neutral-950);
80+
--link: var(--blue-500);
81+
--link-visited: var(--purple-500);
82+
}
83+
}

scripts/doc-processor/cli.js

+63-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,68 @@
11
import fs from "node:fs/promises";
2+
import {createReadStream, createWriteStream} from "node:fs";
3+
import {pipeline} from "node:stream/promises";
4+
import {parseArgs} from "node:util";
25
import {processDocument} from "./index.js";
6+
import {fileURLToPath} from "node:url";
7+
import path from 'node:path';
38

4-
const [pathToFile] = process.argv.slice(2);
5-
const fileContents = await fs.readFile(pathToFile, "utf8");
9+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
610

7-
const file = await processDocument(pathToFile, fileContents);
11+
const {
12+
values: {
13+
'input-dir': inputDir,
14+
'output-dir': outputDir
15+
}
16+
} = parseArgs({
17+
options: {
18+
'input-dir': {
19+
type: 'string',
20+
short: 'i',
21+
default: path.resolve(__dirname, '..', '..', 'docs-raw')
22+
},
23+
'output-dir': {
24+
type: 'string',
25+
short: 'o',
26+
default: path.resolve(__dirname, '..', '..', 'docs')
27+
}
28+
}
29+
});
830

9-
await fs.writeFile(pathToFile, String(file), "utf8");
31+
const writtenAssets = new Set();
32+
33+
for (const inputFile of await fs.readdir(inputDir, {withFileTypes: true})) {
34+
if (inputFile.isDirectory() || !inputFile.name.endsWith(".html")) {
35+
break;
36+
}
37+
const pathToInput = path.join(inputDir, inputFile.name);
38+
const fileContents = await fs.readFile(pathToInput, "utf8");
39+
40+
const {vFile, assets} = await processDocument({
41+
inputFile: {
42+
name: pathToInput,
43+
text: fileContents
44+
},
45+
outputDir
46+
});
47+
48+
for (const [pathToNewAsset, pathToOldAsset] of assets) {
49+
if (writtenAssets.has(pathToNewAsset)) {
50+
break;
51+
}
52+
53+
await pipeline(
54+
createReadStream(pathToOldAsset),
55+
createWriteStream(pathToNewAsset)
56+
);
57+
58+
console.log('write', pathToNewAsset);
59+
60+
writtenAssets.add(pathToNewAsset);
61+
}
62+
63+
const pathToOutput = path.join(outputDir, inputFile.name);
64+
65+
await fs.writeFile(pathToOutput, String(vFile), "utf8");
66+
67+
console.log('write', pathToOutput);
68+
}

scripts/doc-processor/index.js

+37-12
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,40 @@ async function shasum(pathToFile) {
2222
}
2323

2424
/**
25-
* Appends the sha256sum of all each local CSS file to their `href` property
26-
* using a query parameter.
25+
* Renames each locally referenced CSS file with a 7 character short hash of its
26+
* contents. This renders it permanently cachable, as any changes to its content
27+
* will result in a different hash causing it to be re-downloaded.
2728
* @type {import('unified').Plugin<[], import('hast').Root>}
2829
*/
29-
function cacheBustCss({pathToFile}) {
30+
function cacheBustCss({
31+
pathToFile,
32+
outputDir,
33+
assets
34+
}) {
3035
const pathToDir = path.dirname(pathToFile);
3136

3237
return async tree => {
3338
for (const el of selectAll("link[rel=stylesheet]", tree)) {
3439
const href = el.properties.href;
3540

36-
if (href.startsWith("http:")) {
41+
if (href.startsWith("http")) {
42+
// It's an external asset. Ignore it.
3743
break;
3844
}
3945

4046
const [pathPart, searchString] = href.split("?");
47+
const pathToAsset = path.resolve(pathToDir, pathPart);
4148

42-
const hash = await shasum(path.resolve(pathToDir, pathPart));
49+
const hash = await shasum(pathToAsset);
4350

44-
const searchParams = new URLSearchParams(searchString);
45-
searchParams.set("sha256", hash);
51+
const extname = path.extname(pathPart);
52+
const basename = path.basename(pathPart, extname);
4653

47-
el.properties.href = `${pathPart}?${searchParams}`;
54+
const newName = `${basename}-${hash.substring(0, 7)}${extname}`;
55+
56+
assets.set(path.join(outputDir, newName), pathToAsset);
57+
58+
el.properties.href = `${newName}${searchString ? `?${searchString}` : ''}`;
4859
}
4960
};
5061
}
@@ -54,12 +65,21 @@ function cacheBustCss({pathToFile}) {
5465
* @param {string} pathToFile
5566
* @param {string} fileContents
5667
*/
57-
export async function processDocument(pathToFile, fileContents) {
58-
return await unified()
68+
export async function processDocument({
69+
inputFile,
70+
outputDir
71+
}) {
72+
const assets = new Map();
73+
74+
const vFile = await unified()
5975
.use(rehypeParse, {
6076
fragment: false
6177
})
62-
.use(cacheBustCss, {pathToFile})
78+
.use(cacheBustCss, {
79+
pathToFile: inputFile.name,
80+
outputDir,
81+
assets
82+
})
6383
.use(rehypeFormat, {
6484
indentInitial: false,
6585
})
@@ -70,5 +90,10 @@ export async function processDocument(pathToFile, fileContents) {
7090
useNamedReferences: true
7191
}
7292
})
73-
.process(fileContents);
93+
.process(inputFile.text);
94+
95+
return {
96+
vFile,
97+
assets
98+
};
7499
}

0 commit comments

Comments
 (0)