Spaces:
Runtime error
Runtime error
// @ts-check | |
import { readFileSync } from 'fs'; | |
import { globSync } from 'glob'; | |
import { dirname, join } from 'path'; | |
import { fileURLToPath } from 'url'; | |
import { NOTEBOOKS_DIRECTORY_PATH } from './notebook-content-reader.js'; | |
import { NotebookMetadataCollector } from './notebook-metadata-collector.js'; | |
import { toMarkdown } from './notebook-metadata-formatter.js'; | |
import { NotebookMetadataValidationError, validateNotebookMetadata } from './notebook-metadata-validator.js'; | |
/** @typedef {import('../shared/notebook-metadata.ts').INotebookMetadata} INotebookMetadata */ | |
export class NotebookMetadataHandler { | |
/** | |
* @param {string} notebookFilePath | |
*/ | |
constructor(notebookFilePath) { | |
/** @private */ | |
this._notebookFilePath = notebookFilePath; | |
/** @private */ | |
this._metadata = new NotebookMetadataCollector(this._notebookFilePath).getMetadata(); | |
} | |
/** @private @const */ | |
static _skippedNotebooks = this._getSkippedNotebooks(); | |
get metadata() { | |
return this._metadata; | |
} | |
/** | |
* @returns {string | null} Validation error | |
*/ | |
validateMetadata() { | |
try { | |
validateNotebookMetadata(this._metadata); | |
} catch (error) { | |
if (error instanceof NotebookMetadataValidationError) { | |
error.message = `Invalid metadata for notebook "${this._notebookFilePath}".\n${error.message}`; | |
return error.message; | |
} | |
throw error; | |
} | |
return null; | |
} | |
/** | |
* @param {boolean} hasError | |
*/ | |
toMarkdown(hasError) { | |
return toMarkdown(this._metadata, hasError); | |
} | |
static getNotebooksPaths() { | |
return globSync('**/*.ipynb', { | |
ignore: ['**/.ipynb_checkpoints/*', '**/notebook_utils.ipynb', ...this._skippedNotebooks], | |
cwd: NOTEBOOKS_DIRECTORY_PATH, | |
}); | |
} | |
/** | |
* @param {string[]} notebooksPaths | |
* @return {[string | null, string[]]} Tuple of validation error (if exist) and array of metadata markdown representations | |
*/ | |
static validateNotebooks(notebooksPaths) { | |
const errors = []; | |
const metadataMarkdowns = []; | |
for (const notebookPath of notebooksPaths) { | |
if (NotebookMetadataHandler._skippedNotebooks.includes(notebookPath)) { | |
continue; | |
} | |
const notebookMetadataHandler = new NotebookMetadataHandler(notebookPath); | |
const error = notebookMetadataHandler.validateMetadata(); | |
if (error) { | |
errors.push(error); | |
} | |
const metadataMarkdown = notebookMetadataHandler.toMarkdown(Boolean(error)); | |
metadataMarkdowns.push(metadataMarkdown); | |
} | |
return [errors.length ? errors.join('\n\n') : null, metadataMarkdowns]; | |
} | |
static validateAll() { | |
const notebooksPaths = NotebookMetadataHandler.getNotebooksPaths(); | |
return NotebookMetadataHandler.validateNotebooks(notebooksPaths); | |
} | |
/** @private */ | |
static _getSkippedNotebooks() { | |
const currentDirectory = dirname(fileURLToPath(import.meta.url)); | |
const skippedNotebooksFilePath = join(currentDirectory, 'skipped-notebooks.txt'); | |
const skippedNotebooksFileContent = readFileSync(skippedNotebooksFilePath, { encoding: 'utf8' }); | |
return skippedNotebooksFileContent | |
.trim() | |
.split('\n') | |
.map((v) => v.trim()); | |
} | |
} | |