Skip to content

Commit a7d8726

Browse files
author
T
committed
Add legacy .html redirect stubs for old Jekyll URLs
1 parent 3301a79 commit a7d8726

2 files changed

Lines changed: 79 additions & 0 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ jobs:
5353
DOCMD_PROJECT_PREFIX: ${{ steps.base.outputs.prefix }}
5454
run: npx @docmd/core build
5555

56+
- name: Generate legacy .html redirect stubs
57+
# The old Jekyll site served /<page>.html; docmd serves /<page>/.
58+
# Emit redirect stubs so old inbound .html links keep working.
59+
run: node scripts/generate-redirects.mjs site
60+
5661
- name: Preserve custom domain (CNAME)
5762
run: if [ -f CNAME ]; then cp CNAME site/CNAME; fi
5863

scripts/generate-redirects.mjs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env node
2+
/**
3+
* generate-redirects.mjs
4+
*
5+
* The legacy Jekyll site (trustcrypto.github.io) served pages at flat
6+
* `/<slug>.html` URLs. The docmd site serves extensionless `/<slug>/`,
7+
* so every old inbound `.html` link 404s. This script writes a small
8+
* client-side redirect stub at `site/<slug>.html` for each built page so
9+
* those old URLs keep working. The `#anchor` is preserved (e.g.
10+
* `app.html#app-desktop` -> `/app/#app-desktop`).
11+
*
12+
* Run AFTER `docmd build`, against the generated `site/` directory.
13+
*/
14+
import { readdirSync, statSync, existsSync, writeFileSync } from 'node:fs';
15+
import { join } from 'node:path';
16+
17+
const SITE = process.argv[2] || 'site';
18+
19+
// Old slug -> current slug for pages that were renamed during migration.
20+
const LEGACY_ALIASES = {
21+
internationaledition: 'ite',
22+
vitrualmachines: 'virtualmachines',
23+
'keepassxc-2-1-0': 'keepassxc-upgrade',
24+
};
25+
26+
function stub(target) {
27+
// target is the extensionless, trailing-slash path relative to site root
28+
// (e.g. "duousersguide/"). Relative targets keep this working under both
29+
// a custom domain (root) and project-pages (/<repo>/) deployments.
30+
return `<!DOCTYPE html>
31+
<html lang="en">
32+
<head>
33+
<meta charset="utf-8">
34+
<title>Redirecting&hellip;</title>
35+
<link rel="canonical" href="/${target}">
36+
<meta name="robots" content="noindex">
37+
<meta http-equiv="refresh" content="0; url=${target}">
38+
<script>location.replace("${target}" + location.hash);</script>
39+
</head>
40+
<body>Redirecting to <a href="${target}">/${target}</a>&hellip;</body>
41+
</html>
42+
`;
43+
}
44+
45+
if (!existsSync(SITE)) {
46+
console.error(`[redirects] site dir not found: ${SITE}`);
47+
process.exit(1);
48+
}
49+
50+
// One stub per built page directory that contains an index.html.
51+
const slugs = readdirSync(SITE).filter((name) => {
52+
if (name === 'assets') return false;
53+
const dir = join(SITE, name);
54+
return statSync(dir).isDirectory() && existsSync(join(dir, 'index.html'));
55+
});
56+
57+
let written = 0;
58+
for (const slug of slugs) {
59+
const out = join(SITE, `${slug}.html`);
60+
if (existsSync(out)) continue; // never clobber a real built file (e.g. 404.html)
61+
writeFileSync(out, stub(`${slug}/`));
62+
written++;
63+
}
64+
65+
// Legacy renamed-page aliases.
66+
for (const [oldSlug, newSlug] of Object.entries(LEGACY_ALIASES)) {
67+
if (!slugs.includes(newSlug)) continue; // target page must exist
68+
const out = join(SITE, `${oldSlug}.html`);
69+
if (existsSync(out)) continue;
70+
writeFileSync(out, stub(`${newSlug}/`));
71+
written++;
72+
}
73+
74+
console.log(`[redirects] wrote ${written} .html redirect stubs into ${SITE}/`);

0 commit comments

Comments
 (0)