docs: archive newer wiki content for comparison
This commit is contained in:
parent
e3891d18af
commit
4e06340aaa
106 changed files with 2963 additions and 0 deletions
245
package-lock.json
generated
245
package-lock.json
generated
|
|
@ -14,6 +14,8 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/check": "0.9.10",
|
"@astrojs/check": "0.9.10",
|
||||||
|
"linkedom": "0.18.13",
|
||||||
|
"turndown": "7.2.4",
|
||||||
"typescript": "6.0.2"
|
"typescript": "6.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -1791,6 +1793,13 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@mixmark-io/domino": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
"node_modules/@napi-rs/wasm-runtime": {
|
"node_modules/@napi-rs/wasm-runtime": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz",
|
||||||
|
|
@ -3134,6 +3143,13 @@
|
||||||
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
|
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
|
||||||
"license": "CC0-1.0"
|
"license": "CC0-1.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/cssom": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.4.3",
|
"version": "4.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||||
|
|
@ -4124,6 +4140,39 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/htmlparser2": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.3.0",
|
||||||
|
"domhandler": "^5.0.3",
|
||||||
|
"domutils": "^3.2.2",
|
||||||
|
"entities": "^7.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/htmlparser2/node_modules/entities": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/http-cache-semantics": {
|
"node_modules/http-cache-semantics": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
|
||||||
|
|
@ -4547,6 +4596,181 @@
|
||||||
"url": "https://opencollective.com/parcel"
|
"url": "https://opencollective.com/parcel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/linkedom": {
|
||||||
|
"version": "0.18.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/linkedom/-/linkedom-0.18.13.tgz",
|
||||||
|
"integrity": "sha512-ES/o9qotMpzpN2MHs+Iq/JcVoOj8Fa5wiQYrTdFpvAnwXL0g66XHHUc9WUMk6nAlBtGsFQ24ne+SYnvnaQ2FSw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"css-select": "^7.0.0",
|
||||||
|
"cssom": "^0.5.0",
|
||||||
|
"html-escaper": "^3.0.3",
|
||||||
|
"htmlparser2": "^10.1.0",
|
||||||
|
"uhyphen": "^0.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"canvas": ">= 2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"canvas": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/linkedom/node_modules/boolbase": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-DkVaaQHymRhpYEYo9x1oo7Q7B0Y6KJUsjm3c9eTyFDby4MHLBTwZ6ZDWBel5zrYxj1WsZgC5oLpiz+93MluXeA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.19.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/linkedom/node_modules/css-select": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-snmjEVXy+1LnwXdxhYvTMj1d9tOh4HxkA1YmoayVBeeyR2C14Pum7fcxJIm4SswYspVy866eYNwlH6xC3/VH5g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"boolbase": "^2.0.0",
|
||||||
|
"css-what": "^8.0.0",
|
||||||
|
"domhandler": "^6.0.1",
|
||||||
|
"domutils": "^4.0.2",
|
||||||
|
"nth-check": "^3.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.19.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/linkedom/node_modules/css-what": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-what/-/css-what-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-DH0Bqq3DNp5tdOReuNyAA+Ev4Y2GS5FMbZpeTLP6C4CDi0h5nL0BmUPChXw3o/qbHLDWHl49sbNqQVY7bMSDdw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.19.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/linkedom/node_modules/dom-serializer": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^3.0.0",
|
||||||
|
"domhandler": "^6.0.0",
|
||||||
|
"entities": "^8.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.19.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/linkedom/node_modules/domelementtype": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg==",
|
||||||
|
"dev": true,
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.19.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/linkedom/node_modules/domhandler": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.19.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/linkedom/node_modules/domutils": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"dom-serializer": "^3.0.0",
|
||||||
|
"domelementtype": "^3.0.0",
|
||||||
|
"domhandler": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.19.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/linkedom/node_modules/entities": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.19.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/linkedom/node_modules/nth-check": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-GX0gsdbGVCgnRgbeGaubfjpBXyYRWOOCVeYh08bSQvDZqxz5ndXs1OTfAt/h36G1xvI94YIspsI0sVFqAV9+RQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"boolbase": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.19.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/fb55/nth-check?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/longest-streak": {
|
"node_modules/longest-streak": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
|
||||||
|
|
@ -6859,6 +7083,20 @@
|
||||||
"license": "0BSD",
|
"license": "0BSD",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/turndown": {
|
||||||
|
"version": "7.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.4.tgz",
|
||||||
|
"integrity": "sha512-I8yFsfRzmzK0WV1pNNOA4A7y4RDfFxPRxb3t+e3ui14qSGOxGtiSP6GjeX+Y6CHb7HYaFj7ECUD7VE5kQMZWGQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@mixmark-io/domino": "^2.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18",
|
||||||
|
"npm": ">=9"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/typesafe-path": {
|
"node_modules/typesafe-path": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/typesafe-path/-/typesafe-path-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/typesafe-path/-/typesafe-path-0.2.2.tgz",
|
||||||
|
|
@ -6896,6 +7134,13 @@
|
||||||
"integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==",
|
"integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/uhyphen": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uhyphen/-/uhyphen-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/ultrahtml": {
|
"node_modules/ultrahtml": {
|
||||||
"version": "1.7.0",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.7.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
"preview": "astro preview",
|
"preview": "astro preview",
|
||||||
"check": "astro check && node --test",
|
"check": "astro check && node --test",
|
||||||
"check:migration": "node scripts/check-migration.mjs",
|
"check:migration": "node scripts/check-migration.mjs",
|
||||||
|
"capture:live-wiki": "node scripts/capture-live-wiki.mjs",
|
||||||
"test": "node --test"
|
"test": "node --test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -19,6 +20,8 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/check": "0.9.10",
|
"@astrojs/check": "0.9.10",
|
||||||
|
"linkedom": "0.18.13",
|
||||||
|
"turndown": "7.2.4",
|
||||||
"typescript": "6.0.2"
|
"typescript": "6.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
47
scripts/capture-live-wiki.mjs
Normal file
47
scripts/capture-live-wiki.mjs
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
import { crawlWiki } from './lib/live-wiki.mjs';
|
||||||
|
|
||||||
|
const CAPTURE_DATE = '2026-08-02';
|
||||||
|
const SCRIPT_PATH = fileURLToPath(import.meta.url);
|
||||||
|
const PROJECT_ROOT = path.resolve(path.dirname(SCRIPT_PATH), '..');
|
||||||
|
|
||||||
|
export async function runCapture({
|
||||||
|
crawlImpl = crawlWiki,
|
||||||
|
logError = console.error,
|
||||||
|
logInfo = console.log,
|
||||||
|
} = {}) {
|
||||||
|
const manifest = await crawlImpl({
|
||||||
|
capturedAt: CAPTURE_DATE,
|
||||||
|
manifestPath: path.join(PROJECT_ROOT, 'to-be-studied', 'manifest.json'),
|
||||||
|
outputRoot: path.join(PROJECT_ROOT, 'to-be-studied', 'live-wiki', CAPTURE_DATE),
|
||||||
|
});
|
||||||
|
|
||||||
|
const pageCount = manifest.pages.length;
|
||||||
|
const failureCount = manifest.failures.length;
|
||||||
|
if (failureCount > 0) {
|
||||||
|
logError(
|
||||||
|
`Captured ${pageCount} ${pluralize('page', pageCount)} with ${failureCount} ${pluralize('failure', failureCount)}; inspect to-be-studied/manifest.json.`,
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
logInfo(`Captured ${pageCount} ${pluralize('page', pageCount)} with no failures.`);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pluralize(noun, count) {
|
||||||
|
return count === 1 ? noun : `${noun}s`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.argv[1] && path.resolve(process.argv[1]) === SCRIPT_PATH) {
|
||||||
|
try {
|
||||||
|
process.exitCode = await runCapture();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error instanceof Error ? error.message : String(error));
|
||||||
|
process.exitCode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
311
scripts/lib/live-wiki.mjs
Normal file
311
scripts/lib/live-wiki.mjs
Normal file
|
|
@ -0,0 +1,311 @@
|
||||||
|
import { createHash } from 'node:crypto';
|
||||||
|
import { mkdir, rm, writeFile } from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
|
|
||||||
|
import { parseHTML } from 'linkedom';
|
||||||
|
import TurndownService from 'turndown';
|
||||||
|
|
||||||
|
export const LIVE_WIKI_BASE_URL = 'https://wiki.msvincognito.nl/';
|
||||||
|
|
||||||
|
const ASSET_EXTENSION = /\.(?:avif|bmp|css|csv|docx?|eot|gif|ico|jpe?g|js|json|map|mp3|mp4|ogg|otf|pdf|png|pptx?|rar|rss|svg|tar|tiff?|tsv|txt|wav|webm|webmanifest|webp|woff2?|xlsx?|xml|zip)$/i;
|
||||||
|
const NON_CONTENT_SELECTOR = [
|
||||||
|
'script',
|
||||||
|
'style',
|
||||||
|
'header',
|
||||||
|
'nav',
|
||||||
|
'aside',
|
||||||
|
'form',
|
||||||
|
'button',
|
||||||
|
'footer',
|
||||||
|
'noscript',
|
||||||
|
'iframe',
|
||||||
|
'dialog',
|
||||||
|
'[role="navigation"]',
|
||||||
|
'[role="contentinfo"]',
|
||||||
|
].join(',');
|
||||||
|
|
||||||
|
class PageLimitError extends Error {}
|
||||||
|
class SoftNotFoundError extends Error {}
|
||||||
|
|
||||||
|
export function normalizeWikiUrl(input, relativeTo = LIVE_WIKI_BASE_URL) {
|
||||||
|
let url;
|
||||||
|
|
||||||
|
try {
|
||||||
|
url = new URL(input, relativeTo);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const baseUrl = new URL(LIVE_WIKI_BASE_URL);
|
||||||
|
if (url.origin !== baseUrl.origin || !['http:', 'https:'].includes(url.protocol)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
url.search = '';
|
||||||
|
url.hash = '';
|
||||||
|
url.pathname = url.pathname.replace(/\/{2,}/g, '/');
|
||||||
|
|
||||||
|
if (url.pathname !== '/') {
|
||||||
|
url.pathname = url.pathname.replace(/\/+$/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ASSET_EXTENSION.test(url.pathname)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url.href;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function routeToCapturePath(input) {
|
||||||
|
const normalizedUrl = normalizeWikiUrl(input);
|
||||||
|
if (!normalizedUrl) {
|
||||||
|
throw new TypeError(`Cannot map non-content URL to a capture path: ${input}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { pathname } = new URL(normalizedUrl);
|
||||||
|
if (pathname === '/') {
|
||||||
|
return 'index.md';
|
||||||
|
}
|
||||||
|
|
||||||
|
const route = pathname
|
||||||
|
.split('/')
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((segment) => sanitizePathSegment(segment))
|
||||||
|
.join('/');
|
||||||
|
|
||||||
|
return `${route}.md`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function extractPage(html, url) {
|
||||||
|
const { document } = parseHTML(html);
|
||||||
|
const content = document.querySelector('main')
|
||||||
|
?? document.querySelector('article')
|
||||||
|
?? document.body;
|
||||||
|
|
||||||
|
if (!content) {
|
||||||
|
throw new Error(`No readable content root found at ${url}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const links = new Set();
|
||||||
|
const currentUrl = normalizeWikiUrl(url);
|
||||||
|
for (const anchor of content.querySelectorAll('a[href]')) {
|
||||||
|
const normalizedLink = normalizeWikiUrl(anchor.getAttribute('href'), url);
|
||||||
|
if (normalizedLink && normalizedLink !== currentUrl) {
|
||||||
|
links.add(normalizedLink);
|
||||||
|
anchor.setAttribute('href', normalizedLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const heading = content.querySelector('h1, h2, h3');
|
||||||
|
const title = cleanText(heading?.textContent)
|
||||||
|
|| cleanText(document.querySelector('title')?.textContent)
|
||||||
|
|| titleFromUrl(url);
|
||||||
|
|
||||||
|
for (const element of content.querySelectorAll(NON_CONTENT_SELECTOR)) {
|
||||||
|
element.remove();
|
||||||
|
}
|
||||||
|
removeLiveWikiChrome(content);
|
||||||
|
|
||||||
|
const turndown = new TurndownService({
|
||||||
|
bulletListMarker: '-',
|
||||||
|
codeBlockStyle: 'fenced',
|
||||||
|
emDelimiter: '*',
|
||||||
|
headingStyle: 'atx',
|
||||||
|
});
|
||||||
|
turndown.addRule('lineBreakWithoutTrailingWhitespace', {
|
||||||
|
filter: 'br',
|
||||||
|
replacement: () => '<br>\n',
|
||||||
|
});
|
||||||
|
const markdown = `${turndown.turndown(content).trim().replace(/[ \t]+$/gm, '')}\n`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
markdown,
|
||||||
|
links: [...links].sort(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function crawlWiki({
|
||||||
|
capturedAt = new Date().toISOString().slice(0, 10),
|
||||||
|
delayMs = 150,
|
||||||
|
fetchImpl = globalThis.fetch,
|
||||||
|
manifestPath,
|
||||||
|
maxPages = 500,
|
||||||
|
outputRoot,
|
||||||
|
startUrls = [LIVE_WIKI_BASE_URL],
|
||||||
|
waitImpl = wait,
|
||||||
|
} = {}) {
|
||||||
|
if (!outputRoot || !manifestPath) {
|
||||||
|
throw new TypeError('crawlWiki requires outputRoot and manifestPath.');
|
||||||
|
}
|
||||||
|
if (!/^\d{4}-\d{2}-\d{2}$/.test(capturedAt)) {
|
||||||
|
throw new TypeError('capturedAt must use YYYY-MM-DD format.');
|
||||||
|
}
|
||||||
|
if (!Number.isInteger(maxPages) || maxPages < 1) {
|
||||||
|
throw new TypeError('maxPages must be a positive integer.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const queue = [];
|
||||||
|
const discovered = new Set();
|
||||||
|
for (const startUrl of startUrls) {
|
||||||
|
discover(startUrl, LIVE_WIKI_BASE_URL, discovered, queue, maxPages);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pages = [];
|
||||||
|
const failures = [];
|
||||||
|
let requestCount = 0;
|
||||||
|
|
||||||
|
await mkdir(outputRoot, { recursive: true });
|
||||||
|
|
||||||
|
while (queue.length > 0) {
|
||||||
|
queue.sort();
|
||||||
|
const url = queue.shift();
|
||||||
|
|
||||||
|
if (requestCount > 0) {
|
||||||
|
await waitImpl(delayMs);
|
||||||
|
}
|
||||||
|
requestCount += 1;
|
||||||
|
const capturePath = routeToCapturePath(url);
|
||||||
|
const destination = path.join(outputRoot, ...capturePath.split('/'));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetchImpl(url, {
|
||||||
|
headers: {
|
||||||
|
accept: 'text/html,application/xhtml+xml',
|
||||||
|
'user-agent': 'Incognito-Wiki research capture (+https://msvincognito.nl/)',
|
||||||
|
},
|
||||||
|
redirect: 'follow',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response) {
|
||||||
|
throw new Error('No response');
|
||||||
|
}
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP ${response.status} ${response.statusText}`.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentType = response.headers.get('content-type') ?? '';
|
||||||
|
if (contentType && !/\b(?:text\/html|application\/xhtml\+xml)\b/i.test(contentType)) {
|
||||||
|
throw new Error(`Unexpected content type: ${contentType}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const page = extractPage(await response.text(), url);
|
||||||
|
if (page.title === '404' && /This page could not be found\./i.test(page.markdown)) {
|
||||||
|
throw new SoftNotFoundError('Soft 404: This page could not be found.');
|
||||||
|
}
|
||||||
|
for (const link of page.links) {
|
||||||
|
discover(link, url, discovered, queue, maxPages);
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = `> Source: ${url}\n> Captured: ${capturedAt}\n\n${page.markdown}`;
|
||||||
|
|
||||||
|
await mkdir(path.dirname(destination), { recursive: true });
|
||||||
|
await writeFile(destination, content, 'utf8');
|
||||||
|
|
||||||
|
pages.push({
|
||||||
|
url,
|
||||||
|
title: page.title,
|
||||||
|
path: toPosixPath(path.relative(path.dirname(manifestPath), destination)),
|
||||||
|
contentHash: createHash('sha256').update(content).digest('hex'),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof PageLimitError) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
await rm(destination, { force: true });
|
||||||
|
if (error instanceof SoftNotFoundError) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
failures.push({
|
||||||
|
url,
|
||||||
|
error: error instanceof Error ? error.message : String(error),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const manifest = {
|
||||||
|
capturedAt,
|
||||||
|
baseUrl: LIVE_WIKI_BASE_URL,
|
||||||
|
pages: pages.sort(compareByUrl),
|
||||||
|
failures: failures.sort(compareByUrl),
|
||||||
|
};
|
||||||
|
|
||||||
|
await mkdir(path.dirname(manifestPath), { recursive: true });
|
||||||
|
await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
|
||||||
|
|
||||||
|
return manifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanText(value = '') {
|
||||||
|
return value.replace(/\s+/g, ' ').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeLiveWikiChrome(content) {
|
||||||
|
for (const element of content.querySelectorAll('[class]')) {
|
||||||
|
const classes = new Set(element.classList);
|
||||||
|
const text = cleanText(element.textContent);
|
||||||
|
|
||||||
|
const isPreviousNextNavigation = classes.has('mt-16');
|
||||||
|
const isRepeatedPageFooter = classes.has('hidden')
|
||||||
|
&& classes.has('text-sm')
|
||||||
|
&& classes.has('lg:block')
|
||||||
|
&& /Star on GitHub|Create Issues/.test(text);
|
||||||
|
|
||||||
|
if (isPreviousNextNavigation || isRepeatedPageFooter) {
|
||||||
|
element.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sanitizePathSegment(segment) {
|
||||||
|
let decoded;
|
||||||
|
try {
|
||||||
|
decoded = decodeURIComponent(segment);
|
||||||
|
} catch {
|
||||||
|
decoded = segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
const safe = decoded
|
||||||
|
.normalize('NFKC')
|
||||||
|
.replace(/[^\p{Letter}\p{Number}._-]+/gu, '-')
|
||||||
|
.replace(/^-+|-+$/g, '');
|
||||||
|
|
||||||
|
if (!safe || safe === '.' || safe === '..') {
|
||||||
|
throw new Error(`Unsafe live-wiki route segment: ${segment}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return safe;
|
||||||
|
}
|
||||||
|
|
||||||
|
function titleFromUrl(url) {
|
||||||
|
const { pathname } = new URL(url);
|
||||||
|
const lastSegment = pathname.split('/').filter(Boolean).at(-1) ?? 'Home';
|
||||||
|
return decodeURIComponent(lastSegment)
|
||||||
|
.replace(/[-_]+/g, ' ')
|
||||||
|
.replace(/\b\p{Letter}/gu, (letter) => letter.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
function discover(input, relativeTo, discovered, queue, maxPages) {
|
||||||
|
const url = normalizeWikiUrl(input, relativeTo);
|
||||||
|
if (!url || discovered.has(url)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
discovered.add(url);
|
||||||
|
if (discovered.size > maxPages) {
|
||||||
|
throw new PageLimitError(`Discovered more than ${maxPages} content pages; refusing to truncate the crawl.`);
|
||||||
|
}
|
||||||
|
queue.push(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
function compareByUrl(left, right) {
|
||||||
|
return left.url.localeCompare(right.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toPosixPath(input) {
|
||||||
|
return input.split(path.sep).join('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
function wait(milliseconds) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
||||||
|
}
|
||||||
222
tests/live-wiki.test.mjs
Normal file
222
tests/live-wiki.test.mjs
Normal file
|
|
@ -0,0 +1,222 @@
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { createHash } from 'node:crypto';
|
||||||
|
import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
||||||
|
import { tmpdir } from 'node:os';
|
||||||
|
import path from 'node:path';
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
import {
|
||||||
|
crawlWiki,
|
||||||
|
extractPage,
|
||||||
|
normalizeWikiUrl,
|
||||||
|
routeToCapturePath,
|
||||||
|
} from '../scripts/lib/live-wiki.mjs';
|
||||||
|
import { runCapture } from '../scripts/capture-live-wiki.mjs';
|
||||||
|
|
||||||
|
test('normalizes only same-origin content routes', () => {
|
||||||
|
assert.equal(
|
||||||
|
normalizeWikiUrl('/useful-guides/description?draft=1#details'),
|
||||||
|
'https://wiki.msvincognito.nl/useful-guides/description',
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
normalizeWikiUrl('https://wiki.msvincognito.nl/useful-guides/description/'),
|
||||||
|
'https://wiki.msvincognito.nl/useful-guides/description',
|
||||||
|
);
|
||||||
|
assert.equal(normalizeWikiUrl('https://example.com/page'), null);
|
||||||
|
assert.equal(normalizeWikiUrl('/assets/diagram.png'), null);
|
||||||
|
assert.equal(normalizeWikiUrl('mailto:board@msvincognito.nl'), null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('maps routes to readable Markdown files', () => {
|
||||||
|
assert.equal(
|
||||||
|
routeToCapturePath('https://wiki.msvincognito.nl/useful-guides/description'),
|
||||||
|
'useful-guides/description.md',
|
||||||
|
);
|
||||||
|
assert.equal(routeToCapturePath('https://wiki.msvincognito.nl/'), 'index.md');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('extracts the main article and internal links', () => {
|
||||||
|
const html = `
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<nav><a href="/ignored">Repeated navigation</a></nav>
|
||||||
|
<main>
|
||||||
|
<h1>Guide</h1>
|
||||||
|
<p>Text<br>Second line</p>
|
||||||
|
<a href="/next?from=guide#part">Next</a>
|
||||||
|
<a href="https://example.com/external">External</a>
|
||||||
|
<form><input name="secret"><button>Submit</button></form>
|
||||||
|
<script>throw new Error('not content')</script>
|
||||||
|
</main>
|
||||||
|
<footer>Repeated footer</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const page = extractPage(html, 'https://wiki.msvincognito.nl/guide');
|
||||||
|
|
||||||
|
assert.equal(page.title, 'Guide');
|
||||||
|
assert.match(page.markdown, /^# Guide/m);
|
||||||
|
assert.match(page.markdown, /Text/);
|
||||||
|
assert.doesNotMatch(page.markdown, /[ \t]+$/m);
|
||||||
|
assert.doesNotMatch(page.markdown, /Submit|not content|Repeated footer/);
|
||||||
|
assert.deepEqual(page.links, ['https://wiki.msvincognito.nl/next']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('falls back from main to article and then body', () => {
|
||||||
|
const articlePage = extractPage(
|
||||||
|
'<article><h2>Article title</h2><p>Article text</p></article>',
|
||||||
|
'https://wiki.msvincognito.nl/article',
|
||||||
|
);
|
||||||
|
const bodyPage = extractPage(
|
||||||
|
'<html><head><title>Body title</title></head><body><header>Site chrome</header><p>Body text</p></body></html>',
|
||||||
|
'https://wiki.msvincognito.nl/body',
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(articlePage.title, 'Article title');
|
||||||
|
assert.match(articlePage.markdown, /Article text/);
|
||||||
|
assert.equal(bodyPage.title, 'Body title');
|
||||||
|
assert.match(bodyPage.markdown, /Body text/);
|
||||||
|
assert.doesNotMatch(bodyPage.markdown, /Site chrome/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('removes the live wiki previous-next panel and repeated page footer', () => {
|
||||||
|
const page = extractPage(`
|
||||||
|
<main>
|
||||||
|
<div>
|
||||||
|
<h1>Course</h1>
|
||||||
|
<p>Useful article content.</p>
|
||||||
|
<div class="mt-16"><a href="/previous">Previous</a></div>
|
||||||
|
</div>
|
||||||
|
<div class="hidden text-sm lg:block">
|
||||||
|
<a href="https://github.com/example">Star on GitHub</a>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
`, 'https://wiki.msvincognito.nl/course');
|
||||||
|
|
||||||
|
assert.match(page.markdown, /Useful article content/);
|
||||||
|
assert.doesNotMatch(page.markdown, /Previous|Star on GitHub/);
|
||||||
|
assert.deepEqual(page.links, ['https://wiki.msvincognito.nl/previous']);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('crawls in sorted order, writes successful pages, and records failures', async (context) => {
|
||||||
|
const captureRoot = await mkdtemp(path.join(tmpdir(), 'live-wiki-crawl-'));
|
||||||
|
context.after(() => rm(captureRoot, { recursive: true, force: true }));
|
||||||
|
const outputRoot = path.join(captureRoot, 'live-wiki', '2026-08-02');
|
||||||
|
const manifestPath = path.join(captureRoot, 'manifest.json');
|
||||||
|
const requests = [];
|
||||||
|
const waits = [];
|
||||||
|
const responses = new Map([
|
||||||
|
[
|
||||||
|
'https://wiki.msvincognito.nl/',
|
||||||
|
response('<main><h1>Home</h1><a href="/z-last">Z</a><a href="/a-first">A</a></main>'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'https://wiki.msvincognito.nl/a-first',
|
||||||
|
response('<main><h1>First</h1><p>Captured text.</p></main>'),
|
||||||
|
],
|
||||||
|
['https://wiki.msvincognito.nl/z-last', response('Unavailable', 503)],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const manifest = await crawlWiki({
|
||||||
|
capturedAt: '2026-08-02',
|
||||||
|
manifestPath,
|
||||||
|
outputRoot,
|
||||||
|
fetchImpl: async (url) => {
|
||||||
|
requests.push(url);
|
||||||
|
return responses.get(url);
|
||||||
|
},
|
||||||
|
waitImpl: async (milliseconds) => waits.push(milliseconds),
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(requests, [
|
||||||
|
'https://wiki.msvincognito.nl/',
|
||||||
|
'https://wiki.msvincognito.nl/a-first',
|
||||||
|
'https://wiki.msvincognito.nl/z-last',
|
||||||
|
]);
|
||||||
|
assert.deepEqual(waits, [150, 150]);
|
||||||
|
assert.deepEqual(manifest.pages.map(({ url }) => url), [
|
||||||
|
'https://wiki.msvincognito.nl/',
|
||||||
|
'https://wiki.msvincognito.nl/a-first',
|
||||||
|
]);
|
||||||
|
assert.deepEqual(manifest.failures, [{
|
||||||
|
url: 'https://wiki.msvincognito.nl/z-last',
|
||||||
|
error: 'HTTP 503 Service Unavailable',
|
||||||
|
}]);
|
||||||
|
|
||||||
|
const captured = await readFile(path.join(outputRoot, 'a-first.md'), 'utf8');
|
||||||
|
assert.match(captured, /^> Source: https:\/\/wiki\.msvincognito\.nl\/a-first\n> Captured: 2026-08-02\n\n/);
|
||||||
|
assert.match(captured, /# First\n\nCaptured text\./);
|
||||||
|
assert.equal(
|
||||||
|
manifest.pages[1].contentHash,
|
||||||
|
createHash('sha256').update(captured).digest('hex'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const savedManifest = JSON.parse(await readFile(manifestPath, 'utf8'));
|
||||||
|
assert.deepEqual(savedManifest, manifest);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('rejects discovery beyond the configured page ceiling', async (context) => {
|
||||||
|
const captureRoot = await mkdtemp(path.join(tmpdir(), 'live-wiki-limit-'));
|
||||||
|
context.after(() => rm(captureRoot, { recursive: true, force: true }));
|
||||||
|
|
||||||
|
await assert.rejects(
|
||||||
|
crawlWiki({
|
||||||
|
capturedAt: '2026-08-02',
|
||||||
|
manifestPath: path.join(captureRoot, 'manifest.json'),
|
||||||
|
outputRoot: path.join(captureRoot, 'live-wiki', '2026-08-02'),
|
||||||
|
maxPages: 2,
|
||||||
|
fetchImpl: async () => response(
|
||||||
|
'<main><h1>Home</h1><a href="/one">One</a><a href="/two">Two</a></main>',
|
||||||
|
),
|
||||||
|
waitImpl: async () => {},
|
||||||
|
}),
|
||||||
|
/more than 2 content pages/i,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('excludes soft 404 navigation placeholders and removes stale captures', async (context) => {
|
||||||
|
const captureRoot = await mkdtemp(path.join(tmpdir(), 'live-wiki-soft-404-'));
|
||||||
|
context.after(() => rm(captureRoot, { recursive: true, force: true }));
|
||||||
|
const outputRoot = path.join(captureRoot, 'live-wiki', '2026-08-02');
|
||||||
|
const stalePath = path.join(outputRoot, 'missing.md');
|
||||||
|
await mkdir(outputRoot, { recursive: true });
|
||||||
|
await writeFile(stalePath, 'stale capture', 'utf8');
|
||||||
|
|
||||||
|
const manifest = await crawlWiki({
|
||||||
|
capturedAt: '2026-08-02',
|
||||||
|
manifestPath: path.join(captureRoot, 'manifest.json'),
|
||||||
|
outputRoot,
|
||||||
|
fetchImpl: async (url) => url.endsWith('/missing')
|
||||||
|
? response('<main><h3>404</h3><p>This page could not be found.</p></main>')
|
||||||
|
: response('<main><h1>Home</h1><a href="/missing">Missing category</a></main>'),
|
||||||
|
waitImpl: async () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(manifest.pages.map(({ url }) => url), ['https://wiki.msvincognito.nl/']);
|
||||||
|
assert.deepEqual(manifest.failures, []);
|
||||||
|
await assert.rejects(readFile(stalePath, 'utf8'), { code: 'ENOENT' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('capture command reports failure after the crawler preserves its manifest', async () => {
|
||||||
|
const messages = [];
|
||||||
|
const exitCode = await runCapture({
|
||||||
|
crawlImpl: async () => ({
|
||||||
|
pages: [{ url: 'https://wiki.msvincognito.nl/' }],
|
||||||
|
failures: [{ url: 'https://wiki.msvincognito.nl/broken', error: 'HTTP 503' }],
|
||||||
|
}),
|
||||||
|
logError: (message) => messages.push(message),
|
||||||
|
logInfo: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(exitCode, 1);
|
||||||
|
assert.deepEqual(messages, ['Captured 1 page with 1 failure; inspect to-be-studied/manifest.json.']);
|
||||||
|
});
|
||||||
|
|
||||||
|
function response(body, status = 200) {
|
||||||
|
return new Response(body, {
|
||||||
|
status,
|
||||||
|
statusText: status === 200 ? 'OK' : status === 503 ? 'Service Unavailable' : 'Error',
|
||||||
|
headers: { 'content-type': 'text/html; charset=utf-8' },
|
||||||
|
});
|
||||||
|
}
|
||||||
9
to-be-studied/README.md
Normal file
9
to-be-studied/README.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Live-wiki research snapshot
|
||||||
|
|
||||||
|
This directory is a research snapshot of public, unauthenticated pages from `https://wiki.msvincognito.nl/`. It is not a source for the published migration and may contain incomplete, superseded, or outdated material.
|
||||||
|
|
||||||
|
The snapshot was captured on 2026-08-02 with `npm run capture:live-wiki`. The crawler stays on the live wiki's origin, never authenticates or submits forms, waits 150 ms between requests, refuses to crawl more than 500 content pages, and records request failures in `manifest.json`. It converts the first `<main>` element (falling back to `<article>` and then `<body>`) to readable Markdown after removing site chrome. Public navigation enumerated the content; the site's `/sitemap.xml` and `/robots.txt` routes both render its soft-404 page, so neither supplied additional URLs. The capture excludes navigation category URLs that return the same deterministic soft-404 page instead of content.
|
||||||
|
|
||||||
|
Files under `live-wiki/2026-08-02/` retain their public source URL and capture date. `manifest.json` records the sorted capture inventory and SHA-256 hash of every Markdown file. `comparison.md` compares that inventory with the 29-entry DokuWiki export manifest.
|
||||||
|
|
||||||
|
Nothing in this directory is published by Starlight. This directory must never be moved or copied into `src/content/docs/` without a separate content review. It must also remain outside `public/`.
|
||||||
76
to-be-studied/comparison.md
Normal file
76
to-be-studied/comparison.md
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
# Export and live-wiki comparison
|
||||||
|
|
||||||
|
This is a research inventory, not a merge decision. It compares the 98 successful pages in `manifest.json` with all 29 source entries in `docs/migration-manifest.json`. The comparison is page-level: a live course page can be new-only even when its surrounding year/programme taxonomy overlaps an exported index page.
|
||||||
|
|
||||||
|
## New live-wiki pages with no exported page equivalent
|
||||||
|
|
||||||
|
These 88 successful live pages have no one-to-one page in the export. Course titles are listed so every captured course page is concretely classified rather than represented only by a count.
|
||||||
|
|
||||||
|
| Live route or family | Count | Captured pages | Classification |
|
||||||
|
| --- | ---: | --- | --- |
|
||||||
|
| `/computer-science` and `/computer-science/course-description` | 2 | Course Description (two routes with the same sparse content) | The export has no Computer Science programme page; its bachelor programme is Data Science and Artificial Intelligence. |
|
||||||
|
| `/computer-science/year-1/**` | 12 | Discrete Math; Introduction to Computer Science; Procedural Programming; Calculus; Logic; Objects in Programming; Computer Architecture; Data Structures and Algorithms; Linear Algebra; Databases; Algorithmic Design; Statistics | New course-level hierarchy organized by year and period; the export has no corresponding course pages. |
|
||||||
|
| `/computer-science/year-2/**` | 14 | Intelligent User Interfaces; Introduction to Artificial Intelligence; Operating Systems; Computer Networks; Software Engineering and Architectures; Computer Security; Embedded Programming; Parallel Programming; Numerical Methods; Principles of Programming Languages; M2-1: AI and Machine Learning; M2-1: Intelligent Interaction; M2-2: Cybersecurity; M2-2: High Performance Computing | New course/elective pages; no exported equivalents. |
|
||||||
|
| `/computer-science/year-3/**` | 16 | Digital Society; Game Theory; Graph Theory; Introduction to Quantum Computing; Robotics and Embedded Systems; Ubiquitous Computing & Internet of Things; Block Chains; Cryptography; Immersive Technologies; Introduction to Bio-Informatics; Large Scale IT and Cloud Computing; Software and Systems Verification; Startup Engineering: Building Scalable Tech Ventures; The History and Philosophy of Computing; Operating Systems; Theory of Computing | New course/elective pages; no exported equivalents. |
|
||||||
|
| `/data-science-and-artificial-intelligence/year-1/**` | 12 | Discrete Mathematics; Introduction to Data Science and Artificial Intelligence; Procedural Programming; Calculus; Logic; Objects in Programming; Data Structures and Algorithms; Linear Algebra; Principles of Data Science; Computational and Cognitive Neuroscience; Numerical Methods; Software Engineering | The exported Year 1 page is only a schedule/index shell and has no individual course pages. |
|
||||||
|
| `/data-science-and-artificial-intelligence/year-2/**` | 13 | Databases; Graph Theory; Probability and Statistics; Machine Learning; Reasoning Techniques; Simulation and Statistical Analysis; Human Computer Interaction & Affective Computing; Mathematical Modelling; Natural Language Processing; Game Theory; Introduction to Image & Video Processing; Linear Programming; Philosophy & Artificial Intelligence | The exported Year 2 branch contains projects and an honours placeholder, not these course pages. |
|
||||||
|
| `/data-science-and-artificial-intelligence/year-3/**` | 16 | Digital Society; Game Theory; Introduction to Quantum Computing; Multi-Scale Modelling of Biological Systems; Robotics and Embedded Systems; Semantic Web; Business Process & Knowledge Management; Computer Security; Introduction to Bio-Informatics; Large Scale IT and Cloud Computing; Logic for Artificial Intelligence; Parallel Programming; Recommender Systems; Data Analysis; Intelligent Systems; Operations Research | The exported Year 3 branch contains thesis/project/study-abroad material, not these course pages. |
|
||||||
|
| `/useful-guides/housing-guide` | 1 | Housing Guide | New 2025 housing-market and scam-avoidance guide; the exported Handy Locations page only names study/food-location categories. |
|
||||||
|
| `/useful-guides/linux-tricks` | 1 | Linux Tricks | Linux-specific Eduroam, VPN, file-service, and remote-desktop advice; there is no matching exported page. |
|
||||||
|
| `/useful-guides/survivingdacs` | 1 | DACS Survival Guide | Broad study, projects, exams, programming, mathematics, and student-life advice; there is no one-to-one export page. |
|
||||||
|
|
||||||
|
## Exported pages with no obvious live-wiki page equivalent
|
||||||
|
|
||||||
|
All seven exported project pages are called out explicitly. Year landing pages are included because their apparent live category URLs are soft 404s; their taxonomy is compared separately below.
|
||||||
|
|
||||||
|
| Export source path | Exported topic | Evidence/classification |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `pages/study/msv_incognito.txt` | MSV Incognito association | The live home page links the association but has no association-history/membership page. |
|
||||||
|
| `pages/study/bachelor/year_1.txt` | Bachelor Year 1 index and schedule | No valid live Year 1 landing page; live leaf courses are a structural overlap only. |
|
||||||
|
| `pages/study/bachelor/year_1/project_1-1.txt` | Project 1-1 | Exported project page; no live project page. |
|
||||||
|
| `pages/study/bachelor/year_1/project_1-2.txt` | Project 1-2 | Exported project page; no live project page. |
|
||||||
|
| `pages/study/bachelor/year_2.txt` | Bachelor Year 2 index and schedule | No valid live Year 2 landing page; live leaf courses are a structural overlap only. |
|
||||||
|
| `pages/study/bachelor/year_2/honours_programme.txt` | Year 2 honours programme | No live honours page. |
|
||||||
|
| `pages/study/bachelor/year_2/project_2-1.txt` | Project 2-1 | Exported project page; no live project page. |
|
||||||
|
| `pages/study/bachelor/year_2/project_2-2.txt` | Project 2-2 | Exported project page; no live project page. |
|
||||||
|
| `pages/study/bachelor/year_3.txt` | Bachelor Year 3 index and schedule | No valid live Year 3 landing page; live leaf courses are a structural overlap only. |
|
||||||
|
| `pages/study/bachelor/year_3/bachelors_thesis.txt` | Bachelor thesis | No live thesis page. |
|
||||||
|
| `pages/study/bachelor/year_3/honours_programme.txt` | Year 3 honours programme | No live honours page. |
|
||||||
|
| `pages/study/bachelor/year_3/project_3-1.txt` | Project 3-1 | Exported project page; no live project page. |
|
||||||
|
| `pages/study/bachelor/year_3/study_abroad.txt` | Study abroad | No live study-abroad page. |
|
||||||
|
| `pages/study/master_ai/year_1.txt` | MSc AI Year 1 index | The live MSc AI branch has only a sparse course-description page and no year hierarchy. |
|
||||||
|
| `pages/study/master_ai/year_1/project_mai_1.txt` | MSc AI Research Project 1 | Exported project page; no live project page. |
|
||||||
|
| `pages/study/master_ai/year_1/project_mai_2.txt` | MSc AI Research Project 2 | Exported project page; no live project page. |
|
||||||
|
| `pages/study/master_ai/year_2.txt` | MSc AI Year 2 index | No live MSc AI Year 2 page. |
|
||||||
|
| `pages/study/master_dsdm/year_1.txt` | MSc DSDM Year 1 index | The live DSDM branch has only a sparse course-description page and no year hierarchy. |
|
||||||
|
| `pages/study/master_dsdm/year_2.txt` | MSc DSDM Year 2 index | No live DSDM Year 2 page. |
|
||||||
|
| `pages/study/useful_information/pages/dke_locations.txt` | DKE/DACS teaching locations | No live locations page. |
|
||||||
|
| `pages/study/useful_information/pages/handy_locations.txt` | Study, food, and other locations | The Housing Guide is materially different and is not an equivalent. |
|
||||||
|
| `pages/study/useful_information/pages/it_services.txt` | General UM IT services | Linux Tricks overlaps a few technologies but is Linux-specific and not a replacement for the exported service-desk, portal, enrolment, grades, VPN, and printing page. |
|
||||||
|
|
||||||
|
## Overlapping topics and substantive differences
|
||||||
|
|
||||||
|
| Export source path | Live URL | Substantive difference |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `pages/start.txt` + `pages/study.txt` | `https://wiki.msvincognito.nl/` | The export has association/registration/editing instructions, official links, Maastricht University context, and programme descriptions. The live home is a short DACS landing page linking four programme areas and Useful Guides. |
|
||||||
|
| `pages/study/bachelor.txt` | `https://wiki.msvincognito.nl/data-science-and-artificial-intelligence` and `/course-description` | Both identify the Data Science and Artificial Intelligence bachelor area. The export explains the programme index and contribution workflow; both live routes currently contain only a sparse “Course Description / #Hello” page. |
|
||||||
|
| `pages/study/bachelor/year_1.txt` | `https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-1/discrete-mathematics` (representative of 12 Year 1 leaf pages) | The export is a year index with a missing schedule image and page-creation controls. The live wiki has period/course leaf pages but its Year 1 and period category URLs render soft 404s. |
|
||||||
|
| `pages/study/bachelor/year_2.txt` | `https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-1/databases` (representative of 13 Year 2 leaf pages) | The export is a schedule/index shell plus upload instructions. The live wiki replaces that organization with period/elective course leaves and no valid Year 2 landing page. |
|
||||||
|
| `pages/study/bachelor/year_3.txt` | `https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-4/data-analysis` (representative of 16 Year 3 leaf pages) | The export discusses thesis timing and indexes thesis/project/study-abroad pages. The live branch lists course/elective leaves and contains no thesis or project page. |
|
||||||
|
| `pages/study/master_ai.txt` | `https://wiki.msvincognito.nl/artificial-intelligence` and `/course-description` | Both label the MSc Artificial Intelligence area. The export describes course summaries, exams, year navigation, and contribution flow; the live routes are currently a sparse “Course Description / #Hello” page with no year/course content. |
|
||||||
|
| `pages/study/master_dsdm.txt` | `https://wiki.msvincognito.nl/data-science-for-decision-making` and `/course-description` | Both label the MSc Data Science for Decision Making area. The export has year navigation and contribution context; the live routes contain only the sparse description placeholder. |
|
||||||
|
| `pages/study/useful_information.txt` | `https://wiki.msvincognito.nl/useful-guides` and `/description` | The export indexes locations, IT services, and laptop advice. The live index instead presents Housing, Laptop Buying Advice, Linux Tricks, and Surviving DACS, and claims the guides are updated “somewhat regularly.” |
|
||||||
|
| `pages/study/useful_information/pages/laptop_buy_advice.txt` | `https://wiki.msvincognito.nl/useful-guides/laptop-buying-advice` | The live page preserves and edits the exported tier guide, marks it as last updated 2021, and adds a current minimum of 16 GB RAM/512 GB SSD, Apple M-series compatibility, and an Nvidia/CUDA recommendation for data-science programmes. |
|
||||||
|
|
||||||
|
## Navigation placeholders excluded from the capture
|
||||||
|
|
||||||
|
Public navigation enumerated 31 category URLs that return HTTP 200 but render exactly `404` and `This page could not be found.` They are navigation/taxonomy placeholders, not content pages, so the crawler excludes them and `manifest.json` has no failures. All leaf pages reachable through the same public navigation were retained.
|
||||||
|
|
||||||
|
| Route family | Excluded count | Exact category suffixes |
|
||||||
|
| --- | ---: | --- |
|
||||||
|
| `/computer-science/year-1` | 5 | year root; `period-1`; `period-2`; `period-4`; `period-5` |
|
||||||
|
| `/computer-science/year-2` | 7 | year root; `period-1`; `period-2`; `period-4`; `period-5`; `semester-1-electives`; `semester-2-electives` |
|
||||||
|
| `/computer-science/year-3` | 4 | year root; `period-1-electives`; `period-2-electives`; `period-4` |
|
||||||
|
| `/data-science-and-artificial-intelligence/year-1` | 5 | year root; `period-1`; `period-2`; `period-4`; `period-5` |
|
||||||
|
| `/data-science-and-artificial-intelligence/year-2` | 6 | year root; `period-1`; `period-2`; `period-4`; `period-5`; `period-5-electives` |
|
||||||
|
| `/data-science-and-artificial-intelligence/year-3` | 4 | year root; `period-1-electives`; `period-2-electives`; `period-4` |
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/artificial-intelligence
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Course Description
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/artificial-intelligence/course-description
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Course Description
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
||||||
|
#Hello
|
||||||
8
to-be-studied/live-wiki/2026-08-02/computer-science.md
Normal file
8
to-be-studied/live-wiki/2026-08-02/computer-science.md
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Course Description
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/course-description
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Course Description
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-1/discrete-math
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Discrete Math
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-1/discrete-math.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-1/introduction-to-computer-science
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Introduction to Computer Science
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-1/introduction-to-computer-science.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-1/procedural-programming
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Procedural Programming
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-1/procedural-programming.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-2/calculus
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Calculus
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-2/calculus.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-2/logic
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Logic
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-2/logic.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-2/objects-in-programming
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Objects in Programming
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-2/objects-in-programming.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-4/computer-architecture
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Computer Architecture
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-4/computer-architecture.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-4/data-structures-and-algorithms
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Data Structures and Algorithms
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-4/data-structures-and-algorithms.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-4/linear-algebra
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Linear Algebra
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-4/linear-algebra.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-5/databases
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Databases
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-5/databases.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-5/discrete-math
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Algorithmic Design
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-5/discrete-math.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-1/period-5/statistics
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Statistics
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-1/period-5/statistics.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/period-1/intelligent-user-interfaces
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Intelligent User Interfaces
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/period-1/intelligent-user-interfaces.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/period-1/introduction-to-artificial-intelligence
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Introduction to Artificial Intelligence
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/period-1/introduction-to-artificial-intelligence.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/period-1/operating-systems
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Operating Systems
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/period-1/operating-systems.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/period-2/computer-networks
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Computer Networks
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/period-2/computer-networks.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/period-2/software-engineering-and-architectures
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Software Engineering and Architectures
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/period-2/software-engineering-and-architectures.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/period-4/computer-security
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Computer Security
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/period-4/computer-security.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/period-4/embedded-programming
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Embedded Programming
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/period-4/embedded-programming.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/period-4/parallel-programming
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Parallel Programming
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/period-4/parallel-programming.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/period-5/numerical-methods
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Numerical Methods
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/period-5/numerical-methods.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/period-5/principles-of-programming-languages
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Principles of Programming Languages
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/period-5/principles-of-programming-languages.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/semester-1-electives/ai-and-machine-learning
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# M2-1: AI and Machine Learning
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/semester-1-electives/ai-and-machine-learning.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/semester-1-electives/intelligent-interaction
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# M2-1: Intelligent Interaction
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/semester-1-electives/intelligent-interaction.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/semester-2-electives/cybersecurity
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# M2-2: Cybersecurity
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/semester-2-electives/cybersecurity.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-2/semester-2-electives/high-performance-computing
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# M2-2: High Performance Computing
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-2/semester-2-electives/high-performance-computing.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-1-electives/digital-society
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Digital Society
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-1-electives/digital-society.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-1-electives/game-theory
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Game Theory
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-1-electives/game-theory.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-1-electives/graph-theory
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Graph Theory
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-1-electives/graph-theory.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-1-electives/introduction-to-quantum-computing
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Introduction to Quantum Computing
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-1-electives/introduction-to-quantum-computing.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-1-electives/robotics-and-embedded-systems
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Robotics and Embedded Systems
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-1-electives/robotics-and-embedded-systems.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-1-electives/ubiquitous-computing-iot
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Ubiquitous Computing & Internet of Things
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-1-electives/ubiquitous-computing-iot.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-2-electives/block-chains
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Block Chains
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-2-electives/block-chains.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-2-electives/cryptography
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Cryptography
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-2-electives/cryptography.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-2-electives/immersive-technologies
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Immersive Technologies
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-2-electives/immersive-technologies.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-2-electives/introduction-to-bio-informatics
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Introduction to Bio-Informatics
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-2-electives/introduction-to-bio-informatics.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-2-electives/large-scale-it-and-cloud-computing
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Large Scale IT and Cloud Computing
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-2-electives/large-scale-it-and-cloud-computing.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-2-electives/software-and-systems-verification
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Software and Systems Verification
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-2-electives/software-and-systems-verification.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-2-electives/startup-engineering
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Startup Engineering: Building Scalable Tech Ventures
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-2-electives/startup-engineering.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-4/history-and-philosophy-of-computing
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# The History and Philosophy of Computing
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-4/history-and-philosophy-of-computing.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-4/operating-systems
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Operating Systems
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-4/operating-systems.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/computer-science/year-3/period-4/theory-of-computing
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Theory of Computing
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/1.computer-science/year-3/period-4/theory-of-computing.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Course Description
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/course-description
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Course Description
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-1/discrete-mathematics
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Discrete Mathematics
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-1/discrete-mathematics.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-1/introduction-to-data-science-and-ai
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Introduction to Data Science and Artificial Intelligence
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-1/introduction-to-data-science-and-ai.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-1/procedural-programming
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Procedural Programming
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-1/procedural-programming.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-2/calculus
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Calculus
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-2/calculus.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-2/logic
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Logic
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-2/logic.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-2/objects-in-programming
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Objects in Programming
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-2/objects-in-programming.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-4/data-structures-and-algorithms
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Data Structures and Algorithms
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-4/data-structures-and-algorithms.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-4/linear-algebra
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Linear Algebra
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-4/linear-algebra.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-4/principles-of-data-science
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Principles of Data Science
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-4/principles-of-data-science.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-5/computational-and-cognitive-neuroscience
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Computational and Cognitive Neuroscience
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-5/computational-and-cognitive-neuroscience.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-5/numerical-methods
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Numerical Methods
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-5/numerical-methods.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-1/period-5/software-engineering
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Software Engineering
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-1/period-5/software-engineering.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-1/databases
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Databases
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-1/databases.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-1/graph-theory
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Graph Theory
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-1/graph-theory.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-1/probability-and-statistics
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Probability and Statistics
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-1/probability-and-statistics.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-2/machine-learning
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Machine Learning
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-2/machine-learning.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-2/reasoning-techniques
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Reasoning Techniques
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-2/reasoning-techniques.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-2/simulation-and-statistical-analysis
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Simulation and Statistical Analysis
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-2/simulation-and-statistical-analysis.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-4/human-computer-interaction-affective-computing
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Human Computer Interaction & Affective Computing
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-4/human-computer-interaction-affective-computing.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-4/mathematical-modelling
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Mathematical Modelling
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-4/mathematical-modelling.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-4/natural-language-processing
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Natural Language Processing
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-4/natural-language-processing.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-5-electives/game-theory
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Game Theory
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-5-electives/game-theory.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-5-electives/introduction-to-image-video-processing
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Introduction to Image & Video Processing
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-5-electives/introduction-to-image-video-processing.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-5/linear-programming
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Linear Programming
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-5/linear-programming.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-2/period-5/philosophy-and-artificial-intelligence
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Philosophy & Artificial Intelligence
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-2/period-5/philosophy-and-artificial-intelligence.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-1-electives/digital-society
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Digital Society
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-1-electives/digital-society.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-1-electives/game-theory
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Game Theory
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-1-electives/game-theory.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-1-electives/introduction-to-quantum-computing
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Introduction to Quantum Computing
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-1-electives/introduction-to-quantum-computing.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-1-electives/multi-scale-modelling-biological-systems
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Multi-Scale Modelling of Biological Systems
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-1-electives/multi-scale-modelling-biological-systems.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-1-electives/robotics-and-embedded-systems
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Robotics and Embedded Systems
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-1-electives/robotics-and-embedded-systems.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-1-electives/semantic-web
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Semantic Web
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-1-electives/semantic-web.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-2-electives/business-process-knowledge-management
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Business Process & Knowledge Management
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-2-electives/business-process-knowledge-management.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-2-electives/computer-security
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Computer Security
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-2-electives/computer-security.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-2-electives/introduction-to-bio-informatics
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Introduction to Bio-Informatics
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-2-electives/introduction-to-bio-informatics.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-2-electives/large-scale-it-and-cloud-computing
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Large Scale IT and Cloud Computing
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-2-electives/large-scale-it-and-cloud-computing.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-2-electives/logic-for-artificial-intelligence
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Logic for Artificial Intelligence
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-2-electives/logic-for-artificial-intelligence.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-2-electives/parallel-programming
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Parallel Programming
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-2-electives/parallel-programming.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-2-electives/recommender-systems
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Recommender Systems
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-2-electives/recommender-systems.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-4/data-analysis
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Data Analysis
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-4/data-analysis.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-4/intelligent-systems
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Intelligent Systems
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-4/intelligent-systems.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-and-artificial-intelligence/year-3/period-4/operations-research
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Operations Research
|
||||||
|
|
||||||
|
##### Empty Page
|
||||||
|
|
||||||
|
Start writing in `content/2.data-science-and-artificial-intelligence/year-3/period-4/operations-research.md` to see this page taking shape.
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-for-decision-making
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Course Description
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/data-science-for-decision-making/course-description
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Course Description
|
||||||
|
|
||||||
|
#Hello
|
||||||
|
|
||||||
|
#Hello
|
||||||
14
to-be-studied/live-wiki/2026-08-02/index.md
Normal file
14
to-be-studied/live-wiki/2026-08-02/index.md
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
[🎒
|
||||||
|
|
||||||
|
Just moved in? Check out our guides for helpful informationJust moved in? Check out our guides for helpful information](https://wiki.msvincognito.nl/useful-guides)
|
||||||
|
|
||||||
|
# Welcome to the Incognito Wiki!
|
||||||
|
|
||||||
|
The comprehensive knowledge base for DACS students at Maastricht University.<br>
|
||||||
|
Find course materials, exam resources, study guides, and everything you need to succeed in your DACS journey.<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
[](https://wiki.msvincognito.nl/computer-science)[](https://wiki.msvincognito.nl/data-science-and-artificial-intelligence)[](https://wiki.msvincognito.nl/artificial-intelligence)[](https://wiki.msvincognito.nl/data-science-for-decision-making)[](https://wiki.msvincognito.nl/useful-guides)
|
||||||
50
to-be-studied/live-wiki/2026-08-02/useful-guides.md
Normal file
50
to-be-studied/live-wiki/2026-08-02/useful-guides.md
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
> Source: https://wiki.msvincognito.nl/useful-guides
|
||||||
|
> Captured: 2026-08-02
|
||||||
|
|
||||||
|
# Useful Guides
|
||||||
|
|
||||||
|
Essential resources and tips for your academic journey at Maastricht University
|
||||||
|
|
||||||
|
Welcome to the **Useful Guides** section of the Incognito Wiki! This collection contains practical resources and tips to help you navigate your academic journey and student life at **Maastricht University**.
|
||||||
|
|
||||||
|
[
|
||||||
|
|
||||||
|
### Housing Guide
|
||||||
|
|
||||||
|
Essential information for finding accommodation in **Maastricht**. Navigate the housing market, understand rental agreements, and discover the best neighborhoods for students.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
](https://wiki.msvincognito.nl/useful-guides/housing-guide)
|
||||||
|
|
||||||
|
[
|
||||||
|
|
||||||
|
### Laptop Buying Advice
|
||||||
|
|
||||||
|
Recommendations for choosing the right laptop for your studies. Get insights on specifications, brands, and budget considerations tailored for **DACS students**.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
](https://wiki.msvincognito.nl/useful-guides/laptop-buying-advice)
|
||||||
|
|
||||||
|
[
|
||||||
|
|
||||||
|
### Linux Tricks
|
||||||
|
|
||||||
|
Helpful tips and commands for working with **Linux systems**. Master the command line, learn essential shortcuts, and boost your productivity.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
](https://wiki.msvincognito.nl/useful-guides/linux-tricks)
|
||||||
|
|
||||||
|
[
|
||||||
|
|
||||||
|
### Surviving DACS
|
||||||
|
|
||||||
|
Insider tips for making the most of your time in the **Department of Data Science & Knowledge Engineering**. Study strategies, course insights, and academic advice.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
](https://wiki.msvincognito.nl/useful-guides/survivingdacs)
|
||||||
|
|
||||||
|
These guides are created by fellow students and updated somewhat regularly to ensure they remain relevant and helpful. Whether you're a first-year student just starting out or a senior looking for specific technical advice, you'll find valuable information here to support your academic success.
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue