shellfie 1.0.0 → 1.1.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. checksums.yaml +4 -4
  2. data/CHANGELOG.md +56 -2
  3. data/README.md +258 -97
  4. data/lib/shellfie/animation_frame_builder.rb +31 -7
  5. data/lib/shellfie/animation_timeline.rb +2 -1
  6. data/lib/shellfie/ansi_line_buffer.rb +20 -4
  7. data/lib/shellfie/ansi_normalizer.rb +18 -8
  8. data/lib/shellfie/ansi_parser.rb +120 -7
  9. data/lib/shellfie/cassette.rb +76 -0
  10. data/lib/shellfie/cli.rb +65 -2
  11. data/lib/shellfie/cli_authoring.rb +233 -0
  12. data/lib/shellfie/cli_generate.rb +244 -40
  13. data/lib/shellfie/cli_info.rb +106 -6
  14. data/lib/shellfie/cli_run.rb +167 -0
  15. data/lib/shellfie/config.rb +5 -1
  16. data/lib/shellfie/config_defaults.rb +21 -2
  17. data/lib/shellfie/config_validation.rb +93 -4
  18. data/lib/shellfie/dependency_checker.rb +74 -3
  19. data/lib/shellfie/errors.rb +1 -0
  20. data/lib/shellfie/ffmpeg_encoder.rb +46 -0
  21. data/lib/shellfie/font_resolver.rb +11 -1
  22. data/lib/shellfie/gif_generator.rb +157 -11
  23. data/lib/shellfie/gif_palette.rb +8 -4
  24. data/lib/shellfie/html_renderer.rb +54 -0
  25. data/lib/shellfie/line_layout.rb +19 -10
  26. data/lib/shellfie/output_writer.rb +7 -2
  27. data/lib/shellfie/parser.rb +82 -19
  28. data/lib/shellfie/parser_validation.rb +48 -15
  29. data/lib/shellfie/render_geometry.rb +2 -1
  30. data/lib/shellfie/render_segment.rb +17 -5
  31. data/lib/shellfie/renderer.rb +28 -11
  32. data/lib/shellfie/rendering/text_painter.rb +23 -15
  33. data/lib/shellfie/rendering/window_chrome.rb +2 -2
  34. data/lib/shellfie/reproducibility_manifest.rb +41 -0
  35. data/lib/shellfie/session.rb +111 -0
  36. data/lib/shellfie/session_config.rb +562 -0
  37. data/lib/shellfie/session_runner.rb +689 -0
  38. data/lib/shellfie/svg_renderer.rb +222 -0
  39. data/lib/shellfie/terminal_screen.rb +389 -0
  40. data/lib/shellfie/text_metrics.rb +74 -15
  41. data/lib/shellfie/transcript_renderer.rb +92 -0
  42. data/lib/shellfie/version.rb +1 -1
  43. data/lib/shellfie/yaml_safety.rb +147 -0
  44. data/lib/shellfie.rb +8 -1
  45. data/schema/shellfie-v1.schema.json +153 -0
  46. data/schema/shellfie-v2.schema.json +262 -0
  47. metadata +27 -24
  48. data/.rspec +0 -3
  49. data/Rakefile +0 -8
  50. data/docs/.nojekyll +0 -0
  51. data/docs/index.html +0 -205
  52. data/docs/scripts.js +0 -85
  53. data/docs/styles.css +0 -507
  54. data/examples/animation.yml +0 -33
  55. data/examples/colored.yml +0 -20
  56. data/examples/demo.gif +0 -0
  57. data/examples/demo.png +0 -0
  58. data/examples/demo_animation.yml +0 -31
  59. data/examples/headless.png +0 -0
  60. data/examples/headless.yml +0 -16
  61. data/examples/scrolling.yml +0 -48
  62. data/examples/simple.yml +0 -21
  63. data/examples/theme_macos.png +0 -0
  64. data/examples/theme_ubuntu.png +0 -0
  65. data/examples/theme_windows.png +0 -0
  66. data/shellfie.gemspec +0 -32
data/docs/scripts.js DELETED
@@ -1,85 +0,0 @@
1
- const observer = new IntersectionObserver(
2
- (entries) => {
3
- entries.forEach((entry) => {
4
- if (entry.isIntersecting) {
5
- entry.target.classList.add("is-visible");
6
- observer.unobserve(entry.target);
7
- }
8
- });
9
- },
10
- { threshold: 0.2 }
11
- );
12
-
13
- document.querySelectorAll(".section, .card, .code-block, .terminal-card").forEach((el) => {
14
- el.classList.add("fade-in");
15
- observer.observe(el);
16
- });
17
-
18
- const typewriter = document.querySelector(".typewriter");
19
- if (typewriter) {
20
- const rawLines = typewriter.dataset.lines || "";
21
- const lines = rawLines.split("||");
22
- const typingDelay = 45;
23
- const lineDelay = 650;
24
- const loopDelay = 5000;
25
- let lineIndex = 0;
26
- let charIndex = 0;
27
-
28
- const cursor = document.createElement("span");
29
- cursor.className = "typewriter__cursor";
30
-
31
- const renderFrame = () => {
32
- typewriter.innerHTML = "";
33
- lines.forEach((line, index) => {
34
- if (index > lineIndex) return;
35
- const lineEl = document.createElement("div");
36
- const isPrompt = line.trim().startsWith("$");
37
- lineEl.className = `typewriter__line ${
38
- isPrompt ? "typewriter__line--prompt" : "typewriter__line--output"
39
- }`;
40
- const text = index === lineIndex ? line.slice(0, charIndex) : line;
41
- lineEl.textContent = text;
42
- if (index === lineIndex) {
43
- lineEl.appendChild(cursor);
44
- }
45
- typewriter.appendChild(lineEl);
46
- });
47
- };
48
-
49
- const isInstantLine = (line) =>
50
- line.startsWith("Generated:") || line.startsWith("Let the glow begin");
51
-
52
- const typeNext = () => {
53
- if (lineIndex >= lines.length) {
54
- setTimeout(() => {
55
- lineIndex = 0;
56
- charIndex = 0;
57
- typewriter.innerHTML = "";
58
- typeNext();
59
- }, loopDelay);
60
- return;
61
- }
62
-
63
- if (isInstantLine(lines[lineIndex])) {
64
- charIndex = lines[lineIndex].length;
65
- renderFrame();
66
- charIndex = 0;
67
- lineIndex += 1;
68
- setTimeout(typeNext, lineDelay);
69
- return;
70
- }
71
-
72
- if (charIndex <= lines[lineIndex].length) {
73
- renderFrame();
74
- charIndex += 1;
75
- setTimeout(typeNext, typingDelay);
76
- return;
77
- }
78
-
79
- charIndex = 0;
80
- lineIndex += 1;
81
- setTimeout(typeNext, lineDelay);
82
- };
83
-
84
- typeNext();
85
- }
data/docs/styles.css DELETED
@@ -1,507 +0,0 @@
1
- @import url("https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Share+Tech+Mono&display=swap");
2
-
3
- :root {
4
- color-scheme: dark;
5
- --bg: #0b0617;
6
- --bg-alt: #140826;
7
- --neon-pink: #ff5fd2;
8
- --neon-blue: #52f2ff;
9
- --neon-purple: #a07bff;
10
- --neon-green: #34f5b4;
11
- --neon-orange: #ff9f5f;
12
- --neon-sun: #ff4fd8;
13
- --text: #f3eaff;
14
- --muted: #c2b0d8;
15
- --card: rgba(18, 10, 34, 0.85);
16
- --border: rgba(255, 255, 255, 0.08);
17
- --glow: 0 0 24px rgba(255, 95, 210, 0.35);
18
- }
19
-
20
- *,
21
- *::before,
22
- *::after {
23
- box-sizing: border-box;
24
- }
25
-
26
- body {
27
- margin: 0;
28
- min-height: 100vh;
29
- font-family: "Space Grotesk", "Segoe UI", sans-serif;
30
- color: var(--text);
31
- background:
32
- radial-gradient(circle at 10% 20%, rgba(255, 95, 210, 0.15), transparent 40%),
33
- radial-gradient(circle at 90% 10%, rgba(82, 242, 255, 0.2), transparent 45%),
34
- linear-gradient(180deg, #1a0a2f 0%, #0b0617 55%, #05020c 100%);
35
- overflow-x: hidden;
36
- }
37
-
38
- a {
39
- color: inherit;
40
- text-decoration: none;
41
- }
42
-
43
- .ambient-glow {
44
- position: fixed;
45
- inset: -30% auto auto -10%;
46
- width: 60vw;
47
- height: 60vw;
48
- background: radial-gradient(circle, rgba(255, 95, 210, 0.25), rgba(10, 4, 16, 0));
49
- filter: blur(14px);
50
- z-index: 0;
51
- pointer-events: none;
52
- }
53
-
54
- .sun-core {
55
- position: fixed;
56
- top: 8vh;
57
- left: 70%;
58
- width: 280px;
59
- height: 280px;
60
- background: radial-gradient(circle at 50% 35%, var(--neon-sun), #ff8ad2 40%, rgba(255, 79, 216, 0.2) 60%, transparent 70%);
61
- border-radius: 50%;
62
- opacity: 0.55;
63
- filter: blur(1px) saturate(120%);
64
- z-index: 0;
65
- pointer-events: none;
66
- box-shadow: 0 0 28px rgba(255, 79, 216, 0.45);
67
- animation: sunfloat 6s ease-in-out infinite;
68
- }
69
-
70
- .scanlines {
71
- position: fixed;
72
- inset: 0;
73
- background: repeating-linear-gradient(
74
- 180deg,
75
- rgba(255, 255, 255, 0.03),
76
- rgba(255, 255, 255, 0.03) 1px,
77
- transparent 1px,
78
- transparent 3px
79
- );
80
- mix-blend-mode: soft-light;
81
- opacity: 0.18;
82
- pointer-events: none;
83
- z-index: 2;
84
- }
85
-
86
- .stars {
87
- position: fixed;
88
- inset: 0;
89
- background-image:
90
- radial-gradient(circle at 12% 24%, rgba(255, 255, 255, 0.6) 0 1px, transparent 2px),
91
- radial-gradient(circle at 38% 12%, rgba(255, 255, 255, 0.4) 0 1px, transparent 2px),
92
- radial-gradient(circle at 72% 18%, rgba(255, 255, 255, 0.5) 0 1px, transparent 2px),
93
- radial-gradient(circle at 86% 32%, rgba(255, 255, 255, 0.5) 0 1px, transparent 2px),
94
- radial-gradient(circle at 18% 78%, rgba(255, 255, 255, 0.3) 0 1px, transparent 2px),
95
- radial-gradient(circle at 64% 62%, rgba(255, 255, 255, 0.4) 0 1px, transparent 2px);
96
- opacity: 0.2;
97
- pointer-events: none;
98
- z-index: 0;
99
- }
100
-
101
- .grid-floor {
102
- position: fixed;
103
- inset: auto 0 0 0;
104
- height: 45vh;
105
- background-image:
106
- linear-gradient(transparent 60%, rgba(82, 242, 255, 0.12)),
107
- repeating-linear-gradient(90deg, rgba(82, 242, 255, 0.1) 0 1px, transparent 1px 60px),
108
- repeating-linear-gradient(0deg, rgba(82, 242, 255, 0.1) 0 1px, transparent 1px 60px);
109
- transform: perspective(600px) rotateX(65deg);
110
- transform-origin: bottom;
111
- opacity: 0.2;
112
- z-index: 0;
113
- pointer-events: none;
114
- }
115
-
116
- .topbar {
117
- position: sticky;
118
- top: 0;
119
- z-index: 3;
120
- display: flex;
121
- align-items: center;
122
- justify-content: space-between;
123
- padding: 24px 6vw;
124
- backdrop-filter: blur(12px);
125
- background: rgba(7, 4, 15, 0.65);
126
- border-bottom: 1px solid var(--border);
127
- }
128
-
129
- .brand {
130
- display: flex;
131
- align-items: center;
132
- gap: 12px;
133
- }
134
-
135
- .brand__glyph {
136
- font-size: 22px;
137
- color: var(--neon-blue);
138
- text-shadow: 0 0 12px rgba(82, 242, 255, 0.8);
139
- }
140
-
141
- .brand__title {
142
- font-weight: 700;
143
- letter-spacing: 0.08em;
144
- text-transform: uppercase;
145
- }
146
-
147
- .brand__subtitle {
148
- display: block;
149
- font-size: 12px;
150
- color: var(--muted);
151
- }
152
-
153
- .topnav {
154
- display: flex;
155
- gap: 18px;
156
- font-size: 14px;
157
- color: var(--muted);
158
- }
159
-
160
- .topnav a {
161
- position: relative;
162
- padding-bottom: 4px;
163
- }
164
-
165
- .topnav a::after {
166
- content: "";
167
- position: absolute;
168
- left: 0;
169
- bottom: 0;
170
- width: 0;
171
- height: 2px;
172
- background: var(--neon-pink);
173
- transition: width 0.3s ease;
174
- }
175
-
176
- .topnav a:hover::after {
177
- width: 100%;
178
- }
179
-
180
- .cta {
181
- padding: 10px 18px;
182
- border-radius: 999px;
183
- border: 1px solid var(--border);
184
- font-weight: 600;
185
- background: linear-gradient(120deg, rgba(160, 123, 255, 0.2), rgba(255, 95, 210, 0.2));
186
- box-shadow: var(--glow);
187
- transition: transform 0.2s ease, box-shadow 0.2s ease, filter 0.2s ease;
188
- }
189
-
190
- .cta--primary {
191
- background: linear-gradient(120deg, var(--neon-pink), var(--neon-purple));
192
- color: #0b0617;
193
- }
194
-
195
- .cta--ghost {
196
- background: transparent;
197
- border: 1px solid rgba(255, 95, 210, 0.6);
198
- }
199
-
200
- .cta:hover {
201
- transform: translateY(-2px) scale(1.02);
202
- box-shadow: 0 0 28px rgba(255, 95, 210, 0.45);
203
- filter: brightness(1.08);
204
- }
205
-
206
- .cta:active {
207
- transform: translateY(0) scale(0.99);
208
- box-shadow: 0 0 18px rgba(255, 95, 210, 0.35);
209
- }
210
-
211
- main {
212
- position: relative;
213
- z-index: 1;
214
- padding: 0 6vw 80px;
215
- }
216
-
217
- .hero {
218
- display: grid;
219
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
220
- gap: 48px;
221
- padding: 80px 0 40px;
222
- align-items: center;
223
- }
224
-
225
- .hero h1 {
226
- font-size: clamp(32px, 5vw, 56px);
227
- line-height: 1.05;
228
- margin: 0 0 20px;
229
- background: linear-gradient(90deg, #ffffff, #ffb6f5 35%, #7cf6ff 65%, #ffffff);
230
- -webkit-background-clip: text;
231
- background-clip: text;
232
- color: transparent;
233
- }
234
-
235
- .hero__lead {
236
- color: var(--muted);
237
- font-size: 18px;
238
- line-height: 1.6;
239
- }
240
-
241
- .hero__actions {
242
- display: flex;
243
- gap: 16px;
244
- margin: 24px 0;
245
- }
246
-
247
- .hero__meta {
248
- display: flex;
249
- gap: 16px;
250
- flex-wrap: wrap;
251
- font-size: 13px;
252
- color: var(--muted);
253
- }
254
-
255
- .eyebrow {
256
- font-family: "Share Tech Mono", "Courier New", monospace;
257
- letter-spacing: 0.18em;
258
- text-transform: uppercase;
259
- font-size: 12px;
260
- color: var(--neon-green);
261
- margin-bottom: 12px;
262
- }
263
-
264
- .hero__preview {
265
- position: relative;
266
- display: grid;
267
- place-items: center;
268
- }
269
-
270
- .terminal-card {
271
- background: var(--card);
272
- border-radius: 18px;
273
- border: 1px solid rgba(255, 255, 255, 0.12);
274
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.45);
275
- width: min(100%, 420px);
276
- overflow: hidden;
277
- }
278
-
279
- .terminal-card__bar {
280
- display: flex;
281
- gap: 8px;
282
- padding: 12px 16px;
283
- background: rgba(9, 5, 19, 0.8);
284
- }
285
-
286
- .terminal-card__bar span {
287
- width: 12px;
288
- height: 12px;
289
- border-radius: 50%;
290
- background: rgba(255, 95, 210, 0.6);
291
- box-shadow: 0 0 8px rgba(255, 95, 210, 0.6);
292
- }
293
-
294
- .terminal-card__bar span:nth-child(2) {
295
- background: rgba(82, 242, 255, 0.7);
296
- }
297
-
298
- .terminal-card__bar span:nth-child(3) {
299
- background: rgba(52, 245, 180, 0.7);
300
- }
301
-
302
- .terminal-card__body {
303
- font-family: "Share Tech Mono", "Courier New", monospace;
304
- padding: 20px;
305
- font-size: 14px;
306
- color: #e9d7ff;
307
- background: linear-gradient(180deg, rgba(17, 9, 29, 0.9), rgba(9, 5, 19, 0.95));
308
- }
309
-
310
- .typewriter {
311
- min-height: 110px;
312
- line-height: 1.6;
313
- white-space: pre-wrap;
314
- }
315
-
316
- .typewriter__line {
317
- color: #e9d7ff;
318
- }
319
-
320
- .typewriter__line--prompt {
321
- color: var(--neon-blue);
322
- }
323
-
324
- .typewriter__line--output {
325
- color: #f7b6ff;
326
- }
327
-
328
- .typewriter__cursor {
329
- display: inline-block;
330
- width: 10px;
331
- height: 16px;
332
- margin-left: 4px;
333
- background: var(--neon-green);
334
- animation: caret 0.9s steps(1) infinite;
335
- vertical-align: text-bottom;
336
- }
337
-
338
- @keyframes caret {
339
- 0%,
340
- 49% {
341
- opacity: 1;
342
- }
343
- 50%,
344
- 100% {
345
- opacity: 0;
346
- }
347
- }
348
-
349
- .prompt {
350
- color: var(--neon-blue);
351
- }
352
-
353
- .output {
354
- color: #f7b6ff;
355
- }
356
-
357
- .section {
358
- padding: 80px 0;
359
- }
360
-
361
- .section--alt {
362
- background: rgba(20, 8, 38, 0.6);
363
- border: 1px solid var(--border);
364
- border-radius: 24px;
365
- padding: 80px 6vw;
366
- margin: 0 -6vw;
367
- }
368
-
369
- .section__header h2 {
370
- margin: 0 0 12px;
371
- font-size: clamp(26px, 4vw, 40px);
372
- }
373
-
374
- .section__lead {
375
- color: var(--muted);
376
- font-size: 16px;
377
- max-width: 640px;
378
- }
379
-
380
- .grid {
381
- display: grid;
382
- gap: 24px;
383
- grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
384
- margin-top: 36px;
385
- }
386
-
387
- .card {
388
- padding: 24px;
389
- background: var(--card);
390
- border: 1px solid var(--border);
391
- border-radius: 16px;
392
- box-shadow: 0 12px 24px rgba(0, 0, 0, 0.3);
393
- backdrop-filter: blur(4px);
394
- }
395
-
396
- .split {
397
- display: grid;
398
- gap: 28px;
399
- grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
400
- margin-top: 36px;
401
- }
402
-
403
- .code-block {
404
- background: #0a0618;
405
- border-radius: 16px;
406
- border: 1px solid rgba(82, 242, 255, 0.2);
407
- padding: 18px 20px;
408
- box-shadow: inset 0 0 24px rgba(82, 242, 255, 0.08);
409
- }
410
-
411
- .code-block h3 {
412
- margin-top: 0;
413
- }
414
-
415
- .code-block pre {
416
- margin: 12px 0 0;
417
- font-family: "Share Tech Mono", "Courier New", monospace;
418
- color: #bfefff;
419
- white-space: pre-wrap;
420
- }
421
-
422
- .code-block--wide {
423
- max-width: 860px;
424
- }
425
-
426
- .theme-list {
427
- display: flex;
428
- flex-wrap: wrap;
429
- gap: 12px;
430
- margin: 24px 0;
431
- }
432
-
433
- .theme-pill {
434
- padding: 8px 16px;
435
- border-radius: 999px;
436
- border: 1px solid rgba(255, 95, 210, 0.4);
437
- font-size: 14px;
438
- background: rgba(255, 95, 210, 0.08);
439
- text-transform: uppercase;
440
- letter-spacing: 0.08em;
441
- }
442
-
443
- .footer {
444
- padding: 40px 6vw 60px;
445
- text-align: center;
446
- color: var(--muted);
447
- border-top: 1px solid var(--border);
448
- }
449
-
450
- .fade-in {
451
- opacity: 0;
452
- transform: translateY(24px);
453
- transition: opacity 0.8s ease, transform 0.8s ease;
454
- }
455
-
456
- .fade-in.is-visible {
457
- opacity: 1;
458
- transform: translateY(0);
459
- }
460
-
461
- @keyframes sunfloat {
462
- 0% {
463
- transform: translateY(0);
464
- }
465
- 50% {
466
- transform: translateY(-10px);
467
- }
468
- 100% {
469
- transform: translateY(0);
470
- }
471
- }
472
-
473
- @media (max-width: 900px) {
474
- .topbar {
475
- flex-wrap: wrap;
476
- gap: 12px;
477
- }
478
-
479
- .topnav {
480
- flex-wrap: wrap;
481
- justify-content: center;
482
- }
483
-
484
- .hero {
485
- padding-top: 50px;
486
- }
487
-
488
- .section--alt {
489
- padding: 60px 6vw;
490
- }
491
- }
492
-
493
- @media (max-width: 600px) {
494
- .hero__actions {
495
- flex-direction: column;
496
- align-items: flex-start;
497
- }
498
-
499
- .topbar {
500
- padding: 18px 6vw;
501
- }
502
-
503
- .topnav {
504
- gap: 12px;
505
- font-size: 13px;
506
- }
507
- }
@@ -1,33 +0,0 @@
1
- # animation.yml - Animated GIF example
2
- theme: macos
3
- title: "Terminal — zsh"
4
-
5
- window:
6
- width: 600
7
- padding: 20
8
-
9
- animation:
10
- typing_speed: 50
11
- command_delay: 500
12
- cursor_blink: true
13
- loop: true
14
-
15
- frames:
16
- - prompt: "$ "
17
- type: "echo Hello, World!"
18
- delay: 500
19
-
20
- - output: "Hello, World!"
21
- delay: 1000
22
-
23
- - prompt: "$ "
24
- type: "ls -la"
25
- delay: 500
26
-
27
- - output: |
28
- total 24
29
- drwxr-xr-x 5 user staff 160 Jan 10 10:00 .
30
- drwxr-xr-x 3 user staff 96 Jan 10 09:00 ..
31
- -rw-r--r-- 1 user staff 1024 Jan 10 10:00 README.md
32
- -rw-r--r-- 1 user staff 512 Jan 10 10:00 Gemfile
33
- delay: 2000
data/examples/colored.yml DELETED
@@ -1,20 +0,0 @@
1
- # colored.yml - Example with ANSI color codes
2
- theme: ubuntu
3
- title: "user@ubuntu: ~/project"
4
-
5
- window:
6
- width: 700
7
- padding: 20
8
-
9
- lines:
10
- - prompt: "\e[32muser@ubuntu\e[0m:\e[34m~/project\e[0m$ "
11
- command: "bundle exec rspec"
12
-
13
- - output: |
14
- \e[32m.\e[0m\e[32m.\e[0m\e[32m.\e[0m\e[32m.\e[0m\e[32m.\e[0m\e[32m.\e[0m\e[32m.\e[0m\e[32m.\e[0m\e[32m.\e[0m\e[32m.\e[0m
15
-
16
- - output: "Finished in 0.12 seconds (files took 0.5 seconds to load)"
17
- - output: "\e[32m10 examples, 0 failures\e[0m"
18
-
19
- - prompt: "\e[32muser@ubuntu\e[0m:\e[34m~/project\e[0m$ "
20
- command: ""
data/examples/demo.gif DELETED
Binary file
data/examples/demo.png DELETED
Binary file
@@ -1,31 +0,0 @@
1
- theme: macos
2
- title: "Terminal — zsh"
3
-
4
- window:
5
- width: 550
6
- padding: 18
7
- visible_lines: 7
8
-
9
- animation:
10
- typing_speed: 35
11
- command_delay: 400
12
- loop: true
13
-
14
- frames:
15
- - prompt: "$ "
16
- type: "shellfie generate config.yml -o demo.png"
17
- delay: 600
18
-
19
- - output: "Generated: demo.png"
20
- delay: 1200
21
-
22
- - prompt: "$ "
23
- type: "shellfie themes"
24
- delay: 500
25
-
26
- - output: |
27
- Available themes:
28
- macos - macOS Terminal style
29
- ubuntu - Ubuntu Terminal style
30
- windows - Windows Terminal style
31
- delay: 2000
Binary file
@@ -1,16 +0,0 @@
1
- # headless.yml - Terminal output without window decoration
2
- theme: macos
3
- headless: true
4
-
5
- window:
6
- width: 500
7
- padding: 15
8
-
9
- lines:
10
- - prompt: "$ "
11
- command: "ruby -v"
12
-
13
- - output: "ruby 3.3.0 (2024-12-25 revision 5124f9ac75) [arm64-darwin24]"
14
-
15
- - prompt: "$ "
16
- command: ""