generator-latex-template 2026.10.13 → 2026.10.16

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 (56) hide show
  1. package/README.md +12 -153
  2. package/generators/app/CLAUDE.md +4 -2
  3. package/generators/app/index.js +111 -5
  4. package/generators/app/options.js +62 -49
  5. package/generators/app/templates/.github/dependabot.yml +3 -0
  6. package/generators/app/templates/.github/workflows/check.yml +42 -18
  7. package/generators/app/templates/.vscode/extensions.json +3 -2
  8. package/generators/app/templates/Dockerfile.dante +1 -8
  9. package/generators/app/templates/Makefile +59 -22
  10. package/generators/app/templates/README.en.md +393 -368
  11. package/generators/app/templates/Texlivefile +17 -1
  12. package/generators/app/templates/abbreviations.example.en.tex +1 -1
  13. package/generators/app/templates/authorarchive.preamble.en.tex +15 -0
  14. package/generators/app/templates/docs/latex-setup.md +2 -1
  15. package/generators/app/templates/docs/thesis-checklist.md +1 -1
  16. package/generators/app/templates/dot.aspell.de.pws +14 -1
  17. package/generators/app/templates/dot.aspell.en.pws +14 -1
  18. package/generators/app/templates/dot.dockerignore +1 -1
  19. package/generators/app/templates/dot.gitignore +10 -11
  20. package/generators/app/templates/dot.textidote +6 -0
  21. package/generators/app/templates/dot.textidote.replacements +40 -0
  22. package/generators/app/templates/dot.textlintrc.json +10 -2
  23. package/generators/app/templates/embedfile.preamble.en.tex +3 -4
  24. package/generators/app/templates/floats.example.de.tex +1 -1
  25. package/generators/app/templates/floats.example.en.tex +1 -1
  26. package/generators/app/templates/font.preamble.en.tex +12 -8
  27. package/generators/app/templates/latexmkrc +13 -2
  28. package/generators/app/templates/localSettings.yaml +4 -0
  29. package/generators/app/templates/logos/README.md +10 -0
  30. package/generators/app/templates/logos/thu-logo.png +0 -0
  31. package/generators/app/templates/logos/uhh-logo.pdf +0 -0
  32. package/generators/app/templates/main.de.tex +121 -65
  33. package/generators/app/templates/main.en.tex +124 -68
  34. package/generators/app/templates/mermaid.example.en.tex +69 -0
  35. package/generators/app/templates/minted.example.en.tex +1 -1
  36. package/generators/app/templates/mwe-main.de.tex +3 -2
  37. package/generators/app/templates/mwe-main.en.tex +3 -2
  38. package/generators/app/templates/paralist.example.en.tex +3 -3
  39. package/generators/app/templates/plantuml.example.en.tex +77 -21
  40. package/generators/app/templates/puppeteer.json +3 -0
  41. package/generators/app/templates/scientific-thesis-cover.preamble.de.tex +3 -3
  42. package/generators/app/templates/scientific-thesis-cover.preamble.en.tex +3 -3
  43. package/generators/app/templates/subfig.example.en.tex +1 -1
  44. package/generators/app/templates/tables.example.en.tex +19 -0
  45. package/generators/app/templates/thesis-additions.examples.en.tex +3 -3
  46. package/generators/app/templates/tikzuml.example.en.tex +74 -38
  47. package/generators/app/templates/todos.example.en.tex +1 -1
  48. package/generators/app/templates/uml.example.en.tex +81 -0
  49. package/generators/app/templates/uml.mermaid.preamble.en.tex +54 -0
  50. package/generators/app/templates/uml.plantuml.preamble.en.tex +24 -4
  51. package/generators/app/templates/uml.preamble.en.tex +14 -0
  52. package/generators/app/templates/vscode.settings.json +20 -11
  53. package/generators/app/templates/xcolor.preamble.de.tex +4 -0
  54. package/generators/app/templates/zref-clever.example.en.tex +1 -1
  55. package/generators/app/templates/zref-vario.example.en.tex +1 -1
  56. package/package.json +1 -1
package/README.md CHANGED
@@ -2,20 +2,15 @@
2
2
 
3
3
  > Generates latex templates (e.g., for thesis, workshops, conferences, IEEEtran, LNCS, ...) out of "micro-templates"
4
4
 
5
- ## Talks and papers
6
-
7
- - Paper: [Oliver Kopp - The LaTeX template generator: How micro-templates reduce template maintenance effort](https://tug.org/TUGboat/tb44-2/tb137kopp-microtemplates.html)
8
- - Talk: [Oliver Kopp - The LaTeX Template Generator - DANTE Herbsttagung 2019](https://github.com/dante-ev/Vortraege_Tagungen/blob/master/2019-Herbst/Oliver%20Kopp%20-%20The%20LaTeX%20Template%20Generator%20-%20dante2019-herbst.pdf) - a talk on the motivation, user experience, and the contribution
9
-
10
5
  ## Background information
11
6
 
12
- There are many latex templates out there.
7
+ LaTeX templates abound.
13
8
  All of them make use of certain packages such as [hyperref], [listings], or [minted].
14
9
  The packages have to be a) included in the `.tex` file somehow and b) configured.
15
10
  Moreover, some packages offer interfaces (such as new commands or new environments) to users.
16
11
  Minimal examples help to understand how a package works.
17
12
 
18
- The aim of the repository is to provide for each common latex package
13
+ The aim of the repository is to provide for each common LaTeX package
19
14
 
20
15
  1. Configuration
21
16
  2. Usage example
@@ -30,7 +25,7 @@ and a generation into templates:
30
25
 
31
26
  Besides the paper and thesis document classes, the generator offers a **minimal Markdown quick start**, selectable as the `mwe` document class — for people who want a fast start with writing rather than a full thesis with all the tricks.
32
27
 
33
- - Content is written in **Markdown** inside a `\begin{markdown} … \end{markdown}` block in `main.tex` (via the [`markdown`](https://ctan.org/pkg/markdown) package): `#` becomes a chapter, `##` a section; citations (`[@key]`), footnotes, task lists, pipe tables, and images work out of the box.
28
+ - You write the content in **Markdown** inside a `\begin{markdown} … \end{markdown}` block in `main.tex` (via the [`markdown`](https://ctan.org/pkg/markdown) package): `#` becomes a chapter, `##` a section; citations (`[@key]`), footnotes, task lists, pipe tables, and images work out of the box.
34
29
  - It compiles with **LuaLaTeX + biber** (the `markdown` package needs Lua; the bibliography uses biblatex).
35
30
  - [`zref-clever`](https://ctan.org/pkg/zref-clever) turns the Markdown `{#id}` identifiers into smart `\zcref` cross-references that print the type name (e.g. "Figure 1.1" / "Abbildung 1.1").
36
31
  - It generates a single minimal `main.tex` — no thesis scaffolding, abbreviations, or `commands.tex` — hides the paper/thesis-only prompts, and ships a trimmed, quick-start README.
@@ -44,7 +39,7 @@ yo latex-template --documentclass=mwe --lang=en
44
39
  ### Precondition for the generator
45
40
 
46
41
  One has to install [Node.js](https://nodejs.org/en/) version 18 (or later) to get this generator running.
47
- For simple installation, just head to <https://nodejs.org/> and follow the installation instructions.
42
+ For a simple installation, head to <https://nodejs.org/> and follow the installation instructions.
48
43
 
49
44
  ### Using the generator
50
45
 
@@ -92,162 +87,26 @@ You can use the magic of `git` to prevent that:
92
87
 
93
88
  ## Resources
94
89
 
90
+ - Paper: [Oliver Kopp - The LaTeX template generator: How micro-templates reduce template maintenance effort](https://tug.org/TUGboat/tb44-2/tb137kopp-microtemplates.html)
91
+ - Talk: [Oliver Kopp - The LaTeX Template Generator - DANTE Herbsttagung 2019](https://github.com/dante-ev/Vortraege_Tagungen/blob/master/2019-Herbst/Oliver%20Kopp%20-%20The%20LaTeX%20Template%20Generator%20-%20dante2019-herbst.pdf) - a talk on the motivation, user experience, and the contribution
95
92
  - [IEEE](https://latextemplates.github.io/ieee-enhanced/) - example: [paper-conference-minted.tex](https://github.com/latextemplates/ieee-enhanced/blob/main/paper-conference-minted.tex)
96
93
  - [LNCS](https://latextemplates.github.io/lncs-enhanced/) - example: [paper.tex](https://github.com/latextemplates/lncs-enhanced/blob/main/paper.tex)
97
94
  - [scientific-thesis-template](https://latextemplates.github.io/scientific-thesis-template/) - example: [latexhints-english.tex](https://github.com/latextemplates/scientific-thesis-template/blob/main/latexhints-english.tex)
98
95
  - [alpenwasser/TeX](https://github.com/alpenwasser/TeX)
99
96
 
100
- ## Development roadmap
101
-
102
- In the long run, the contents of the `paper.tex` (and similar) files in repositories of the [latextemplates](https://latextemplates.github.io/) organization should be generated automatically.
103
-
104
- ## Development hints
105
-
106
- - Templating language: <https://ejs.co/>
107
- - Conditional questions: <https://stackoverflow.com/a/18706640/873282>.
108
- - Types of prompts: <https://github.com/SBoudrias/Inquirer.js#prompt-types>
109
- - E.g., [Question](https://github.com/SBoudrias/Inquirer.js#question)
110
- - Add a new question
111
- - Also adapt `__tests__/app.js`
112
- - Execute tests with `npm test` (runs ESLint, then the tests via Node's built-in test runner). A bare run is `node --test`.
113
- - Update NPM dependencies
114
- - `npx npm-update-all`. See [FreeCodeCamp](https://www.freecodecamp.org/news/10-npm-tricks-that-will-make-you-a-pro-a945982afb25/) for more details.
115
- - `npx npm-check-updates -u`. [[Source](https://www.carlrippon.com/upgrading-npm-dependencies/)]
116
- - See <https://github.com/yeoman/generator/releases> for changes in the generator.
117
- - Generate `package-lock.json` only: `npm i --package-lock-only`
118
- - When one encounters `Cannot find module 'yeoman-generator'`, please update the npm dependencies.
119
- That error occurred when using version `4.13.0` and `5.4.2` was available.
120
- - In case of the error "Error: EACCES, permission denied '/root/.config/configstore/insight-yo.json'", one needs to execute `chmod g+rwx /root /root/.config /root/.config/configstore`
121
- - Check GitHub actions
122
- - Use [actionlint](https://github.com/rhysd/actionlint#readme)
123
- - Use [vs.code GitHub actions plugin](https://marketplace.visualstudio.com/items?itemName=cschleiden.vscode-github-actions)
124
- - Use [act](https://github.com/nektos/act) for checking: `act --rm --platform ubuntu-latest=fwilhe2/act-runner:latest -W .github/workflows/check-ieee-conference-a4-pdflatex-bibtex-2023-true.yml`
125
- - When adding a new package use `DEPP` (see above) or execute following steps:
126
- 1. execute `npx` with `--generatereitzig` (in a clean directory)
127
- 2. run `pdflatex`
128
- 3. run `{repository-root}/generate-texlivefile.sh`
129
- 4. copy `Texlivefile` to the root of the `{repository-root}/generators/app/templates`
130
- 5. adapt `Texlivefile` as required
131
- - When issues with the template occur: `npx ejs-lint main.en.tex`
132
- - Cancel workflows:
133
- - `gh run list -L 100 --json databaseId -s queued -R latextemplates/generator-latex-template | jq -r '.[] | .databaseId' | awk '{gsub(/\\r\\n/,RS)} 1' | while read -r run_id; do gh run cancel "$run_id" -R latextemplates/generator-latex-template || true; done`
134
- - `gh run list -L 100 --json databaseId -s in_progress -R latextemplates/generator-latex-template | jq -r '.[] | .databaseId' | awk '{gsub(/\\r\\n/,RS)} 1' | while read -r run_id; do gh run cancel "$run_id" -R latextemplates/generator-latex-template || true; done`
135
- - Update submodule of "derived" templates (LNCS, ...): `scripts/spread-updates.sh`. It also links the generator's `refine-ltg` PR in the description of each template's "Update LTG" PR.
136
- - Keep the `refine-ltg` PR description current: it links every issue the cycle fixes (the same `[repo#N]` links as the CHANGELOG).
137
- - Sort `dot.aspell.en.pws`: `cat dot.aspell.en.pws | (sed -u 1q; sort) | sponge dot.aspell.en.pws` <!-- hint by https://stackoverflow.com/a/56151840/873282 -->
138
-
139
- ### Testing
140
-
141
- - All workflows test `overleaf=no` - and (nearly) all possible combinations.
142
- - All `*-refined` repositories test with `overleaf=true` - and only the typical settings for the template.
143
- - `refine-ltg` is the development branch for the template generator; only a small set of workflows enabled there due to load during testing.
144
- - `update-ltg` is the development branch at each `*-refined` template.
145
-
146
- ### Test locally
147
-
148
- - Create empty directory ("target directory")
149
- - Change to the target directory
150
- - Run `npx yo <path-to-git-repository>/generators/app/index.js`. Background: Starting from 5.0.0 on, [one needs to specify the full path to index.js](https://github.com/yeoman/yo/issues/797#issuecomment-2541794625).
151
- - Windows: `npx yo c:\git-repositories\latextemplates\generator-latex-template\generators\app\index.js`
152
-
153
- #### Linux
154
-
155
- Parameters can be set using command line
156
-
157
- - LNCS: `npx yo /tmp/repo/generators/app/index.js --documentclass=lncs --papersize=a4 --latexcompiler=pdflatex --bibtextool=bibtex --texlive=2026 --docker=false --lang=en --font=default --listings=listings --enquotes=csquotes --tweakouterquote=babel --todo=pdfcomment --examples=true --howtotext=true`
158
-
159
- #### Windows
160
-
161
- Parameters can be set using command line
162
-
163
- - IEEE template (with pdflatex and bibtex): `npx yo c:\git-repositories\latextemplates\generator-latex-template\generators\app\index.js --overleaf=false --documentclass=ieee --ieeevariant=conference --papersize=a4 --latexcompiler=pdflatex --bibtextool=bibtex --texlive=2026 --docker=reitzig --lang=en --font=default --listings=listings --enquotes=csquotes --tweakouterquote=babel --todo=pdfcomment --examples=true --howtotext=true`
164
- - LNCS template (with pdflatex and bibtex): `npx yo c:\git-repositories\latextemplates\generator-latex-template\generators\app\index.js --overleaf=false --documentclass=lncs ---papersize=a4 --latexcompiler=pdflatex --bibtextool=bibtex --texlive=2026 --docker=false --lang=en --font=default --listings=listings --enquotes=csquotes --tweakouterquote=babel --todo=pdfcomment --examples=true --howtotext=true`
165
- - Scientific Thesis template: `npx yo c:\git-repositories\latextemplates\generator-latex-template\generators\app\index.js --overleaf=false --documentclass=scientific-thesis --papersize=a4 --latexcompiler=pdflatex --bibtextool=bibtex --texlive=2026 --lang=en --font=default --listings=listings --enquotes=csquotes --tweakouterquote=babel --todo=pdfcomment --examples=true --howtotext=true`
166
- - USTUTT template: `npx yo c:\git-repositories\latextemplates\generator-latex-template\generators\app\index.js --overleaf=false --documentclass=ustutt --papersize=a5 --latexcompiler=lualatex --bibtextool=biblatex --texlive=2026 --lang=en --font=default --listings=listings --enquotes=csquotes --tweakouterquote=babel --todo=todonotes --examples=true --howtotext=true` -- `todonotes` is the preferred TODO package here.
167
-
168
- <!-- markdownlint-disable-next-line MD004 -->
169
- * Run `latexmk` to build the PDF
170
-
171
- ##### Using DEPP
172
-
173
- To fire up a TeX Live installation and use the [Dependency Printer for TeX Live](https://gitlab.com/islandoftex/texmf/depp) to refine `Texlivefile`, execute following steps:
174
-
175
- ```cmd
176
- docker run -it --rm -v c:\temp\ltg:/ltg registry.gitlab.com/islandoftex/images/texlive:latest
177
- ```
97
+ ## Contributing
178
98
 
179
- ```bash
180
- cd /tmp
181
- git clone https://gitlab.com/islandoftex/texmf/depp.git
182
- cd depp
183
- l3build install
184
- cd /ltg
185
- # edit paper.tex and add `\RequirePackage[dependency-file=Texlivefile]{depp}`
186
- lualatex/pdflatex paper
187
- ```
188
-
189
- ##### Running reitzig
190
-
191
- 1. `docker build --progress=plain -t reitzig -f Dockerfile .`
192
- 2. `docker run -it --rm -v c:\temp\ltg:/work/src -v c:\temp\ltg-out:/work/out reitzig work latexmk`
193
-
194
- ### Useful snippets
195
-
196
- ```ejs
197
- <% if (howtotext) { -%>
198
- <% } else { -%>
199
- <% } -%>
200
- ```
201
-
202
- ```ejs
203
- <% switch (documentclass) { case "lncs": -%>
204
- <% break; case "ieee": -%>
205
- <% break; default: -%>
206
- <% break; } -%>
207
- ```
208
-
209
- ### Debugging
210
-
211
- A `launch.json` configured for Windows and Visual Studio Code is included.
212
- Just press <kbd>F5</kbd> and the generator should run in debug mode.
213
-
214
- ```terminal
215
- ejslint.cmd c:\git-repositories\latextemplates\generator-latex-template\generators\app\templates\main.en.tex
216
- ```
217
-
218
- ### Releasing a new version
219
-
220
- > **Cut the release from `main`, never from `refine-ltg`.**
221
- > Releasing from the dev branch publishes an unmerged tree with a not-yet-finalized CHANGELOG — that is what broke the 2026.6.26 release (a stale `## [2026.6.25]` heading, a missing `[2026.6.26]:` compare link, and an `[Unreleased]:` link that was never bumped).
222
- > So after the squash-merge, `git switch main && git pull` and confirm `git branch --show-current` prints `main` before doing anything below.
223
-
224
- 1. Once the `refine-ltg` PR is green, **squash-merge** it into `main`, then `git switch main && git pull` (confirm you are on `main`).
225
- 2. Update `CHANGELOG.md`: rename the top `## [Unreleased]` heading to `## [<version>]`, add the matching `[<version>]: …/compare/<prev>...<version>` link definition, and bump `[Unreleased]: …/compare/<version>...main`.
226
- 3. **Verify the CHANGELOG before publishing:**
227
- - Run heylogs (the same check as CI's `check-changelog.yml`) and get **0 problems**:
228
- `jbang com.github.nbbrd.heylogs:heylogs-cli:0.18.1:bin check CHANGELOG.md`
229
- - heylogs **cannot** validate the version links here: our CalVer headings omit the date, so `linkable`/`date-displayed`/`all-h2-contain-a-version` are off in `heylogs.properties` and heylogs skips link-checking a dateless heading. So **also check the links by hand** — the top `## [<version>]` must equal the version `release-it` will publish, and both the `[<version>]:` and the bumped `[Unreleased]:` definitions must be present and point at the right tags. Quick grep:
230
- `grep -nE '^## \[|^\[Unreleased\]:|^\[<version>\]:' CHANGELOG.md`
231
- 4. Update `package.json`, publish to [npmjs](https://www.npmjs.com/package/generator-latex-template), create GitHub release.
232
- Use [release-it](https://www.npmjs.com/package/release-it) (do not create a release on GitHub) and [github-release-from-changelog](https://www.npmjs.com/package/github-release-from-changelog).
233
-
234
- - `npx release-it`
235
- - Confirm the publish: `npm view generator-latex-template version` must print the new version (2026.10.1 was tagged and released on GitHub but never published to npm).
236
- - `GITHUB_TOKEN=$(gh auth token) npx github-release-from-changelog` (Git Bash; it needs a GitHub token, which the logged-in `gh` CLI provides)
237
- 5. On `main`, run `scripts/end-new-cycle.sh`, then **squash-merge** each template's "Update LTG" PR once it is green.
238
- 6. Release the templates: `scripts/release-templates.sh <YYYY-MM-DD>` (try `--dry-run` first) finalizes the CHANGELOG of every template with unreleased entries, commits "Release <date>", tags, pushes, and creates the GitHub release with the CHANGELOG section as notes.
99
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for how to contribute and for development hints, including testing and releasing.
239
100
 
240
101
  ## License
241
102
 
242
- The code is licensed [0BSD](https://choosealicense.com/licenses/0bsd/#), the snippets (both LaTeX and text) 0BSD, too.
243
- See [benbalter/talks#15](https://github.com/benbalter/talks/issues/15#issuecomment-599704662), for a reasoning, why [CC0](https://creativecommons.org/share-your-work/public-domain/cc0/) cannot be used.
103
+ The code has the license [0BSD](https://choosealicense.com/licenses/0bsd/#), the snippets (both LaTeX and text) 0BSD, too.
104
+ See [benbalter/talks#15](https://github.com/benbalter/talks/issues/15#issuecomment-599704662), for the reasoning why we cannot use [CC0](https://creativecommons.org/share-your-work/public-domain/cc0/).
244
105
 
245
- - `generators/app/templates/splncs04nat.bst` is taken from [tpavlic/splncs04nat](https://github.com/tpavlic/splncs04nat) and is MIT-licensed.
246
- - `generators/app/templates/logos/`: This directory contains logos, which have special licenses.
106
+ - `generators/app/templates/splncs04nat.bst` comes from [tpavlic/splncs04nat](https://github.com/tpavlic/splncs04nat) and is MIT-licensed.
107
+ - `generators/app/templates/logos/`: This directory contains logos, which have special licenses (see [`logos/README.md`](generators/app/templates/logos/README.md)).
247
108
  - `generators/app/templates/figures/ulm-minster.jpg` is [Landappbw 79389 1820 Ulmer Münster Ulm.jpg](https://commons.wikimedia.org/w/index.php?curid=131463041) by wkrauth, dedicated to the public domain under [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/).
248
109
 
249
110
  [hyperref]: https://ctan.org/pkg/hyperref
250
111
  [listings]: https://ctan.org/pkg/listings
251
112
  [minted]: https://ctan.org/pkg/minted
252
-
253
- <!-- markdownlint-disable-file MD013 MD033 -->
@@ -29,7 +29,8 @@ the feature vanishes for some switch combination without any error.
29
29
  3. **`Texlivefile`** — add the TeX Live package name, guarded (usually
30
30
  `githubpublish || <condition>`; `githubpublish` deliberately bundles everything).
31
31
  4. **Shell-escape is derived, never hardcoded.** It is the boolean
32
- `requiresShellEscape` in `index.js` (`listings == "minted" || uml == "plantuml"`).
32
+ `requiresShellEscape` in `index.js` (`uml == "plantuml"`, and minted only up to TeX Live 2024:
33
+ minted 3 runs `latexminted`, which TeX Live permits in restricted shell escape).
33
34
  Extend that expression if the new package needs `\write18`; the `latexmkrc` and the
34
35
  `main.*.tex` editor hints read the flag.
35
36
  5. **New user switch?** Decide **prompt vs. plain flag** first:
@@ -82,6 +83,7 @@ The consequence (and a real footgun): **the blank-line layout of the output is n
82
83
  layout of the source.** Because `-%>` eats one trailing newline, two adjacent
83
84
  `-%>`-terminated blocks/includes render with **no** blank line between them. To get a
84
85
  blank line between blocks you need one of:
86
+
85
87
  - the first block's file to **end with a trailing blank line** (how most
86
88
  `*.preamble.*.tex` separate themselves — e.g. `font.preamble` ends with a blank line
87
89
  then `<% } -%>`), **or**
@@ -111,5 +113,5 @@ formats) catch things a single local `yo` + compile does not. Two that have bitt
111
113
  language's example must be defined in **both** `abbreviations.en.tex` and
112
114
  `abbreviations.de.tex` (the unused one just never appears in that document's list). Making
113
115
  `\gls` entries language-exclusive breaks the other language's variant with
114
- "Glossary entry `…' has not been defined". The same single-shared-file logic applies to
116
+ ``Glossary entry `…' has not been defined``. The same single-shared-file logic applies to
115
117
  other `this.fs.copy`'d siblings (`commands.tex`, …).
@@ -12,7 +12,11 @@ export default class extends Generator {
12
12
  this.log(yosay(`Welcome to the ${chalk.red("latex-template")} generator!`));
13
13
 
14
14
  // See "Development hints" in README.md for help on Inquirer.js
15
- const props = await this._optionOrPrompt(options);
15
+ // yeoman-option-or-prompt mutates the prompts (deletes `when`, replaces `choices`/`default`
16
+ // functions by their result); pass copies so that runs in one process (the tests) stay independent.
17
+ const props = await this._optionOrPrompt(
18
+ options.map((prompt) => ({ ...prompt })),
19
+ );
16
20
 
17
21
  // To access props later use this.props.someAnswer;
18
22
  this.props = props;
@@ -179,10 +183,17 @@ export default class extends Generator {
179
183
  this.props.Vref = "\\zvref[S]";
180
184
  }
181
185
 
182
- // Only minted and the PlantUML UML example need shell-escape; tikz-uml and the
183
- // remaining thesis content do not.
186
+ // The program that processes the bibliography: biber for biblatex, bibtex otherwise.
187
+ this.props.bibrunner =
188
+ this.props.bibtextool === "biblatex" ? "biber" : "bibtex";
189
+
190
+ // Only the PlantUML UML example needs shell-escape. minted 3 (TeX Live 2025 and later)
191
+ // runs latexminted, which TeX Live permits in restricted shell escape; minted 2
192
+ // (TeX Live 2024) still needs shell-escape.
184
193
  this.props.requiresShellEscape =
185
- this.props.listings == "minted" || this.props.uml == "plantuml";
194
+ (this.props.listings == "minted" && this.props.texlive < 2025) ||
195
+ this.props.uml == "plantuml" ||
196
+ this.props.uml == "mermaid";
186
197
 
187
198
  // Two-column layouts (IEEE, and the ACM conference/journal formats) cannot use
188
199
  // `longtable` ("longtable not in 1-column mode"), so the longtable example must
@@ -205,6 +216,45 @@ export default class extends Generator {
205
216
  ? "latest"
206
217
  : `TL${this.props.texlive}-historic`);
207
218
 
219
+ // The DANTE e.V. image additionally contains PlantUML (and the Mermaid CLI), needed by
220
+ // --uml=plantuml and --uml=mermaid. Its tags: https://hub.docker.com/r/danteev/texlive/tags
221
+ const danteTags = {
222
+ 2021: "2021-D",
223
+ 2023: "2023-A",
224
+ 2024: "2024-B",
225
+ 2025: "2026-B",
226
+ 2026: "2026-B",
227
+ };
228
+ this.props.danteImage =
229
+ "danteev/texlive:" + (danteTags[this.props.texlive] ?? "edge");
230
+
231
+ // The image used to compile in Docker (README, Makefile, VS Code settings)
232
+ this.props.dockerImage =
233
+ this.props.docker === "dante"
234
+ ? this.props.danteImage
235
+ : this.props.iotImage;
236
+ this.props.dockerCompile =
237
+ this.props.docker === "iot" || this.props.docker === "dante";
238
+
239
+ // The generator options of this template, used in the README to tell how to generate an own
240
+ // copy (e.g., with PlantUML). The options that distinguish the main files of a published
241
+ // template (thesis variant, language, package for source code) are left open, so that the
242
+ // generator asks for them.
243
+ this.props.regenerateOptions = [
244
+ "documentclass",
245
+ "latexcompiler",
246
+ "overleaf",
247
+ "texlive",
248
+ "enquotes",
249
+ "tweakouterquote",
250
+ "todo",
251
+ "examples",
252
+ "howtotext",
253
+ ]
254
+ .filter((name) => this.props[name] !== undefined)
255
+ .map((name) => `--${name}=${this.props[name]}`)
256
+ .join(" ");
257
+
208
258
  createFeatures(props);
209
259
  createHeadingCommands(props);
210
260
  createAvailable(props);
@@ -310,7 +360,7 @@ export default class extends Generator {
310
360
  );
311
361
  this.fs.copyTpl(
312
362
  this.templatePath("latexmkrc"),
313
- this.destinationPath(this.props.overleaf ? "_latexmkrc" : ".latexmkrc"),
363
+ this.destinationPath(".latexmkrc"),
314
364
  this.props,
315
365
  );
316
366
  this.fs.copyTpl(
@@ -354,6 +404,40 @@ export default class extends Generator {
354
404
  );
355
405
  }
356
406
 
407
+ // TeXtidote (spelling, grammar, and style; CI job "textidote") reads its options from .textidote.
408
+ // Its dictionary contains the words of both aspell word lists (without their header lines).
409
+ // Both files must not depend on the language: some templates publish both languages into one repository.
410
+ if (this.props.documentclass !== "mwe") {
411
+ this.fs.copy(
412
+ this.templatePath("dot.textidote"),
413
+ this.destinationPath(".textidote"),
414
+ );
415
+ this.fs.copy(
416
+ this.templatePath("dot.textidote.replacements"),
417
+ this.destinationPath(".textidote.replacements"),
418
+ );
419
+ const words = [
420
+ ...new Set(
421
+ ["en", "de"].flatMap((lang) =>
422
+ this.fs
423
+ .read(this.templatePath(`dot.aspell.${lang}.pws`))
424
+ .split("\n")
425
+ .slice(1)
426
+ .filter((word) => word !== ""),
427
+ ),
428
+ ),
429
+ ]
430
+ .sort((a, b) => a.localeCompare(b, "en"))
431
+ .join("\n");
432
+ // aspell word lists cannot contain hyphenated words
433
+ const hyphenated =
434
+ "zref-clever\nZref-clever\nzref-vario\nZref-vario\npgf-umlsd\nmarkdown-latex-quickstart\n";
435
+ this.fs.write(
436
+ this.destinationPath(".textidote.dict"),
437
+ words + "\n" + hyphenated,
438
+ );
439
+ }
440
+
357
441
  if (this.props.documentclass === "lncs") {
358
442
  this.fs.copy(
359
443
  this.templatePath("splncs04nat.bst"),
@@ -442,6 +526,20 @@ export default class extends Generator {
442
526
  );
443
527
  }
444
528
 
529
+ if (this.props.documentclass == "scientific-thesis") {
530
+ const logos = {
531
+ "university-of-hamburg": "uhh-logo.pdf",
532
+ thu: "thu-logo.png",
533
+ };
534
+ const logo = logos[this.props.thesisvariant];
535
+ if (logo) {
536
+ this.fs.copy(
537
+ this.templatePath("logos/" + logo),
538
+ this.destinationPath("figures/" + logo),
539
+ );
540
+ }
541
+ }
542
+
445
543
  if (this.props.documentclass == "ustutt") {
446
544
  /*
447
545
  this.props.documentclass = "ustutt-include";
@@ -523,6 +621,14 @@ export default class extends Generator {
523
621
  this.fs.copy(this.templatePath("docs/*"), this.destinationPath("docs/"));
524
622
  }
525
623
 
624
+ if (this.props.uml === "mermaid") {
625
+ // lets the headless Chromium of the Mermaid CLI run without sandbox (see uml.mermaid.preamble.en.tex)
626
+ this.fs.copy(
627
+ this.templatePath("puppeteer.json"),
628
+ this.destinationPath("puppeteer.json"),
629
+ );
630
+ }
631
+
526
632
  this.fs.copy(
527
633
  this.templatePath(".github/dependabot.yml"),
528
634
  this.destinationPath(".github/dependabot.yml"),
@@ -114,6 +114,10 @@ export const options = [
114
114
  name: "Universität Hamburg",
115
115
  value: "university-of-hamburg",
116
116
  },
117
+ {
118
+ name: "Technische Hochschule Ulm",
119
+ value: "thu",
120
+ },
117
121
  ],
118
122
  default: "ustutt",
119
123
  },
@@ -159,28 +163,18 @@ export const options = [
159
163
  type: "list",
160
164
  name: "texlive",
161
165
  message: "Which TeXLive compatibility?",
162
- choices(state) {
163
- const res = [
164
- {
165
- name: "TeXLive 2024",
166
- value: 2024,
167
- },
168
- ];
169
- if (!state.overleaf) {
170
- res.push({
171
- name: "TeXLive 2025",
172
- value: 2025,
173
- });
174
- }
175
- return res;
176
- },
177
- default(state) {
178
- if (state.overleaf) {
179
- return 2024;
180
- }
181
-
182
- return 2025;
183
- },
166
+ // Overleaf offers the current TeX Live (select it in the project settings).
167
+ choices: [
168
+ {
169
+ name: "TeXLive 2025",
170
+ value: 2025,
171
+ },
172
+ {
173
+ name: "TeXLive 2026",
174
+ value: 2026,
175
+ },
176
+ ],
177
+ default: 2026,
184
178
  },
185
179
  {
186
180
  type: "list",
@@ -197,7 +191,7 @@ export const options = [
197
191
  value: "pdflatex",
198
192
  },
199
193
  ];
200
- if (state.texlive == 2025) {
194
+ if (state.texlive == 2026) {
201
195
  res.push({
202
196
  name: "pdflatex-dev",
203
197
  value: "pdflatex-dev",
@@ -207,7 +201,7 @@ export const options = [
207
201
  name: "lualatex",
208
202
  value: "lualatex",
209
203
  });
210
- if (state.texlive == 2025) {
204
+ if (state.texlive == 2026) {
211
205
  res.push({
212
206
  name: "lualatex-dev",
213
207
  value: "lualatex-dev",
@@ -254,30 +248,6 @@ export const options = [
254
248
  }
255
249
  },
256
250
  },
257
- {
258
- type: "list",
259
- name: "docker",
260
- message: "Should a Dockerfile be generated?",
261
- choices: [
262
- {
263
- name: "no",
264
- value: false,
265
- },
266
- {
267
- name: "yes (Island of TeX)",
268
- value: "iot",
269
- },
270
- {
271
- name: "yes (Reiztig)",
272
- value: "reitzig",
273
- },
274
- {
275
- name: "yes (DANTE e.V.)",
276
- value: "dante",
277
- },
278
- ],
279
- default: false,
280
- },
281
251
  {
282
252
  type: "list",
283
253
  name: "lang",
@@ -484,10 +454,53 @@ export const options = [
484
454
  value: "tikz-uml",
485
455
  },
486
456
  {
487
- name: "PlantUML (needs LuaLaTeX, --shell-escape, and a PlantUML/Java install)",
457
+ name: "PlantUML (needs --shell-escape, Java, and PlantUML; contained in the Docker image by DANTE e.V.)",
488
458
  value: "plantuml",
489
459
  },
460
+ {
461
+ name: "Mermaid (needs --shell-escape and the Mermaid CLI; contained in the Docker image by DANTE e.V.)",
462
+ value: "mermaid",
463
+ },
490
464
  ],
491
465
  default: "none",
492
466
  },
467
+ {
468
+ type: "list",
469
+ name: "docker",
470
+ message: "Should a Dockerfile be generated?",
471
+ // PlantUML and the Mermaid CLI are contained only in the image by DANTE e.V.
472
+ choices(state) {
473
+ const needsDante = state.uml === "plantuml" || state.uml === "mermaid";
474
+ const res = [
475
+ {
476
+ name: "no",
477
+ value: false,
478
+ },
479
+ ];
480
+ if (!needsDante) {
481
+ res.push(
482
+ {
483
+ name: "yes (Island of TeX)",
484
+ value: "iot",
485
+ },
486
+ {
487
+ name: "yes (Reiztig)",
488
+ value: "reitzig",
489
+ },
490
+ );
491
+ }
492
+ res.push({
493
+ name: needsDante
494
+ ? "yes (DANTE e.V.; contains PlantUML and the Mermaid CLI)"
495
+ : "yes (DANTE e.V.)",
496
+ value: "dante",
497
+ });
498
+ return res;
499
+ },
500
+ default(state) {
501
+ return state.uml === "plantuml" || state.uml === "mermaid"
502
+ ? "dante"
503
+ : false;
504
+ },
505
+ },
493
506
  ];
@@ -4,3 +4,6 @@ updates:
4
4
  directory: '/'
5
5
  schedule:
6
6
  interval: 'weekly'
7
+ groups:
8
+ actions:
9
+ patterns: ["*"]