Open exam PDFs in new tabs
This commit is contained in:
parent
edca813c20
commit
aa28e1ff21
3 changed files with 66 additions and 1 deletions
|
|
@ -4,6 +4,7 @@ import { unified } from '@astrojs/markdown-remark';
|
||||||
import { sidebar } from './src/config/sidebar.mjs';
|
import { sidebar } from './src/config/sidebar.mjs';
|
||||||
import { legacyBachelorRedirects } from './src/config/legacy-bachelor-redirects.mjs';
|
import { legacyBachelorRedirects } from './src/config/legacy-bachelor-redirects.mjs';
|
||||||
import { baseAwareLinks } from './src/config/base-aware-markdown.mjs';
|
import { baseAwareLinks } from './src/config/base-aware-markdown.mjs';
|
||||||
|
import { openExamLinksInNewTab } from './src/config/open-exam-links.mjs';
|
||||||
|
|
||||||
const site = process.env.SITE || 'http://localhost:4321';
|
const site = process.env.SITE || 'http://localhost:4321';
|
||||||
const base = process.env.BASE || '/';
|
const base = process.env.BASE || '/';
|
||||||
|
|
@ -17,7 +18,12 @@ export default defineConfig({
|
||||||
base,
|
base,
|
||||||
redirects: Object.fromEntries(Object.entries(legacyBachelorRedirects).map(([from, to]) => [from, `${normalizedBase}${to}`])),
|
redirects: Object.fromEntries(Object.entries(legacyBachelorRedirects).map(([from, to]) => [from, `${normalizedBase}${to}`])),
|
||||||
markdown: {
|
markdown: {
|
||||||
processor: unified({ remarkPlugins: [[baseAwareLinks, { base }]] }),
|
processor: unified({
|
||||||
|
remarkPlugins: [
|
||||||
|
[baseAwareLinks, { base }],
|
||||||
|
openExamLinksInNewTab,
|
||||||
|
],
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
integrations: [
|
integrations: [
|
||||||
starlight({
|
starlight({
|
||||||
|
|
|
||||||
24
src/config/open-exam-links.mjs
Normal file
24
src/config/open-exam-links.mjs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
const examArchivePath = /(?:^|[/\\])previous-exams-and-documents\.md$/;
|
||||||
|
|
||||||
|
export function openExamLinksInNewTab() {
|
||||||
|
return (tree, file) => {
|
||||||
|
if (!examArchivePath.test(file?.path ?? '')) return;
|
||||||
|
|
||||||
|
const visit = (node) => {
|
||||||
|
if (node.type === 'link' && /\.pdf(?:[?#]|$)/i.test(node.url ?? '')) {
|
||||||
|
node.data = {
|
||||||
|
...node.data,
|
||||||
|
hProperties: {
|
||||||
|
...node.data?.hProperties,
|
||||||
|
target: '_blank',
|
||||||
|
rel: 'noopener noreferrer',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const child of node.children ?? []) visit(child);
|
||||||
|
};
|
||||||
|
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
}
|
||||||
35
tests/open-exam-links.test.mjs
Normal file
35
tests/open-exam-links.test.mjs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import test from 'node:test';
|
||||||
|
import { openExamLinksInNewTab } from '../src/config/open-exam-links.mjs';
|
||||||
|
|
||||||
|
test('opens PDF links from the exam archive in a new tab', () => {
|
||||||
|
const tree = {
|
||||||
|
type: 'root',
|
||||||
|
children: [
|
||||||
|
{ type: 'link', url: '/media/exam.pdf', children: [] },
|
||||||
|
{ type: 'link', url: '/computer-science/', children: [] },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
openExamLinksInNewTab()(tree, {
|
||||||
|
path: '/project/src/content/docs/previous-exams-and-documents.md',
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.deepEqual(tree.children[0].data, {
|
||||||
|
hProperties: {
|
||||||
|
target: '_blank',
|
||||||
|
rel: 'noopener noreferrer',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
assert.equal(tree.children[1].data, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('leaves PDF links on other pages unchanged', () => {
|
||||||
|
const link = { type: 'link', url: '/media/notes.pdf', children: [] };
|
||||||
|
|
||||||
|
openExamLinksInNewTab()({ type: 'root', children: [link] }, {
|
||||||
|
path: '/project/src/content/docs/course.md',
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(link.data, undefined);
|
||||||
|
});
|
||||||
Loading…
Add table
Reference in a new issue