presently 0.2.0 → 0.3.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: 8b7e990c7b6d2f4ef66e333bc95793d0682011102614d92bf02c0278053a42c9
4
- data.tar.gz: 4f7ec48d87c12425dd4ecf02d7cf6c3530a9bdd1199ef030b0ab2fb8ed31e669
3
+ metadata.gz: cbb2d491928f3efc616d50e71f949a51d9ac4eca645a981372434a28855f86aa
4
+ data.tar.gz: 1a8eed679adbe70ab3303912f67789fb17cae0a723e6a363a96609ff70ec8e39
5
5
  SHA512:
6
- metadata.gz: 9d9629f50e5827eaf97d0fed33b01b1abfcece8f31a2232fc4c98ca765c3538e389fbb8a6f877a6ead1b9131e0a10ddabbfaf8d4b034c964012e86cad1c960c4
7
- data.tar.gz: 0f867425bd65d0d39d6252dabef8ffad6d9b952316b7305ed76397fae7561d07cea7656031ad153bd6fa42194e213beae69a65f2168b0599dbda3f74e3686a85
6
+ metadata.gz: 40fba8bd5e994c33136e8627459a634b0c710539a19e06542ffcdacb525b003cff161418ab860c19a59ba91e8eabd2267a0b2bc004b2d509fc838ba8964ab8ab
7
+ data.tar.gz: e312ec32e02e1d3f21a36eb064ccedc82280984289382ffe996e3c3a03c9973a84da795e6dfd85bbc2b34fd7e4c8834387480128440ffbd5ba8c2773a3625e51
checksums.yaml.gz.sig ADDED
Binary file
@@ -21,46 +21,61 @@ module Presently
21
21
  module Parser
22
22
  # Markly extensions enabled for all slide Markdown rendering.
23
23
  EXTENSIONS = [:table, :tasklist, :strikethrough, :autolink]
24
-
24
+
25
25
  module_function
26
-
26
+
27
27
  # Parse the file and return a {Slide}.
28
28
  # @parameter path [String] The file path to parse.
29
29
  # @returns [Slide]
30
30
  def load(path)
31
31
  raw = File.read(path)
32
-
32
+
33
33
  # Parse once, with native front matter support.
34
34
  document = Markly.parse(raw, flags: Markly::UNSAFE | Markly::FRONT_MATTER, extensions: EXTENSIONS)
35
-
35
+
36
36
  # Extract front matter from the first AST node if present.
37
37
  front_matter = nil
38
38
  if (front_matter_node = document.first_child) && front_matter_node.type == :front_matter
39
39
  front_matter = YAML.safe_load(front_matter_node.string_content)
40
40
  front_matter_node.delete
41
41
  end
42
-
42
+
43
43
  # Find the last hrule, which acts as the separator between slide content and presenter notes.
44
44
  last_hrule = nil
45
45
  document.each{|node| last_hrule = node if node.type == :hrule}
46
-
46
+
47
47
  if last_hrule
48
48
  notes_fragment = Markly::Node.new(:document)
49
49
  while child = last_hrule.next
50
50
  notes_fragment.append_child(child)
51
51
  end
52
52
  last_hrule.delete
53
-
53
+
54
+ # Extract the last javascript code block from the notes as the slide script.
55
+ script_node = nil
56
+ notes_fragment.each do |node|
57
+ if node.type == :code_block && node.fence_info.to_s.strip == "javascript"
58
+ script_node = node
59
+ end
60
+ end
61
+
62
+ script = nil
63
+ if script_node
64
+ script = script_node.string_content
65
+ script_node.delete
66
+ end
67
+
54
68
  content = parse_sections(document.each)
55
69
  notes = render_nodes(notes_fragment.each)
56
70
  else
57
71
  content = parse_sections(document.each)
58
72
  notes = nil
73
+ script = nil
59
74
  end
60
-
61
- Slide.new(path, front_matter: front_matter, content: content, notes: notes)
75
+
76
+ Slide.new(path, front_matter: front_matter, content: content, notes: notes, script: script)
62
77
  end
63
-
78
+
64
79
  # Parse a list of AST nodes into sections based on top-level Markdown headings.
65
80
  # Each heading becomes a named key; content before the first heading
66
81
  # is collected under `"body"`. Headings inside code blocks are invisible
@@ -71,7 +86,7 @@ module Presently
71
86
  sections = {}
72
87
  current_key = "body"
73
88
  current_nodes = []
74
-
89
+
75
90
  nodes.each do |node|
76
91
  if node.type == :header
77
92
  sections[current_key] = render_nodes(current_nodes) unless current_nodes.empty?
@@ -81,12 +96,12 @@ module Presently
81
96
  current_nodes << node
82
97
  end
83
98
  end
84
-
99
+
85
100
  sections[current_key] = render_nodes(current_nodes) unless current_nodes.empty?
86
-
101
+
87
102
  sections
88
103
  end
89
-
104
+
90
105
  # Render a list of AST nodes to HTML via a temporary document.
91
106
  # @parameter nodes [Array(Markly::Node)] The nodes to render.
92
107
  # @returns [String] The rendered HTML.
@@ -96,74 +111,79 @@ module Presently
96
111
  Renderer.new(flags: Markly::UNSAFE, extensions: EXTENSIONS).render(doc)
97
112
  end
98
113
  end
99
-
114
+
100
115
  # Load and parse a slide from a Markdown file.
101
116
  # @parameter path [String] The file path to the Markdown slide.
102
117
  # @returns [Slide]
103
118
  def self.load(path)
104
119
  Parser.load(path)
105
120
  end
106
-
121
+
107
122
  # Initialize a slide with pre-parsed data.
108
123
  # @parameter path [String] The file path of the slide.
109
124
  # @parameter front_matter [Hash | Nil] The parsed YAML front_matter.
110
125
  # @parameter content [Hash(String, String)] Content sections keyed by heading name.
111
126
  # @parameter notes [String | Nil] The rendered HTML presenter notes.
112
- def initialize(path, front_matter: nil, content: {}, notes: nil)
127
+ # @parameter script [String | Nil] JavaScript to execute after the slide renders.
128
+ def initialize(path, front_matter: nil, content: {}, notes: nil, script: nil)
113
129
  @path = path
114
130
  @front_matter = front_matter
115
131
  @content = content
116
132
  @notes = notes
133
+ @script = script
117
134
  end
118
-
135
+
119
136
  # @attribute [String] The file path of the slide.
120
137
  attr :path
121
-
138
+
122
139
  # @attribute [Hash | Nil] The parsed YAML front_matter.
123
140
  attr :front_matter
124
-
141
+
125
142
  # @attribute [Hash(String, String)] The content sections keyed by heading name.
126
143
  attr :content
127
-
144
+
128
145
  # @attribute [String | Nil] The rendered HTML presenter notes.
129
146
  attr :notes
130
-
147
+
148
+ # @attribute [String | Nil] JavaScript to execute after the slide renders on the display.
149
+ attr :script
150
+
131
151
  # The template to use for rendering this slide.
132
152
  # @returns [String] The template name from front_matter, or `"default"`.
133
153
  def template
134
154
  @front_matter&.fetch("template", "default") || "default"
135
155
  end
136
-
156
+
137
157
  # The expected duration of this slide in seconds.
138
158
  # @returns [Integer] The duration from front_matter, or `60`.
139
159
  def duration
140
160
  @front_matter&.fetch("duration", 60) || 60
141
161
  end
142
-
162
+
143
163
  # The title of this slide.
144
164
  # @returns [String] The title from front_matter, or the filename without extension.
145
165
  def title
146
166
  @front_matter&.fetch("title", File.basename(@path, ".md")) || File.basename(@path, ".md")
147
167
  end
148
-
168
+
149
169
  # Whether this slide should be skipped in the presentation.
150
170
  # @returns [Boolean]
151
171
  def skip?
152
172
  @front_matter&.fetch("skip", false) || false
153
173
  end
154
-
174
+
155
175
  # The navigation marker for this slide, used in the presenter's jump-to dropdown.
156
176
  # @returns [String | Nil] The marker label, or `nil` if not marked.
157
177
  def marker
158
178
  @front_matter&.fetch("marker", nil)
159
179
  end
160
-
180
+
161
181
  # The transition type for animating into this slide.
162
- # @returns [String | Nil] The transition name (e.g. `"fade"`, `"slide-left"`, `"magic-move"`), or `nil` for instant swap.
182
+ # @returns [String | Nil] The transition name (e.g. `"fade"`, `"slide-left"`, `"morph"`), or `nil` for instant swap.
163
183
  def transition
164
184
  @front_matter&.fetch("transition", nil)
165
185
  end
166
-
186
+
167
187
  # The line range to focus on for code slides.
168
188
  # @returns [Array(Integer, Integer) | Nil] The `[start, end]` line numbers (1-based), or `nil`.
169
189
  def focus
@@ -36,6 +36,11 @@ module Presently
36
36
  classes = [@css_class, extra_class].compact.join(" ")
37
37
  builder.tag(:div, class: classes, data: {template: slide.template}) do
38
38
  builder.raw(html)
39
+ if slide.script
40
+ builder.tag(:script, type: "text/slide-script") do
41
+ builder.raw(slide.script)
42
+ end
43
+ end
39
44
  end
40
45
  end
41
46
  end
@@ -5,5 +5,5 @@
5
5
 
6
6
  # @namespace
7
7
  module Presently
8
- VERSION = "0.2.0"
8
+ VERSION = "0.3.0"
9
9
  end
@@ -40,6 +40,7 @@ html, body {
40
40
  }
41
41
 
42
42
  .slide-inner {
43
+ position: relative;
43
44
  width: 100%;
44
45
  height: 100%;
45
46
  display: flex;
@@ -63,6 +64,14 @@ html, body {
63
64
 
64
65
  .default-template .slide-body li {
65
66
  margin-bottom: 0.5em;
67
+ transition: opacity 0.4s ease, transform 0.4s ease;
68
+ }
69
+
70
+ @starting-style {
71
+ .default-template .slide-body li {
72
+ opacity: 0;
73
+ transform: translateX(-0.5em);
74
+ }
66
75
  }
67
76
 
68
77
  /* Title template */
@@ -125,6 +134,16 @@ html, body {
125
134
  margin-bottom: 0.4em;
126
135
  }
127
136
 
137
+ /* Diagram template */
138
+ .diagram-template {
139
+ padding: 0;
140
+ }
141
+
142
+ .diagram-template .slide-body > div {
143
+ position: absolute;
144
+ box-sizing: border-box;
145
+ }
146
+
128
147
  /* Image template */
129
148
  .image-template .slide-caption {
130
149
  font-size: 1.6rem;
@@ -353,12 +372,12 @@ html[data-transition="slide-right"]::view-transition-new(slide-container) {
353
372
  /* Magic move — the browser interpolates position/size for matched
354
373
  view-transition-name elements. No cross-fade on the container
355
374
  to avoid background dimming. */
356
- html[data-transition="magic-move"]::view-transition-old(slide-container) {
375
+ html[data-transition="morph"]::view-transition-old(slide-container) {
357
376
  animation: none;
358
377
  opacity: 0;
359
378
  }
360
379
 
361
- html[data-transition="magic-move"]::view-transition-new(slide-container) {
380
+ html[data-transition="morph"]::view-transition-new(slide-container) {
362
381
  animation: none;
363
382
  }
364
383
 
@@ -392,6 +411,72 @@ html[data-transition="magic-move"]::view-transition-new(slide-container) {
392
411
  to { transform: translateX(0); opacity: 1; }
393
412
  }
394
413
 
414
+ /* ========================
415
+ BUILD EFFECTS
416
+ ======================== */
417
+
418
+ /* Suppress both pseudo-elements for hidden build elements so they
419
+ neither crossfade in nor crossfade out during the transition. */
420
+ ::view-transition-old(.build-hidden),
421
+ ::view-transition-new(.build-hidden) {
422
+ display: none;
423
+ }
424
+
425
+ /* Fade */
426
+ ::view-transition-new(.build-fade) {
427
+ animation: vt-fade-in 0.4s ease;
428
+ }
429
+
430
+ /* Fly in from left */
431
+ @keyframes build-fly-in-left {
432
+ from { transform: translateX(-2rem); opacity: 0; }
433
+ to { transform: translateX(0); opacity: 1; }
434
+ }
435
+
436
+ ::view-transition-new(.build-fly-left) {
437
+ animation: build-fly-in-left 0.4s ease;
438
+ }
439
+
440
+ /* Fly in from right */
441
+ @keyframes build-fly-in-right {
442
+ from { transform: translateX(2rem); opacity: 0; }
443
+ to { transform: translateX(0); opacity: 1; }
444
+ }
445
+
446
+ ::view-transition-new(.build-fly-right) {
447
+ animation: build-fly-in-right 0.4s ease;
448
+ }
449
+
450
+ /* Fly in from bottom */
451
+ @keyframes build-fly-in-up {
452
+ from { transform: translateY(2rem); opacity: 0; }
453
+ to { transform: translateY(0); opacity: 1; }
454
+ }
455
+
456
+ ::view-transition-new(.build-fly-up) {
457
+ animation: build-fly-in-up 0.4s ease;
458
+ }
459
+
460
+ /* Fly in from top */
461
+ @keyframes build-fly-in-down {
462
+ from { transform: translateY(-2rem); opacity: 0; }
463
+ to { transform: translateY(0); opacity: 1; }
464
+ }
465
+
466
+ ::view-transition-new(.build-fly-down) {
467
+ animation: build-fly-in-down 0.4s ease;
468
+ }
469
+
470
+ /* Scale in */
471
+ @keyframes build-scale-in {
472
+ from { transform: scale(0.8); opacity: 0; }
473
+ to { transform: scale(1); opacity: 1; }
474
+ }
475
+
476
+ ::view-transition-new(.build-scale) {
477
+ animation: build-scale-in 0.4s ease;
478
+ }
479
+
395
480
  /* ========================
396
481
  PRESENTER VIEW
397
482
  ======================== */
@@ -617,6 +702,10 @@ html[data-transition="magic-move"]::view-transition-new(slide-container) {
617
702
  margin: 0.3em 0;
618
703
  }
619
704
 
705
+ .notes-content em {
706
+ color: var(--ahead);
707
+ }
708
+
620
709
  .notes .no-notes {
621
710
  opacity: 0.4;
622
711
  font-style: italic;
@@ -1,5 +1,6 @@
1
1
  import { Live } from 'live';
2
2
  import Syntax from '@socketry/syntax';
3
+ import { Slide } from './slide.js';
3
4
 
4
5
  const live = Live.start();
5
6
 
@@ -65,6 +66,29 @@ function applyCodeFocus() {
65
66
  });
66
67
  }
67
68
 
69
+ // Run the script for a single slide element.
70
+ // Wrapped in try/catch so syntax errors don't crash the presentation.
71
+ function runScript(slideEl) {
72
+ const scriptEl = slideEl.querySelector('script[type="text/slide-script"]');
73
+ if (!scriptEl) return;
74
+
75
+ const container = slideEl.querySelector('.slide-body') ?? slideEl;
76
+ const slide = new Slide(container);
77
+
78
+ try {
79
+ const fn = new Function('slide', scriptEl.textContent);
80
+ fn(slide);
81
+ } catch (error) {
82
+ console.error('Slide script error:', error);
83
+ }
84
+ }
85
+
86
+ // Run scripts for all slide elements currently in the DOM.
87
+ function runSlideScripts() {
88
+ document.querySelectorAll('.slide').forEach(runScript);
89
+ }
90
+
91
+
68
92
  // Detect the transition type from the incoming HTML before morphdom applies it.
69
93
  function detectTransition(html) {
70
94
  const match = html.match(/data-transition="([^"]+)"/);
@@ -82,11 +106,12 @@ live.update = function(id, html, options) {
82
106
 
83
107
  if (transition && document.startViewTransition && !activeTransition) {
84
108
  document.documentElement.dataset.transition = transition;
85
-
109
+
86
110
  activeTransition = document.startViewTransition(() => {
87
111
  originalUpdate(id, html, options);
112
+ runSlideScripts();
88
113
  });
89
-
114
+
90
115
  activeTransition.finished.finally(() => {
91
116
  delete document.documentElement.dataset.transition;
92
117
  activeTransition = null;
@@ -95,6 +120,7 @@ live.update = function(id, html, options) {
95
120
  });
96
121
  } else {
97
122
  originalUpdate(id, html, options);
123
+ runSlideScripts();
98
124
  Syntax.highlight();
99
125
  applyCodeFocus();
100
126
  }
@@ -108,8 +134,9 @@ const observer = new MutationObserver(() => {
108
134
  });
109
135
  observer.observe(document.body, { childList: true, subtree: true });
110
136
 
111
- // Initial focus application:
137
+ // Initial focus and script application:
112
138
  applyCodeFocus();
139
+ runSlideScripts();
113
140
 
114
141
  // Jump-to select: forward the selected slide index to the presenter view.
115
142
  document.addEventListener('change', (event) => {
data/public/slide.js ADDED
@@ -0,0 +1,52 @@
1
+ // Represents a collection of elements within a slide to be revealed sequentially.
2
+ // Has no side effects until build() is called.
3
+ export class SlideElements {
4
+ constructor(elements) {
5
+ this._elements = elements;
6
+ }
7
+
8
+ // Show the first n elements and hide the rest.
9
+ // Assigns view-transition-names and applies build visibility in one step.
10
+ // @parameter n [Integer] Number of elements to show.
11
+ // @parameter options [Object]
12
+ // group: prefix for view-transition-name (default: "build")
13
+ // effect: "fade", "fly-up", "fly-down", "fly-left", "fly-right", "scale"
14
+ build(n, options = {}) {
15
+ const prefix = options.group || 'build';
16
+
17
+ this._elements.forEach((element, index) => {
18
+ element.style.viewTransitionName = `${prefix}-${index + 1}`;
19
+
20
+ if (index < n) {
21
+ element.style.visibility = 'visible';
22
+ // Newly revealed element: apply the enter effect.
23
+ // Already-visible elements: clear any class so they morph normally.
24
+ element.style.viewTransitionClass = (index === n - 1 && options.effect)
25
+ ? `build-${options.effect}`
26
+ : '';
27
+ } else {
28
+ element.style.visibility = 'hidden';
29
+ // Hidden elements: suppress both pseudo-elements so they don't
30
+ // crossfade in or out during the transition.
31
+ element.style.viewTransitionClass = 'build-hidden';
32
+ }
33
+ });
34
+ }
35
+ }
36
+
37
+ // The scripting context passed to each slide's javascript block.
38
+ // Scopes element queries to the slide body.
39
+ export class Slide {
40
+ constructor(container) {
41
+ this._container = container;
42
+ }
43
+
44
+ // Find elements within this slide matching the given CSS selector.
45
+ // Use comma-separated selectors to combine multiple element types, e.g. "h2, li".
46
+ // @parameter selector [String] A CSS selector scoped to the slide body.
47
+ // @returns [SlideElements]
48
+ find(selector) {
49
+ const elements = Array.from(this._container.querySelectorAll(selector));
50
+ return new SlideElements(elements);
51
+ }
52
+ }
data/readme.md CHANGED
@@ -17,13 +17,27 @@ A web-based presentation tool built with [Lively](https://github.com/socketry/li
17
17
 
18
18
  ## Usage
19
19
 
20
- Please see the [project documentation](https://github.com/socketry/presently) for more details.
20
+ Please see the [project documentation](https://socketry.github.io/presently/) for more details.
21
21
 
22
- - [Getting Started](https://github.com/socketry/presentlyguides/getting-started/index) - This guide explains how to use `presently` to create and deliver web-based presentations using Markdown slides.
22
+ - [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.
23
+
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.
23
25
 
24
26
  ## Releases
25
27
 
26
- Please see the [project releases](https://github.com/socketry/presentlyreleases/index) for all releases.
28
+ Please see the [project releases](https://socketry.github.io/presently/releases/index) for all releases.
29
+
30
+ ### v0.3.0
31
+
32
+ - Add `diagram` template with a `position: relative` container — direct `<div>` children are `position: absolute` by default for free-form layouts.
33
+ - All slide templates now have `position: relative` on the slide inner container, allowing absolutely positioned overlays in any template.
34
+ - Add slide scripting: a fenced ` ```javascript ``` ` block at the end of presenter notes is extracted and executed in the browser after each slide renders. The script receives a `slide` object scoped to the slide body.
35
+ - Add `Slide#find(selector)` — a pure CSS selector query returning a `SlideElements` collection with no side effects.
36
+ - Add `SlideElements#build(n, options)` — shows the first `n` matched elements, hides the rest, and assigns `view-transition-name` for morph transition matching. Accepts `group` (name prefix) and `effect` (entry animation) options.
37
+ - Add build effects via `view-transition-class`: `fade`, `fly-left`, `fly-right`, `fly-up`, `fly-down`, `scale`. Requires Chromium 125+; degrades gracefully to instant appear in other browsers.
38
+ - Rename `magic-move` transition to `morph`.
39
+ - Italic text in presenter notes is styled in amber to distinguish stage directions from spoken words.
40
+ - Add transitions guide and animating slides guide to documentation.
27
41
 
28
42
  ### v0.2.0
29
43
 
data/releases.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Releases
2
2
 
3
+ ## v0.3.0
4
+
5
+ - Add `diagram` template with a `position: relative` container — direct `<div>` children are `position: absolute` by default for free-form layouts.
6
+ - All slide templates now have `position: relative` on the slide inner container, allowing absolutely positioned overlays in any template.
7
+ - Add slide scripting: a fenced ` ```javascript ``` ` block at the end of presenter notes is extracted and executed in the browser after each slide renders. The script receives a `slide` object scoped to the slide body.
8
+ - Add `Slide#find(selector)` — a pure CSS selector query returning a `SlideElements` collection with no side effects.
9
+ - Add `SlideElements#build(n, options)` — shows the first `n` matched elements, hides the rest, and assigns `view-transition-name` for morph transition matching. Accepts `group` (name prefix) and `effect` (entry animation) options.
10
+ - Add build effects via `view-transition-class`: `fade`, `fly-left`, `fly-right`, `fly-up`, `fly-down`, `scale`. Requires Chromium 125+; degrades gracefully to instant appear in other browsers.
11
+ - Rename `magic-move` transition to `morph`.
12
+ - Italic text in presenter notes is styled in amber to distinguish stage directions from spoken words.
13
+ - Add transitions guide and animating slides guide to documentation.
14
+
3
15
  ## v0.2.0
4
16
 
5
17
  - Use Markly's native front matter parser (`Markly::FRONT_MATTER`) instead of manual string splitting, parsing each slide document once and extracting front matter directly from the AST.
@@ -0,0 +1,5 @@
1
+ <div class="slide-inner diagram-template">
2
+ <div class="slide-body">
3
+ #{self.section("body")}
4
+ </div>
5
+ </div>
data.tar.gz.sig ADDED
Binary file
metadata CHANGED
@@ -1,12 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: presently
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  bindir: bin
9
- cert_chain: []
9
+ cert_chain:
10
+ - |
11
+ -----BEGIN CERTIFICATE-----
12
+ MIIE2DCCA0CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMRgwFgYDVQQDDA9zYW11
13
+ ZWwud2lsbGlhbXMxHTAbBgoJkiaJk/IsZAEZFg1vcmlvbnRyYW5zZmVyMRIwEAYK
14
+ CZImiZPyLGQBGRYCY28xEjAQBgoJkiaJk/IsZAEZFgJuejAeFw0yMjA4MDYwNDUz
15
+ MjRaFw0zMjA4MDMwNDUzMjRaMGExGDAWBgNVBAMMD3NhbXVlbC53aWxsaWFtczEd
16
+ MBsGCgmSJomT8ixkARkWDW9yaW9udHJhbnNmZXIxEjAQBgoJkiaJk/IsZAEZFgJj
17
+ bzESMBAGCgmSJomT8ixkARkWAm56MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
18
+ igKCAYEAomvSopQXQ24+9DBB6I6jxRI2auu3VVb4nOjmmHq7XWM4u3HL+pni63X2
19
+ 9qZdoq9xt7H+RPbwL28LDpDNflYQXoOhoVhQ37Pjn9YDjl8/4/9xa9+NUpl9XDIW
20
+ sGkaOY0eqsQm1pEWkHJr3zn/fxoKPZPfaJOglovdxf7dgsHz67Xgd/ka+Wo1YqoE
21
+ e5AUKRwUuvaUaumAKgPH+4E4oiLXI4T1Ff5Q7xxv6yXvHuYtlMHhYfgNn8iiW8WN
22
+ XibYXPNP7NtieSQqwR/xM6IRSoyXKuS+ZNGDPUUGk8RoiV/xvVN4LrVm9upSc0ss
23
+ RZ6qwOQmXCo/lLcDUxJAgG95cPw//sI00tZan75VgsGzSWAOdjQpFM0l4dxvKwHn
24
+ tUeT3ZsAgt0JnGqNm2Bkz81kG4A2hSyFZTFA8vZGhp+hz+8Q573tAR89y9YJBdYM
25
+ zp0FM4zwMNEUwgfRzv1tEVVUEXmoFCyhzonUUw4nE4CFu/sE3ffhjKcXcY//qiSW
26
+ xm4erY3XAgMBAAGjgZowgZcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O
27
+ BBYEFO9t7XWuFf2SKLmuijgqR4sGDlRsMC4GA1UdEQQnMCWBI3NhbXVlbC53aWxs
28
+ aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MC4GA1UdEgQnMCWBI3NhbXVlbC53aWxs
29
+ aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MA0GCSqGSIb3DQEBCwUAA4IBgQB5sxkE
30
+ cBsSYwK6fYpM+hA5B5yZY2+L0Z+27jF1pWGgbhPH8/FjjBLVn+VFok3CDpRqwXCl
31
+ xCO40JEkKdznNy2avOMra6PFiQyOE74kCtv7P+Fdc+FhgqI5lMon6tt9rNeXmnW/
32
+ c1NaMRdxy999hmRGzUSFjozcCwxpy/LwabxtdXwXgSay4mQ32EDjqR1TixS1+smp
33
+ 8C/NCWgpIfzpHGJsjvmH2wAfKtTTqB9CVKLCWEnCHyCaRVuKkrKjqhYCdmMBqCws
34
+ JkxfQWC+jBVeG9ZtPhQgZpfhvh+6hMhraUYRQ6XGyvBqEUe+yo6DKIT3MtGE2+CP
35
+ eX9i9ZWBydWb8/rvmwmX2kkcBbX0hZS1rcR593hGc61JR6lvkGYQ2MYskBveyaxt
36
+ Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
37
+ voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
38
+ -----END CERTIFICATE-----
10
39
  date: 1980-01-02 00:00:00.000000000 Z
11
40
  dependencies:
12
41
  - !ruby/object:Gem::Dependency
@@ -1029,10 +1058,12 @@ files:
1029
1058
  - public/_static/index.css
1030
1059
  - public/application.js
1031
1060
  - public/mermaid-diagram.js
1061
+ - public/slide.js
1032
1062
  - readme.md
1033
1063
  - releases.md
1034
1064
  - templates/code.xrb
1035
1065
  - templates/default.xrb
1066
+ - templates/diagram.xrb
1036
1067
  - templates/fill.xrb
1037
1068
  - templates/image.xrb
1038
1069
  - templates/section.xrb
@@ -1043,6 +1074,7 @@ homepage: https://github.com/socketry/presently
1043
1074
  licenses:
1044
1075
  - MIT
1045
1076
  metadata:
1077
+ documentation_uri: https://socketry.github.io/presently/
1046
1078
  source_code_uri: https://github.com/socketry/presently.git
1047
1079
  rdoc_options: []
1048
1080
  require_paths:
metadata.gz.sig ADDED
Binary file