Skip to content

Commit a91c609

Browse files
Make plugin code more readable
Add tests for exception handling
1 parent 3730ac0 commit a91c609

2 files changed

Lines changed: 65 additions & 12 deletions

File tree

plugins/src/notebook-gallery.mjs

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,36 @@ function loadMetadata(metadataPath) {
2727
}
2828

2929

30+
// MyST markdown templates — kept separate from logic for readability
31+
const clickableCardMyst = (link, title, description) => [
32+
'```{card}',
33+
`:link: ${link}`,
34+
`:header: [${title} →](${link})`,
35+
description,
36+
'```',
37+
].join('\n');
38+
39+
const unrecognizedCardMyst = (filePath) => [
40+
'```{card}',
41+
':header: ⚠️ _Unrecognised notebook_',
42+
`Could not find \`${filePath}\``,
43+
'```',
44+
].join('\n');
45+
46+
const metadataErrorMyst = (metadataPath) => [
47+
`:::{error} \`notebook-gallery\` error`,
48+
`Could not read metadata from \`${metadataPath}\``,
49+
':::',
50+
].join('\n');
51+
52+
const gridOfCardsMyst = (cards) => [
53+
'````{grid} 1 2 2 3',
54+
...cards,
55+
'````',
56+
].join('\n\n');
57+
// End of MyST markdown templates
58+
59+
3060
/**
3161
* MyST directive: notebook-gallery
3262
*
@@ -56,27 +86,35 @@ const notebookGalleryDirective = {
5686
body: { type: String, required: true },
5787

5888
run(data, vfile, ctx) {
89+
// Resolve the metadata file path relative to the repo root and load it
5990
const metadataPath = path.resolve(REPO_ROOT, data.arg);
6091
const metadataByFile = loadMetadata(metadataPath);
6192

6293
if (!metadataByFile) {
63-
return ctx.parseMyst(`:::danger\nnotebook-gallery: could not read \`${metadataPath}\`\n:::`).children;
94+
return ctx.parseMyst(metadataErrorMyst(metadataPath)).children;
6495
}
6596

97+
// Links in cards must be relative to the file that contains this directive
6698
const callerDir = path.dirname(path.resolve(vfile.path));
6799

68-
const cards = data.body.split('\n')
100+
// Parse the body: one notebook path per line, skip blank lines and comments
101+
const notebookFilePaths = data.body.split('\n')
69102
.map(l => l.trim())
70-
.filter(l => l && !l.startsWith('#'))
71-
.map(filePath => {
72-
const meta = metadataByFile[filePath];
73-
if (!meta) return `:::warning\nnotebook-gallery: not found in metadata: \`${filePath}\`\n:::`;
74-
const link = path.relative(callerDir, path.resolve(REPO_ROOT, filePath));
75-
return `\`\`\`{card}\n:link: ${link}\n:header: [${meta.title} →](${link})\n${meta.description}\n\`\`\``;
76-
});
77-
78-
const myst = `\`\`\`\`{grid} 1 2 2 3\n${cards.join('\n\n')}\n\`\`\`\``;
79-
return ctx.parseMyst(myst).children;
103+
.filter(l => l && !l.startsWith('#'));
104+
105+
// Build a MyST card string for each notebook path
106+
const cards = notebookFilePaths.map(filePath => {
107+
const meta = metadataByFile[filePath];
108+
if (!meta) return unrecognizedCardMyst(filePath);
109+
const link = path.relative(callerDir, path.resolve(REPO_ROOT, filePath));
110+
const title = meta.title ?? path.basename(filePath, path.extname(filePath)); // fall back to filename
111+
const description = meta.description ?? ''; // fall back to no description
112+
return clickableCardMyst(link, title, description);
113+
});
114+
115+
// Wrap all cards in a grid, parse the combined MyST string, and return the
116+
// resulting AST nodes to be inserted in place of this directive.
117+
return ctx.parseMyst(gridOfCardsMyst(cards)).children;
80118
},
81119
};
82120

tutorials/euclid/euclid.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,18 @@ tutorials/euclid/euclid-cloud-access.md
2424
tutorials/euclid/euclid_clusters_tutorial.md
2525
tutorials/euclid/Euclid_ERO.md
2626
```
27+
28+
## notebook-gallery exception handling tests
29+
### Invalid notebook path
30+
```{notebook-gallery} notebook_metadata.yml
31+
tutorials/euclid/1_Euclid_intro_MER_images.md
32+
tutorials/euclid/does_not_exist.md
33+
tutorials/euclid/2_Euclid_intro_MER_catalog.md
34+
```
35+
36+
### Invalid metadata path
37+
```{notebook-gallery} does_not_exist.yml
38+
tutorials/euclid/1_Euclid_intro_MER_images.md
39+
tutorials/euclid/2_Euclid_intro_MER_catalog.md
40+
tutorials/euclid/3_Euclid_intro_1D_spectra.md
41+
```

0 commit comments

Comments
 (0)