mdeck 3.0.0 → 3.2.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 (47) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/assets/base.css +24 -0
  3. package/assets/{packs/lagoon → extensions/palettes}/lagoon/extension.toml +3 -0
  4. package/assets/{packs/aurora → extensions/palettes}/neon/extension.toml +3 -0
  5. package/assets/{packs/academic → extensions/palettes}/nordic/extension.toml +3 -0
  6. package/assets/{packs/minimal → extensions/palettes}/paper/extension.toml +3 -0
  7. package/assets/{packs/neue → extensions/palettes}/swiss/extension.toml +3 -0
  8. package/assets/{packs/academic → extensions/themes}/academic/extension.toml +3 -0
  9. package/assets/{packs/aurora → extensions/themes}/aurora/extension.toml +3 -0
  10. package/assets/{packs/minimal → extensions/themes}/minimal/extension.toml +3 -0
  11. package/assets/{packs/neue → extensions/themes}/neue/extension.toml +3 -0
  12. package/docs/reference/authoring.md +16 -3
  13. package/docs/reference/extensions.md +42 -35
  14. package/docs/reference/palettes.md +1 -1
  15. package/docs/reference/themes.md +3 -3
  16. package/docs/site/content/appearance.md +11 -9
  17. package/docs/site/content/commands.md +2 -1
  18. package/docs/site/content/theme-authoring.md +1 -1
  19. package/docs/site/content/theme-repository.md +36 -28
  20. package/package.json +2 -2
  21. package/skills/write-slides/SKILL.md +1 -1
  22. package/src/build/editorPlugin.js +22 -17
  23. package/src/build/themeCheck.js +14 -3
  24. package/src/cli/args.js +2 -1
  25. package/src/cli/index.js +7 -6
  26. package/src/cli/themes.js +99 -92
  27. package/src/editor/api.js +11 -10
  28. package/src/editor/components/DesignApp.jsx +9 -11
  29. package/src/editor/components/ExtensionEditor.jsx +10 -11
  30. package/src/editor/components/ExtensionsPanel.jsx +24 -28
  31. package/src/extensions/discover.js +28 -35
  32. package/src/extensions/installed.js +73 -48
  33. package/src/extensions/manifest.js +20 -3
  34. package/src/extensions/moved.js +14 -7
  35. package/src/extensions/packages.js +318 -0
  36. package/src/paths.js +0 -2
  37. package/src/runtime/markedSetup.js +7 -0
  38. package/assets/packs/academic/pack.toml +0 -8
  39. package/assets/packs/aurora/pack.toml +0 -8
  40. package/assets/packs/lagoon/pack.toml +0 -8
  41. package/assets/packs/minimal/pack.toml +0 -8
  42. package/assets/packs/neue/pack.toml +0 -8
  43. package/src/extensions/packs.js +0 -357
  44. /package/assets/{packs/academic → extensions/themes}/academic/styles.css +0 -0
  45. /package/assets/{packs/aurora → extensions/themes}/aurora/styles.css +0 -0
  46. /package/assets/{packs/minimal → extensions/themes}/minimal/styles.css +0 -0
  47. /package/assets/{packs/neue → extensions/themes}/neue/styles.css +0 -0
package/CHANGELOG.md CHANGED
@@ -1,11 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.2.0 — 2026-10-07
4
+
5
+ - Pictures written in the text fit on the slide in every theme: a paragraph of nothing but pictures shrinks into the room below the heading instead of running off the slide, keeping its proportions (small pictures keep their size), and several pictures in one paragraph sit side by side. Such paragraphs have the class `pictures`, for themes that set them their own way; a picture in a sentence is left alone.
6
+ - Tables have room below them in every theme, so a sentence after a table no longer sits right against it.
7
+ - `mdeck themes build` also renders an icon for each theme: its title slide at 96×54 (drawn at twice that, about 3 KB), listed as `icon` in `catalogue.json` and `looks.json`. The theme repository's gallery shows it in its list instead of the palette's colours, which said little about a theme.
8
+
9
+ ## 3.1.0 — 2026-10-07
10
+
11
+ - Packs are gone: every theme and palette is installed on its own. `mdeck themes install duet` installs the theme with its default palette (`cobalt`), and `mdeck palettes install solarized` a palette; both have `search`, `remove`, `update` and `list`. A palette made for one theme (FHNW's `brand`) brings that theme along and goes with it. A palette an installed theme uses by default is not removed while that theme is there. Installs go into `themes/<id>/` and `palettes/<id>/` of the extensions folder, so a theme and a palette may share a name.
12
+ - A theme or palette carries its version, author, licence and the oldest mdeck it needs in its own `extension.toml` (`version`, `author`, `license`, `homepage`, `mdeck`); `pack.toml` is gone. The built-in ones are back in `assets/extensions/themes` and `assets/extensions/palettes`, and are removed and installed again one by one (`theme:aurora` in `~/.mdeck/removed.json`).
13
+ - The theme repository has a folder per theme and per palette (`themes/<id>`, `palettes/<id>`) and serves `catalogue.json`; mdeck 3.0 cannot read it. The design page lists themes and palettes to install one by one.
14
+ - The palette `candy` works with every theme: raspberry and blue accents that can be read as text; `pop` takes its pastel fills from the palette (`--pop-fill-1`, `--pop-fill-2`, `--pop-line`, `--pop-shadow`, `--pop-ink`), with black shadows in the dark.
15
+ - The palettes `graphite` and `ember` are gone from the theme repository: they looked almost the same as the built-in `nordic` and `paper`. A deck that names one is told which to use instead.
16
+ - A deck that names a theme or palette that left mdeck in 3.0 is told the command for it, `mdeck themes install duet` or `mdeck palettes install forest`, not "beside the deck".
17
+ - Tests run with an empty `MDECK_HOME`, so what is installed on the computer does not change their results.
18
+
3
19
  ## 3.0.0 — 2026-10-07
4
20
 
5
21
  - Every theme and palette now comes in a pack, also those that come with mdeck: `neue`, `academic`, `aurora` and `minimal` (each a theme with its palette) and the palette `lagoon`. `graphite`, close to `nordic`, moved to the theme repository as a pack of its own. They work right away and offline, and can be removed: `mdeck themes remove aurora` hides it from every deck, `mdeck themes install aurora` brings it back without the internet. A newer version from the theme repository replaces the bundled one. A deck without a theme still uses `neue`, and says so when it was removed; the last theme cannot be removed.
6
22
  - `mdeck themes install <pack>` installs for every deck by default; a slide file, a folder or `--local` installs beside that deck. Packs can require other packs (`requires = ["lagoon"]` in `pack.toml`) for palettes their themes use: installing one installs those too, and removing a pack another one needs is refused. The design page lists the packs you can install, including removed bundled ones, and removes a pack for every deck.
7
23
  - `mdeck check` no longer warns about themes installed for every deck.
8
- - Fewer built-in looks: mdeck now comes with the themes `neue`, `academic`, `aurora` and the new `minimal` and the palettes `swiss`, `nordic`, `neon`, `lagoon` and `graphite`. The others moved to the theme repository as packs of the same name: `duet` (with `cobalt`), `editorial` (with `terra`), `fhnw` (with `brand`), `terminal` (with `phosphor`) and `sketch` (with `pastel`), and the palettes `ember` and `forest` as `earth`. A deck that uses one gets an error that says what to run, for example `mdeck themes install duet my-talk.md`; files made with `mdeck send` or `mdeck build` keep working, because they carry their theme.
24
+ - Fewer built-in looks: the themes `duet` (with `cobalt`), `editorial` (with `terra`), `fhnw` (with `brand`), `terminal` (with `phosphor`) and `sketch` (with `pastel`), and the palettes `ember` and `forest` (as `earth`) and `graphite`, moved to the theme repository as packs. A deck that uses one gets an error that names the command to run, for example `mdeck themes install duet`; files made with `mdeck send` or `mdeck build` keep working, because they carry their theme.
9
25
  - New theme `minimal`: nothing but the content, in the computer's own fonts (no web fonts, so it works offline), with medium weights, space instead of rules and boxes, and "Chapter 2" as a quiet label above chapter titles. Its default palette is the new `paper`: off-white and near-black with one orange accent, charcoal and a softer orange in the dark.
10
26
  - The sample deck's picture is a drawing in the palette's colours, and an SVG data URL that uses theme colours is drawn inline like an SVG file. A drawing in a picture's place now takes the space the layout gives it, like a photo, instead of pushing headings aside.
11
27
  - The launch page of `mdeck run` has a Theme editor tile under Write and learn; it opens the design page of the deck's editor.
package/assets/base.css CHANGED
@@ -162,11 +162,35 @@ deck-stage[data-ink-hidden] .slide-ink { display: none; }
162
162
  /* ── Code blocks ─────────────────────────────────────────────────────────── */
163
163
  .code-block { white-space: pre-wrap; overflow-x: hidden; }
164
164
 
165
+ /* ── Pictures written in the text ───────────────────────────────────────── */
166
+ /* A paragraph of nothing but pictures (marked in markedSetup.js) fits into
167
+ the room the slide has left: a large picture shrinks, keeping its
168
+ proportions, and never runs off the slide; a small one keeps its size.
169
+ Several sit side by side. Themes may set them differently (a grid, cropped
170
+ to fill); a picture in a sentence is left alone. */
171
+ .slide-body p.pictures {
172
+ display: flex;
173
+ align-items: center;
174
+ gap: 16px;
175
+ flex: 0 1 auto;
176
+ min-height: 0;
177
+ }
178
+ .slide-body p.pictures > :is(img, .themed-picture) {
179
+ flex: 0 1 auto;
180
+ min-width: 0;
181
+ min-height: 0;
182
+ max-width: 100%;
183
+ max-height: 100%;
184
+ object-fit: contain;
185
+ }
186
+
165
187
  /* ── Tables ──────────────────────────────────────────────────────────────── */
166
188
  .slide-body table {
167
189
  border-collapse: collapse;
168
190
  width: 100%;
169
191
  font-size: var(--fs-body);
192
+ /* Room before what follows, such as a sentence about the numbers. */
193
+ margin-bottom: calc(var(--gap-item, 24px) * 1.5);
170
194
  }
171
195
  .slide-body th,
172
196
  .slide-body td {
@@ -3,6 +3,9 @@ kind = "palette"
3
3
  id = "lagoon"
4
4
  title = "Lagoon"
5
5
  description = "Teal on warm stone, with an orange second accent."
6
+ version = "1.0.0"
7
+ author = "Tilman Schieber"
8
+ license = "MIT"
6
9
 
7
10
  [light]
8
11
  "--bg" = "#f8f8f6"
@@ -3,6 +3,9 @@ kind = "palette"
3
3
  id = "neon"
4
4
  title = "Neon"
5
5
  description = "Violet and magenta; loud, for workshops."
6
+ version = "1.0.0"
7
+ author = "Tilman Schieber"
8
+ license = "MIT"
6
9
 
7
10
  [light]
8
11
  "--bg" = "#ffffff"
@@ -3,6 +3,9 @@ kind = "palette"
3
3
  id = "nordic"
4
4
  title = "Nordic"
5
5
  description = "Ice grey, deep navy and a cool steel blue; calm."
6
+ version = "1.0.0"
7
+ author = "Tilman Schieber"
8
+ license = "MIT"
6
9
 
7
10
  [light]
8
11
  "--bg" = "#f3f6f8"
@@ -3,6 +3,9 @@ kind = "palette"
3
3
  id = "paper"
4
4
  title = "Paper"
5
5
  description = "Off-white paper and near-black ink, with one orange accent; charcoal and a softer orange in the dark."
6
+ version = "1.0.0"
7
+ author = "Tilman Schieber"
8
+ license = "MIT"
6
9
 
7
10
  [light]
8
11
  "--bg" = "#fbfaf7"
@@ -3,6 +3,9 @@ kind = "palette"
3
3
  id = "swiss"
4
4
  title = "Swiss"
5
5
  description = "White, black and signal red, like a Swiss poster."
6
+ version = "1.0.0"
7
+ author = "Tilman Schieber"
8
+ license = "MIT"
6
9
 
7
10
  [light]
8
11
  "--bg" = "#ffffff"
@@ -3,6 +3,9 @@ kind = "theme"
3
3
  id = "academic"
4
4
  title = "Academic"
5
5
  description = "A lecture: Source Sans and Source Serif, compact slides with the heading in a fixed place, theorem and definition blocks, booktabs tables and a footnote rule."
6
+ version = "1.0.0"
7
+ author = "Tilman Schieber"
8
+ license = "MIT"
6
9
  # The palette this theme uses unless the deck sets one; colours come only from palettes.
7
10
  palette = "nordic"
8
11
  fonts = [
@@ -3,6 +3,9 @@ kind = "theme"
3
3
  id = "aurora"
4
4
  title = "Aurora"
5
5
  description = "Northern lights: curtains of light in the accent colours, night-sky chapter and statement slides, frosted glass."
6
+ version = "1.0.0"
7
+ author = "Tilman Schieber"
8
+ license = "MIT"
6
9
  # The palette this theme uses unless the deck sets one; colours come only from palettes.
7
10
  palette = "neon"
8
11
  fonts = [
@@ -3,6 +3,9 @@ kind = "theme"
3
3
  id = "minimal"
4
4
  title = "Minimal"
5
5
  description = "Nothing but the content: system fonts, calm type, plenty of space, no decoration. Works offline."
6
+ version = "1.0.0"
7
+ author = "Tilman Schieber"
8
+ license = "MIT"
6
9
  # The palette this theme uses unless the deck sets one; colours come only from palettes.
7
10
  palette = "paper"
8
11
  # System fonts only: nothing to download, the same on every computer that has them.
@@ -3,6 +3,9 @@ kind = "theme"
3
3
  id = "neue"
4
4
  title = "Neue"
5
5
  description = "Swiss typography: large flush-left type, rules instead of boxes, signal red on white."
6
+ version = "1.0.0"
7
+ author = "Tilman Schieber"
8
+ license = "MIT"
6
9
  # The palette this theme uses unless the deck sets one; colours come only from palettes.
7
10
  palette = "swiss"
8
11
  fonts = [
@@ -109,7 +109,7 @@ view is reachable in any build through `?view=reader`.
109
109
 
110
110
  More themes (duet, editorial, fhnw, terminal, sketch) are in the theme
111
111
  repository: `mdeck themes search` lists them, and
112
- `mdeck themes install <pack> <deck>.md` puts one beside the deck.
112
+ `mdeck themes install <theme> <deck>.md` puts one beside the deck.
113
113
 
114
114
  `mdeck list <deck>.md` lists the built-in themes together with any themes kept
115
115
  beside the deck.
@@ -128,8 +128,8 @@ Each palette has a light and a dark variant; `appearance:` picks one.
128
128
  | `lagoon` | Teal on warm stone | Bright teal on teal-black |
129
129
  | `paper` | Off-white, near-black, orange (minimal's default) | Charcoal, soft orange |
130
130
 
131
- More palettes (cobalt, terra, phosphor, pastel, ember, forest, among others)
132
- are in the theme repository; install them with `mdeck themes install <pack> <deck>.md`.
131
+ More palettes (cobalt, terra, phosphor, pastel, forest, among others)
132
+ are in the theme repository; install them with `mdeck palettes install <palette> <deck>.md`.
133
133
 
134
134
  ---
135
135
 
@@ -594,6 +594,19 @@ Reference images with standard Markdown syntax or the `image:` frontmatter field
594
594
  ![Alt text](./img/diagram.png)
595
595
  ```
596
596
 
597
+ A paragraph of nothing but pictures fits into the room the slide has left: a
598
+ large picture shrinks, keeping its proportions, and a small one keeps its
599
+ size. Several pictures in one paragraph sit side by side:
600
+
601
+ ```markdown
602
+ # Three mornings
603
+
604
+ ![Fjord](./img/fjord.jpg) ![Mountains](./img/mountains.jpg) ![Snow](./img/snow.jpg)
605
+ ```
606
+
607
+ A picture inside a sentence stays in the sentence. Themes may set picture
608
+ paragraphs their own way (Lightbox fills a grid edge to edge).
609
+
597
610
  A local SVG whose source contains `var(--…)` is drawn inline instead of as an
598
611
  `<img>`, both in slide text (`![…](./img/drawing.svg)` or `<img src>`) and as a
599
612
  layout's `image` (`title`, `chapter`, `image-text`, `full-bleed-image`, and
@@ -211,41 +211,48 @@ Built-in extensions cannot be changed; copy one under a new id to change it.
211
211
  New themes always start as a copy. Layouts are not edited there. The page
212
212
  writes the same files described above.
213
213
 
214
- ## Installed extensions and packs
215
-
216
- Every theme and palette comes in a **pack**. mdeck looks for them in this
217
- order: the packs that come with mdeck (`assets/packs/`, minus those removed
218
- with `mdeck themes remove`, listed in `~/.mdeck/removed.json`), the user's
219
- folder (`~/.mdeck/extensions`, or `$MDECK_HOME/extensions`), and the
220
- `extensions/` folder beside the deck. For themes and palettes a later place
221
- replaces an earlier one with the same id: an installed newer version replaces
222
- the bundled one, and a deck's own copy replaces both (with a warning when it
223
- replaces one installed for every deck). Layouts are built in and may not be
224
- replaced; within one place an id may appear only once.
225
-
226
- `mdeck themes install <pack>` installs a pack for every deck, into the user's
227
- folder; given a slide file, a folder or `--local`, it installs into the
228
- `extensions/` folder beside the deck. Installing a bundled pack for every deck
229
- offers it again; beside a deck it is copied. A pack is a folder with a
230
- `pack.toml` (`schema`, `id`, `title`, `description`, `version`, `author`,
231
- `license`, `homepage`, `mdeck = ">=X.Y.Z"`, the oldest mdeck it works with,
232
- and `requires = [...]`, the packs it needs) and one folder per theme or
233
- palette, each holding only `extension.toml` and, for a theme, `styles.css`. A
234
- theme's palettes must be in its pack or in a pack it requires; installing a
235
- pack installs those too, and `remove` refuses while another installed pack
236
- needs one. Theme fonts must come from `https://fonts.googleapis.com/` or
237
- `https://fonts.bunny.net/`, and `styles.css` may contain neither `@import`
238
- nor `url()` other than `data:` URLs. Each installed folder gets a
239
- `.mdeck-pack.json` with the pack, its version, its requirements, its source
240
- and a checksum of every file; `update` and `remove` refuse to touch files
241
- changed since then unless given `--force`.
242
-
243
- The repository serves `index.json` (`{ schema: 1, packs: [...] }`, each with
244
- its ids, `requires`, `url`, `sha256`, `previews`, and `bundled` for the packs
245
- that come with mdeck) and one JSON file per pack version holding the text of
246
- its files. `mdeck themes build <packs> -o <out> [--check]` writes both from a
247
- folder of packs and mdeck's bundled packs; `MDECK_THEMES_URL` points mdeck at
248
- another index. Without a connection, mdeck offers its bundled packs.
214
+ ## Installed themes and palettes
215
+
216
+ Every theme and palette can be installed on its own, as a package. mdeck looks
217
+ for them in this order: its own (`assets/extensions/`, minus those removed
218
+ with `mdeck themes remove` or `mdeck palettes remove`, listed in
219
+ `~/.mdeck/removed.json` as `theme:<id>` or `palette:<id>`), the user's folder
220
+ (`~/.mdeck/extensions`, or `$MDECK_HOME/extensions`), and the `extensions/`
221
+ folder beside the deck. For themes and palettes a later place replaces an
222
+ earlier one with the same id: an installed newer version replaces the built-in
223
+ one, and a deck's own copy replaces both (with a warning when it replaces one
224
+ installed for every deck). Layouts are built in and may not be replaced;
225
+ within one place an id may appear only once per kind.
226
+
227
+ A theme or palette meant to be installed carries a few more settings in its
228
+ `extension.toml`: `version` (`1.0.0`), `author`, `license`, `homepage`, and
229
+ `mdeck = ">=X.Y.Z"`, the oldest mdeck it works with. What it needs follows
230
+ from its settings: a theme needs its default `palette`, and a palette with
231
+ `theme = "<id>"` needs that theme. Installing one installs what it needs;
232
+ removing a palette is refused while an installed theme uses it by default, and
233
+ removing a theme removes the palettes that belong only to it.
234
+
235
+ `mdeck themes install <theme>` and `mdeck palettes install <palette>` install
236
+ for every deck, into `themes/<id>/` or `palettes/<id>/` in the user's folder;
237
+ given a slide file, a folder or `--local`, into the `extensions/` folder
238
+ beside the deck (what it needs too, unless it is built in). Installing a
239
+ built-in one for every deck offers it again. A package holds only
240
+ `extension.toml` and, for a theme, `styles.css`. Theme fonts must come from
241
+ `https://fonts.googleapis.com/` or `https://fonts.bunny.net/`, and
242
+ `styles.css` may contain neither `@import` nor `url()` other than `data:`
243
+ URLs. Each installed folder gets a `.mdeck-package.json` with its kind, id,
244
+ version, source and a checksum of every file; `update` and `remove` refuse to
245
+ touch files changed since then unless given `--force`.
246
+
247
+ The repository serves `catalogue.json` (`{ schema: 2, themes: [...],
248
+ palettes: [...] }`, each with its id, version, default palette or theme,
249
+ `url`, `sha256`, `preview`, for a theme an `icon` (its title slide at
250
+ 96×54, drawn at twice that for sharp screens), and `builtIn` for those that
251
+ come with mdeck) and
252
+ one JSON file per version holding the text of its files.
253
+ `mdeck themes build <repository> -o <out> [--check]` writes both from a
254
+ folder with `themes/` and `palettes/`; `MDECK_THEMES_URL` points mdeck at
255
+ another catalogue. Without a connection, mdeck offers its built-in ones.
249
256
 
250
257
  ## Listing what is available
251
258
 
@@ -30,7 +30,7 @@ The presenter view and the reader view switch palette and light or dark without
30
30
 
31
31
  Each theme names a default: neue uses `swiss`, academic `nordic`, aurora `neon`.
32
32
 
33
- More palettes are in the [theme repository](https://github.com/tilman-schieber/mdeck-themes). The palettes cobalt, terra, phosphor, pastel, ember and forest, built in before mdeck 3.0, are there: cobalt in the `duet` pack, terra in `editorial`, phosphor in `terminal`, pastel in `sketch`, and ember and forest in `earth`. Install one with `mdeck themes install <pack> my-talk.md`.
33
+ More palettes are in the [theme repository](https://github.com/tilman-schieber/mdeck-themes). The palettes cobalt, terra, phosphor, pastel and forest, built in before mdeck 3.0, are there; installing the theme duet, editorial, terminal or sketch brings its palette along. Graphite and ember were removed because the built-in nordic and paper look almost the same; a deck that names them is told which to use. Install one with `mdeck palettes install <palette> my-talk.md`.
34
34
 
35
35
  ## Colours
36
36
 
@@ -24,9 +24,9 @@ theme: neue
24
24
  `mdeck list my-talk.md` lists them with their descriptions.
25
25
 
26
26
  More themes are in the [theme repository](https://github.com/tilman-schieber/mdeck-themes):
27
- `mdeck themes search` lists them, and `mdeck themes install <pack> my-talk.md`
28
- puts one beside the deck. The themes duet, editorial, fhnw, terminal and sketch,
29
- built in before mdeck 3.0, are there as packs of the same name.
27
+ `mdeck themes search` lists them, and `mdeck themes install <theme> my-talk.md`
28
+ puts one beside the deck, with its default palette. The themes duet, editorial,
29
+ fhnw, terminal and sketch, built in before mdeck 3.0, are there.
30
30
 
31
31
  ## Theme structure
32
32
 
@@ -119,21 +119,23 @@ Its theme, palette and light or dark controls, under the notes, let you try othe
119
119
 
120
120
  ## More themes from other people
121
121
 
122
- The themes above come with mdeck as packs. The theme repository has more: `mdeck themes search` lists them, and `mdeck themes install <pack>` installs one for all your decks. You can also remove the ones you never use; see [Install, remove or share a theme](theme-repository.html).
122
+ The themes above come with mdeck. The theme repository has more: `mdeck themes search` and `mdeck palettes search` list them, and `mdeck themes install <theme>` installs one for all your decks, with its palette. You can also remove the ones you never use; see [Install, remove or share a theme](theme-repository.html).
123
123
 
124
124
  ### Themes that moved to the repository
125
125
 
126
- Earlier versions of mdeck came with more themes and palettes. They are now packs in the theme repository:
126
+ Earlier versions of mdeck came with more themes and palettes. They are now in the theme repository:
127
127
 
128
- | Pack | What it holds |
128
+ | Theme | What it looks like (its palette) |
129
129
  |---|---|
130
- | `duet` | The duet theme (two accent colours that take turns, slab headings) and the `cobalt` palette |
131
- | `editorial` | The editorial theme (a magazine spread with serif headlines and pull quotes) and the `terra` palette |
130
+ | `duet` | Two accent colours that take turns, slab headings (`cobalt`) |
131
+ | `editorial` | A magazine spread with serif headlines and pull quotes (`terra`) |
132
132
  | `fhnw` | The FHNW visual identity, with its own `brand` palette only |
133
- | `terminal` | The terminal theme (headings typed at a prompt, a status bar) and the `phosphor` palette; it starts dark |
134
- | `sketch` | The sketch theme (handwriting, marker scribbles, sticky notes) and the `pastel` palette |
135
- | `earth` | The `ember` and `forest` palettes |
136
- | `graphite` | The `graphite` palette: black and white with a steel-blue accent |
133
+ | `terminal` | Headings typed at a prompt, a status bar; it starts dark (`phosphor`) |
134
+ | `sketch` | Handwriting, marker scribbles, sticky notes (`pastel`) |
135
+
136
+ The palette `forest` is there too: `mdeck palettes install forest`.
137
+
138
+ The palettes `graphite` and `ember` were removed: use `nordic` or `paper`, which come with mdeck and look almost the same.
137
139
 
138
140
  A deck that still names one of them stops with a message that tells you what to install, for example:
139
141
 
@@ -12,7 +12,8 @@ For how the commands, the views and the servers fit together, see [Views, comman
12
12
  | `mdeck new` | Make a presentation with guided questions |
13
13
  | `mdeck run my-talk.md` | Open the launch page: present, edit, check and send from one place; slides reload when you save |
14
14
  | `mdeck edit my-talk.md` | Edit slides, colors and themes in the browser; saves to the file |
15
- | `mdeck themes search`, `install <pack>`, `remove`, `update`, `list` | Themes and palettes: install more, remove the ones you do not use; see [Install, remove or share a theme](theme-repository.html) |
15
+ | `mdeck themes search`, `install <theme>`, `remove`, `update`, `list` | Themes: install more (each with its palette), remove the ones you do not use; see [Install, remove or share a theme](theme-repository.html) |
16
+ | `mdeck palettes search`, `install <palette>`, … | The same for palettes |
16
17
  | `mdeck design [my-talk.md or folder]` | Look at themes and palettes on a sample deck and fine-tune them; saves to `extensions/` |
17
18
  | `mdeck migrate my-talk.md --dry-run` | Preview the changes needed for API 2.0 |
18
19
  | `mdeck check my-talk.md` | Check settings and look for missing local files |
@@ -14,7 +14,7 @@ The rest of this page is the reference for what it writes, and for anyone comfor
14
14
 
15
15
  To look at the result and fine-tune it, run `mdeck design my-talk.md` (or `mdeck design` in a folder without a deck). It shows the theme or palette on a sample deck with every kind of slide, light and dark, and has forms for colours, fonts, sizes and spacing; see [Edit slides in your browser](editing.html). The files it writes are the ones described here.
16
16
 
17
- Someone may already have made what you need: `mdeck themes search` lists the theme repository, and [Install, remove or share a theme](theme-repository.html) explains how to install a pack or share yours.
17
+ Someone may already have made what you need: `mdeck themes search` lists the theme repository, and [Install, remove or share a theme](theme-repository.html) explains how to install one or share yours.
18
18
 
19
19
  Themes and palettes are **extensions**: each one is a folder with an `extension.toml` file that says what it is. Slide layouts use the same idea. Put the folder in `extensions/` beside your slide file and mdeck finds it automatically; there is nothing to register. The [extensions reference](extensions.html) has the complete list of settings.
20
20
 
@@ -1,80 +1,88 @@
1
1
  # Install, remove or share a theme
2
2
 
3
- Every theme and palette in mdeck comes in a **pack**: one theme with the palettes made for it, or a set of palettes. A few packs come with mdeck: `neue`, `academic`, `aurora` and `minimal`, each a theme with its own palette, and the palette `lagoon`. They work right away, also without an internet connection. More packs are in the **theme repository**; try them all on a sample deck at <https://gh.tschieber.de/mdeck-themes/>.
3
+ mdeck comes with four themes, `neue`, `academic`, `aurora` and `minimal`, and five palettes, `swiss`, `nordic`, `neon`, `paper` and `lagoon`. They work right away, also without an internet connection. More themes and palettes are in the **theme repository**; try every one on a sample deck, light and dark, at <https://gh.tschieber.de/mdeck-themes/>.
4
4
 
5
5
  ## Find and install one
6
6
 
7
- See what there is:
7
+ Themes and palettes each have their own command, with the same words:
8
8
 
9
9
  ```sh
10
10
  mdeck themes search
11
11
  mdeck themes search warm
12
+ mdeck palettes search
12
13
  ```
13
14
 
14
- Install a pack:
15
+ Install a theme:
15
16
 
16
17
  ```sh
17
18
  mdeck themes install duet
18
19
  ```
19
20
 
20
- It is installed for every deck on this computer, in a folder in your home folder (`~/.mdeck/extensions`). Then choose it at the top of a slide file (`theme: duet`) or in the editor's **Deck** tab. Some packs need another pack, for example for a palette their theme uses; `install` brings that one along.
21
+ A theme comes with its default palette, so this installs the palette `cobalt` too. A palette installs on its own:
21
22
 
22
- The design page has the same: open it with `mdeck design`, choose **Show what you can install**, and press **Install** under a pack.
23
+ ```sh
24
+ mdeck palettes install solarized
25
+ ```
26
+
27
+ They are installed for every deck on this computer, in a folder in your home folder (`~/.mdeck/extensions`). Then choose one at the top of a slide file (`theme: duet`, `palette: solarized`) or in the editor's **Deck** tab.
28
+
29
+ The design page has the same: open it with `mdeck design`, choose **Show what you can install**, and press **Install** beside a theme or palette.
23
30
 
24
31
  ## Beside one deck
25
32
 
26
- Give a slide file (or the folder it is in) to put the pack into the `extensions` folder next to it instead:
33
+ Give a slide file (or the folder it is in) to put it into the `extensions` folder next to it instead:
27
34
 
28
35
  ```sh
29
36
  mdeck themes install duet my-talk.md
30
37
  ```
31
38
 
32
- The slide folder then carries the theme, so it works on a computer where the pack is not installed, for example when you send a colleague the folder. A deck's own copy is used before one installed for every deck. Files made with `mdeck send`, `mdeck build` or `mdeck pdf` always carry their theme, wherever it came from.
39
+ The slide folder then carries the theme and its palette, so it works on a computer where they are not installed, for example when you send the folder to a colleague.
33
40
 
34
41
  ## Update and remove
35
42
 
36
43
  ```sh
37
44
  mdeck themes list # what comes with mdeck, and what is installed
38
- mdeck themes update # newer versions of everything installed
45
+ mdeck themes update # newer versions of the installed themes
46
+ mdeck palettes update
39
47
  mdeck themes remove duet
48
+ mdeck palettes remove cobalt
40
49
  ```
41
50
 
42
- Add a slide file, or `--local`, to work on the packs beside that deck. If you changed an installed file by hand, `update` and `remove` stop and tell you which one, so your change is not lost; add `--force` to go ahead anyway. A pack that another installed pack needs stays until that one is removed.
51
+ Add a slide file, or `--local`, to work beside that deck. If you changed an installed file by hand, `update` and `remove` stop and tell you which one, so your change is not lost; add `--force` to go ahead anyway.
52
+
53
+ A palette that an installed theme uses by default stays until that theme is removed. A palette made for one theme only (like FHNW's `brand`) comes and goes with that theme.
43
54
 
44
- The packs that come with mdeck can be removed too: `mdeck themes remove aurora` hides it from every deck and from the lists. `mdeck themes install aurora` brings it back, without needing the internet. A deck that sets no theme uses `neue`; if you removed it, mdeck tells you to install it again or to choose another theme. The last theme cannot be removed: install another one first.
55
+ The themes and palettes that come with mdeck can be removed too: `mdeck themes remove aurora` hides it from every deck and from the lists, and `mdeck themes install aurora` brings it back, without the internet. The last theme always stays. A deck without a `theme:` setting uses `neue`; if you removed it, `mdeck check` tells you.
45
56
 
46
- ## What a pack may contain
57
+ ## What may be in one
47
58
 
48
- Packs hold only theme and palette settings (`extension.toml`) and theme stylesheets (`styles.css`). They never contain code that runs in your slides. Fonts may come only from Google Fonts or Bunny Fonts, and stylesheets may not load anything from the web. mdeck checks this again when it installs a pack, and refuses a pack that does not match the checksum the repository lists for it.
59
+ A theme holds only its settings (`extension.toml`) and its stylesheet (`styles.css`); a palette only its settings. They never contain code that runs in your slides. Fonts may come only from Google Fonts or Bunny Fonts, and stylesheets may not load anything from the web. mdeck checks this again when it installs one, and refuses one that does not match the checksum the repository lists for it.
49
60
 
50
61
  ## Share your own
51
62
 
52
63
  1. Make the theme or palette as described in [Create a theme or palette](theme-authoring.html), and fine-tune it with `mdeck design`.
53
- 2. Fork the theme repository and add a folder `packs/<your-pack>/` with a `pack.toml` and one folder per theme or palette:
64
+ 2. Fork the theme repository and add it as a folder of its own, `themes/<id>/` or `palettes/<id>/`:
54
65
 
55
66
  ```text
56
- packs/
67
+ themes/
57
68
  harbour/
58
- pack.toml
59
- harbour/ a theme
60
- extension.toml
61
- styles.css
62
- harbour-night/ its palette
63
- extension.toml
69
+ extension.toml
70
+ styles.css
71
+ palettes/
72
+ harbour-night/
73
+ extension.toml
64
74
  ```
65
75
 
76
+ with a few more settings at the top of `extension.toml`:
77
+
66
78
  ```toml
67
- schema = 1
68
- id = "harbour"
69
- title = "Harbour"
70
- description = "Navy and brass, with a serif for headings."
71
79
  version = "1.0.0"
72
80
  author = "Your Name"
73
81
  license = "MIT"
74
- mdeck = ">=3.0.0"
82
+ mdeck = ">=3.1.0"
75
83
  ```
76
84
 
77
- A pack whose theme uses a palette from another pack names that pack: `requires = ["lagoon"]`.
85
+ A theme names its default palette (`palette = "harbour-night"`); it must be in the repository or come with mdeck, and is installed along with the theme.
78
86
 
79
- 3. Check it the way the repository will: `mdeck themes build packs -o site --check` shows every theme and palette in the pack on every kind of slide, light and dark, and fails on text that does not fit or is hard to read.
80
- 4. Open a pull request. Once it is merged, `mdeck themes search` lists it. For a new version, raise `version` in `pack.toml`.
87
+ 3. Check it the way the repository will: `mdeck themes build . -o site --check` shows every theme and palette on every kind of slide, light and dark, and fails on text that does not fit or is hard to read.
88
+ 4. Open a pull request. Once it is merged, `mdeck themes search` or `mdeck palettes search` lists it. For a new version, raise `version`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mdeck",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "type": "module",
5
5
  "description": "Write slides as a plain text file, present them in the browser, share them as one HTML file or PDF.",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@
40
40
  "CHANGELOG.md"
41
41
  ],
42
42
  "scripts": {
43
- "test": "node --test",
43
+ "test": "node --test --import ./tests/isolate-home.js",
44
44
  "test:browser": "node tools/browser-check.mjs",
45
45
  "test:server": "node tools/server-check.mjs",
46
46
  "test:docs": "node tools/docs-check.mjs",
@@ -135,7 +135,7 @@ Fix anything it reports. When you worked from source material, list what you lef
135
135
 
136
136
  ## 5. A new look: themes and palettes
137
137
 
138
- When the user wants a look the built-in themes and palettes do not give (their institute's colours, a font, the style of a poster or picture), first run `mdeck themes search` (with a word or two): someone may have shared it, and `mdeck themes install <pack> <deck>.md` puts it beside the deck, so the slide folder carries it. Otherwise make it as an extension in `extensions/` beside the deck, never as styling on single slides. Read `extensions.md` from the reference folder first; it lists every setting.
138
+ When the user wants a look the built-in themes and palettes do not give (their institute's colours, a font, the style of a poster or picture), first run `mdeck themes search` or `mdeck palettes search` (with a word or two): someone may have shared it, and `mdeck themes install <theme> <deck>.md` (with its palette) or `mdeck palettes install <palette> <deck>.md` puts it beside the deck, so the slide folder carries it. Otherwise make it as an extension in `extensions/` beside the deck, never as styling on single slides. Read `extensions.md` from the reference folder first; it lists every setting.
139
139
 
140
140
  - **Colours only: a palette.** `extensions/<id>/extension.toml` with `kind = "palette"`, and every colour role (`--bg`, `--surface`, `--ink`, `--ink-soft`, `--muted`, `--rule`, `--accent`, `--accent-2`, `--on-accent`) in both `[light]` and `[dark]`. Text colours must stay readable on `--bg` and `--surface` in both variants, because themes use the other variant for inverted slides.
141
141
  - **Fonts, sizes, spacing or arrangement: a theme.** Copy the folder of the closest built-in theme (`assets/extensions/themes/<id>/` in the mdeck repository or in `$(npm root -g)/mdeck/`) to `extensions/<new-id>/`, change `id` and `title`, then its tokens and `styles.css`. A theme takes no colours of its own: it names its default `palette`, and the colours come from palettes.
@@ -5,9 +5,9 @@
5
5
  import { createHash } from 'node:crypto'
6
6
  import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, rmSync, unlinkSync } from 'node:fs'
7
7
  import { resolve, basename, dirname, relative } from 'node:path'
8
- import { bundledPacks, loadRegistry, removedPacks, serializeRegistry } from '../extensions/discover.js'
9
- import { findPack, loadCatalogue, PackError } from '../extensions/packs.js'
10
- import { installHere, packsAt, removeHere, target } from '../extensions/installed.js'
8
+ import { loadRegistry, removedBuiltIns, serializeRegistry, userExtensionsDir } from '../extensions/discover.js'
9
+ import { findEntry, installedPackages, keyOf, loadCatalogue, PackageError } from '../extensions/packages.js'
10
+ import { installHere, removeHere, target } from '../extensions/installed.js'
11
11
  import { createRequire } from 'node:module'
12
12
  import { ManifestError, KINDS, ID_RE, MANIFEST_FILENAME, parseManifestText, validateManifest } from '../extensions/manifest.js'
13
13
 
@@ -201,26 +201,31 @@ export function editorMiddleware(deckFile, { registryFor, extensions = createExt
201
201
  response.setHeader('Allow', 'GET, PUT, DELETE')
202
202
  return send(response, 405, { error: 'Method not allowed' })
203
203
  }
204
- // Packs: what the repository and mdeck offer, and installing one for
205
- // every deck (as mdeck themes install does).
206
- if (pathname === '/themes/index' && request.method === 'GET') {
207
- const catalogue = await loadCatalogue({ bundled: bundledPacks({ all: true }) })
208
- const removed = removedPacks()
209
- const installed = Object.fromEntries(Object.entries(packsAt(target(null, false))).map(([id, pack]) => [id, { version: pack.version ?? null, bundled: Boolean(pack.bundled) }]))
210
- return send(response, 200, { url: catalogue.url, offline: catalogue.offline, packs: catalogue.packs.map(({ dir, ...pack }) => ({ ...pack, removed: removed.includes(pack.id) })), installed })
204
+ // Themes and palettes: what mdeck and the repository offer, and
205
+ // installing or removing one for every deck (as mdeck themes does).
206
+ if (pathname === '/themes/catalogue' && request.method === 'GET') {
207
+ const catalogue = await loadCatalogue()
208
+ const hidden = removedBuiltIns()
209
+ const installed = installedPackages(userExtensionsDir())
210
+ const entries = catalogue.entries.map(({ dir, ...entry }) => {
211
+ const key = keyOf(entry.kind, entry.id)
212
+ const removed = entry.builtIn && hidden.includes(key)
213
+ return { ...entry, removed, available: Boolean(installed[key]) || (entry.builtIn && !removed), ...(entry.preview ? { preview: new URL(entry.preview, catalogue.url).href } : {}) }
214
+ })
215
+ return send(response, 200, { url: catalogue.url, offline: catalogue.offline, entries })
211
216
  }
212
217
  if (pathname === '/themes/install' && request.method === 'POST') {
213
218
  const body = await readJson(request)
214
- const catalogue = await loadCatalogue({ bundled: bundledPacks({ all: true }) })
215
- findPack(catalogue, String(body?.id ?? ''))
216
- const steps = await installHere(catalogue, String(body.id), target(null, false), { mdeckVersion: VERSION })
219
+ const kind = String(body?.kind ?? ''), id = String(body?.id ?? '')
220
+ const catalogue = await loadCatalogue()
221
+ findEntry(catalogue, kind, id)
222
+ const steps = await installHere(catalogue, kind, id, target(null, false), { mdeckVersion: VERSION })
217
223
  return send(response, 200, { steps, registry: serializeRegistry(registryFor()) })
218
224
  }
219
225
  if (pathname === '/themes/remove' && request.method === 'POST') {
220
226
  const body = await readJson(request)
221
- const catalogue = await loadCatalogue({ bundled: bundledPacks({ all: true }), online: false })
222
- const removed = removeHere(catalogue, String(body?.id ?? ''), target(null, false))
223
- return send(response, 200, { ...removed, registry: serializeRegistry(registryFor()) })
227
+ const removed = removeHere(String(body?.kind ?? ''), String(body?.id ?? ''), target(null, false))
228
+ return send(response, 200, { removed, registry: serializeRegistry(registryFor()) })
224
229
  }
225
230
  if (pathname === '/deck' && request.method === 'GET') {
226
231
  const registry = registryFor()
@@ -238,7 +243,7 @@ export function editorMiddleware(deckFile, { registryFor, extensions = createExt
238
243
  if (['/deck', '/source'].includes(pathname)) { response.setHeader('Allow', pathname === '/deck' ? 'GET' : 'POST'); return send(response, 405, { error: 'Method not allowed' }) }
239
244
  return next()
240
245
  } catch (error) {
241
- if (error instanceof PackError) return send(response, 400, { error: error.message })
246
+ if (error instanceof PackageError) return send(response, 400, { error: error.message })
242
247
  if (error instanceof ManifestError) return send(response, 500, { error: error.message })
243
248
  return send(response, error.status ?? 500, { error: error.message })
244
249
  }