presently 0.14.0 → 0.15.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46e3cc47613d0f667aeead379bdb8ed4c311ae9375c08ca32ceeeca4d57b5919
4
- data.tar.gz: d4bf90e706c3a358a30937a3589f493a9c42f70a87babf9cc976407714124b98
3
+ metadata.gz: 42f99b653f49a0ac23d4c6b49314cde4ef814e70a7d274c7d67914e4f707514d
4
+ data.tar.gz: f308373c9741dad960682283d52df1d34e285e32e0c9155cd0911d3e62405562
5
5
  SHA512:
6
- metadata.gz: 07702bbfa6107d4ee4554015450a7008d09d69e6e2c7486a5b5aa6d94b7b15ba188557810634e8fca79bbadcc450793b7d36f01c6878cf04f9d0fe7a74f77de9
7
- data.tar.gz: 6b31a696453ce2a9d9adf6fe3b084a4aba9a20a23f4535b3582fab49af4999e62cebe41389cacc3ce7d9227bf0653365b2009892377cb09e20396bfa02a9d204
6
+ metadata.gz: 48116005297631e4fbdc4d06c1b83cfadb847d61dcb03ea60e603af4c28d9d0e678539fe114fbf6ce4f12e0fbc590281094e7fa40c2be003e9d488be31a25516
7
+ data.tar.gz: ed77bebb4005f828ab6b09c321cf075778a394706f0ff0bd6ffc2e2852e3c73ac2da3944e1ad7744cb82e3546702d0f81c4a966acc346f9c374b032f29100df9
checksums.yaml.gz.sig CHANGED
Binary file
@@ -50,12 +50,15 @@ def pdf(output: "presentation.pdf", slides_root: "slides", notes: true, speaker:
50
50
  begin
51
51
  environment = Async::Service::Environment.build(
52
52
  Presently::Environment::Application,
53
- root: context.root,
54
- slides_root: File.expand_path(slides_root, context.root),
53
+ root: Dir.pwd,
54
+ slides_root: slides_root,
55
55
  endpoint: Async::HTTP::Endpoint.parse("http://localhost", bound_endpoint)
56
56
  )
57
57
 
58
- evaluator = environment.evaluator
58
+ # PDF export always requires an HTTP server, regardless of the configured
59
+ # Lively transport:
60
+ transport = environment.with(environment.evaluator.http_environment)
61
+ evaluator = transport.evaluator
59
62
  server = evaluator.make_server(evaluator.endpoint)
60
63
  server_task = task.async{server.run}
61
64
 
@@ -0,0 +1,254 @@
1
+ # Animating Slides
2
+
3
+ This guide explains how to animate content within slides using the slide scripting system.
4
+
5
+ ## Slide Scripts
6
+
7
+ Any slide can include a JavaScript block at the end of its presenter notes section. The script runs in the browser immediately after the slide renders.
8
+
9
+ ~~~ markdown
10
+ ---
11
+ template: default
12
+ duration: 30
13
+ ---
14
+
15
+ - First point
16
+ - Second point
17
+ - Third point
18
+
19
+ ---
20
+
21
+ Your presenter notes here.
22
+
23
+ ```javascript
24
+ slide.find("li").show(1)
25
+ ```
26
+ ~~~
27
+
28
+ The script receives a `slide` object — an instance of the `Slide` class from `slide.js` — scoped to the current slide's body.
29
+
30
+ If the script contains a syntax error or throws an exception, the error is logged to the browser console and the presentation continues unaffected.
31
+
32
+ ## The Slide API
33
+
34
+ ### `slide.find(selector)`
35
+
36
+ Queries elements within the slide body matching the given CSS selector. Returns a `SlideElements` collection. This is a pure query with no side effects.
37
+
38
+ ``` javascript
39
+ slide.find("li") // all list items
40
+ slide.find("h2, li") // headings and list items in document order
41
+ slide.find(".callout") // elements with a specific class
42
+ ```
43
+
44
+ ### `elements.show(n, options)`
45
+
46
+ Shows the first `n` elements in the collection and hides the rest. Returns a `Promise` that resolves when any reveal animation completes.
47
+
48
+ ``` javascript
49
+ slide.find("li").show(0) // all hidden
50
+ slide.find("li").show(1) // first visible, rest hidden
51
+ slide.find("li").show(3) // first three visible, rest hidden
52
+ ```
53
+
54
+ Options:
55
+
56
+ | Option | Description |
57
+ |---|---|
58
+ | `effect` | Entry animation for the newly revealed element. See effects below. |
59
+
60
+ ### `elements.builder(options)`
61
+
62
+ Creates a `SlideBuilder` with default options and a cached position. Use this instead of calling `show()` manually when you want to reveal elements one at a time from a script.
63
+
64
+ ``` javascript
65
+ const bullets = slide.find("li").builder({effect: "fly-up"})
66
+ bullets.show(0) // hide all initially
67
+ bullets.next() // reveal first, plays fly-up
68
+ bullets.next() // reveal second, plays fly-up
69
+ bullets.finished // true when all revealed
70
+ ```
71
+
72
+ ### `SlideBuilder#next(overrides)`
73
+
74
+ Reveals the next element using the builder's default effect. Only touches the single newly revealed element — O(1). Returns a `Promise`. Accepts optional overrides for this step.
75
+
76
+ ### `SlideBuilder#show(n, overrides)`
77
+
78
+ Sets the builder to an arbitrary position. Useful for initialization and jumping. Iterates all elements for correctness.
79
+
80
+ ### `SlideBuilder#play(interval, callback)`
81
+
82
+ Reveals all remaining elements in sequence, with `interval` milliseconds between each step. An optional callback is invoked after each `next()` — return `false` to stop playback early. Requires the builder to be created via `slide.find(...).builder()` so that timeouts are tracked and cancelled when the slide changes.
83
+
84
+ ``` javascript
85
+ // Play all elements at 400ms intervals:
86
+ boxes.play(400)
87
+
88
+ // Stop early based on a condition:
89
+ boxes.play(400, () => !paused)
90
+
91
+ // Inspect the builder after each step:
92
+ boxes.play(400, (builder) => !builder.finished)
93
+ ```
94
+
95
+ ### `SlideBuilder#finished`
96
+
97
+ Returns `true` when all elements have been revealed.
98
+
99
+ ## Build Sequences
100
+
101
+ A build sequence is a series of consecutive slides with the same content, each revealing one more element. Because the slides are real files, each has its own duration and presenter notes — you can write exactly what to say when each element appears.
102
+
103
+ ~~~ markdown
104
+ <!-- 030-overview.md -->
105
+ ---
106
+ template: default
107
+ duration: 20
108
+ transition: fade
109
+ ---
110
+
111
+ - Real-time synchronization
112
+ - Markdown-based slides
113
+ - Multiple templates
114
+
115
+ ---
116
+
117
+ Let's walk through the key features.
118
+
119
+ ```javascript
120
+ slide.find("li").show(0)
121
+ ```
122
+ ~~~
123
+
124
+ ~~~ markdown
125
+ <!-- 031-overview.md -->
126
+ ---
127
+ template: default
128
+ duration: 20
129
+ transition: fade
130
+ ---
131
+
132
+ - Real-time synchronization
133
+ - Markdown-based slides
134
+ - Multiple templates
135
+
136
+ ---
137
+
138
+ The display and presenter stay in sync over a WebSocket connection.
139
+
140
+ ```javascript
141
+ slide.find("li").show(1)
142
+ ```
143
+ ~~~
144
+
145
+ Because all elements are in the DOM from the start (just hidden), the vertical layout stays consistent throughout the sequence — there is no shift as elements appear.
146
+
147
+ ## Build Effects
148
+
149
+ Pass an `effect` option to animate the newly revealed element as it appears. The effect plays as a CSS animation on the element and is removed automatically once it completes.
150
+
151
+ ``` javascript
152
+ slide.find("li").show(2, {effect: "fly-up"})
153
+ ```
154
+
155
+ Available effects:
156
+
157
+ | Effect | Animation |
158
+ |---|---|
159
+ | `fade` | Fades in |
160
+ | `fly-left` | Slides in from the left |
161
+ | `fly-right` | Slides in from the right |
162
+ | `fly-up` | Rises in from below |
163
+ | `fly-down` | Drops in from above |
164
+ | `scale` | Scales up from 80% |
165
+
166
+ ## Multiple Build Groups
167
+
168
+ A slide can have multiple independent build groups. Each `find().show()` call is self-contained:
169
+
170
+ ``` javascript
171
+ // Reveal list items as one group, callout div as another
172
+ slide.find("li").show(3)
173
+ slide.find(".callout").show(1, {effect: "fly-up"})
174
+ ```
175
+
176
+ ## In-Slide Animation with `slide.after()`
177
+
178
+ For sequential reveals within a single slide (without navigating to the next slide), use `slide.after()`. Each step fires a delay in milliseconds relative to the previous step. Returns a `SlideContext` so subsequent `.after()` calls chain naturally.
179
+
180
+ ``` javascript
181
+ const panes = slide.find(".pane").builder({effect: "fade"})
182
+ const items = slide.find(".item").builder({effect: "fly-up"})
183
+ panes.show(0)
184
+ items.show(0)
185
+
186
+ slide
187
+ .after(400, () => panes.next())
188
+ .after(400, () => items.next())
189
+ .after(300, () => items.next())
190
+ .after(400, () => panes.next())
191
+ ```
192
+
193
+ All timeouts registered via `slide.after()` (and the underlying `slide.setTimeout()`) are automatically cancelled when the user navigates to another slide, so stale callbacks never fire.
194
+
195
+ The global `setTimeout` in slide scripts is also automatically tracked — you can use it directly and it will be cancelled on slide change.
196
+
197
+ ## Looping Animations with `slide.loop()`
198
+
199
+ To repeat an animation indefinitely, use `slide.loop()`. The callback receives a fresh `SlideContext` each iteration and can use `after()` to schedule steps in the same way as a regular chain. The loop waits for all steps to complete and then restarts, with an optional extra pause between iterations.
200
+
201
+ ``` javascript
202
+ const steps = slide.find(".step").builder({effect: "fly-up"})
203
+ steps.show(0)
204
+
205
+ slide.loop((context) => {
206
+ steps.show(0) // reset at the start of each iteration
207
+ context
208
+ .after(800, () => steps.next())
209
+ .after(800, () => steps.next())
210
+ .after(800, () => steps.next())
211
+ }, { delay: 1500 })
212
+ ```
213
+
214
+ The `delay` option adds extra time after the last step before the next iteration begins — useful for giving the audience a moment to read the fully-revealed state before it resets.
215
+
216
+ The callback is responsible for resetting any state (such as calling `builder.show(0)`) at the start of each iteration. This keeps the loop body self-contained and makes the reset timing explicit.
217
+
218
+ All timeouts are tracked through the parent slide, so the loop stops automatically when the user navigates away — no cleanup needed.
219
+
220
+ ## Absolutely Positioned Elements
221
+
222
+ All slide templates support absolutely positioned elements since the slide container is `position: relative`. You can overlay any element on top of normal slide content:
223
+
224
+ ~~~ markdown
225
+ <div style="position: absolute; bottom: 2rem; right: 2rem; background: var(--accent); color: white; padding: 0.5rem 1rem; border-radius: 6px;">
226
+ Callout text
227
+ </div>
228
+ ~~~
229
+
230
+ In the `diagram` template, all direct `<div>` children are `position: absolute` by default, so you can build free-form layouts without repeating the positioning declaration:
231
+
232
+ ~~~ markdown
233
+ ---
234
+ template: diagram
235
+ ---
236
+
237
+ <div style="left: 10%; top: 20%; width: 35%; height: 30%; background: var(--surface-light);">
238
+ Node A
239
+ </div>
240
+
241
+ <div style="left: 55%; top: 20%; width: 35%; height: 30%; background: var(--surface-light);">
242
+ Node B
243
+ </div>
244
+ ~~~
245
+
246
+ Combine with the scripting system to animate diagram elements into place:
247
+
248
+ ``` javascript
249
+ const nodes = slide.find("div").builder({group: "node", effect: "fade"})
250
+ nodes.show(0)
251
+ slide
252
+ .after(400, () => nodes.next())
253
+ .after(400, () => nodes.next())
254
+ ```
@@ -0,0 +1,321 @@
1
+ # Getting Started
2
+
3
+ This guide explains how to use `presently` to create and deliver web-based presentations using Markdown slides.
4
+
5
+ ## Installation
6
+
7
+ Add the gem to your project:
8
+
9
+ ``` bash
10
+ $ gem install presently
11
+ ```
12
+
13
+ ## Core Concepts
14
+
15
+ Presently has several core concepts:
16
+
17
+ - A {ruby Presently::Presentation} which loads and manages slide content from Markdown files.
18
+ - A {ruby Presently::PresentationController} which manages the mutable state of a presentation: current slide, clock, and listeners.
19
+ - A {ruby Presently::Slide} which represents a single slide parsed from a Markdown file with YAML frontmatter.
20
+ - A {ruby Presently::DisplayView} which renders the audience-facing full-screen display.
21
+ - A {ruby Presently::PresenterView} which renders the presenter console with notes, timing, and slide previews.
22
+
23
+ ## Creating Your First Presentation
24
+
25
+ Create a new directory for your presentation:
26
+
27
+ ``` bash
28
+ $ mkdir my-talk
29
+ $ cd my-talk
30
+ $ mkdir slides
31
+ ```
32
+
33
+ ### Writing Slides
34
+
35
+ Each slide is a Markdown file in the `slides/` directory. Files are ordered alphabetically, so prefix them with numbers:
36
+
37
+ ``` markdown
38
+ ---
39
+ template: title
40
+ duration: 30
41
+ ---
42
+
43
+ # Title
44
+
45
+ Welcome to My Talk
46
+
47
+ # Subtitle
48
+
49
+ A presentation built with Presently
50
+
51
+ ---
52
+
53
+ These are presenter notes — only visible in the presenter view.
54
+ ```
55
+
56
+ Each slide has three parts:
57
+
58
+ 1. **YAML frontmatter** between `---` markers at the top, specifying the template, duration, and other metadata.
59
+ 2. **Content** with Markdown headings that become named sections for the template.
60
+ 3. **Presenter notes** after a `---` separator in the body (optional).
61
+
62
+ ### Running the Presentation
63
+
64
+ Start the server from your presentation directory:
65
+
66
+ ``` bash
67
+ $ presently
68
+ ```
69
+
70
+ Then open two browser windows:
71
+
72
+ - `http://localhost:9292/` — the audience display.
73
+ - `http://localhost:9292/presenter` — the presenter console.
74
+
75
+ Advancing slides in either window updates both in real-time via WebSockets.
76
+
77
+ ### Keyboard Controls
78
+
79
+ - **Arrow Right / Space / Page Down** — next slide.
80
+ - **Arrow Left / Page Up** — previous slide.
81
+ - **F** — toggle full-screen (display view).
82
+
83
+ ## Templates
84
+
85
+ Templates define the visual layout of each slide. Select a template using the `template` field in the frontmatter.
86
+
87
+ ### Default
88
+
89
+ A general-purpose content slide. All content without a heading goes into the `body` section.
90
+
91
+ ``` markdown
92
+ ---
93
+ template: default
94
+ duration: 60
95
+ ---
96
+
97
+ - First point
98
+ - Second point
99
+ - Third point
100
+ ```
101
+
102
+ ### Title
103
+
104
+ A large title with a subtitle, centered on the slide.
105
+
106
+ ``` markdown
107
+ ---
108
+ template: title
109
+ duration: 30
110
+ ---
111
+
112
+ # Title
113
+
114
+ My Presentation Title
115
+
116
+ # Subtitle
117
+
118
+ A subtitle or tagline
119
+ ```
120
+
121
+ ### Section
122
+
123
+ A section divider slide with a large heading and accent background.
124
+
125
+ ``` markdown
126
+ ---
127
+ template: section
128
+ duration: 15
129
+ ---
130
+
131
+ # Heading
132
+
133
+ Part Two
134
+ ```
135
+
136
+ ### Two Column
137
+
138
+ A side-by-side layout with `left` and `right` sections.
139
+
140
+ ``` markdown
141
+ ---
142
+ template: two_column
143
+ duration: 90
144
+ ---
145
+
146
+ # Left
147
+
148
+ **Server Side**
149
+
150
+ - Ruby + Lively
151
+ - WebSocket connections
152
+
153
+ # Right
154
+
155
+ **Client Side**
156
+
157
+ - Live DOM updates
158
+ - CSS animations
159
+ ```
160
+
161
+ ### Code
162
+
163
+ A syntax-highlighted code slide with optional focus regions for code walkthroughs. Use the `focus` frontmatter to specify which lines to highlight (1-based). Lines outside the focus range are dimmed, and the code scrolls to center the focused region.
164
+
165
+ ``` markdown
166
+ ---
167
+ template: code
168
+ duration: 60
169
+ focus: 2-8
170
+ title: Constructor
171
+ ---
172
+
173
+ ```ruby
174
+ class Presentation
175
+ def initialize
176
+ @slides = []
177
+ @current_index = 0
178
+ end
179
+
180
+ def advance!
181
+ @current_index += 1
182
+ end
183
+ end
184
+ ​```
185
+ ```
186
+
187
+ Create animated walkthroughs by using multiple slides with the same code but different `focus` ranges. The transition between them smoothly scrolls and shifts the dim overlays.
188
+
189
+ ### Statement
190
+
191
+ A prominent statement or quote, centered on the slide. Supports an optional `# Translation` section.
192
+
193
+ ``` markdown
194
+ ---
195
+ template: statement
196
+ duration: 30
197
+ ---
198
+
199
+ The best way to predict the future is to create it.
200
+
201
+ # Translation
202
+
203
+ 未来を予測する最善の方法は、それを創ることである。
204
+ ```
205
+
206
+ ### Translations
207
+
208
+ All templates support an optional `# Translation` section. When present, the translation is displayed below the main content in a lighter style. This works with `title`, `section`, `statement`, and `image` templates.
209
+
210
+ ### Image
211
+
212
+ A centered image with an optional caption.
213
+
214
+ ``` markdown
215
+ ---
216
+ template: image
217
+ duration: 30
218
+ ---
219
+
220
+ ![Architecture diagram](/images/architecture.png)
221
+
222
+ # Caption
223
+
224
+ System architecture overview
225
+ ```
226
+
227
+ ### Diagram
228
+
229
+ A free-form layout slide with a `position: relative` container. Direct `<div>` children are `position: absolute` by default, so you can place elements precisely using inline styles. Use this for custom diagrams, annotated layouts, or any slide that doesn't fit a standard template.
230
+
231
+ ``` markdown
232
+ ---
233
+ template: diagram
234
+ duration: 60
235
+ ---
236
+
237
+ <div style="left: 10%; top: 20%; width: 35%; height: 25%;">
238
+ Browser
239
+ </div>
240
+
241
+ <div style="left: 55%; top: 20%; width: 35%; height: 25%;">
242
+ Server
243
+ </div>
244
+ ```
245
+
246
+ All other templates also support absolutely positioned overlays since the slide container is `position: relative`. This lets you add callouts, badges, or annotations on top of any template's normal content.
247
+
248
+ ## Transitions
249
+
250
+ Slides transition instantly by default. Add a `transition` key to the frontmatter to animate between slides:
251
+
252
+ ``` markdown
253
+ ---
254
+ template: default
255
+ transition: fade
256
+ ---
257
+ ```
258
+
259
+ Available transitions:
260
+
261
+ | Transition | Effect |
262
+ |---|---|
263
+ | `fade` | Crossfade between slides |
264
+ | `slide-left` | Current slide exits left, next enters from right |
265
+ | `slide-right` | Current slide exits right, next enters from left |
266
+
267
+ ## Presenter Notes
268
+
269
+ Presenter notes appear after a `---` separator in the slide body. They support standard Markdown including **bold** and *italic*. Italic text is styled as a stage direction — use it for cues that shouldn't be spoken aloud:
270
+
271
+ ``` markdown
272
+ ---
273
+
274
+ *Take a breath and wait for the room to settle.*
275
+
276
+ Hi everyone, thanks for being here.
277
+
278
+ *Make eye contact with the front row.*
279
+ ```
280
+
281
+ ## Presenter Console
282
+
283
+ The presenter view at `/presenter` provides:
284
+
285
+ - **Current and next slide previews** — see what's coming without switching windows.
286
+ - **Presenter notes** — notes from the slide's `---` separator section.
287
+ - **Timer controls** — Start, Pause, Resume, and Reset buttons.
288
+ - **Pacing indicator** — shows whether you're on time, ahead, or behind based on per-slide `duration` metadata.
289
+ - **Progress bar** — visual indicator of time consumed for the current slide.
290
+ - **Reload button** — reload slides from disk without restarting the server.
291
+
292
+ ## Custom Templates
293
+
294
+ You can provide your own `.xrb` template files by configuring the templates root:
295
+
296
+ ``` ruby
297
+ # In your environment configuration:
298
+ service "presently" do
299
+ include Presently::Environment::Application
300
+
301
+ def templates_root
302
+ File.expand_path("templates", self.root)
303
+ end
304
+ end
305
+ ```
306
+
307
+ Templates receive a {ruby Presently::TemplateScope} with access to `self.slide` (the {ruby Presently::Slide} instance) and `self.section(name)` for retrieving named content sections.
308
+
309
+ ## Customizing the Application
310
+
311
+ For advanced customization, create an `application.rb` and run with `presently application.rb`:
312
+
313
+ ``` ruby
314
+ #!/usr/bin/env presently
315
+
316
+ class Application < Presently::Application
317
+ def title
318
+ "My Conference Talk"
319
+ end
320
+ end
321
+ ```
@@ -0,0 +1,16 @@
1
+ # Automatically generated context index for Utopia::Project guides.
2
+ # Do not edit then files in this directory directly, instead edit the guides and then run `bake utopia:project:agent:context:update`.
3
+ ---
4
+ description: A web-based presentation tool built with Lively.
5
+ metadata:
6
+ documentation_uri: https://socketry.github.io/presently/
7
+ source_code_uri: https://github.com/socketry/presently.git
8
+ files:
9
+ - path: getting-started.md
10
+ title: Getting Started
11
+ description: This guide explains how to use `presently` to create and deliver web-based
12
+ presentations using Markdown slides.
13
+ - path: animating-slides.md
14
+ title: Animating Slides
15
+ description: This guide explains how to animate content within slides using the
16
+ slide scripting system.
@@ -20,8 +20,16 @@ module Presently
20
20
  PageSize = Struct.new(:slide_width_px, :slide_height_px, :notes_height_px, keyword_init: true) do
21
21
  PX_PER_CM = 96.0 / 2.54
22
22
 
23
+ # Convert the slide width from CSS pixels to centimetres.
24
+ # @returns [Float] The slide width in centimetres.
23
25
  def slide_width_cm = (slide_width_px / PX_PER_CM).round(4)
26
+
27
+ # Convert the slide height from CSS pixels to centimetres.
28
+ # @returns [Float] The slide height in centimetres.
24
29
  def slide_height_cm = (slide_height_px / PX_PER_CM).round(4)
30
+
31
+ # Convert the notes panel height from CSS pixels to centimetres.
32
+ # @returns [Float] The notes panel height in centimetres.
25
33
  def notes_height_cm = (notes_height_px / PX_PER_CM).round(4)
26
34
  end
27
35
 
@@ -249,7 +249,7 @@ module Presently
249
249
  end
250
250
 
251
251
  # The transition type for animating into this slide.
252
- # @returns [String | Nil] The transition name (e.g. `"fade"`, `"slide-left"`, `"morph"`), or `nil` for instant swap.
252
+ # @returns [String | Nil] The transition name (e.g. `"fade"`, `"slide-left"`, `"slide-right"`), or `nil` for instant swap.
253
253
  def transition
254
254
  @front_matter&.fetch("transition", nil)
255
255
  end
@@ -5,5 +5,5 @@
5
5
 
6
6
  # @namespace
7
7
  module Presently
8
- VERSION = "0.14.0"
8
+ VERSION = "0.15.0"
9
9
  end
@@ -364,18 +364,6 @@ html[data-transition="slide-right"]::view-transition-new(slide-container) {
364
364
  animation: vt-slide-in-left 0.4s ease-in-out;
365
365
  }
366
366
 
367
- /* Magic move — the browser interpolates position/size for matched
368
- view-transition-name elements. No cross-fade on the container
369
- to avoid background dimming. */
370
- html[data-transition="morph"]::view-transition-old(slide-container) {
371
- animation: none;
372
- opacity: 0;
373
- }
374
-
375
- html[data-transition="morph"]::view-transition-new(slide-container) {
376
- animation: none;
377
- }
378
-
379
367
  @keyframes vt-fade-out {
380
368
  from { opacity: 1; }
381
369
  to { opacity: 0; }
@@ -410,13 +398,6 @@ html[data-transition="morph"]::view-transition-new(slide-container) {
410
398
  BUILD EFFECTS
411
399
  ======================== */
412
400
 
413
- /* Suppress both pseudo-elements for hidden build elements so they
414
- neither crossfade in nor crossfade out during the transition. */
415
- ::view-transition-old(.build-hidden),
416
- ::view-transition-new(.build-hidden) {
417
- display: none;
418
- }
419
-
420
401
  /* Fade */
421
402
  .build-fade {
422
403
  animation: vt-fade-in 0.4s ease;
data/public/slide.js CHANGED
@@ -3,7 +3,6 @@
3
3
  // instead of tracking count manually. Created via SlideElements#builder(options).
4
4
  export class SlideBuilder {
5
5
  #elements;
6
- #prefix;
7
6
  #defaultEffect;
8
7
  #slide;
9
8
  #step = 0;
@@ -11,7 +10,6 @@ export class SlideBuilder {
11
10
  constructor(slide, elements, options = {}) {
12
11
  this.#slide = slide;
13
12
  this.#elements = elements;
14
- this.#prefix = options.group || 'build';
15
13
  this.#defaultEffect = options.effect || null;
16
14
  }
17
15
 
@@ -26,16 +24,8 @@ export class SlideBuilder {
26
24
  let revealedElement = null;
27
25
 
28
26
  this.#elements.forEach((element, index) => {
29
- // Only assign a group name if the element doesn't already have an explicit one.
30
- // Preserving explicit names allows elements to participate in morph transitions
31
- // to other slides while still being managed by the build system.
32
- if (!element.style.viewTransitionName || element.style.viewTransitionName === 'none') {
33
- element.style.viewTransitionName = `${this.#prefix}-${index + 1}`;
34
- }
35
-
36
27
  if (index < count) {
37
28
  element.style.visibility = 'visible';
38
- element.style.viewTransitionClass = '';
39
29
 
40
30
  if (index === count - 1 && effect) {
41
31
  element.classList.add(`build-${effect}`);
@@ -43,9 +33,6 @@ export class SlideBuilder {
43
33
  }
44
34
  } else {
45
35
  element.style.visibility = 'hidden';
46
- // Keep viewTransitionClass set so morph transitions can suppress
47
- // crossfading on hidden elements when called inside startViewTransition.
48
- element.style.viewTransitionClass = 'build-hidden';
49
36
  }
50
37
  });
51
38
 
@@ -75,11 +62,7 @@ export class SlideBuilder {
75
62
  const effect = this.#slide.animated ? (overrides.effect !== undefined ? overrides.effect : this.#defaultEffect) : null;
76
63
  const element = this.#elements[this.#step];
77
64
 
78
- if (!element.style.viewTransitionName || element.style.viewTransitionName === 'none') {
79
- element.style.viewTransitionName = `${this.#prefix}-${this.#step + 1}`;
80
- }
81
65
  element.style.visibility = 'visible';
82
- element.style.viewTransitionClass = '';
83
66
 
84
67
  this.#step += 1;
85
68
 
@@ -141,7 +124,6 @@ export class SlideElements {
141
124
 
142
125
  // Create a stateful SlideBuilder for this element collection with default options.
143
126
  // @parameter options [Object] Default options applied to every show() / next() call.
144
- // group: prefix for view-transition-name (default: "build")
145
127
  // effect: "fade", "fly-up", "fly-down", "fly-left", "fly-right", "scale"
146
128
  // @returns [SlideBuilder]
147
129
  builder(options = {}) {
@@ -152,7 +134,6 @@ export class SlideElements {
152
134
  // Delegates to SlideBuilder for the actual implementation.
153
135
  // @parameter count [Integer] Number of elements to show.
154
136
  // @parameter options [Object]
155
- // group: prefix for view-transition-name (default: "build")
156
137
  // effect: "fade", "fly-up", "fly-down", "fly-left", "fly-right", "scale"
157
138
  // @returns [Promise] Resolves when the animation completes (or immediately if no effect).
158
139
  show(count, options = {}) {
data/readme.md CHANGED
@@ -23,12 +23,19 @@ Please see the [project documentation](https://socketry.github.io/presently/) fo
23
23
 
24
24
  - [Getting Started](https://socketry.github.io/presently/guides/getting-started/index) - This guide explains how to use `presently` to create and deliver web-based presentations using Markdown slides.
25
25
 
26
- - [Animating Slides](https://socketry.github.io/presently/guides/animating-slides/index) - This guide explains how to animate content within slides using the `morph` transition and the slide scripting system.
26
+ - [Animating Slides](https://socketry.github.io/presently/guides/animating-slides/index) - This guide explains how to animate content within slides using the slide scripting system.
27
27
 
28
28
  ## Releases
29
29
 
30
30
  Please see the [project releases](https://socketry.github.io/presently/releases/index) for all releases.
31
31
 
32
+ ### v0.15.0
33
+
34
+ q
35
+
36
+ - Export works from current working directory.
37
+ - Remove explicit support for `morph` transition.
38
+
32
39
  ### v0.14.0
33
40
 
34
41
  - Increase code font size by 50%.
@@ -77,10 +84,6 @@ Please see the [project releases](https://socketry.github.io/presently/releases/
77
84
 
78
85
  - Add `bake presently:slides:speakers` task to print a timing breakdown grouped by speaker. Each speaker's slides are listed in presentation order with individual and total durations, making it easy to balance talk time in multi-speaker presentations. Slides without a `speaker` key are grouped under `(no speaker)`.
79
86
 
80
- ### v0.5.0
81
-
82
- - Add optional `speaker` front matter key to slides. When present, the current speaker's name is shown in the timing bar. If the next slide has a different speaker, a handoff indicator (e.g. `→ Next Speaker`) is shown alongside, giving presenters an at-a-glance cue for tag-team talks.
83
-
84
87
  ## See Also
85
88
 
86
89
  - [lively](https://github.com/socketry/lively) — The real-time application framework that powers Presently.
data/releases.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Releases
2
2
 
3
+ ## v0.15.0
4
+
5
+ q
6
+
7
+ - Export works from current working directory.
8
+ - Remove explicit support for `morph` transition.
9
+
3
10
  ## v0.14.0
4
11
 
5
12
  - Increase code font size by 50%.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: presently
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.0
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0.16'
47
+ version: '0.18'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0.16'
54
+ version: '0.18'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: markly
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -90,6 +90,9 @@ files:
90
90
  - bake/presently/rehearse.rb
91
91
  - bake/presently/slides.rb
92
92
  - bin/presently
93
+ - context/animating-slides.md
94
+ - context/getting-started.md
95
+ - context/index.yaml
93
96
  - lib/presently.rb
94
97
  - lib/presently/application.rb
95
98
  - lib/presently/clock.rb
@@ -240,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
240
243
  - !ruby/object:Gem::Version
241
244
  version: '0'
242
245
  requirements: []
243
- rubygems_version: 4.0.6
246
+ rubygems_version: 4.0.10
244
247
  specification_version: 4
245
248
  summary: A web-based presentation tool built with Lively.
246
249
  test_files: []
metadata.gz.sig CHANGED
Binary file