slidev-theme-tud 0.0.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 (56) hide show
  1. package/.envrc +1 -0
  2. package/.github/workflows/deploy.yml +84 -0
  3. package/.github/workflows/release.yml +89 -0
  4. package/.vscode/extensions.json +3 -0
  5. package/README.md +60 -0
  6. package/assets/TUD-logo-bl.svg +1 -0
  7. package/assets/TUD-logo-no-color.svg +1 -0
  8. package/assets/TUD-logo-text-no-color.svg +1 -0
  9. package/assets/TUD-logo-text-small-no-color.svg +1 -0
  10. package/assets/TUD-logo-tr.svg +1 -0
  11. package/assets/favicons/apple-touch-icon.png +0 -0
  12. package/assets/favicons/dark/apple-touch-icon.png +0 -0
  13. package/assets/favicons/dark/favicon-16x16.png +0 -0
  14. package/assets/favicons/dark/favicon-32x32.png +0 -0
  15. package/assets/favicons/dark/favicon.ico +0 -0
  16. package/assets/favicons/favicon-16x16.png +0 -0
  17. package/assets/favicons/favicon-32x32.png +0 -0
  18. package/assets/favicons/favicon.ico +0 -0
  19. package/assets/fonts/FiraCode-VariableFont_wght.ttf +0 -0
  20. package/assets/fonts/NotoSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  21. package/assets/fonts/NotoSans-VariableFont_wdth,wght.ttf +0 -0
  22. package/assets/fonts/OFL.txt +93 -0
  23. package/components/.gitkeep +0 -0
  24. package/components/Background.vue +130 -0
  25. package/components/Footnotes.vue +164 -0
  26. package/example.mdc +372 -0
  27. package/flake.lock +61 -0
  28. package/flake.nix +22 -0
  29. package/global-bottom.vue +79 -0
  30. package/global-top.vue +72 -0
  31. package/layouts/README.md +2 -0
  32. package/layouts/cols.vue +38 -0
  33. package/layouts/cover-blue.vue +60 -0
  34. package/layouts/cover-white.vue +58 -0
  35. package/layouts/cover.vue +10 -0
  36. package/layouts/default.vue +15 -0
  37. package/layouts/section-blue.vue +32 -0
  38. package/layouts/section-n.vue +171 -0
  39. package/layouts/section-white.vue +25 -0
  40. package/layouts/section.vue +10 -0
  41. package/markdown.ts +196 -0
  42. package/package.json +70 -0
  43. package/pnpm-workspace.yaml +23 -0
  44. package/scripts/background.ts +69 -0
  45. package/scripts/color.ts +81 -0
  46. package/scripts/util.ts +51 -0
  47. package/setup/katex.ts +35 -0
  48. package/setup/shiki.ts +48 -0
  49. package/shims.d.ts +27 -0
  50. package/styles/fade-transition.css +36 -0
  51. package/styles/font.css +28 -0
  52. package/styles/index.ts +5 -0
  53. package/styles/layout.css +184 -0
  54. package/tsconfig.json +30 -0
  55. package/uno.config.ts +35 -0
  56. package/vite.config.ts +29 -0
@@ -0,0 +1,164 @@
1
+ <script setup lang="ts">
2
+ import { useSlideContext } from '@slidev/client'
3
+ import { computed, nextTick, onBeforeUnmount, onMounted, ref, unref, watch } from 'vue'
4
+
5
+ // Markdown footnotes are wrapped in this component by the footnote render-rule
6
+ // override in vite.config.ts. Instead of rendering inline at the bottom of the
7
+ // slide (where they get caught by slide transitions), we teleport them into a
8
+ // target in global-bottom.vue. That layer is rendered *outside* Slidev's
9
+ // transition group, so the footnotes no longer animate, and they sit right
10
+ // next to the footer for easy styling.
11
+ const { $nav, $page, $clicks } = useSlideContext()
12
+
13
+ // Each mounted slide (the active one, preloaded neighbours, every print page)
14
+ // renders its own <Footnotes>. Only the slide that is currently shown teleports
15
+ // into the shared target; the others render nothing (see v-if below) so they
16
+ // neither collide in the target nor flash their footnotes in-place while
17
+ // sliding out during a transition.
18
+ const isActive = computed(() => unref($page) === unref(($nav as any).value.currentPage))
19
+
20
+ // The target id is scoped to the page number. In print/export each page has
21
+ // its own global-bottom with a page-scoped nav, so this keeps every page's
22
+ // footnotes pointed at *its own* target instead of all resolving to the first.
23
+ const target = computed(() => `#footnotes-containter-${unref($page)}`)
24
+
25
+ // --- Footnote <-> reference visibility mirroring -----------------------------
26
+ // markdown-it-footnote already links each footnote to its in-text references:
27
+ // reference: <sup class="footnote-ref"><a href="#fnN" id="fnrefN[:k]">[N]</a>
28
+ // footnote: <li id="fnN" class="footnote-item">
29
+ // so a footnote `fnN` corresponds to every `.footnote-ref a[href="#fnN"]`.
30
+ //
31
+ // The references live in the slide body and may sit inside a `v-click` (or any
32
+ // other reveal), which fades them via opacity. Because the footnote block is
33
+ // teleported out of the slide it no longer shares that opacity, so on its own
34
+ // it would always be fully visible. We mirror it here: each footnote item takes
35
+ // the *max* opacity of its references (visible as soon as any one reference is),
36
+ // reading the live, mid-transition value so the footnote fades in lockstep.
37
+
38
+ // Hidden marker that stays in the (non-teleported) slide body, used purely to
39
+ // locate the slide root that contains this instance's references.
40
+ const anchorEl = ref<HTMLElement | null>(null)
41
+ // Wrapper around the teleported list; `display: contents` keeps it transparent
42
+ // to layout while giving us a handle on *this* instance's footnote items.
43
+ const listEl = ref<HTMLElement | null>(null)
44
+ let slideRoot: HTMLElement | null = null
45
+
46
+ // Cumulative (visible) opacity of `el` relative to `root`: the product of every
47
+ // opacity along the ancestor chain, so nested reveals compose correctly.
48
+ function visibleOpacity(el: HTMLElement, root: HTMLElement) {
49
+ let opacity = 1
50
+ let node: HTMLElement | null = el
51
+ while (node) {
52
+ opacity *= Number.parseFloat(getComputedStyle(node).opacity) || 0
53
+ if (node === root)
54
+ break
55
+ node = node.parentElement
56
+ }
57
+ return opacity
58
+ }
59
+
60
+ // Mirror every footnote item's opacity onto the max of its references' opacity.
61
+ // Returns whether anything changed this pass (used to detect a settled fade).
62
+ function syncOnce() {
63
+ const list = listEl.value
64
+ if (!slideRoot || !list)
65
+ return false
66
+ let changed = false
67
+ list.querySelectorAll<HTMLElement>('.footnote-item').forEach((item) => {
68
+ const refs = slideRoot!.querySelectorAll<HTMLElement>(
69
+ `.footnote-ref a[href="#${item.id}"]`,
70
+ )
71
+ let max = 0
72
+ refs.forEach((a) => {
73
+ const o = visibleOpacity(a, slideRoot!)
74
+ if (o > max)
75
+ max = o
76
+ })
77
+ // No reference found (e.g. print quirks) -> leave the footnote untouched.
78
+ const next = refs.length ? String(max) : ''
79
+ if (item.style.opacity !== next) {
80
+ item.style.opacity = next
81
+ changed = true
82
+ }
83
+ })
84
+ return changed
85
+ }
86
+
87
+ // References fade over a CSS transition; follow it frame-by-frame until the
88
+ // value settles (a few stable frames) instead of snapping to the end state.
89
+ let rafId = 0
90
+ function syncAnimated() {
91
+ cancelAnimationFrame(rafId)
92
+ let stable = 0
93
+ const step = () => {
94
+ stable = syncOnce() ? 0 : stable + 1
95
+ if (stable < 4)
96
+ rafId = requestAnimationFrame(step)
97
+ }
98
+ step()
99
+ }
100
+
101
+ onMounted(async () => {
102
+ slideRoot = anchorEl.value?.closest<HTMLElement>('[data-slidev-no]') ?? null
103
+ // A reference's fade is driven by CSS, so its transition events are our cue
104
+ // to re-follow the opacity even when no click index changed.
105
+ slideRoot?.addEventListener('transitionstart', syncAnimated)
106
+ slideRoot?.addEventListener('transitionend', syncAnimated)
107
+ await nextTick()
108
+ syncAnimated()
109
+ })
110
+
111
+ onBeforeUnmount(() => {
112
+ cancelAnimationFrame(rafId)
113
+ slideRoot?.removeEventListener('transitionstart', syncAnimated)
114
+ slideRoot?.removeEventListener('transitionend', syncAnimated)
115
+ })
116
+
117
+ // Re-sync when this slide becomes the active (teleporting) one, and on every
118
+ // click step that may reveal/hide a reference.
119
+ watch(isActive, () => nextTick(syncAnimated))
120
+ watch($clicks, () => nextTick(syncAnimated))
121
+ </script>
122
+
123
+ <template>
124
+ <!-- Stays in the slide body; only used to find the slide root above. -->
125
+ <span ref="anchorEl" class="hidden" />
126
+ <!-- `defer` (Vue 3.5+) resolves the target *after* the render flush, so when
127
+ currentPage flips the teleport finds global-bottom's freshly-rendered
128
+ target instead of racing it (which made the footnotes pop in late). -->
129
+ <Teleport v-if="isActive" :to="target" defer>
130
+ <div ref="listEl" class="contents">
131
+ <slot />
132
+ </div>
133
+ </Teleport>
134
+ </template>
135
+
136
+ <style>
137
+ /* Inline footnote reference ([^1] superscript) — stays in the slide body. */
138
+ .footnote-ref a {
139
+ @apply no-underline border-0 text-gray;
140
+ }
141
+
142
+ /* The footnotes *block* is teleported into global-bottom.vue */
143
+ .footnotes {
144
+ @apply flex-auto flex flex-col justify-end pt-1 text-gray border-t-1 border-gray;
145
+ }
146
+ .footnotes p {
147
+ @apply m-0 text-xs;
148
+ }
149
+ .footnotes-list {
150
+ /* UnoCSS resets list-style off every ol/ul, which dropped the footnote
151
+ numbers; list-decimal re-enables them. pl-7 leaves room for the markers. */
152
+ @apply m-0 list-decimal pl-7;
153
+ }
154
+ .footnotes ::marker {
155
+ /* numbers a touch lighter than the note text so they read as labels */
156
+ @apply text-xs text-gray;
157
+ }
158
+
159
+ /* markdown-it emits a separator rule and per-note backref links we don't want. */
160
+ .footnotes-sep,
161
+ .footnote-backref {
162
+ @apply hidden;
163
+ }
164
+ </style>
package/example.mdc ADDED
@@ -0,0 +1,372 @@
1
+ ---
2
+ theme: ./
3
+ # Hash-based routing to make reload work on GitHub Pages
4
+ routerMode: hash
5
+ # layout: "cover"
6
+ author: "Your Name"
7
+ title: "Some very catchy title"
8
+ subtitle: "With a sub-title"
9
+ group: "Verified System Design Automation"
10
+ location: "Dresden"
11
+
12
+ # Use single quotes so YAML keeps the backslash literally (double quotes turn \t etc. into escapes).
13
+ date: '\today' # \today -> current date in the long format; \today[YYYY-MM-DD] for a custom day.js format
14
+ # date: '\now[YYYY-MM-DD HH:mm:ss]' # \now defaults to date + time; both \today and \now accept any day.js format
15
+ # date: "January 1st, 2000"
16
+
17
+ # footer: "{title}\n{group} / {author}\n{location}, {date}"
18
+ # footer: false
19
+ layout: "cover-white"
20
+ addons:
21
+ - slidev-component-progress
22
+ ---
23
+
24
+ <!-- If you want to have a different title on
25
+ the slide than in the metadata use a level 1 heading -->
26
+
27
+ # Here goes your fancy Title
28
+
29
+ <!-- same thing for the sub-title -->
30
+ ## With another sub-title
31
+
32
+ <!--
33
+ The last comment on every page will be display
34
+ as the speaker notes in the presenter view
35
+ -->
36
+
37
+ ---
38
+ layout: "cover-blue"
39
+ ---
40
+
41
+ # A blue cover slide
42
+
43
+ ---
44
+ layout: "section-white"
45
+ ---
46
+
47
+ # A white section
48
+
49
+ ## Using `section-white`
50
+
51
+ ---
52
+ layout: "section"
53
+ ---
54
+
55
+
56
+ # And a blue section
57
+
58
+ ## Using `section` or `section-blue`
59
+
60
+ ---
61
+ layout: "section-n"
62
+ variant: 1
63
+ ---
64
+
65
+
66
+ # Here is the title of the section
67
+
68
+ Here is a subtitle, the name of the speaker, and additional
69
+ contextual information.
70
+
71
+ You can customize the colors within the TUD color set.
72
+
73
+ ::detail::
74
+
75
+ This slide uses `section-n` with `variant: 1`.
76
+
77
+ ---
78
+ layout: "section-n"
79
+ variant: 2
80
+ ---
81
+
82
+
83
+
84
+ # Here is the title of the section
85
+
86
+ Here is a subtitle, the name of the speaker, and additional<br>
87
+ contextual information.
88
+
89
+ You can customize the colors within the TUD color set.
90
+
91
+ This slide uses `section-n` with `variant: 2`.
92
+
93
+
94
+ ---
95
+ layout: "section-n"
96
+ variant: 3
97
+ ---
98
+
99
+
100
+ # Another section
101
+
102
+
103
+ Here is a subtitle, the name of the speaker, and additional<br>
104
+ contextual information.
105
+
106
+ You can customize the colors within the TUD color set.
107
+
108
+ ::detail::
109
+
110
+ This slide uses `section-n` with `variant: 3`.
111
+
112
+ ---
113
+ layout: "section-n"
114
+ variant: 4
115
+ ---
116
+
117
+
118
+ # Another section
119
+
120
+ ## Using `section-n` with `variant: 4`
121
+
122
+ ---
123
+ layout: "section-n"
124
+ variant: 5
125
+ ---
126
+
127
+
128
+ # Another section
129
+
130
+ ## Using `section-n` with `variant: 5`
131
+
132
+ ---
133
+ layout: "section-n"
134
+ variant: 6
135
+ ---
136
+
137
+
138
+ # Another section
139
+
140
+ ## Using `section-n` with `variant: 6`
141
+
142
+ ---
143
+
144
+
145
+ # A `default` slide
146
+
147
+ This slide shows the default layout
148
+
149
+ The TUD theme also supports _italic_, **bold** and `code` text,
150
+ as well as other markdown features like bullet lists:
151
+
152
+ - statement 1
153
+ - statement 2
154
+
155
+ ## 2nd level heading
156
+
157
+ normal lists:
158
+
159
+ 1. test
160
+ 2. test
161
+
162
+ ---
163
+
164
+ # Other markdown features
165
+
166
+ ::div{.flex.justify-between}
167
+ ## Blockquotes:
168
+
169
+ > This is a very important
170
+ > quote from a very important person
171
+ ::
172
+
173
+ > # Theorem 1 {.test}
174
+ > Bla bla bla bla blaa
175
+ > theorem bla bla bla
176
+ >
177
+ > $$f(x) := y \times z^2$$
178
+
179
+ ::div{.flex.justify-between.items-center}
180
+ ::div
181
+ | Left Align | Center Align | Right Align |
182
+ |:-----------|:------------:|------------:|
183
+ | 1 | 1 | 1 |
184
+ | 2 | 2 | 2 |
185
+ | 3 | 3 | 3 |
186
+
187
+ A plain caption underneath the table. {.caption}
188
+ ::
189
+
190
+ ## Tables
191
+
192
+ ::div
193
+ | Left Align | Center Align | Right Align |
194
+ |:-----------|:------------:|------------:|
195
+ | 1 | 1 | 1 |
196
+ | 2 | 2 | 2 |
197
+ | 3 | 3 | 3 |
198
+
199
+ A numbered caption with a "Table N:" prefix. {.caption .numbered}
200
+ ::
201
+ ::
202
+
203
+ ---
204
+
205
+ # More numbered tables
206
+
207
+ ::div{.flex.justify-between.items-center}
208
+ ::div
209
+ | Left Align | Center Align | Right Align |
210
+ |:-----------|:------------:|------------:|
211
+ | 1 | 1 | 1 |
212
+ | 2 | 2 | 2 |
213
+ | 3 | 3 | 3 |
214
+
215
+ A plain caption underneath the table. {.caption .numbered}
216
+ ::
217
+
218
+ ## Tables
219
+
220
+ ::div
221
+ | Left Align | Center Align | Right Align |
222
+ |:-----------|:------------:|------------:|
223
+ | 1 | 1 | 1 |
224
+ | 2 | 2 | 2 |
225
+ | 3 | 3 | 3 |
226
+
227
+ A numbered caption with a "Table N:" prefix. {.caption .numbered}
228
+ ::
229
+ ::
230
+
231
+ ---
232
+
233
+ # Latex support
234
+
235
+ Did you ever use google slides for a theoretical presentation?
236
+ Well then you probably had a lot of pain with formulas.
237
+
238
+ But with the right tools formulas can be as easy as writing a bit of latex.
239
+
240
+ $$
241
+ \forall\, \green{p}~src.\\
242
+ \texttt{\red{in}}[src] = \green{p} \to \lozenge~\texttt{\blue{out}}[p.dst] = \green{p}
243
+ $$
244
+
245
+ Note the usage of the official color scheme inside of latex formulas
246
+
247
+ ---
248
+ layout: "cols"
249
+ ---
250
+
251
+ # A slots layout with multiple columns
252
+
253
+ This layout is named `cols`
254
+
255
+ > You can put some content above the columns that will span then whole slide
256
+
257
+ ::col-1::
258
+
259
+ ## First {.red}
260
+
261
+ This shows on the left in red
262
+
263
+ ::col-3::
264
+
265
+ ## Third {.green}
266
+
267
+ This shows on the right in green
268
+
269
+ ::col-2::
270
+
271
+ ## Second {.magenta}
272
+
273
+ This shows in the middle in magenta
274
+
275
+ ::bottom::
276
+
277
+ ::div{.violet}
278
+ > # The `bottom` slot
279
+ >
280
+ > This is shown on the bottom (below the columns) and spans the whole slide again.
281
+ ::
282
+
283
+ ---
284
+
285
+ # Code examples
286
+
287
+ Enjoy the ligatures of FiraCode: (And automatic syntax highlighting)
288
+
289
+ ```coq /stalls/ [some-title.js ~~]
290
+ Lemma reset_all_inputs_nsp_correct {data_t dims IdxEnv} {lcl : idx_t dims} (nsp : @noc_state_partial data_t dims IdxEnv) ext1 ext2
291
+ (stalls : vect bool (length dims * 2 * 2)) :
292
+ (∀ i,
293
+ vect_nth stalls i = false ->
294
+ vect_nth nsp.(nsp_pkgs1)?[vect_nth (list_neighbors_du lcl) (idx_div 2 i)] i = None) ->
295
+ ∀ sig REnv (sigma : ∀ f : ext_fn_t dims, Sig_denote (Sigma (data_t:=data_t) dims f)) Γv Q,
296
+ kpm_entails_ret (R:=R dims) (REnv:=REnv) (represent_nsp (nsp_map_pkgs1 nsp (in_channel_update lcl (reset_all_inputs_spec stalls))) ext1 ext2) Γv (tau:=unit_t) (eq Ob) Q ->
297
+ kpm_entails (R:=R dims) (REnv:=REnv) (represent_nsp nsp ext1 ext2) Γv (wp_total (sigma:=sigma) (sig:=sig) (InternalCall (reset_all_inputs lcl) (ConstCtx #{
298
+ ("stalls", array_t (bits_t 1) (length dims * 2 * 2)) => represent stalls
299
+ }#)) Q).
300
+ ```
301
+
302
+ ```js
303
+ function recolor(theme: any, shade: 1 | 2) {
304
+ return {
305
+ ...theme,
306
+ tokenColors: theme.tokenColors?.map((rule: any) => {
307
+ const scopes: string[] = (Array.isArray(rule.scope) ? rule.scope : [rule.scope]).filter(Boolean)
308
+ if (scopes.some(isComment)) return rule
309
+ const category = CATEGORIES.find(c => scopes.some(c.match))
310
+ if (!category || !rule.settings?.foreground) return rule
311
+ return { ...rule, settings: { ...rule.settings, foreground: category.color(shade) } }
312
+ }),
313
+ }
314
+ }
315
+ ```
316
+
317
+ ---
318
+
319
+ # Images with captions
320
+
321
+ Add `{.caption}` to an image and its alt text becomes a LaTeX-style
322
+ caption below it:
323
+
324
+ ![A plain caption](https://placehold.co/400x300){.caption .w-40}
325
+
326
+ ::div{.flex.justify-between}
327
+ ::div{.flex.flex-col.items-center}
328
+ Add `{.numbered}` as well for a "Figure N:" prefix:
329
+
330
+ ![A picture with a very long caption that hopefully eventually line breaks into another second caption line.](https://placehold.co/400x300){.caption .numbered .w-60}
331
+ ::
332
+ ::div{.flex.flex-col.items-center}
333
+ Without the class, an image renders as usual (no caption):
334
+
335
+ ![this alt text stays hidden](https://placehold.co/400x300){.w-60}
336
+ ::
337
+ ::
338
+
339
+ ---
340
+
341
+ <!-- # Footnotes -->
342
+
343
+ <v-click>
344
+
345
+ And another footnote here[^note2][]
346
+
347
+ </v-click>
348
+
349
+ [^note2]: another 2nd footnote
350
+
351
+
352
+ Test[^note][]
353
+
354
+ [^note]: Some test
355
+
356
+ ---
357
+
358
+ # More Footnotes
359
+
360
+ <v-click>
361
+
362
+ And another footnote here[^note2][]
363
+
364
+ </v-click>
365
+
366
+ [^note2]: different footnote
367
+
368
+
369
+ Test[^note][] [^note3][]
370
+
371
+ [^note]: another one
372
+ [^note3]: another one
package/flake.lock ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "nodes": {
3
+ "flake-utils": {
4
+ "inputs": {
5
+ "systems": "systems"
6
+ },
7
+ "locked": {
8
+ "lastModified": 1731533236,
9
+ "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
10
+ "owner": "numtide",
11
+ "repo": "flake-utils",
12
+ "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
13
+ "type": "github"
14
+ },
15
+ "original": {
16
+ "owner": "numtide",
17
+ "repo": "flake-utils",
18
+ "type": "github"
19
+ }
20
+ },
21
+ "nixpkgs": {
22
+ "locked": {
23
+ "lastModified": 1768649915,
24
+ "narHash": "sha256-jc21hKogFnxU7KXSVTRmxC7u5D4RHwm9BAvDf5/Z1Uo=",
25
+ "owner": "nixos",
26
+ "repo": "nixpkgs",
27
+ "rev": "3e3f3c7f9977dc123c23ee21e8085ed63daf8c37",
28
+ "type": "github"
29
+ },
30
+ "original": {
31
+ "owner": "nixos",
32
+ "ref": "release-25.05",
33
+ "repo": "nixpkgs",
34
+ "type": "github"
35
+ }
36
+ },
37
+ "root": {
38
+ "inputs": {
39
+ "flake-utils": "flake-utils",
40
+ "nixpkgs": "nixpkgs"
41
+ }
42
+ },
43
+ "systems": {
44
+ "locked": {
45
+ "lastModified": 1681028828,
46
+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
47
+ "owner": "nix-systems",
48
+ "repo": "default",
49
+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
50
+ "type": "github"
51
+ },
52
+ "original": {
53
+ "owner": "nix-systems",
54
+ "repo": "default",
55
+ "type": "github"
56
+ }
57
+ }
58
+ },
59
+ "root": "root",
60
+ "version": 7
61
+ }
package/flake.nix ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ inputs = {
3
+ nixpkgs.url = "github:nixos/nixpkgs/release-25.05";
4
+ flake-utils.url = "github:numtide/flake-utils";
5
+ };
6
+
7
+ outputs = { self, nixpkgs, flake-utils }:
8
+ flake-utils.lib.eachDefaultSystem (system:
9
+ let
10
+ pkgs = import nixpkgs {
11
+ inherit system;
12
+ overlays = [ ];
13
+ };
14
+ in
15
+ {
16
+ # devShells.default = self.packages.${system}.default;
17
+ devShells.default = pkgs.mkShell {
18
+ packages = [ pkgs.pnpm pkgs.nodejs ];
19
+ };
20
+ }
21
+ );
22
+ }
@@ -0,0 +1,79 @@
1
+ <template>
2
+ <div>
3
+ <Background
4
+ :bl="pageLogo?.bl" :tr="pageLogo?.tr" :fill="pageLogo?.fill"
5
+ :background="pageBackground"
6
+ />
7
+
8
+ <div v-html="rawLogoText"
9
+ :style="{ fill: logos.text }" :class="{'opacity-0': !logos.text}"
10
+ class="[&>svg]:w-[220px] duration-[0.5s] transition-[opacity,fill] absolute left-[64px] top-[42px] z-10"
11
+ ></div>
12
+ <div v-html="rawLogo"
13
+ :style="{ fill: logos.normal }" :class="{'opacity-0': !logos.normal}"
14
+ class="[&>svg]:w-[68px] duration-[0.5s] transition-[opacity,fill] absolute left-[64px] top-[42px] z-10"
15
+ ></div>
16
+
17
+ <div v-html="rawLogoSmall"
18
+ :style="{ fill: logos.small }" :class="{'opacity-0': !logos.small}"
19
+ class="duration-[0.5s] transition-[opacity,fill] absolute left-[64px] top-[660px] z-10 w-[54px]"
20
+ ></div>
21
+
22
+ <footer class="absolute bottom-0 h-16 pb-[13px] pr-[64px] pl-[164px] flex items-baseline gap-x-6 w-full z-100">
23
+ <div :class="{'opacity-0': !show_footer}" class="duration-[0.5s] transition-opacity text-primary">
24
+ <div v-if="$slidev.configs.footer !== false" class="whitespace-pre">
25
+ {{ footer }}
26
+ </div>
27
+ </div>
28
+
29
+ <!-- Footnotes teleport target (see components/Footnotes.vue) -->
30
+ <div class="relative flex-1 min-w-0 self-end flex flex-col h-full">
31
+ <div :id="footnotesTargetId" class="absolute bottom-0 w-full min-h-full pb-2"></div>
32
+ </div>
33
+
34
+ <div :class="{'opacity-0': !show_footer}" class="duration-[0.5s] transition-opacity w-[66px]">
35
+ <div class="flex items-baseline justify-center">
36
+ <span class="flex-1 text-right font-bold text-lg text-primary">{{ $nav.currentPage }}</span>
37
+ <span :class="{ 'opacity-0': $nav.clicksTotal == 0 }" class="text-left text-gray text-xs">.</span>
38
+ <span :class="{ 'opacity-0': $nav.clicksTotal == 0 }" class="flex-1 text-left text-gray text-xs">{{ $nav.clicks+1 }}</span>
39
+ </div>
40
+ </div>
41
+ </footer>
42
+ </div>
43
+ </template>
44
+ <script setup lang="ts">
45
+ import { useSlideContext } from '@slidev/client'
46
+ import { computed, unref } from 'vue';
47
+ import { expandDateTokens } from './scripts/util';
48
+ import { formatString } from './scripts/util';
49
+ import { slideBackgrounds, slideBgLogos, slideLogos } from './scripts/background';
50
+
51
+ import rawLogo from './assets/TUD-logo-no-color.svg?raw';
52
+ import rawLogoSmall from './assets/TUD-logo-text-small-no-color.svg?raw';
53
+ import rawLogoText from './assets/TUD-logo-text-no-color.svg?raw';
54
+
55
+ const { $slidev, $nav } = useSlideContext()
56
+ const pageBackground = computed(() => slideBackgrounds[$nav.value.currentPage] ?? 'transparent')
57
+
58
+ // use $nav instead of useNav to ensure that the export works correctly
59
+ const footnotesTargetId = computed(() => `footnotes-containter-${unref(($nav as any).value.currentPage)}`)
60
+
61
+ const logos = computed(() => slideLogos[$nav.value.currentPage] ?? {})
62
+
63
+ const show_footer = computed(() => !new Set(['cover', 'cover-blue', 'cover-white', 'section', 'section-blue', 'section-white', 'section-n']).has($nav.value.currentLayout))
64
+
65
+ const get_date = computed(() => {
66
+ const d = ($slidev.configs as any).date
67
+ return d ? expandDateTokens(String(d)) : d
68
+ })
69
+ const footer = computed(() => {
70
+ let fstring = "{title} • {author}"
71
+ return formatString(($slidev.configs as any).footer ?
72
+ ($slidev.configs as any).footer : fstring,
73
+ {...$slidev.configs, date: get_date.value}
74
+ )
75
+ })
76
+
77
+ const pageLogo = computed(() => slideBgLogos[$nav.value.currentPage])
78
+
79
+ </script>