UNPKG

myst-cli

Version:
216 lines (215 loc) 8.11 kB
import { z } from 'zod'; import { notNullish } from '../../utils/defined.js'; import { ExportFormats } from 'myst-frontmatter'; import { parse } from 'node:path'; const JupyterBookConfig = z.object({ title: z.string().nullish(), author: z.string().nullish(), copyright: z.string().nullish(), logo: z.string().nullish(), exclude_patterns: z.array(z.string()).nullish(), parse: z .object({ myst_enable_extensions: z.union([z.null(), z.array(z.string())]).nullish(), myst_url_schemes: z.union([z.null(), z.array(z.string())]).nullish(), myst_dmath_double_inline: z.boolean().default(true), }) .nullish(), execute: z .object({ eval_regex: z.string().default('^.*$'), raise_on_error: z.boolean().default(false), show_tb: z.boolean().default(false), execute_notebooks: z .union([ z.literal('auto'), z.literal('cache'), z.literal('force'), z.literal('inline'), z.literal('off'), z.literal(false), ]) .default('auto'), cache: z.string().nullish(), timeout: z.number().gte(-1).default(30), allow_errors: z.boolean().default(false), stderr_output: z .enum(['show', 'remove', 'remove-warn', 'warn', 'error', 'severe']) .default('show'), run_in_temp: z.boolean().default(false), exclude_patterns: z.array(z.string()).nullish(), }) .nullish(), html: z .object({ favicon: z.string().nullish(), use_edit_page_button: z.boolean().nullish(), use_repository_button: z.boolean().nullish(), use_issues_button: z.boolean().nullish(), extra_footer: z.string().nullish(), // Legacy analytics field google_analytics_id: z.string().nullish(), analytics: z .object({ plausible_analytics_domain: z.string().nullish(), google_analytics_id: z.string().nullish(), }) .nullish(), home_page_in_navbar: z.boolean().nullish(), baseurl: z.string().nullish(), comments: z .object({ hypothesis: z.union([z.boolean(), z.record(z.any())]).nullish(), utterances: z.union([z.boolean(), z.record(z.any())]).nullish(), }) .nullish(), announcement: z.string().nullish(), }) .nullish(), latex: z .object({ latex_engine: z.string().default('pdflatex'), use_jupyterbook_latex: z.boolean().nullish(), latex_documents: z .object({ targetname: z.string().nullish(), }) .nullish(), }) .nullish(), bibtex_bibfiles: z.array(z.string()).nullish(), launch_buttons: z .object({ notebook_interface: z.string().nullish(), binderhub_url: z.string().nullish(), jupyterhub_url: z.string().nullish(), thebe: z.boolean().nullish(), colab_url: z.string().nullish(), }) .nullish(), repository: z .object({ url: z.string().nullish(), path_to_book: z.string().nullish(), branch: z.string().nullish(), }) .nullish(), sphinx: z .object({ extra_extensions: z.union([z.null(), z.array(z.string())]).nullish(), local_extensions: z.union([z.null(), z.record(z.any())]).nullish(), recursive_update: z.boolean().nullish(), config: z.union([z.null(), z.record(z.any())]).nullish(), }) .nullish(), }); /** * Validate a loaded Jupyter Book _config.yml, or return undefined * * @param config - config object */ export function validateJupyterBookConfig(config) { const result = JupyterBookConfig.safeParse(config); if (!result.success) { const errors = result.error.errors.map((issue) => `${issue.path.join('.')}: ${issue.message} (${issue.code})`); throw new Error(`Error(s) in parsing Jupyter Book configuration:\n${errors}`); } else { return result.data; } } /** * Parse a GitHub repo URL to extract the user/repo substring * * @param url - GitHub URL */ function parseGitHubRepoURL(url) { //eslint-disable-next-line const match = url.match(/(?:git@|https:\/\/)github.com[:\/](.*)(?:.git)?/); if (!match) { return undefined; } return match[1]; } /** * Upgrade a Jupyter Book _config.yml into a myst.yml configuration * * @param config - validated Jupyter Book configuration */ export function upgradeConfig(data) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s; const project = {}; const siteOptions = {}; const site = { options: siteOptions, template: 'book-theme', }; if (notNullish(data.title)) { project.title = data.title; } if (notNullish(data.author)) { // Try and parse comma-delimited author lists into separate authors const authors = data.author.split(/,\s*(?:and\s)?\s*|\s+and\s+/); if (authors.length === 1) { project.authors = [{ name: data.author }]; // TODO prompt user for alias? } else { project.authors = authors.map((name) => ({ name })); } } if (notNullish(data.copyright)) { project.copyright = data.copyright; } if (notNullish(data.logo)) { siteOptions.logo = data.logo; } if (notNullish(data.exclude_patterns)) { project.exclude = data.exclude_patterns; } if (notNullish((_a = data.html) === null || _a === void 0 ? void 0 : _a.favicon)) { siteOptions.favicon = data.html.favicon; } if (notNullish((_c = (_b = data.html) === null || _b === void 0 ? void 0 : _b.analytics) === null || _c === void 0 ? void 0 : _c.google_analytics_id)) { siteOptions.analytics_google = data.html.analytics.google_analytics_id; } else if (notNullish((_d = data.html) === null || _d === void 0 ? void 0 : _d.google_analytics_id)) { siteOptions.analytics_google = data.html.google_analytics_id; } if (notNullish((_f = (_e = data.html) === null || _e === void 0 ? void 0 : _e.analytics) === null || _f === void 0 ? void 0 : _f.plausible_analytics_domain)) { siteOptions.analytics_plausible = data.html.analytics.plausible_analytics_domain; } const repo = notNullish((_g = data.repository) === null || _g === void 0 ? void 0 : _g.url) ? parseGitHubRepoURL((_h = data.repository) === null || _h === void 0 ? void 0 : _h.url) : undefined; if (notNullish(repo)) { project.github = repo; } // Do we want to enable thebe and mybinder? if (notNullish(repo) && (notNullish((_j = data.launch_buttons) === null || _j === void 0 ? void 0 : _j.binderhub_url) || !!((_k = data.launch_buttons) === null || _k === void 0 ? void 0 : _k.thebe))) { project.thebe = { binder: { repo: repo, provider: 'github', url: (_m = (_l = data.launch_buttons) === null || _l === void 0 ? void 0 : _l.binderhub_url) !== null && _m !== void 0 ? _m : undefined, ref: (_p = (_o = data.repository) === null || _o === void 0 ? void 0 : _o.branch) !== null && _p !== void 0 ? _p : undefined, }, }; } // Take bibliography if (notNullish(data.bibtex_bibfiles)) { project.bibliography = data.bibtex_bibfiles; } // Defined LaTeX target name if (notNullish((_r = (_q = data.latex) === null || _q === void 0 ? void 0 : _q.latex_documents) === null || _r === void 0 ? void 0 : _r.targetname)) { project.exports = (_s = project.exports) !== null && _s !== void 0 ? _s : []; // Strip any extensions const { name } = parse(data.latex.latex_documents.targetname); project.exports.push({ format: ExportFormats.pdf, template: 'plain_latex_book', output: `exports/${name}.pdf`, }); } return { project, site }; }