@anja.codes/vitakit 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +52 -131
  2. package/dist/check.mjs +20 -11
  3. package/dist/chunks/authoring.mjs +372 -0
  4. package/dist/{shared/vitakit.CypCF-4Q.mjs → chunks/bibliography.mjs} +74 -237
  5. package/dist/chunks/build.mjs +178 -0
  6. package/dist/chunks/documents.mjs +152 -0
  7. package/dist/chunks/draft.mjs +222 -0
  8. package/dist/chunks/eject.mjs +59 -0
  9. package/dist/chunks/emit.mjs +216 -0
  10. package/dist/chunks/eta.mjs +16 -0
  11. package/dist/chunks/fields.mjs +79 -0
  12. package/dist/chunks/inventory.mjs +201 -0
  13. package/dist/chunks/migrations.mjs +218 -0
  14. package/dist/chunks/plan.mjs +172 -0
  15. package/dist/chunks/prompt.mjs +33 -0
  16. package/dist/chunks/publication-lists.mjs +202 -0
  17. package/dist/chunks/schema-source.mjs +12 -0
  18. package/dist/chunks/schemas.mjs +109 -0
  19. package/dist/chunks/sections.mjs +109 -0
  20. package/dist/chunks/snippets.mjs +199 -0
  21. package/dist/chunks/validate.mjs +133 -0
  22. package/dist/chunks/vue.mjs +153 -0
  23. package/dist/chunks/yaml.mjs +62 -0
  24. package/dist/cli.d.mts +33 -40
  25. package/dist/cli.mjs +7 -224
  26. package/dist/index.d.mts +379 -49
  27. package/dist/index.mjs +15 -7
  28. package/dist/nuxt.mjs +48 -10
  29. package/dist/runtime/components/VitaPublications.vue +21 -22
  30. package/dist/runtime/components/VitaSection.vue +94 -38
  31. package/dist/runtime/composables/useVitakit.ts +14 -3
  32. package/dist/schemas/education.ts +4 -4
  33. package/dist/schemas/employment.ts +3 -3
  34. package/dist/schemas/publications.ts +10 -8
  35. package/dist/schemas/supervision.ts +3 -3
  36. package/dist/schemas/talks.ts +1 -1
  37. package/dist/schemas/teaching.ts +3 -3
  38. package/dist/shared/index.d.mts +60 -9
  39. package/dist/shared/index.mjs +3 -57
  40. package/dist/shared/{vitakit.D8WRg_Xx.d.mts → vitakit.BfR_mUHm.d.mts} +25 -12
  41. package/dist/shared/vitakit.CCTDg7pz.mjs +199 -0
  42. package/dist/shared/vitakit.CfB3hMHl.mjs +60 -0
  43. package/dist/shared/{vitakit.BlU-p01e.mjs → vitakit.CtChKO0I.mjs} +1 -1
  44. package/dist/shared/vitakit.D-DdJaDZ.mjs +20 -0
  45. package/dist/shared/vitakit.D10HyDhF.mjs +19 -0
  46. package/dist/shared/vitakit.DCK90zq4.mjs +67 -0
  47. package/dist/shared/vitakit.DQ6PmGoL.mjs +34 -0
  48. package/dist/shared/vitakit.DcQOdM4I.mjs +57 -0
  49. package/dist/shared/vitakit.DteA9vLy.mjs +135 -0
  50. package/dist/shared/vitakit.DvABWuUc.mjs +121 -0
  51. package/dist/shared/vitakit.DvvUYUTS.mjs +200 -0
  52. package/dist/shared/vitakit.TSMTC5Jl.mjs +6 -0
  53. package/dist/shared/vitakit.UfoXdL7U.mjs +22 -0
  54. package/dist/shared/vitakit.zwr1ssO5.mjs +1850 -0
  55. package/dist/tex/templates/_generic.eta +6 -4
  56. package/dist/tex/templates/education.eta +10 -5
  57. package/dist/tex/templates/employment.eta +12 -5
  58. package/dist/tex/templates/publications.eta +7 -3
  59. package/dist/tex/templates/supervision.eta +10 -2
  60. package/dist/tex/templates/talks.eta +5 -1
  61. package/dist/tex/templates/teaching.eta +6 -4
  62. package/dist/tex/vitakit-cv.cls +36 -10
  63. package/dist/tex.d.mts +80 -11
  64. package/dist/tex.mjs +27 -117
  65. package/package.json +10 -7
  66. package/src/bin/vitakit.mjs +3 -153
  67. package/dist/shared/vitakit.BRhjqpAt.mjs +0 -250
  68. package/dist/shared/vitakit.BxcnlFGP.mjs +0 -325
  69. package/src/bin/vitakit-build-cv.mjs +0 -50
  70. package/src/bin/vitakit-check.mjs +0 -57
@@ -1,158 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * The vitakit command. Three subcommands, each of which only writes files you
4
- * could have written yourself — see docs/cli.md for why there are not more.
3
+ * The vitakit command; see `pnpm vitakit --help` or docs/cli/.
5
4
  */
6
5
  import process from 'node:process'
7
- import { relative } from 'node:path'
8
- import { addSection, eject, listEjectable } from '../../dist/cli.mjs'
6
+ import { main } from '../../dist/cli.mjs'
9
7
 
10
- const USAGE = `vitakit — files for a vitakit project
11
-
12
- Usage
13
- pnpm vitakit <command> [options]
14
-
15
- Commands
16
- add <name> set up a new section: content file, schema, component
17
- list show everything that can be ejected
18
- eject <name> copy a package default into your project
19
-
20
- Run a command with --help for details and examples.
21
-
22
- Related commands, from the same package:
23
- pnpm build:cv render content/ into cv-tex/ and run latexmk
24
- pnpm check typecheck, generate the site, and verify the output
25
- `
26
-
27
- const HELP = {
28
- add: `vitakit add <name> — set up a new section
29
-
30
- A section is a file in content/, a schema describing what it may contain, and
31
- usually a component deciding how it looks. This writes whichever of those are
32
- missing; it never overwrites a file you have.
33
-
34
- pnpm vitakit add outreach
35
-
36
- content/outreach.yml your data — edit this first
37
- schemas/outreach.ts the shape of an entry
38
- app/components/OutreachSection.vue how the entries look
39
-
40
- If content/<name>.yml already exists, the schema is drafted from it: field
41
- types are guessed from your data — dates, URLs, enums, and which fields are
42
- optional — so you correct a draft instead of writing one.
43
-
44
- pnpm vitakit add outreach # after writing content/outreach.yml
45
-
46
- Options
47
- --no-component do not write a component; the section then renders through
48
- <VitaSection>, which is a fallback rather than a design
49
-
50
- Notes
51
- The name becomes a file name: lowercase, kebab-case (research-stays).
52
- For a built-in section (education, employment, teaching, talks,
53
- supervision) you do not need this: create content/<name>.yml and it works.
54
- To change what a built-in section may contain, use \`vitakit eject <name>\`.
55
-
56
- Afterwards
57
- Show it on a page with <OutreachSection /> in app/pages/, or put
58
- \\vitasection{outreach} in cv-tex/cv.tex to add it to the PDF.`,
59
-
60
- list: `vitakit list — show everything that can be ejected
61
-
62
- Prints each item, what kind of thing it is, and where a copy would land:
63
-
64
- VitaSection component -> app/components/VitaSection.vue
65
- talks.eta template -> cv-tex/templates/talks.eta
66
- teaching schema -> schemas/teaching.ts
67
- publications schema -> schemas/publications.ts
68
- publications.csl style -> content/publications.csl
69
- vitakit-cv.cls class -> cv-tex/vitakit-cv.cls
70
-
71
- component how a section looks on the website
72
- schema what a section may contain; for publications, the groups,
73
- the links after each reference and the fields passed on
74
- template how a section is written into the PDF
75
- style how publications.bib is formatted on the website (CSL)
76
- class the LaTeX document class: fonts, spacing, the entry macros`,
77
-
78
- eject: `vitakit eject <name> — copy a package default into your project
79
-
80
- The copy wins from then on: vitakit always prefers a file in your project over
81
- its own. This is the only command that exists purely for convenience — the
82
- files live inside node_modules/.pnpm/…, at a path that changes with every
83
- update, so copying them by hand is impractical.
84
-
85
- pnpm vitakit eject VitaSection # restyle how sections look
86
- pnpm vitakit eject teaching # add or remove fields of a section
87
- pnpm vitakit eject talks.eta # change how talks appear in the PDF
88
- pnpm vitakit eject publications.csl # change the citation style of the website
89
- pnpm vitakit eject vitakit-cv.cls # take over the LaTeX document class
90
-
91
- Use \`vitakit list\` to see the names.
92
-
93
- Options
94
- --force overwrite an existing file
95
-
96
- Trade-off
97
- An ejected file is yours forever: later improvements to it in vitakit will
98
- not reach you. Everything that can carry a bug — validation, rendering,
99
- sorting, escaping — stays in the package, so this is usually the right
100
- trade, but eject deliberately rather than by default.
101
-
102
- Before ejecting a component, check whether CSS is enough: the classes
103
- (vita-entry, vita-entry__date, …) are styled in app/assets/css/main.css.`,
104
- }
105
-
106
- const [command, ...rest] = process.argv.slice(2)
107
- const wantsHelp = rest.includes('--help') || rest.includes('-h')
108
- const root = process.cwd()
109
- const pascal = name => name.split('-').map(part => part[0].toUpperCase() + part.slice(1)).join('')
110
-
111
- try {
112
- if (!command || command === '--help' || command === '-h' || command === 'help') {
113
- console.log(USAGE)
114
- process.exit(command ? 0 : 1)
115
- }
116
-
117
- if (!HELP[command]) {
118
- throw new Error(`unknown command "${command}".\n\n${USAGE}`)
119
- }
120
-
121
- if (wantsHelp) {
122
- console.log(HELP[command])
123
- process.exit(0)
124
- }
125
-
126
- if (command === 'add') {
127
- const name = rest.find(argument => !argument.startsWith('-'))
128
- if (!name) throw new Error(`missing name.\n\n${HELP.add}`)
129
- const written = await addSection(name, root, { component: !rest.includes('--no-component') })
130
- for (const file of written) console.log(` ${file.path.padEnd(34)} ${file.note}`)
131
- console.log(`\nShow it with <${pascal(name)}Section /> on a page,`)
132
- console.log(`or add \\vitasection{${name}} to cv-tex/cv.tex for the PDF.`)
133
- } else if (command === 'list') {
134
- const items = await listEjectable()
135
- const width = Math.max(...items.map(item => item.name.length))
136
- for (const item of items) {
137
- console.log(`${item.name.padEnd(width)} ${item.kind.padEnd(9)} -> ${item.target}`)
138
- }
139
- console.log('\nCopy one with `pnpm vitakit eject <name>`; see --help for what each kind does.')
140
- } else if (command === 'eject') {
141
- const name = rest.find(argument => !argument.startsWith('-'))
142
- if (!name) throw new Error(`missing name. Run \`pnpm vitakit list\` to see the options.`)
143
- const { item, path } = await eject(name, root, { force: rest.includes('--force') })
144
- console.log(`vitakit: wrote ${relative(root, path)}`)
145
- const hints = {
146
- publications: ' Edit it to change the publication groups, badges or fields; the website,\n'
147
- + ' vitakit-check and the PDF all read it from now on.',
148
- schema: ' Edit it to change what this section may contain; it now defines the section.',
149
- style: ' Edit it, or replace it with any CSL style (e.g. from zotero.org/styles);\n'
150
- + ' it formats content/publications.bib on the website from now on.',
151
- }
152
- const hint = item.kind === 'schema' && item.name === 'publications' ? hints.publications : hints[item.kind]
153
- console.log(hint ?? ' It takes precedence over the package copy from now on.')
154
- }
155
- } catch (error) {
156
- console.error(`\nvitakit: ${error instanceof Error ? error.message : String(error)}\n`)
157
- process.exit(1)
158
- }
8
+ process.exitCode = await main(process.argv.slice(2))
@@ -1,250 +0,0 @@
1
- import { readdir, readFile, mkdir, writeFile } from 'node:fs/promises';
2
- import { existsSync } from 'node:fs';
3
- import { basename, join } from 'node:path';
4
- import { Eta } from 'eta';
5
- import { m as fail, p as formatZodIssues, k as atMost, o as resolveAsset, n as isSitePath } from './vitakit.BxcnlFGP.mjs';
6
- import { entrySecondaryParts, entryTitleField, formatDateRange } from './index.mjs';
7
- import { r as richSource } from './vitakit.BlU-p01e.mjs';
8
- import { parse } from 'yaml';
9
- import { z } from 'zod';
10
-
11
- const REPLACEMENTS = {
12
- "\\": "\\textbackslash{}",
13
- "&": "\\&",
14
- "%": "\\%",
15
- $: "\\$",
16
- "#": "\\#",
17
- _: "\\_",
18
- "{": "\\{",
19
- "}": "\\}",
20
- "~": "\\textasciitilde{}",
21
- "^": "\\textasciicircum{}"
22
- };
23
- const TYPOGRAPHY = [
24
- // Directional quotes: "..." -> ``...''
25
- [/"([^"]*)"/g, "``$1''"],
26
- // An en dash written literally
27
- [/\u2013/g, "--"],
28
- [/\u2014/g, "---"],
29
- [/\u2026/g, "\\ldots{}"],
30
- [/\u00a0/g, "~"]
31
- ];
32
- function escapeTex(value, { typography = true, source } = {}) {
33
- if (source !== void 0 && /(?<!\\)\$/.test(value)) {
34
- throw new Error(`unbalanced math delimiters in: ${source}`);
35
- }
36
- let result = value.replace(/[\\&%$#_{}~^]/g, (character) => REPLACEMENTS[character]);
37
- if (typography) {
38
- for (const [pattern, replacement] of TYPOGRAPHY) result = result.replace(pattern, replacement);
39
- }
40
- return result;
41
- }
42
- function escapeRichTex(value) {
43
- const parts = [];
44
- const pattern = /\$\$[\s\S]*?\$\$|\$(?:\\.|[^$\\])*\$/g;
45
- let index = 0;
46
- for (const match of value.matchAll(pattern)) {
47
- const start = match.index;
48
- parts.push(escapeTex(value.slice(index, start), { source: value }));
49
- parts.push(match[0]);
50
- index = start + match[0].length;
51
- }
52
- parts.push(escapeTex(value.slice(index), { source: value }));
53
- return parts.join("");
54
- }
55
- const URL_SPECIAL = /%[0-9A-Fa-f]{2}|[%\\{}^ #&]/g;
56
- function escapeUrl(value) {
57
- return value.replace(URL_SPECIAL, (match) => {
58
- if (match.length === 3 || match === "#" || match === "&") return `\\${match}`;
59
- return `\\%${match.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`;
60
- });
61
- }
62
-
63
- const sectionOptions = z.strictObject({
64
- /**
65
- * Keep entries whose field equals the value, or one of several values:
66
- *
67
- * ```yaml
68
- * where: { kind: invited }
69
- * where: { kind: [invited, seminar] }
70
- * ```
71
- */
72
- where: z.record(z.string(), z.union([z.string(), z.array(z.string()).min(1)])).default({}),
73
- /** Keep only the newest N entries. */
74
- limit: z.number().int().positive().optional(),
75
- /** Drop entries starting before this year. */
76
- since: z.number().int().optional(),
77
- /** Drop entries starting after this year. */
78
- until: z.number().int().optional(),
79
- /** Heading used by `\vitasection`; defaults to the section id, capitalised. */
80
- title: z.string().min(1).optional()
81
- });
82
- const documentSchema = z.strictObject({
83
- /**
84
- * Highest visibility level this document may include. Defaults to `cv`,
85
- * because a CV is the reason the `cv` level exists; use `private` for an
86
- * application containing a cover letter, address or referees.
87
- *
88
- * There is no "publish this PDF" option: PDFs are never part of the website
89
- * build (see `vitakit-check`), and the website renders CV data directly.
90
- */
91
- visibility: z.enum(["public", "cv", "private"]).default("cv"),
92
- sections: z.record(z.string(), sectionOptions).default({}),
93
- publications: z.strictObject({
94
- groups: z.array(z.string()).optional()
95
- }).default({})
96
- });
97
- const DEFAULTS = documentSchema.parse({});
98
- async function discoverDocuments(cvDir) {
99
- const files = (await readdir(cvDir).catch(() => fail("cv-tex/", "directory is missing"))).filter((name) => name.endsWith(".tex")).sort();
100
- const documents = [];
101
- for (const file of files) {
102
- const name = basename(file, ".tex");
103
- const source = await readFile(join(cvDir, file), "utf8");
104
- if (!/\\begin\{document\}/.test(source)) continue;
105
- const optionsFile = join(cvDir, `${name}.yml`);
106
- const raw = await readFile(optionsFile, "utf8").catch(() => void 0);
107
- let options = DEFAULTS;
108
- if (raw !== void 0) {
109
- const parsed = documentSchema.safeParse(parse(raw) ?? {});
110
- if (!parsed.success) fail(`cv-tex/${name}.yml`, `invalid
111
- ${formatZodIssues(parsed.error)}`);
112
- options = parsed.data;
113
- }
114
- documents.push({ name, texFile: join(cvDir, file), options });
115
- }
116
- if (!documents.length) fail("cv-tex/", "no .tex file contains \\begin{document}");
117
- return documents;
118
- }
119
- function valueOf(entry, field) {
120
- if (field === "year") return entry.date?.from?.year;
121
- const value = entry[field];
122
- if (typeof value === "object" && value !== null && "text" in value) return value.text;
123
- if (typeof value === "object" && value !== null && "name" in value) return value.name;
124
- return value;
125
- }
126
- function selectEntries(entries, options, sectionId) {
127
- const section = options.sections[sectionId] ?? { where: {} };
128
- let result = entries.filter((entry) => atMost(entry.visibility, options.visibility));
129
- if (section.since !== void 0) {
130
- result = result.filter((entry) => Number(valueOf(entry, "year") ?? 0) >= section.since);
131
- }
132
- if (section.until !== void 0) {
133
- result = result.filter((entry) => Number(valueOf(entry, "year") ?? Infinity) <= section.until);
134
- }
135
- for (const [field, expected] of Object.entries(section.where ?? {})) {
136
- const wanted = new Set(Array.isArray(expected) ? expected : [expected]);
137
- result = result.filter((entry) => wanted.has(String(valueOf(entry, field) ?? "")));
138
- }
139
- return section.limit ? result.slice(0, section.limit) : result;
140
- }
141
-
142
- const bundledTexDir = resolveAsset("tex");
143
- const eta = new Eta({ autoEscape: false, autoTrim: [false, false] });
144
- function tidy(body) {
145
- return body.replace(/[ \t]+$/gm, "").replace(/\n{2,}/g, "\n").trim();
146
- }
147
- const SITE_PATH_HELP = "is a path on the website, and the PDF can only link it with the address the site is published at: add it to content/profile.yml, e.g. `url: https://jane.example.org/`";
148
- function helpers(where, source) {
149
- const tex = (value) => value === void 0 || value === null ? "" : escapeTex(String(value));
150
- const rich = (value) => {
151
- if (value === void 0 || value === null) return "";
152
- const source2 = richSource(value);
153
- try {
154
- return escapeRichTex(source2);
155
- } catch (error) {
156
- return fail(where, error instanceof Error ? error.message : String(error));
157
- }
158
- };
159
- const href = (value) => {
160
- if (isSitePath(value)) fail(source, `${value} ${SITE_PATH_HELP}`);
161
- return escapeUrl(value);
162
- };
163
- const url = (value) => value ? href(String(value)) : "";
164
- const inst = (value) => {
165
- const institution = value;
166
- if (!institution?.name) return "";
167
- return institution.url ? `\\href{${href(institution.url)}}{${escapeTex(institution.name)}}` : escapeTex(institution.name);
168
- };
169
- const linkOrText = (value) => {
170
- if (typeof value === "string") return escapeTex(value);
171
- const item = value;
172
- if (!item?.label) return "";
173
- return item.url ? `\\href{${href(item.url)}}{${escapeTex(item.label)}}` : escapeTex(item.label);
174
- };
175
- const date = (value) => escapeTex(formatDateRange(value));
176
- const term = (entry) => typeof entry.term === "string" ? escapeTex(entry.term) : date(entry.date);
177
- const titleOf = (entry) => {
178
- const field = entryTitleField(entry);
179
- return field ? entry[field] : "";
180
- };
181
- const secondaryOf = (entry) => entrySecondaryParts(entry, entryTitleField(entry)).map((part) => part.kind === "institution" ? inst(part.institution) : escapeTex(part.text)).filter(Boolean).join(", ");
182
- const bibgroup = (group) => {
183
- const unsafe = /[\s%#\\{},~]/;
184
- const bad = [group.id, ...group.entries.map((entry) => entry.key)].find((value) => !value || unsafe.test(value));
185
- if (bad !== void 0) {
186
- fail(where, `"${bad}" cannot be used as a citation key or group id in LaTeX; use letters, digits and - _ : . / +`);
187
- }
188
- return `\\vitabibgroup{${group.id}}{${group.entries.map((entry) => entry.key).join(",")}}`;
189
- };
190
- return { tex, rich, url, inst, linkOrText, date, term, titleOf, secondaryOf, bibgroup };
191
- }
192
- async function resolveTemplate(id, userDir) {
193
- const candidates = [join(userDir, `${id}.eta`), join(bundledTexDir, "templates", `${id}.eta`), join(bundledTexDir, "templates", "_generic.eta")];
194
- for (const path of candidates) {
195
- if (existsSync(path)) return { path, source: await readFile(path, "utf8") };
196
- }
197
- throw new Error(`vitakit: no template for section ${id}`);
198
- }
199
- async function assertTemplatesAreUsed(templateDir, ids) {
200
- const files = await readdir(templateDir).catch(() => []);
201
- const known = /* @__PURE__ */ new Set([...ids, "publications", "_generic"]);
202
- for (const file of files.filter((name) => name.endsWith(".eta")).sort()) {
203
- const id = file.slice(0, -".eta".length);
204
- if (known.has(id)) continue;
205
- const suggestion = ids.find((candidate) => candidate.startsWith(id) || id.startsWith(candidate));
206
- fail(
207
- `cv-tex/templates/${file}`,
208
- `no section is called "${id}", so this template is never used${suggestion ? `; did you mean ${suggestion}.eta?` : ""}
209
- sections: ${ids.join(", ") || "(none)"}`
210
- );
211
- }
212
- }
213
- async function emitDocument(emit) {
214
- await mkdir(emit.outDir, { recursive: true });
215
- await assertTemplatesAreUsed(emit.templateDir, Object.keys(emit.sections));
216
- const written = [];
217
- for (const [id, entries] of Object.entries(emit.sections)) {
218
- const where = `cv-tex/generated/${id}.tex`;
219
- const selected = selectEntries(entries, emit.options, id);
220
- const { source } = await resolveTemplate(id, emit.templateDir);
221
- let body;
222
- try {
223
- body = tidy(eta.renderString(source, { entries: selected, ...helpers(where, `content/${id}.yml`) }));
224
- } catch (error) {
225
- throw new Error(`template ${id}.eta: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
226
- }
227
- const file = join(emit.outDir, `${id}.tex`);
228
- await writeFile(file, `% Generated by vitakit. Do not edit; edit content/${id}.yml instead.
229
- ${body.trim()}
230
- `);
231
- written.push(file);
232
- }
233
- if (emit.publications.length) {
234
- const groups = emit.options.publications.groups ? emit.options.publications.groups.map((id) => emit.publications.find((group) => group.id === id)).filter((group) => group !== void 0) : emit.publications;
235
- if (!emit.siteUrl) {
236
- const local = groups.flatMap((group) => group.entries).find((entry) => entry.titleUrl && isSitePath(entry.titleUrl));
237
- if (local) fail("content/publications.bib", `${local.key}: url ${local.titleUrl} ${SITE_PATH_HELP}`);
238
- }
239
- const { source } = await resolveTemplate("publications", emit.templateDir);
240
- const body = tidy(eta.renderString(source, { groups, ...helpers("publications.tex", "content/publications.bib") }));
241
- const file = join(emit.outDir, "publications.tex");
242
- await writeFile(file, `% Generated by vitakit. Do not edit; edit content/publications.bib instead.
243
- ${body.trim()}
244
- `);
245
- written.push(file);
246
- }
247
- return written;
248
- }
249
-
250
- export { SITE_PATH_HELP as S, escapeTex as a, bundledTexDir as b, escapeUrl as c, discoverDocuments as d, emitDocument as e, documentSchema as f, escapeRichTex as g, selectEntries as s };