@honeydeck/honeydeck 0.3.0 → 0.5.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 (66) hide show
  1. package/DEVELOPMENT.md +4 -1
  2. package/Readme.md +2 -2
  3. package/SPEC.md +3 -3
  4. package/docs/components-browser-frame.md +34 -0
  5. package/docs/components-keyboard.md +31 -0
  6. package/docs/components-list-style.md +49 -0
  7. package/docs/components-notes.md +36 -0
  8. package/docs/components-reveal-group.md +58 -0
  9. package/docs/components-reveal-with.md +37 -0
  10. package/docs/components-reveal.md +33 -0
  11. package/docs/components-timeline-steps.md +48 -0
  12. package/docs/components.md +13 -54
  13. package/docs/configuration.md +11 -0
  14. package/docs/deeper-dive.md +30 -7
  15. package/docs/getting-started.md +2 -2
  16. package/docs/navigation.md +1 -1
  17. package/docs/pdf-export.md +4 -2
  18. package/docs/presenter-mode.md +6 -3
  19. package/docs/skills.md +3 -3
  20. package/docs/slidev-migration.md +3 -0
  21. package/docs/steps-and-reveals.md +143 -8
  22. package/package.json +4 -1
  23. package/skills/SPEC.md +2 -2
  24. package/skills/honeydeck/SKILL.md +2 -2
  25. package/skills/slidev-migration/SKILL.md +1 -0
  26. package/src/SPEC.md +8 -3
  27. package/src/cli/SPEC.md +3 -2
  28. package/src/cli/pdf.ts +11 -4
  29. package/src/layouts/SPEC.md +1 -1
  30. package/src/remark/SPEC.md +102 -2
  31. package/src/remark/code-utils.ts +151 -0
  32. package/src/remark/shiki-code-blocks.ts +329 -136
  33. package/src/remark/step-numbering.ts +408 -103
  34. package/src/runtime/Deck.tsx +133 -116
  35. package/src/runtime/EffectiveColorModeContext.tsx +37 -0
  36. package/src/runtime/SPEC.md +21 -8
  37. package/src/runtime/SlideCanvas.tsx +19 -16
  38. package/src/runtime/SlideScaleContext.tsx +23 -0
  39. package/src/runtime/components/CodeBlock.tsx +19 -202
  40. package/src/runtime/components/CodeBlockCopyButton.tsx +64 -0
  41. package/src/runtime/components/CodeBlockShared.ts +17 -0
  42. package/src/runtime/components/Fade.tsx +51 -0
  43. package/src/runtime/components/FadeGroup.tsx +175 -0
  44. package/src/runtime/components/FadeWith.tsx +54 -0
  45. package/src/runtime/components/MagicCodeBlock.tsx +223 -0
  46. package/src/runtime/components/NavBar.tsx +1 -1
  47. package/src/runtime/components/NormalCodeBlock.tsx +128 -0
  48. package/src/runtime/components/Reveal.tsx +27 -27
  49. package/src/runtime/components/RevealGroup.tsx +143 -41
  50. package/src/runtime/components/RevealWith.tsx +63 -0
  51. package/src/runtime/components/SPEC.md +112 -7
  52. package/src/runtime/components/TimelineReveal.tsx +81 -0
  53. package/src/runtime/components/index.ts +13 -5
  54. package/src/runtime/components/timelineVisibility.ts +45 -0
  55. package/src/runtime/index.ts +9 -1
  56. package/src/runtime/navigation.ts +6 -4
  57. package/src/runtime/presentationApi.ts +449 -0
  58. package/src/runtime/views/PresenterCastButton.tsx +39 -0
  59. package/src/runtime/views/PresenterView.tsx +21 -4
  60. package/src/runtime/views/SPEC.md +7 -5
  61. package/src/theme/base.css +67 -2
  62. package/src/vite-plugin/SPEC.md +20 -2
  63. package/src/vite-plugin/index.ts +16 -2
  64. package/src/vite-plugin/layout-demo-crawler.ts +304 -33
  65. package/src/vite-plugin/splitter.ts +1 -0
  66. package/src/vite-plugin/virtual-modules.ts +16 -6
package/docs/skills.md CHANGED
@@ -31,9 +31,9 @@ npx skills add <honeydeck-repo-url> --copy --skill slidev-migration
31
31
 
32
32
  | Skill | Use it for |
33
33
  | --- | --- |
34
- | `honeydeck` | Honeydeck-specific guidance for MDX decks, layouts, CSS imports, presenter notes, reveals, code steps, PDF export, and package docs. |
34
+ | `honeydeck` | Honeydeck-specific guidance for MDX decks, layouts, CSS imports, presenter notes, reveals, code steps, Magic Code, PDF export, and package docs. |
35
35
  | `presentation-writing` | Framework-agnostic help with audience, storyline, slide headlines, speaker notes, timing, and review heuristics. |
36
- | `slidev-migration` | Migrating Slidev decks to Honeydeck while preserving source files until you approve cleanup. |
36
+ | `slidev-migration` | Migrating Slidev decks to Honeydeck, including rewriting Slidev `md magic-move` blocks to Honeydeck `md magic-code`, while preserving source files until you approve cleanup. |
37
37
 
38
38
  The `honeydeck` and `presentation-writing` skills work well together: one keeps the agent inside Honeydeck conventions, while the other improves the story and delivery. Add `slidev-migration` when you are converting an existing Slidev project.
39
39
 
@@ -48,7 +48,7 @@ For example, an agent with the `honeydeck` skill should prefer:
48
48
  - slide frontmatter for layouts
49
49
  - explicit imports from `@honeydeck/honeydeck`
50
50
  - `<Notes>` for speaker notes
51
- - `<Reveal>`, `<RevealGroup>`, and code metadata for steps
51
+ - `<Reveal>`, `<RevealGroup>`, code metadata, and Magic Code for steps
52
52
  - `honeydeck pdf` for PDF export
53
53
 
54
54
  The skills also point agents back to the packaged docs and specs, so generated deck changes can stay aligned with the installed Honeydeck version.
@@ -36,7 +36,10 @@ The skill guides an agent through the common Slidev-to-Honeydeck mapping:
36
36
  | `components/*.vue` | React `components/*.tsx` |
37
37
  | `layouts/*.vue` or Slidev themes | Honeydeck layouts, layout maps, React components, and CSS |
38
38
  | `<v-click>` / `<v-clicks>` | `<Reveal>` / `<RevealGroup>` |
39
+ | Slidev Magic Move code blocks (`md magic-move`) | Honeydeck Magic Code blocks (`md magic-code`) |
39
40
  | trailing note comments | `<Notes>` |
40
41
  | `slidev`, `slidev build`, `slidev export` | `honeydeck dev`, `honeydeck build`, `honeydeck pdf` |
41
42
 
43
+ The migration skill rewrites Slidev `md magic-move` code animation blocks to Honeydeck's canonical `md magic-code` syntax. Honeydeck still accepts `md magic-move` as a compatibility alias.
44
+
42
45
  Advanced Slidev features such as Vue directives, `$clicks`, custom theme internals, Monaco/live-code blocks, and complex click positioning may need React-specific follow-up after the first migration pass.
@@ -1,16 +1,17 @@
1
1
  # Steps & Reveals
2
2
 
3
- Honeydeck has a first-class step concept. Each slide has a timeline built from `Reveal`/`RevealGroup` components, custom component step blocks, and code highlight ranges, counted in document order.
3
+ Honeydeck has a first-class step concept. Each slide has a timeline built from `Reveal`/`RevealGroup`/`Fade`/`FadeGroup` components, `RevealWith`/`FadeWith` synchronized content, custom component step blocks, code highlight ranges, and Magic Code states, counted in document order.
4
4
 
5
5
  ## Timeline Model
6
6
 
7
7
  - Slides start at **step 0** — no reveals or custom component steps active.
8
8
  - Stepped code blocks show their first highlight group immediately whenever the block is visible.
9
- - Each `Reveal`, `RevealGroup` child, `TimelineSteps` block, or code highlight group after the first adds a step.
9
+ - Magic Code blocks show their first inner code fence and first highlight group immediately whenever the block is visible.
10
+ - Each `Reveal`, `Fade`, `RevealGroup`/`FadeGroup` child, `TimelineSteps` block, code highlight group after the first, or Magic Code state after the first adds a step.
11
+ - `RevealWith` and `FadeWith` add no steps. They watch existing steps by `target` or numeric `at`.
10
12
  - All step-producing elements share one slide-local timeline.
11
- - Nested step-producing elements are flattened into that same timeline. A parent
12
- reveal target appears first; nested reveals, reveal groups, and code highlight
13
- ranges appear after the parent and before the next sibling target.
13
+ - Nested step-producing elements are flattened into that same timeline for reveal targets. A parent reveal target appears first; nested reveal/fade groups and code highlight ranges appear after the parent and before the next sibling target.
14
+ - Fade targets must not contain nested timeline producers because a faded parent would hide later nested steps. Put fades inside reveals instead.
14
15
 
15
16
  ## Reveal
16
17
 
@@ -31,13 +32,74 @@ import { Reveal } from '@honeydeck/honeydeck'
31
32
  ### Behavior
32
33
 
33
34
  - **Cumulative** — once visible, content stays visible for the rest of the slide.
34
- - **Layout-stable** — hidden content reserves space (`opacity: 0` / `visibility: hidden`, not `display: none`).
35
+ - **Layout-stable by default** — hidden content reserves space (`opacity: 0` / `visibility: hidden`, not `display: none`).
36
+ - **Ephemeral when requested** — add `ephemeral` to render hidden content as `null`, so it reserves no layout space. Presenter previews still show a muted ghost.
35
37
  - **Default effect** — fade-in. Customize with `className` and Tailwind/CSS.
38
+ - Optional `name="..."` gives a reveal a slide-local target for `RevealWith`.
39
+
40
+ ## RevealWith
41
+
42
+ Use `RevealWith` when content should appear at the same step as another reveal,
43
+ code highlight, group item, Magic Code state, or custom `TimelineSteps` state.
44
+ It never adds a new step.
45
+
46
+ ````mdx
47
+ import { Reveal, RevealWith } from '@honeydeck/honeydeck'
48
+
49
+ <Reveal name="headline">Headline appears first</Reveal>
50
+ <RevealWith target="headline">Supporting detail appears with it</RevealWith>
51
+
52
+ ```ts {1|2|3}
53
+ const answer = 42
54
+ console.log(answer)
55
+ ```
56
+
57
+ <RevealWith at={2}>This appears with the second slide step</RevealWith>
58
+ ````
59
+
60
+ Rules:
61
+
62
+ - Use exactly one of `target="name"` or `at={n}`.
63
+ - `target` points to a same-slide `<Reveal name="name">`; forward references work.
64
+ - `at` is a 1-based slide-local step and can target any existing timeline step.
65
+ - `name`, `target`, and `at` must be literal values so Honeydeck can validate them at build time.
66
+
67
+ ## Fade
68
+
69
+ `Fade` is the inverse of `Reveal`: content starts visible and fades out at its timeline step.
70
+
71
+ ```mdx
72
+ import { Fade } from '@honeydeck/honeydeck'
73
+
74
+ <Fade>Visible at step 0, gone at step 1</Fade>
75
+ <Fade ephemeral>Gone at step 2 and no longer reserves space</Fade>
76
+ ```
77
+
78
+ Behavior:
79
+
80
+ - Visible while `stepIndex < at`.
81
+ - Hidden while `stepIndex >= at`.
82
+ - Hidden content reserves layout space by default.
83
+ - With `ephemeral`, hidden content renders `null` and reserves no layout space.
84
+ - Fade content must not contain nested timeline producers. Put `Fade` inside `Reveal`, not `Reveal` inside `Fade`.
85
+
86
+ ## FadeWith
87
+
88
+ Use `FadeWith` for a fade-out controlled by an explicit target step or named reveal target without adding its own timeline step:
89
+
90
+ ```mdx
91
+ import { FadeWith } from '@honeydeck/honeydeck'
92
+
93
+ <FadeWith target={3}>Disappears when step 3 is active</FadeWith>
94
+ <FadeWith at={2}>Disappears with slide step 2</FadeWith>
95
+ ```
96
+
97
+ `FadeWith` never increments the slide step count. It uses the same `target`/`at` validation rules as `RevealWith`.
36
98
 
37
99
  ## RevealGroup
38
100
 
39
101
  Reveals each direct child as its own step. If a direct child is a list, each
40
- list item is revealed as its own step:
102
+ top-level list item is revealed as its own step:
41
103
 
42
104
  ```mdx
43
105
  import { RevealGroup } from '@honeydeck/honeydeck'
@@ -49,7 +111,20 @@ import { RevealGroup } from '@honeydeck/honeydeck'
49
111
  </RevealGroup>
50
112
  ```
51
113
 
52
- To reveal multiple elements together, wrap them in a single `Reveal` instead.
114
+ Set `listRevealMode="nested"` to reveal nested list items depth-first:
115
+
116
+ ```mdx
117
+ <RevealGroup listRevealMode="nested">
118
+ - Parent
119
+ - Child A
120
+ - Child B
121
+ - Sibling
122
+ </RevealGroup>
123
+ ```
124
+
125
+ Timeline: parent → child A → child B → sibling. The default `"direct"` mode keeps nested items grouped with their parent.
126
+
127
+ To reveal multiple elements together, wrap them in a single `Reveal` instead. Add `ephemeral` to the group when hidden generated children should not reserve layout space.
53
128
 
54
129
  Nested reveals and code walkthroughs work inside group items:
55
130
 
@@ -76,6 +151,20 @@ Timeline:
76
151
  3. Code item appears with line 1 highlighted
77
152
  4. Code highlights line 2
78
153
 
154
+ ## FadeGroup
155
+
156
+ `FadeGroup` is the inverse of `RevealGroup`: each meaningful direct child starts visible and fades out one by one. Direct lists are preserved, and each list item gets its own fade-out step. Fade group targets must not contain nested timeline producers.
157
+
158
+ ```mdx
159
+ import { FadeGroup } from '@honeydeck/honeydeck'
160
+
161
+ <FadeGroup ephemeral>
162
+ - Remove this at step 1
163
+ - Remove this at step 2
164
+ - Remove this at step 3
165
+ </FadeGroup>
166
+ ```
167
+
79
168
  ## Custom Component Steps
80
169
 
81
170
  Use `TimelineSteps` when an imported React component should control part of
@@ -141,6 +230,52 @@ console.log(c)
141
230
  - **Dim approach:** Non-highlighted lines are dimmed (controlled by `--honeydeck-code-line-dim-opacity: 0.4`).
142
231
  - **Shiki at build time:** No runtime JS cost for syntax highlighting.
143
232
 
233
+ ## Magic Code
234
+
235
+ Magic Code animates between multiple code states while keeping the same Honeydeck timeline model. It builds on Shiki Magic Code / Shiki Magic Move and uses build-time precompiled highlighting data.
236
+
237
+ `````mdx
238
+ ````md magic-code {duration:500}
239
+ ```ts
240
+ const count = 1
241
+ ```
242
+
243
+ ```ts
244
+ const count = 2
245
+ ```
246
+ ````
247
+ `````
248
+
249
+ - The canonical Honeydeck syntax is `md magic-code`.
250
+ - `md magic-move` is accepted as a Slidev compatibility alias.
251
+ - Use `{duration:500}` to override the animation duration for one block.
252
+ - Set a deck-wide default with `magicCodeDuration: 500` in deck-level frontmatter.
253
+ - Content inside a Magic Code block that is not a fenced code block is ignored.
254
+ - Magic Code looks and copies like a normal Honeydeck code block. Copying always copies the currently visible code text.
255
+
256
+ Inner code fences keep normal code step metadata:
257
+
258
+ `````mdx
259
+ ````md magic-code
260
+ ```ts {1|2}
261
+ const a = 1
262
+ const b = 2
263
+ ```
264
+
265
+ ```ts {all}
266
+ const sum = a + b
267
+ ```
268
+ ````
269
+ `````
270
+
271
+ Timeline:
272
+
273
+ 1. First code state, line 1 highlighted
274
+ 2. First code state, line 2 highlighted
275
+ 3. Morph to second code state, all lines highlighted
276
+
277
+ Magic Code states may use different languages, but animations usually look best when all states use the same language.
278
+
144
279
  ## Mixed Timeline Example
145
280
 
146
281
  ````mdx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@honeydeck/honeydeck",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "MDX and React-based presentation framework for AI-friendly slide decks.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -80,6 +80,8 @@
80
80
  "./themes/bee.css": "./src/theme/bee.css",
81
81
  "./components": "./src/runtime/components/index.ts",
82
82
  "./components/code-block": "./src/runtime/components/CodeBlock.tsx",
83
+ "./components/code-block/normal": "./src/runtime/components/NormalCodeBlock.tsx",
84
+ "./components/code-block/magic": "./src/runtime/components/MagicCodeBlock.tsx",
83
85
  "./remark/shiki-code-blocks": "./src/remark/shiki-code-blocks.ts"
84
86
  },
85
87
  "imports": {
@@ -103,6 +105,7 @@
103
105
  "@clack/prompts": "^1.3.0",
104
106
  "@mdx-js/mdx": "^3.1.1",
105
107
  "@mdx-js/rollup": "^3.1.1",
108
+ "@shikijs/magic-move": "^4.2.0",
106
109
  "@tailwindcss/vite": "^4.3.0",
107
110
  "lucide-react": "^1.16.0",
108
111
  "pdf-lib": "^1.17.1",
package/skills/SPEC.md CHANGED
@@ -8,7 +8,7 @@ Honeydeck ships installable agent skills:
8
8
 
9
9
  - `skills/honeydeck/SKILL.md` (`honeydeck`) helps AI agents use Honeydeck correctly: MDX entrypoint, deck frontmatter, exact `---` slide separators, slide frontmatter, built-in layouts, explicit theme/CSS imports, presenter notes, steps/reveals, code blocks, PDF export, custom React components, customization, canonical package docs, and runtime reference pages.
10
10
  - `skills/presentation-writing/SKILL.md` (`presentation-writing`) gives opinionated guidance for writing great slides and delivering good presentations: audience/goal/duration discovery, storyline, one idea per slide, strong headlines, sparse visuals, speaker notes, timing, narrative flow, progressive disclosure, and review heuristics.
11
- - `skills/slidev-migration/SKILL.md` (`slidev-migration`) helps AI agents migrate presentations from Slidev/sli.dev to Honeydeck: initialize a Honeydeck project when needed, convert `slides.md` to `deck.mdx`, map Slidev frontmatter/layouts/assets/notes/reveals/scripts to Honeydeck equivalents, and flag Vue/theme features that need manual React follow-up.
11
+ - `skills/slidev-migration/SKILL.md` (`slidev-migration`) helps AI agents migrate presentations from Slidev/sli.dev to Honeydeck: initialize a Honeydeck project when needed, convert `slides.md` to `deck.mdx`, map Slidev frontmatter/layouts/assets/notes/reveals/scripts/Magic Move code blocks to Honeydeck equivalents, and flag Vue/theme features that need manual React follow-up.
12
12
 
13
13
  Expected behavior:
14
14
 
@@ -16,7 +16,7 @@ Expected behavior:
16
16
  - The `honeydeck` skill instructs agents to use Honeydeck documentation (`Readme.md` for package overview, `docs/getting-started.md` for first-run guidance, package/root `SPEC.md`, linked colocated `SPEC.md` files, `docs/deeper-dive.md`, `docs/slides.md`, `docs/steps-and-reveals.md`, `docs/customization.md`, `docs/configuration.md`, and related docs) as the source of truth when available.
17
17
  - The `honeydeck` skill documents a local docs discovery order: current project's `node_modules/@honeydeck/honeydeck`, monorepo checkout `packages/honeydeck`, package-root checkout docs, then the public docs URL.
18
18
  - The `presentation-writing` skill is framework-agnostic enough to help with presentation quality, while still working well alongside the Honeydeck skill.
19
- - The `slidev-migration` skill instructs agents to inspect existing Slidev projects, preserve source files until the user approves cleanup, initialize or merge Honeydeck starter files, migrate common Slidev syntax to Honeydeck MDX/React, and document unsupported or approximated features.
19
+ - The `slidev-migration` skill instructs agents to inspect existing Slidev projects, preserve source files until the user approves cleanup, initialize or merge Honeydeck starter files, migrate common Slidev syntax to Honeydeck MDX/React, rewrite `md magic-move` blocks to Honeydeck's canonical `md magic-code` syntax, and document unsupported or approximated features.
20
20
  - `honeydeck init` should offer to open the interactive skills installer for the generated project and make clear that accepting runs `npx skills add`.
21
21
  - `honeydeck init` and `honeydeck skill` should delegate bundled skill selection, scope selection, and agent selection to the same `npx skills add <honeydeck-package-source> --copy` flow.
22
22
  - `docs/skills.md` should document why and how to install the bundled skills, list the `honeydeck`, `presentation-writing`, and `slidev-migration` skills, and link to the Slidev migration guide for migration-specific details.
@@ -25,7 +25,7 @@ Important docs:
25
25
  - `docs/deeper-dive.md` for CLI details, feature overview, architecture, exports, and agent skills
26
26
  - root/package `SPEC.md` and linked colocated `SPEC.md` files for expected behavior
27
27
  - `docs/slides.md` for deck structure, slide separators, and multi-file decks
28
- - `docs/steps-and-reveals.md` for step-by-step reveals and code steps
28
+ - `docs/steps-and-reveals.md` for step-by-step reveals, code steps, and Magic Code
29
29
  - `docs/customization.md` for themes, layouts, custom React components, layout maps, demos, and design tokens
30
30
  - `docs/configuration.md` for frontmatter options
31
31
  - `docs/navigation.md`, `docs/mobile.md`, `docs/presenter-mode.md`, and `docs/pdf-export.md` for presenting/exporting
@@ -42,7 +42,7 @@ If the user is inside a generated Honeydeck project and package docs are not nea
42
42
  - Frontmatter may provide additional properties for the selected layout. Check layout source or docs for available properties.
43
43
  - Built-in layouts include `Blank`, `Cover`, `Default`, `Section`, `TwoCol`, `Image`, `ImageLeft`, and `ImageRight`.
44
44
  - Built-in styling is explicit: generated decks import `./styles.css`, and that file imports Honeydeck/Tailwind theme CSS.
45
- - MDX can mix Markdown, JSX, imported React components, Honeydeck components, and code blocks.
45
+ - MDX can mix Markdown, JSX, imported React components, Honeydeck components, code blocks, and Magic Code blocks.
46
46
  - Presenter notes belong in slide frontmatter when useful for narrative, timing, and delivery cues.
47
47
  - Use reveals/steps for progressive disclosure, not for every bullet by default.
48
48
  - PDF export is available with `npx honeydeck pdf`; use `--steps all` when revealed states matter.
@@ -99,6 +99,7 @@ import { Reveal, RevealGroup, TimelineSteps, Notes, BrowserFrame } from '@honeyd
99
99
 
100
100
  - Keep normal fenced code blocks.
101
101
  - Convert common Slidev stepped highlights like `{1|2|3}` to Honeydeck-supported code step metadata when possible. If unsure, preserve the fence and leave a TODO comment near the block.
102
+ - Convert Slidev Magic Move code blocks (`md magic-move`) to Honeydeck's canonical Magic Code syntax (`md magic-code`). Preserve inner fenced code blocks and their line-highlight metadata. Honeydeck accepts `md magic-move` as a compatibility alias, but migrated decks should use `md magic-code`.
102
103
  - Slidev Monaco/live-code features need manual React components or simplified static code.
103
104
 
104
105
  ### Vue to React conversion
package/src/SPEC.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  ```ts
10
10
  // Core components
11
- import { Reveal, RevealGroup, TimelineSteps, ListStyle, Keyboard, BrowserFrame, Notes, ColorModeImage } from '@honeydeck/honeydeck'
11
+ import { Reveal, RevealWith, RevealGroup, Fade, FadeWith, FadeGroup, TimelineSteps, ListStyle, Keyboard, BrowserFrame, Notes, ColorModeImage } from '@honeydeck/honeydeck'
12
12
 
13
13
  // Types for kit authors
14
14
  import type { LayoutProps, LayoutMap, LayoutDemo } from '@honeydeck/honeydeck/types'
@@ -45,7 +45,11 @@ import {
45
45
  // Public component barrel
46
46
  import {
47
47
  Reveal as BarrelReveal,
48
+ RevealWith as BarrelRevealWith,
48
49
  RevealGroup as BarrelRevealGroup,
50
+ Fade as BarrelFade,
51
+ FadeWith as BarrelFadeWith,
52
+ FadeGroup as BarrelFadeGroup,
49
53
  TimelineSteps as BarrelTimelineSteps,
50
54
  ListStyle as BarrelListStyle,
51
55
  Keyboard as BarrelKeyboard,
@@ -55,8 +59,9 @@ import {
55
59
  } from '@honeydeck/honeydeck/components'
56
60
  import type { ColorMode } from '@honeydeck/honeydeck/components'
57
61
 
58
- // Reserved injected component (generated by Honeydeck remark plugins; not intended for manual slide author use)
59
- import { HoneydeckCodeBlock } from '@honeydeck/honeydeck/components/code-block'
62
+ // Reserved injected components (generated by Honeydeck remark plugins; not intended for manual slide author use)
63
+ import { HoneydeckCodeBlock } from '@honeydeck/honeydeck/components/code-block/normal'
64
+ import { HoneydeckMagicCodeBlock } from '@honeydeck/honeydeck/components/code-block/magic'
60
65
  ```
61
66
 
62
67
  ### Type Definitions
package/src/cli/SPEC.md CHANGED
@@ -214,8 +214,9 @@ PDF color mode resolves in this order:
214
214
 
215
215
  ### Step Handling
216
216
 
217
- - `pdfSteps: final` — each slide appears once, all reveals visible, code at final highlight
218
- - `pdfSteps: all` — step `0` through final step state are separate PDF pages
217
+ - `pdfSteps: final` — each slide appears once, all reveals visible, code at final highlight, and Magic Code at final code state/final highlight
218
+ - `pdfSteps: all` — step `0` through final step state are separate PDF pages, including Magic Code line-highlight states and morph states
219
+ - Magic Code is captured at the requested state, not mid-transition; PDF export disables Magic Move animation while preserving the selected timeline state
219
220
  - Capture order is slide order first; in `pdfSteps: all`, step states ascend within each slide. Parallel capture must not change this final PDF page order.
220
221
  - During `pdfSteps: final`, `useTimeline()` and `useTimelineSteps()` expose
221
222
  `isPdfFinalRender: true` so custom step-driven components can render an
package/src/cli/pdf.ts CHANGED
@@ -86,6 +86,10 @@ const __dirname = dirname(__filename);
86
86
  const FINAL_STEP_INDEX = 999;
87
87
  const MAX_PDF_CAPTURE_CONCURRENCY = 16;
88
88
 
89
+ function buildPdfRenderQuery(isPdfFinalRender: boolean): string {
90
+ return `?honeydeckPdfRender=${isPdfFinalRender ? "final" : "step"}`;
91
+ }
92
+
89
93
  // ---------------------------------------------------------------------------
90
94
  // Arg parsing
91
95
  // ---------------------------------------------------------------------------
@@ -342,7 +346,7 @@ function startStaticServer(dir: string): Promise<StaticServer> {
342
346
  * counts are identical to what the runtime reports.
343
347
  */
344
348
  async function getStepCounts(entryPath: string): Promise<number[]> {
345
- const { slides } = loadDeck(entryPath);
349
+ const { deckFrontmatter, slides } = loadDeck(entryPath);
346
350
 
347
351
  const counts: number[] = [];
348
352
 
@@ -353,7 +357,10 @@ async function getStepCounts(entryPath: string): Promise<number[]> {
353
357
  remarkFrontmatter,
354
358
  remarkH1Extract,
355
359
  remarkStepNumbering,
356
- remarkShikiCodeBlocks,
360
+ [
361
+ remarkShikiCodeBlocks,
362
+ { magicCodeDuration: deckFrontmatter.magicCodeDuration },
363
+ ],
357
364
  ],
358
365
  jsxImportSource: "react",
359
366
  outputFormat: "program",
@@ -498,7 +505,7 @@ async function captureSlide(
498
505
  getPageError: () => Error | null,
499
506
  ): Promise<Buffer> {
500
507
  if (firstLoad) {
501
- const pdfRenderQuery = isPdfFinalRender ? "?honeydeckPdfRender=final" : "";
508
+ const pdfRenderQuery = buildPdfRenderQuery(isPdfFinalRender);
502
509
 
503
510
  // Full navigation: boots the SPA and waits for network to settle.
504
511
  await page.goto(`${serverUrl}/${pdfRenderQuery}#/${slide}/${step}`, {
@@ -537,7 +544,7 @@ async function prepareCapturePage(
537
544
  isPdfFinalRender: boolean,
538
545
  getPageError: () => Error | null,
539
546
  ): Promise<void> {
540
- const pdfRenderQuery = isPdfFinalRender ? "?honeydeckPdfRender=final" : "";
547
+ const pdfRenderQuery = buildPdfRenderQuery(isPdfFinalRender);
541
548
 
542
549
  await page.goto(`${serverUrl}/${pdfRenderQuery}#/1/0`, {
543
550
  waitUntil: "networkidle",
@@ -180,7 +180,7 @@ Building the future of presentations.`,
180
180
  }
181
181
  ```
182
182
 
183
- `mdx` is required on `LayoutDemo` and is the single source for both the live visual preview and the copyable snippet shown in the layouts docs tab. Honeydeck compiles this MDX with the same slide MDX compiler family, extracts frontmatter/title/steps from it, and renders the resulting slide through the active layout map. Honeydeck statically crawls analyzable active layout maps at build time and discovers colocated `demo` exports from layout modules. Dynamic maps, computed entries, non-static imports, and demos whose `mdx` value is not a static string may be skipped with warnings. If no static MDX demo is discovered, the layout still appears in the reference pages with a "No demo MDX provided" hint.
183
+ `mdx` is required on `LayoutDemo` and is the single source for both the live visual preview and the copyable snippet shown in the layouts docs tab. Honeydeck compiles this MDX with the same slide MDX compiler family, extracts frontmatter/title/steps from it, and renders the resulting slide through the active layout map. Honeydeck statically crawls analyzable active layout maps at build time and discovers colocated `demo` exports from layout modules. Analyzable map entries include direct static imports, named imports from layout barrels, spread static default imports, and static member references into an imported layout map such as `Default: defaultLayouts.Default`. Dynamic maps, computed entries, non-static imports, and demos whose `mdx` value is not a static string may be skipped with warnings. If no static MDX demo is discovered, the layout still appears in the reference pages with a "No demo MDX provided" hint.
184
184
 
185
185
  ### TwoCol Slot Components
186
186
 
@@ -1,6 +1,22 @@
1
1
  # Honeydeck Remark Transform Specification
2
2
 
3
- > Observable behavior for code highlighting transforms.
3
+ > Observable behavior for timeline annotation and code highlighting transforms.
4
+
5
+ ## Timeline Step Annotation
6
+
7
+ Honeydeck's remark pipeline assigns slide-local timeline metadata to built-in components before MDX is compiled.
8
+
9
+ Behavior:
10
+
11
+ - `<Reveal>` consumes one timeline step in document order and receives an internal `at` prop for runtime visibility. Author-authored `at` on `<Reveal>` is a compile error; use `<RevealWith at={n}>` for same-step synchronization.
12
+ - `<RevealGroup>` consumes one step per meaningful direct child/list item, including nested timeline gaps, and receives internal `at`/target metadata for runtime visibility. Author-authored `at` on `<RevealGroup>` is a compile error; use `<RevealWith at={n}>` for same-step synchronization.
13
+ - `<RevealWith>` consumes no timeline steps. It receives an internal resolved `at` prop based on either a same-slide `<Reveal name="...">` target or a literal numeric `at={n}` target.
14
+ - Named reveal targets are slide-local. Duplicate `<Reveal name="...">` values on the same slide are compile errors; reuse across slides is allowed.
15
+ - `<RevealWith target="...">` supports forward references to named reveals anywhere on the same slide.
16
+ - `<RevealWith>` requires exactly one of `target` or `at`; both and neither are compile errors.
17
+ - `Reveal` `name`, `RevealWith` `target`, and `RevealWith` `at` must be literal values. Empty names/targets, non-positive numeric `at`, and numeric `at` values greater than the slide's final step count are compile errors.
18
+ - `RevealWith at={n}` can target any existing slide timeline step, including code, Magic Code, `RevealGroup`, and `TimelineSteps` steps.
19
+ - Flow/block usages of `<Reveal>` and `<RevealWith>` receive an internal block wrapper marker; text/inline usages receive an internal inline wrapper marker so compiled HTML remains valid.
4
20
 
5
21
  ## Code Highlighting
6
22
 
@@ -34,15 +50,99 @@ Syntax:
34
50
  - Each active code group highlights only the specified lines (non-cumulative)
35
51
  - Non-highlighted lines are dimmed (`--honeydeck-code-line-dim-opacity`)
36
52
  - Dimming is applied by Honeydeck runtime markup/styles independently of Tailwind utility generation
37
- - Code steps participate in the same slide timeline as `Reveal` components
53
+ - Code steps participate in the same slide timeline as `Reveal`, `Fade`, `RevealGroup`, and `FadeGroup` components
54
+ - `RevealWith` and `FadeWith` never add timeline steps; they only watch existing steps through `target`
55
+ - `RevealWith`, `FadeWith`, `Fade`, and `FadeGroup` targets reject nested timeline producers
38
56
  - Unsupported/failed languages render as plain code using Honeydeck CSS tokens
39
57
  - Code blocks expose a hover/focus copy control that copies the original fenced code text, not the highlighted HTML
40
58
 
59
+ ## Magic Code
60
+
61
+ Honeydeck supports **Magic Code** as built-in Markdown syntax for animated transitions between code states. Magic Code builds on Shiki Magic Code / Shiki Magic Move, but Honeydeck precompiles the highlighted token data at build time.
62
+
63
+ Canonical syntax:
64
+
65
+ `````mdx
66
+ ````md magic-code {duration:500}
67
+ ```ts
68
+ const count = 1
69
+ ```
70
+
71
+ ```ts
72
+ const count = 2
73
+ ```
74
+ ````
75
+ `````
76
+
77
+ Compatibility alias:
78
+
79
+ `````mdx
80
+ ````md magic-move
81
+ ```ts
82
+ const count = 1
83
+ ```
84
+
85
+ ```ts
86
+ const count = 2
87
+ ```
88
+ ````
89
+ `````
90
+
91
+ Rules:
92
+
93
+ - Magic Code is triggered only by an outer `md` fence whose first metadata token is `magic-code` or `magic-move`.
94
+ - `magic-code` is Honeydeck's canonical syntax. `magic-move` is a silent compatibility alias for Slidev migration.
95
+ - Documentation and generated examples use `magic-code`.
96
+ - The only supported block option is `{duration:<number>}` in milliseconds.
97
+ - Duration resolution is block option, then deck-level `magicCodeDuration`, then Honeydeck default `800`.
98
+ - Slide-level frontmatter does not configure Magic Code.
99
+ - Unknown outer extras/options are ignored. An explicit invalid `duration` is a compile error.
100
+ - Only inner fenced code blocks produce output. Other Markdown inside the Magic Code block is ignored.
101
+ - Zero inner code fences render nothing and add no timeline steps.
102
+ - One inner code fence renders one code state with normal Honeydeck code highlighting/step behavior.
103
+ - Two or more inner code fences render one animated code block backed by build-time precompiled Shiki Magic Move token data for Honeydeck's built-in light and dark syntax themes.
104
+ - Inner code fences keep normal Honeydeck code fence behavior, including language selection and line-highlight metadata.
105
+ - Inner code fences may use different languages, though animations are expected to look best when states use the same language.
106
+ - Magic Code uses the same visual treatment and copy affordance as normal Honeydeck code blocks.
107
+ - Copying copies the currently visible code text. Highlight-only steps copy the same code text; morph steps copy the active state's code text.
108
+
109
+ Timeline behavior:
110
+
111
+ - Each inner code fence contributes its normal line-highlight states.
112
+ - Magic Code advances through the current code state's line-highlight groups before morphing to the next code state.
113
+ - The target state's baseline line highlight is active immediately when the morph state becomes current.
114
+ - `total timeline states = sum(inner fence highlight groups)`.
115
+ - `timeline steps added = total timeline states - 1`.
116
+
117
+ Example:
118
+
119
+ `````mdx
120
+ ````md magic-code
121
+ ```ts {1|2}
122
+ const a = 1
123
+ const b = 2
124
+ ```
125
+
126
+ ```ts {all}
127
+ const sum = a + b
128
+ ```
129
+ ````
130
+ `````
131
+
132
+ Timeline:
133
+
134
+ 1. First code state, line 1 highlighted
135
+ 2. First code state, line 2 highlighted
136
+ 3. Morph to second code state, all lines highlighted
137
+
41
138
  ### Visual Style
42
139
 
43
140
  - Highlighted lines: normal brightness
44
141
  - Non-highlighted lines: dimmed (reduced opacity)
45
142
  - No background stripe
143
+ - Magic Code uses the same code block surface, syntax colors, typography, light/dark behavior, and copy button as normal code blocks
144
+ - Honeydeck ships the Shiki Magic Move transition CSS through its base theme CSS; deck authors do not import Magic Move CSS manually
145
+ - Magic Code does not render filename/title chrome in v1
46
146
 
47
147
  ### Theme
48
148