feat: redirect legacy bachelor routes to data science

This commit is contained in:
msa46 2026-08-15 20:55:56 +02:00
parent 10eead03da
commit 808f10037f
5 changed files with 55 additions and 1 deletions

View file

@ -1,6 +1,7 @@
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import { sidebar } from './src/config/sidebar.mjs';
import { legacyBachelorRedirects } from './src/config/legacy-bachelor-redirects.mjs';
const site = process.env.SITE || 'http://localhost:4321';
const base = process.env.BASE || '/';
@ -12,6 +13,7 @@ const matomoConsentScript = `${normalizedBase}/matomo-consent.js`;
export default defineConfig({
site,
base,
redirects: legacyBachelorRedirects,
integrations: [
starlight({
title: 'Incognito Wiki',

View file

@ -0,0 +1,22 @@
const routes = [
'',
'year-1/',
'year-1/project-1-1', 'year-1/project-1-2',
'year-1/block-1/discrete-mathematics', 'year-1/block-1/introduction-to-data-science-and-artifical-intelligence', 'year-1/block-1/procedural-programming',
'year-1/block-2/calculus', 'year-1/block-2/logic', 'year-1/block-2/objects-in-programming',
'year-1/block-4/data-structures-and-algorithms', 'year-1/block-4/linear-algebra', 'year-1/block-4/principles-of-data-science',
'year-1/block-5/computational-and-cognitive-neuroscience', 'year-1/block-5/numerical-methods', 'year-1/block-5/software-engineering',
'year-2/', 'year-2/project-2-1', 'year-2/project-2-2', 'year-2/honours-programme',
'year-2/block-1/databases', 'year-2/block-1/graph-theory', 'year-2/block-1/probability-and-statistics',
'year-2/block-2/machine-learning', 'year-2/block-2/reasoning-techniques', 'year-2/block-2/simulation-and-statisical-analysis',
'year-2/block-4/human-computer-interaction-and-affective-computing', 'year-2/block-4/mathematical-modelling', 'year-2/block-4/natural-language-processing',
'year-2/block-5/game-theory', 'year-2/block-5/introduction-to-image-and-video-processing', 'year-2/block-5/linear-programming', 'year-2/block-5/philosophy-and-artificial-intelligence',
'year-3/', 'year-3/bachelors-thesis', 'year-3/project-3-1', 'year-3/study-abroad', 'year-3/honours-programme',
'year-3/block-1/prolog', 'year-3/block-1/robotics-and-embedded-systems', 'year-3/block-1/semantic-web', 'year-3/block-1/software-and-systems-verification',
'year-3/block-2/introduction-to-bio-informatics', 'year-3/block-2/logic-for-artificial-intelligence', 'year-3/block-2/parallel-programming', 'year-3/block-2/quantum-computation', 'year-3/block-2/recommender-systems', 'year-3/block-2/secure-web-applications',
'year-3/block-4/data-analysis', 'year-3/block-4/intelligent-systems', 'year-3/block-4/operations-research-case-studies',
];
export const legacyBachelorRedirects = Object.freeze(Object.fromEntries(
routes.sort().map((route) => [`/bachelor/${route}`, `/data-science-and-ai/${route}`]),
));

View file

@ -7,7 +7,7 @@ export const sidebar = [
{
label: 'Bachelor',
items: [
{ slug: 'bachelor' },
{ slug: 'data-science-and-ai' },
{
label: 'Year 1',
items: [

View file

@ -18,4 +18,8 @@ test('Data Science & AI owns the former generic bachelor content tree', async ()
assert.doesNotMatch(content, /src\/content\/docs\/bachelor\//, `${file} has an old destination`);
assert.doesNotMatch(content, /href="\.\/bachelor\/"/, `${file} has an old public link`);
}
const sidebar = await readFile('src/config/sidebar.mjs', 'utf8');
assert.doesNotMatch(sidebar, /slug: 'bachelor'/);
assert.match(sidebar, /slug: 'data-science-and-ai'/);
});

View file

@ -0,0 +1,26 @@
import assert from 'node:assert/strict';
import { readdir } from 'node:fs/promises';
import test from 'node:test';
import { legacyBachelorRedirects } from '../src/config/legacy-bachelor-redirects.mjs';
async function routes(directory, prefix = '') {
const entries = await readdir(directory, { withFileTypes: true });
const found = [];
for (const entry of entries) {
const relative = `${prefix}${entry.name}`;
if (entry.isDirectory()) found.push(...await routes(`${directory}/${entry.name}`, `${relative}/`));
else if (/\.mdx?$/.test(entry.name)) {
const stem = relative.replace(/\.mdx?$/, '').replace(/index$/, '');
found.push(`/data-science-and-ai/${stem}`.replace(/\/+/g, '/'));
}
}
return found.sort();
}
test('every Data Science & AI page has an exact legacy bachelor redirect', async () => {
const canonical = await routes('src/content/docs/data-science-and-ai');
const expected = Object.fromEntries(canonical.map((target) => [target.replace('/data-science-and-ai/', '/bachelor/'), target]));
assert.deepEqual(legacyBachelorRedirects, expected);
assert.equal(legacyBachelorRedirects['/bachelor/'], '/data-science-and-ai/');
assert.equal(legacyBachelorRedirects['/bachelor/year-1/block-2/calculus'], '/data-science-and-ai/year-1/block-2/calculus');
});