mdeck 3.7.1 → 3.9.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 (59) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +3 -3
  3. package/assets/base.css +9 -5
  4. package/assets/extensions/themes/academic/extension.toml +4 -1
  5. package/assets/extensions/themes/academic/styles.css +22 -22
  6. package/assets/extensions/themes/glass/extension.toml +7 -1
  7. package/assets/extensions/themes/glass/styles.css +17 -17
  8. package/assets/extensions/themes/minimal/extension.toml +3 -1
  9. package/assets/extensions/themes/minimal/styles.css +14 -14
  10. package/assets/extensions/themes/neue/extension.toml +3 -1
  11. package/assets/extensions/themes/neue/styles.css +14 -14
  12. package/assets/extensions/themes/plain/extension.toml +7 -1
  13. package/assets/extensions/themes/plain/styles.css +17 -17
  14. package/assets/extensions/themes/work/extension.toml +8 -2
  15. package/assets/extensions/themes/work/styles.css +26 -26
  16. package/docs/reference/authoring.md +21 -4
  17. package/docs/reference/extensions.md +5 -1
  18. package/docs/reference/themes.md +6 -2
  19. package/docs/site/content/drawing.md +1 -1
  20. package/docs/site/content/presenting.md +45 -0
  21. package/docs/site/content/theme-authoring.md +28 -0
  22. package/examples/python/slides.de.md +493 -0
  23. package/examples/python/{slides.md → slides.en.md} +1 -1
  24. package/examples/python/slides.fa.md +492 -0
  25. package/examples/python/slides.hi.md +492 -0
  26. package/examples/showcase/slides.md +33 -0
  27. package/package.json +1 -1
  28. package/skills/write-slides/SKILL.md +1 -0
  29. package/src/build/config.js +1 -1
  30. package/src/build/slidesPlugin.js +34 -4
  31. package/src/cli/index.js +4 -0
  32. package/src/cli/themes.js +2 -0
  33. package/src/components/callout.css +10 -10
  34. package/src/components/citation.css +2 -2
  35. package/src/components/code-block.css +3 -3
  36. package/src/components/poll.css +6 -6
  37. package/src/components/video-player.css +1 -1
  38. package/src/core/editDeck.js +3 -2
  39. package/src/core/icons.js +1 -0
  40. package/src/core/languages.js +51 -0
  41. package/src/core/parseSlides.js +15 -3
  42. package/src/core/validateDeck.js +13 -1
  43. package/src/editor/components/DeckSettings.jsx +37 -3
  44. package/src/editor/components/ExtensionForms.jsx +12 -0
  45. package/src/editor/components/MetaFields.jsx +7 -0
  46. package/src/editor/extensions.js +6 -3
  47. package/src/extensions/appearance.js +6 -2
  48. package/src/extensions/manifest.js +3 -3
  49. package/src/extensions/params.js +113 -0
  50. package/src/layouts/layoutApi.jsx +7 -1
  51. package/src/live/answer/answer.css +2 -2
  52. package/src/runtime/chrome.jsx +6 -7
  53. package/src/runtime/deck-stage.js +249 -11
  54. package/src/runtime/hotspots.js +98 -0
  55. package/src/runtime/ink/bus.js +12 -1
  56. package/src/runtime/ink/room.js +20 -8
  57. package/src/runtime/main.jsx +152 -22
  58. package/src/runtime/zoom/camera.js +77 -0
  59. /package/examples/python/{slides.drawings.json → slides.en.drawings.json} +0 -0
@@ -3,7 +3,7 @@ kind = "theme"
3
3
  id = "plain"
4
4
  title = "Plain"
5
5
  description = "Black on white and lots of room: Inter, the heading in a column of its own beside the content, lists of short titles with a line under each, the accent only in small places; in greyscale, dark is the same, inverted."
6
- version = "0.1.0"
6
+ version = "0.2.0"
7
7
  author = "Tilman Schieber"
8
8
  license = "MIT"
9
9
  # The palette this theme uses unless the deck sets one; colours come only from palettes.
@@ -48,14 +48,20 @@ styles = "styles.css"
48
48
  [params.fontDisplay]
49
49
  token = "--font-display"
50
50
  title = "Display font"
51
+ type = "font"
51
52
 
52
53
  [params.fontBody]
53
54
  token = "--font-body"
54
55
  title = "Body font"
56
+ type = "font"
55
57
 
56
58
  [params.side]
57
59
  token = "--side"
58
60
  title = "Width of the heading column"
61
+ type = "size"
62
+ min = 400
63
+ max = 640
64
+ description = "560px of the 1920px slide by default, from about 400px to 640px; the content takes the rest."
59
65
 
60
66
  # What this theme is for and how to write for it: shown in listings, and read
61
67
  # by assistants that write slides as the theme author's advice.
@@ -27,7 +27,7 @@
27
27
  .slide-logo {
28
28
  position: absolute;
29
29
  top: var(--pad-y);
30
- left: var(--pad-x);
30
+ inset-inline-start: var(--pad-x);
31
31
  height: 48px;
32
32
  width: auto;
33
33
  max-width: 280px;
@@ -153,25 +153,25 @@ strong { font-weight: 600; color: var(--ink); }
153
153
  grid-row: 1 / span 40;
154
154
  align-self: center;
155
155
  margin: 0;
156
- padding-right: 24px;
156
+ padding-inline-end: 24px;
157
157
  }
158
158
  .slide-body > :last-child { margin-bottom: 0; }
159
159
 
160
160
  /* ─────────────────────────────────────────────
161
161
  LISTS — a short title with a line under it; plain lines otherwise
162
162
  ───────────────────────────────────────────── */
163
- .slide-body ul > li { line-height: 1.45; padding-left: 34px; }
163
+ .slide-body ul > li { line-height: 1.45; padding-inline-start: 34px; }
164
164
  .slide-body ul > li::before {
165
165
  content: '\2013';
166
166
  position: absolute;
167
- left: 0;
167
+ inset-inline-start: 0;
168
168
  top: 0;
169
169
  color: var(--muted);
170
170
  }
171
171
  /* An item that starts in bold: the bold part is a title on its own line,
172
172
  the rest a smaller description under it, and no marker. */
173
173
  .slide-body ul > li:has(> strong:first-child) {
174
- padding-left: 0;
174
+ padding-inline-start: 0;
175
175
  font-size: calc(var(--fs-body) * 0.86);
176
176
  line-height: 1.45;
177
177
  color: var(--ink-soft);
@@ -184,11 +184,11 @@ strong { font-weight: 600; color: var(--ink); }
184
184
  color: var(--ink);
185
185
  margin-bottom: 4px;
186
186
  }
187
- .slide-body ol > li { line-height: 1.45; padding-left: 46px; }
187
+ .slide-body ol > li { line-height: 1.45; padding-inline-start: 46px; }
188
188
  .slide-body ol > li::before {
189
189
  content: counter(slide-ol) '.';
190
190
  position: absolute;
191
- left: 0;
191
+ inset-inline-start: 0;
192
192
  top: 0;
193
193
  font-variant-numeric: tabular-nums;
194
194
  color: var(--accent);
@@ -309,10 +309,10 @@ strong { font-weight: 600; color: var(--ink); }
309
309
  column-gap: 96px;
310
310
  align-content: center;
311
311
  align-items: start;
312
- text-align: left;
312
+ text-align: start;
313
313
  }
314
314
  .slide--focus .slide-body:has(> .focus-eyebrow) > * { grid-column: 2; }
315
- .slide--focus .slide-body:has(> .focus-eyebrow) > .focus-eyebrow { grid-column: 1; grid-row: 1 / span 2; align-self: center; padding-right: 24px; }
315
+ .slide--focus .slide-body:has(> .focus-eyebrow) > .focus-eyebrow { grid-column: 1; grid-row: 1 / span 2; align-self: center; padding-inline-end: 24px; }
316
316
  .slide--focus .slide-body:has(> .focus-eyebrow) .focus-content { align-items: flex-start; }
317
317
  .slide--focus .slide-body:has(> .focus-eyebrow) :is(.focus-statement, .focus-content h1, .focus-content p) {
318
318
  font-family: var(--font-body);
@@ -321,7 +321,7 @@ strong { font-weight: 600; color: var(--ink); }
321
321
  line-height: 1.4;
322
322
  letter-spacing: -0.005em;
323
323
  max-width: 900px;
324
- text-align: left;
324
+ text-align: start;
325
325
  }
326
326
 
327
327
  /* ─────────────────────────────────────────────
@@ -368,7 +368,7 @@ strong { font-weight: 600; color: var(--ink); }
368
368
  column-gap: 80px;
369
369
  align-items: center;
370
370
  }
371
- .slide--split .split-heading { margin: 0; padding-right: 24px; }
371
+ .slide--split .split-heading { margin: 0; padding-inline-end: 24px; }
372
372
  .slide--split .split-heading h1 { margin: 0; }
373
373
  .slide--split .slide-body:has(> .split-heading) .split-columns { align-self: stretch; }
374
374
 
@@ -402,7 +402,7 @@ strong { font-weight: 600; color: var(--ink); }
402
402
  .slide-body .callout {
403
403
  background: var(--surface);
404
404
  border: 0;
405
- border-left: 3px solid var(--accent);
405
+ border-inline-start: 3px solid var(--accent);
406
406
  border-radius: 0 8px 8px 0;
407
407
  padding: 20px 28px 22px;
408
408
  margin: 0 0 16px;
@@ -416,9 +416,9 @@ strong { font-weight: 600; color: var(--ink); }
416
416
  color: var(--ink);
417
417
  margin: 0 0 4px 0;
418
418
  }
419
- .slide-body .callout p { padding-left: 0; margin: 0; color: var(--ink-soft); }
419
+ .slide-body .callout p { padding-inline-start: 0; margin: 0; color: var(--ink-soft); }
420
420
  .slide-body .callout :is(.callout-title) { color: var(--ink); }
421
- .slide-body .callout:is(.callout-warning, .callout-caution) { border-left-color: var(--accent-3); }
421
+ .slide-body .callout:is(.callout-warning, .callout-caution) { border-inline-start-color: var(--accent-3); }
422
422
  .slide-body .callout.callout-proof { background: none; border: 0; padding: 0; }
423
423
 
424
424
  /* ─────────────────────────────────────────────
@@ -444,7 +444,7 @@ strong { font-weight: 600; color: var(--ink); }
444
444
  .slide-body .code-block-wrapper { margin: 0 0 var(--gap-item); }
445
445
 
446
446
  .slide-body table { font-size: calc(var(--fs-body) * 0.9); font-variant-numeric: tabular-nums; }
447
- .slide-body :is(th, td) { padding: 12px 24px 12px 0; }
447
+ .slide-body :is(th, td) { padding-block: 12px; padding-inline: 0 24px; }
448
448
  .slide-body th { font-weight: 600; color: var(--ink); border-bottom: 1px solid var(--ink); }
449
449
  .slide-body td { border-bottom: 1px solid var(--rule); }
450
450
 
@@ -464,7 +464,7 @@ strong { font-weight: 600; color: var(--ink); }
464
464
  FOOTNOTES, MATH, AUDIENCE QUESTIONS
465
465
  ───────────────────────────────────────────── */
466
466
  .slide-footnotes, .slide-citations { font-family: var(--font-body); }
467
- .slide .katex-display { font-size: var(--fs-sub); margin: 24px 0; overflow-x: auto; overflow-y: hidden; text-align: left; }
467
+ .slide .katex-display { font-size: var(--fs-sub); margin: 24px 0; overflow-x: auto; overflow-y: hidden; text-align: start; }
468
468
  .slide .poll-track, .slide .scale-track { border-radius: 4px; background: var(--surface); }
469
469
  .slide .poll-fill, .slide .scale-fill { border-radius: 4px; background: var(--accent); }
470
- .slide .question-cards li { border-radius: 8px; border-left: 0; background: var(--surface); }
470
+ .slide .question-cards li { border-radius: 8px; border-inline-start: 0; background: var(--surface); }
@@ -3,7 +3,7 @@ kind = "theme"
3
3
  id = "work"
4
4
  title = "Work"
5
5
  description = "An everyday company template: IBM Plex Sans, an accent band along the top, the logo top left, headings in a fixed place, section dividers with a large number in the accent, a quiet footer with the page number."
6
- version = "0.1.0"
6
+ version = "0.2.0"
7
7
  author = "Tilman Schieber"
8
8
  license = "MIT"
9
9
  # The palette this theme uses unless the deck sets one; colours come only from palettes.
@@ -47,14 +47,20 @@ styles = "styles.css"
47
47
  [params.fontDisplay]
48
48
  token = "--font-display"
49
49
  title = "Display font"
50
+ type = "font"
50
51
 
51
52
  [params.fontBody]
52
53
  token = "--font-body"
53
54
  title = "Body font"
55
+ type = "font"
54
56
 
55
57
  [params.band]
56
58
  token = "--band"
57
- title = "Height of the band along the top (0px for none)"
59
+ title = "Height of the band along the top"
60
+ type = "size"
61
+ min = 0
62
+ max = 32
63
+ description = "14px by default, up to about 32px; 0px leaves the top without a band."
58
64
 
59
65
  # What this theme is for and how to write for it: shown in listings, and read
60
66
  # by assistants that write slides as the theme author's advice.
@@ -15,8 +15,8 @@
15
15
  content: '';
16
16
  position: absolute;
17
17
  top: 0;
18
- left: 0;
19
- right: 0;
18
+ inset-inline-start: 0;
19
+ inset-inline-end: 0;
20
20
  height: var(--band);
21
21
  background: var(--accent);
22
22
  z-index: 3;
@@ -47,7 +47,7 @@
47
47
  .slide-logo {
48
48
  position: absolute;
49
49
  top: var(--pad-y);
50
- left: var(--pad-x);
50
+ inset-inline-start: var(--pad-x);
51
51
  height: 72px;
52
52
  width: auto;
53
53
  max-width: 360px;
@@ -181,29 +181,29 @@ strong { font-weight: 600; color: var(--ink); }
181
181
  /* ─────────────────────────────────────────────
182
182
  LISTS — square bullets, numbers in the accent
183
183
  ───────────────────────────────────────────── */
184
- .slide-body ul > li { line-height: 1.4; padding-left: 40px; }
184
+ .slide-body ul > li { line-height: 1.4; padding-inline-start: 40px; }
185
185
  .slide-body ul > li::before {
186
186
  content: '';
187
187
  position: absolute;
188
- left: 2px;
188
+ inset-inline-start: 2px;
189
189
  top: calc(0.7em - 6px);
190
190
  width: 12px;
191
191
  height: 12px;
192
192
  background: var(--accent);
193
193
  }
194
194
  /* A point inside a point: a dash. */
195
- .slide-body li ul > li { padding-left: 34px; }
195
+ .slide-body li ul > li { padding-inline-start: 34px; }
196
196
  .slide-body li ul > li::before {
197
197
  top: calc(0.7em - 1.5px);
198
198
  width: 16px;
199
199
  height: 3px;
200
200
  background: var(--muted);
201
201
  }
202
- .slide-body ol > li { line-height: 1.4; padding-left: 52px; }
202
+ .slide-body ol > li { line-height: 1.4; padding-inline-start: 52px; }
203
203
  .slide-body ol > li::before {
204
204
  content: counter(slide-ol) '.';
205
205
  position: absolute;
206
- left: 0;
206
+ inset-inline-start: 0;
207
207
  top: 0;
208
208
  font-weight: 600;
209
209
  font-variant-numeric: tabular-nums;
@@ -238,7 +238,7 @@ strong { font-weight: 600; color: var(--ink); }
238
238
  .slide--title.has-image .title-image {
239
239
  position: absolute;
240
240
  top: 0;
241
- right: 0;
241
+ inset-inline-end: 0;
242
242
  bottom: 0;
243
243
  width: 40%;
244
244
  height: 100%;
@@ -248,7 +248,7 @@ strong { font-weight: 600; color: var(--ink); }
248
248
  }
249
249
  .slide--title.has-image .slide-header > span:last-child:not(.brand) { visibility: hidden; }
250
250
  /* The footer's hairline stops short of the picture (40% of 1920px, and a gap). */
251
- :is(.slide--title, .slide--chapter).has-image .slide-footer { margin-right: 712px; }
251
+ :is(.slide--title, .slide--chapter).has-image .slide-footer { margin-inline-end: 712px; }
252
252
 
253
253
  /* ─────────────────────────────────────────────
254
254
  LAYOUT: CHAPTER — a section divider: the number in the accent, a broader band
@@ -262,7 +262,7 @@ strong { font-weight: 600; color: var(--ink); }
262
262
  letter-spacing: -0.04em;
263
263
  font-variant-numeric: tabular-nums;
264
264
  color: var(--accent);
265
- margin: 0 0 40px -6px;
265
+ margin-block: 0 40px; margin-inline: -6px 0;
266
266
  }
267
267
  .chapter-meta {
268
268
  font-family: var(--font-body);
@@ -298,7 +298,7 @@ strong { font-weight: 600; color: var(--ink); }
298
298
  .slide--chapter.has-image .chapter-image {
299
299
  position: absolute;
300
300
  top: 0;
301
- right: 0;
301
+ inset-inline-end: 0;
302
302
  bottom: 0;
303
303
  width: 40%;
304
304
  height: 100%;
@@ -319,14 +319,14 @@ strong { font-weight: 600; color: var(--ink); }
319
319
  letter-spacing: 0.1em;
320
320
  text-transform: uppercase;
321
321
  color: var(--accent);
322
- margin: 0 0 32px 58px;
322
+ margin-block: 0 32px; margin-inline: 58px 0;
323
323
  }
324
324
  .focus-content {
325
325
  display: flex;
326
326
  flex-direction: column;
327
327
  align-items: flex-start;
328
- border-left: 10px solid var(--accent);
329
- padding: 6px 0 10px 48px;
328
+ border-inline-start: 10px solid var(--accent);
329
+ padding-block: 6px 10px; padding-inline: 48px 0;
330
330
  }
331
331
  .focus-statement,
332
332
  .slide--focus .focus-content h1,
@@ -345,7 +345,7 @@ strong { font-weight: 600; color: var(--ink); }
345
345
  font-family: var(--font-body);
346
346
  font-size: var(--fs-body);
347
347
  color: var(--muted);
348
- margin: 32px 0 0 58px;
348
+ margin-block: 32px 0; margin-inline: 58px 0;
349
349
  }
350
350
 
351
351
  /* ─────────────────────────────────────────────
@@ -386,8 +386,8 @@ strong { font-weight: 600; color: var(--ink); }
386
386
  ───────────────────────────────────────────── */
387
387
  .split-columns { gap: 0; }
388
388
  .slide--split :is(.split-left, .split-right) { padding: 0 56px; }
389
- .slide--split .split-left { padding-left: 0; border-right: 1px solid var(--rule); }
390
- .slide--split .split-right { padding-right: 0; }
389
+ .slide--split .split-left { padding-inline-start: 0; border-inline-end: 1px solid var(--rule); }
390
+ .slide--split .split-right { padding-inline-end: 0; }
391
391
 
392
392
  /* ─────────────────────────────────────────────
393
393
  LAYOUT: FULL-BLEED IMAGE — the title on a label at the lower left
@@ -407,8 +407,8 @@ strong { font-weight: 600; color: var(--ink); }
407
407
  letter-spacing: -0.015em;
408
408
  color: var(--ink);
409
409
  background: var(--bg);
410
- border-left: 10px solid var(--accent);
411
- padding: 28px 44px 32px 40px;
410
+ border-inline-start: 10px solid var(--accent);
411
+ padding-block: 28px 32px; padding-inline: 40px 44px;
412
412
  margin: 0;
413
413
  max-width: 1300px;
414
414
  text-wrap: balance;
@@ -433,7 +433,7 @@ strong { font-weight: 600; color: var(--ink); }
433
433
  --bar: var(--accent);
434
434
  background: var(--surface);
435
435
  border: 0;
436
- border-left: 8px solid var(--bar);
436
+ border-inline-start: 8px solid var(--bar);
437
437
  border-radius: 0 4px 4px 0;
438
438
  padding: 22px 32px 24px;
439
439
  margin: 14px 0 0;
@@ -447,7 +447,7 @@ strong { font-weight: 600; color: var(--ink); }
447
447
  text-transform: uppercase;
448
448
  margin: 0 0 8px 0;
449
449
  }
450
- .slide-body .callout p { padding-left: 0; margin: 0; color: var(--ink); }
450
+ .slide-body .callout p { padding-inline-start: 0; margin: 0; color: var(--ink); }
451
451
  .slide-body :is(.callout-note, .callout-tip, .callout-important) { --bar: var(--accent); }
452
452
  .slide-body :is(.callout-warning, .callout-caution) { --bar: var(--accent-3); }
453
453
  .slide-body .callout-definition { --bar: var(--accent-2); }
@@ -479,7 +479,7 @@ strong { font-weight: 600; color: var(--ink); }
479
479
  .slide-body blockquote {
480
480
  position: relative;
481
481
  margin: 0 0 var(--gap-item);
482
- padding: 0 0 0 64px;
482
+ padding-block: 0; padding-inline: 64px 0;
483
483
  border: 0;
484
484
  max-width: 1300px;
485
485
  font-size: calc(var(--fs-body) * 1.1);
@@ -490,7 +490,7 @@ strong { font-weight: 600; color: var(--ink); }
490
490
  .slide-body blockquote::before {
491
491
  content: '\201C';
492
492
  position: absolute;
493
- left: 0;
493
+ inset-inline-start: 0;
494
494
  top: -0.12em;
495
495
  font-family: var(--font-display);
496
496
  font-size: 104px;
@@ -503,7 +503,7 @@ strong { font-weight: 600; color: var(--ink); }
503
503
  FOOTNOTES, MATH, AUDIENCE QUESTIONS
504
504
  ───────────────────────────────────────────── */
505
505
  .slide-footnotes, .slide-citations { font-family: var(--font-body); }
506
- .slide .katex-display { font-size: var(--fs-sub); margin: 32px 0; overflow-x: auto; overflow-y: hidden; text-align: left; }
506
+ .slide .katex-display { font-size: var(--fs-sub); margin: 32px 0; overflow-x: auto; overflow-y: hidden; text-align: start; }
507
507
  .slide .poll-track, .slide .scale-track { border-radius: 2px; background: var(--surface); }
508
508
  .slide .poll-fill, .slide .scale-fill { border-radius: 2px; background: var(--accent); }
509
- .slide .question-cards li { border-radius: 4px; border-left: 6px solid var(--accent); background: var(--surface); }
509
+ .slide .question-cards li { border-radius: 4px; border-inline-start: 6px solid var(--accent); background: var(--surface); }
@@ -60,25 +60,31 @@ Each `---` line starts a new slide. Frontmatter is only needed when you want a s
60
60
  | `session.id` | from the title | Name the session code is derived from |
61
61
  | `session.code` | from `session.id` | The session code itself, 4 to 8 digits; phones join at `<server>/<code>` |
62
62
  | `components` | — | Extra folders of Preact components shared between decks, relative to the deck or starting with `~/` |
63
- | `params` | — | Theme-specific color/font overrides (see below) |
63
+ | `params` | — | The theme's own settings, such as its fonts (see below) |
64
64
  | `reader.themes` | `true` | Whether the reader view offers a switch between light and dark (see below) |
65
65
  | `reader.notes` | `false` | Whether the reader view shows speaker notes under each slide in Read mode |
66
66
  | `bibliography` | — | Reference file, or a list of them, relative to the deck: `.bib`, `.json` (CSL-JSON) or `.yml` (Hayagriva) (see [Citations](#citations-and-references)) |
67
67
  | `csl` | `apa` | Citation style: `apa`, `vancouver`, `harvard1`, or a `.csl` file |
68
68
  | `nocite` | — | References to list without citing them; `['*']` lists the whole file |
69
69
  | `show.citations` | `true` | `false` leaves out each slide's own references above the footer |
70
+ | `hotspots` | `off` | Number keys zoom in on parts of a slide while presenting: `auto` (pictures, code, tables, formulas, videos, callouts, columns, polls and `data-hotspot` elements), `marked` (only `data-hotspot` elements) or `off` (1–9 go to slides) |
70
71
 
71
72
  ### Theme params
72
73
 
73
- Some themes expose their fonts as settings. Set them under `params:`:
74
+ Themes offer settings of their own: their fonts, and often the size or
75
+ strength of what makes them look the way they do. Set them under `params:`:
74
76
 
75
77
  ```yaml
76
78
  params:
77
79
  fontDisplay: "Georgia, serif"
80
+ glassBlur: 12px
78
81
  ```
79
82
 
80
- Available params depend on the theme; `mdeck list themes` shows them. Colours
81
- are not params: they come from the palette.
83
+ Available params depend on the theme; `mdeck list themes` shows them with the
84
+ kind of value each takes: a size in pixels, a number, a switch (`1` or `0`), a
85
+ choice or a font. `0` or `0px` turns a feature off. A value that does not fit
86
+ is left out, and `mdeck check` says why. Colours are not params: they come from
87
+ the palette.
82
88
 
83
89
  ---
84
90
 
@@ -162,6 +168,7 @@ description: A short description shown under the title.
162
168
  | `layout` | Slide layout (see below) |
163
169
  | `section` | Section label shown in the slide header (auto-propagated — see below) |
164
170
  | `title` | Name in the outline and reader navigation, for slides without a heading (not shown on the slide) |
171
+ | `hotspots` | This slide's own hotspots: `auto`, `marked`, `off` or `false` (see the deck field) |
165
172
 
166
173
  ### Section labels
167
174
 
@@ -537,6 +544,16 @@ A title written after the type on the `:::` line still wins over both.
537
544
 
538
545
  The presenter view, the launch page and the editor are tools for the author and always stay English.
539
546
 
547
+ ### One talk in several languages
548
+
549
+ Write the talk once per language, in files named for it, side by side: `talk.en.md`, `talk.de.md`, `talk.hi.md` and so on. The language is a two-letter code after the name, with a region if needed (`talk.de-CH.md`). A file named this way needs no `lang`: its name gives it.
550
+
551
+ `mdeck run talk.en.md` finds the other files with the same name and adds a **Language** switch to the presenter view (**L** goes to the next language). Switching changes the slides, your notes and mdeck's own words in every window: the audience window, a paired iPad and the phones following the talk. Your place stays, as do the step on the slide, the drawings and the poll results: slides match by their place in the deck, so keep the same slides in the same order in every language. A deck in one language shows no switch.
552
+
553
+ A language written from right to left, such as Farsi (`fa`), Arabic or Hebrew, sets its slides and your notes from right to left: the text, lists, quotations, tables and the place of the header and the page number. Code and maths stay left to right, as do mdeck's own controls.
554
+
555
+ Each file is a complete deck: `mdeck check`, `mdeck edit` and `mdeck send` work on one language at a time, and drawings and results are kept beside the file you run.
556
+
540
557
  To change single words, name them under `labels`:
541
558
 
542
559
  ```yaml
@@ -201,7 +201,11 @@ Keep headings to a few words; three or four points make a good slide.
201
201
  `:root` block from them, so the stylesheet only contains rules.
202
202
  - `params` name the settings authors may change under `params:` in the deck.
203
203
  Each points at a token; its default is the token's value, so nothing is
204
- written twice.
204
+ written twice. `type` (`size`, `number`, `switch`, `choice` or `font`) says
205
+ what kind of value it takes; `min`, `max` and `step` go with a size (in
206
+ pixels) or a number, `choices` with a choice. The token's value must be of
207
+ that type. The editor shows a slider, a box to tick or a list for it, and
208
+ `mdeck check` reports a deck value that does not fit.
205
209
  - `fonts` are stylesheet URLs. Normal builds load them; single files (`mdeck send`,
206
210
  `--single-file`) and PDFs embed their Latin character sets, so they look the
207
211
  same offline. The fallbacks named in the token values apply when a font
@@ -77,8 +77,12 @@ params:
77
77
  fontDisplay: "Georgia, serif"
78
78
  ```
79
79
 
80
- A parameter's default is its token's value. Unknown parameter names are
81
- reported by `mdeck check`.
80
+ A parameter's default is its token's value. `type` says what kind of value it
81
+ takes: `size` (pixels, with `min`, `max` and `step`), `number` (with the same
82
+ three), `switch` (1 or 0), `choice` (one of `choices`) or `font`. A deck value
83
+ that does not fit is left out, and `mdeck check` reports it, like unknown
84
+ parameter names; one outside `min` and `max` is used, with a warning. Without
85
+ a `type`, a parameter takes any text.
82
86
 
83
87
  Optional settings: `description`, `appearance = "dark"` for a theme that starts
84
88
  dark, and `palettes = [...]` to offer only those palettes (a corporate design
@@ -14,7 +14,7 @@ Press **D** in standalone slides or in the presenter view, or use the pen button
14
14
  | Laser pointer | A red dot with a white core and a short trail that disappears by itself, for pointing at something. With a pencil that can hover, the dot follows it without touching. Never kept. |
15
15
  | Eraser | Removes whole strokes you touch. |
16
16
 
17
- **Zoom**: two fingers zoom into the slide and move around it, one finger moves a zoomed slide, and Ctrl + scroll (a trackpad pinch) zooms on a laptop. Only the slide grows; the bars and the toolbar keep their size. The audience window shows the same part of the slide. **1:1** at the top left shows the whole slide again, as does the next slide.
17
+ **Zoom**: two fingers zoom into the slide and move around it, one finger moves a zoomed slide, and Ctrl + scroll (a trackpad pinch) zooms on a laptop. Only the slide grows; the bars and the toolbar keep their size. The audience window shows the same part of the slide. **1:1** at the top left shows the whole slide again, as does the next slide. To zoom straight to a picture or a table with a number key, see [hotspots](presenting.html#zoom-in-on-part-of-a-slide).
18
18
 
19
19
  On a touch screen such as an iPad, drawing is on as soon as the presenter view opens, and in the deck as soon as the pencil touches it, with the toolbar folded into its button in the bottom right corner (↘ folds it again). Until then, a tap on the right third of the screen goes forward, on the left third back, and a swipe does the same. Drawing starts with the laser pointer; choose the pen or the highlighter to write. The pen and the highlighter each have colours and three sizes, and each keeps its own; one pen colour is **Accent**, the accent colour of the theme and palette: a drawing in it changes with them. The other pen colours follow light and dark: on dark slides red, blue and green are lighter, and the text colour is white instead of black. The toolbar also has undo and redo (also Cmd/Ctrl+Z and Cmd/Ctrl+Shift+Z), **Clear this slide**, and **×** to stop drawing; **D** and **Escape** do the same. While you draw, the pencil and the mouse draw; fingers keep working: a swipe to the left goes forward, to the right back, a tap on a stroke selects it, and buttons and polls on the slide still respond. Turn slides with the arrow keys or the presenter view's arrows, as always. Holding the pen still for half a second at the end of a stroke makes it a straight line; near a multiple of 15° (horizontal, vertical, 45° …) it snaps to that angle.
20
20
 
@@ -61,11 +61,56 @@ To let people answer a question on their phones, put a poll on a slide. See [Ask
61
61
  | I | Hide or show the drawings |
62
62
  | F | Full screen, where the browser allows it |
63
63
  | N | Open or close the notes drawer, in the presenter view's slide-only layout |
64
+ | L | Switch to the talk's next language, for a talk written in several (see below) |
65
+ | 1–9 | Zoom in on a part of the slide, with hotspots on (see below); without them, go to slide 1–9 |
66
+ | 0 or Escape | Show the whole slide again |
67
+ | H | Turn hotspots on or off for this talk, in the presenter view |
64
68
 
65
69
  Click the slide area if your keys are not controlling it. Keys behave normally while you are typing in a text field.
66
70
 
67
71
  The timer is for your own reference; you can start, pause, and reset it in the presenter view.
68
72
 
73
+ ## Zoom in on part of a slide
74
+
75
+ Hotspots let you show one part of a slide large: a picture, a chart, a code block, a table. Turn them on in the deck's settings:
76
+
77
+ ```markdown
78
+ ---
79
+ hotspots: auto
80
+ ---
81
+ ```
82
+
83
+ The presenter view then puts a small numbered key on each part of the slide you can zoom to. Press its number, or tap the key on an iPad, and the slide zooms smoothly until that part fills the screen. A part of another shape than the screen keeps the slide around it in view. The audience window, a paired iPad and phones following the talk zoom along; only the presenter view shows the keys.
84
+
85
+ To see the whole slide again, press the same number again, **0** or **Escape**, tap the slide, or use **1:1**. The next point or the next slide shows the whole slide by itself, so you never need an extra key press to move on. Another number while zoomed goes straight to that part.
86
+
87
+ | Setting | What gets a key |
88
+ |---|---|
89
+ | `hotspots: auto` | Pictures, code blocks, tables, formulas, videos, callouts, columns and polls, and anything marked `data-hotspot` |
90
+ | `hotspots: marked` | Only what you marked with `data-hotspot`; nothing is found by itself |
91
+ | `hotspots: off` | Nothing. This is the default: 1–9 go to slides 1–9 |
92
+
93
+ A slide can have its own setting in its frontmatter, such as `hotspots: false` for a slide whose numbers you do not want, or `hotspots: auto` on one slide of a deck without hotspots. Mark a part of your own in inline HTML with `data-hotspot`, and keep a found one out with `data-hotspot="off"`:
94
+
95
+ ```markdown
96
+ The rate is <span data-hotspot>**2.4 %** a year</span>, for now.
97
+ ```
98
+
99
+ Parts that nearly fill the slide, or its whole width, get no key, since there is nothing to zoom; what is inside them may. A part inside another one shares its key: a column with a formula and a tip in it is one part. The keys follow reading order, up to nine on a slide. In the editor, the deck's settings and each slide's details have a **Hotspots** choice too. **H**, or the button beside **Draw**, turns hotspots on or off for the rest of the talk without changing the deck; a slide set to `false` stays without them.
100
+
101
+ ## One talk in several languages
102
+
103
+ To give a talk in English, German or another language as the room needs, write it once per language, in files side by side named for it:
104
+
105
+ ```text
106
+ talk.en.md
107
+ talk.de.md
108
+ ```
109
+
110
+ Start either with `mdeck run talk.en.md`: the presenter view gets a **Language** switch, and **L** goes to the next language. Switching changes the slides, your notes and the words mdeck shows in every window, including the audience window, a paired iPad and phones following along, and keeps your place, the step on the slide and the drawings. Slides match by their place in the deck, so keep the same slides in the same order in every file. A talk in one language shows no switch.
111
+
112
+ `mdeck send talk.de.md` makes the German file to hand out; each file is a complete deck of its own.
113
+
69
114
  ## Reveal points one at a time
70
115
 
71
116
  Wrap a list in a steps block:
@@ -140,6 +140,34 @@ params:
140
140
 
141
141
  Its default is simply the token's value. Colours are not parameters: they come from the palette.
142
142
 
143
+ Say what kind of value a parameter takes with `type`, so mdeck can check what authors write and the editor can offer the right control:
144
+
145
+ ```toml
146
+ [params.bar]
147
+ token = "--bar"
148
+ title = "Thickness of the bar under headings"
149
+ type = "size"
150
+ min = 0
151
+ max = 20
152
+ description = "12px by default, from about 6px to 20px; 0px leaves headings without bars."
153
+ ```
154
+
155
+ | `type` | Takes | The editor shows | Settings |
156
+ |---|---|---|---|
157
+ | `size` | pixels: `12px`, or just `12` | a slider | `min`, `max`, `step` in pixels |
158
+ | `number` | a number; a strength from 0 to 1 | a slider | `min`, `max`, `step` |
159
+ | `switch` | `1` or `0` (also `true`/`false`, `on`/`off`) | a box to tick | |
160
+ | `choice` | one of its `choices` | a list | `choices = ["left", "right"]` |
161
+ | `font` | a CSS font list | a text box | |
162
+
163
+ The token's value must be a value of that type: a `size` is written `"12px"`, a `switch` `"1"`. A value in the deck that does not fit is left out, and the theme's own value stays; `mdeck check` says why. A value outside `min` and `max` is used, with a warning: the range is what the theme was made for. A parameter without a `type` takes any text, as before.
164
+
165
+ A few habits make parameters easy to use:
166
+
167
+ - Turn a feature off with its parameter at zero (`0px`, `0`) rather than a second parameter.
168
+ - Use a switch or a strength by multiplying with it, as in `calc(330px * var(--shapes))`.
169
+ - Let the `description` give the default and a sensible range: the editor shows it under the control, and assistants read it.
170
+
143
171
  ## Say what it is for
144
172
 
145
173
  A `[guide]` tells people, and assistants that write slides, what your theme is good for and how slides for it are written: