Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion scripts/review/documents.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ function readRegistry(source) {
return entries(source).map((e) => e.values);
}
function validLocation(location) {
if (!/^[a-zA-Z0-9][a-zA-Z0-9_./-]*$/.test(location) || location.split('/').some((p) => !p || p === '.' || p === '..'))
if (
typeof location !== 'string' ||
!/^[a-zA-Z0-9][a-zA-Z0-9_./-]*$/.test(location) ||
location.split('/').some((p) => !p || p === '.' || p === '..')
)
throw Error('Invalid document location');
return location;
}
Expand All @@ -40,6 +44,8 @@ const ASSET_ROOTS = ['figures', 'bibliographies', 'files', 'downloads'];
function registryMap(source) {
const result = new Map();
for (const entry of readRegistry(source)) {
// Download-only landing-page tiles have no MDX document identity.
if (!Object.hasOwn(entry, 'doc_location') && typeof entry.downloadUrl === 'string' && entry.downloadUrl.trim()) continue;
const location = validLocation(entry.doc_location);
if (result.has(location)) throw Error(`Duplicate document location: ${location}`);
result.set(location, entry);
Expand Down
22 changes: 21 additions & 1 deletion tests/review-documents.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const { readRegistry, flipDraft, documentScope, publicationChanges, registryChanges } = require('../scripts/review/documents');
const { readRegistry, flipDraft, documentScope, publicationChanges, registryChanges, validLocation } = require('../scripts/review/documents');
const source = `const docs = [{doc_location:'a/manual', active:true, draft:true},{doc_location:'b/manual',active:true,draft:true}]; module.exports={docs};`;
test('actual registry supports PDF-only tiles while detecting document changes', () => {
const registry = require('node:fs').readFileSync(require('node:path').join(__dirname, '../src/docConfig.js'), 'utf8');
assert.deepEqual(registryChanges(registry, registry), []);
const changed = registry.replace('const docs = [', "const docs = [{doc_location:'regression/manual',active:true,draft:true},");
assert.deepEqual(registryChanges(registry, changed), ['regression/manual']);
});

test('PDF-only tiles need no document path but malformed document entries are rejected', () => {
const pdf = `const docs=[{downloadUrl:'/report.pdf',doc_name:'Report'}];`;
assert.deepEqual(registryChanges(pdf, pdf), []);
for (const entry of ['{}', "{downloadUrl:''}", "{doc_location:null,downloadUrl:'/report.pdf'}"]) {
assert.throws(() => registryChanges(`const docs=[${entry}];`, source), /Invalid document location/);
}
});

test('document locations reject non-string values with a validation error', () => {
for (const value of [undefined, null, 123, true, {}, '']) {
assert.throws(() => validLocation(value), /Invalid document location/);
}
});
test('only the explicitly selected registry flag changes', () => {
const result = flipDraft(source, 'a/manual');
assert.equal(readRegistry(result)[0].draft, false);
Expand Down
Loading