Skip to content

Commit 9eade29

Browse files
boneskullclaude
andcommitted
docs(chore): load asciinema-player from node_modules
- Import asciinema-player CSS and JS from npm package instead of CDN - Add workaround for background color rendering issue See: asciinema/asciinema-player#302 - Override dark theme pre styling to allow transparent backgrounds - Support Astro View Transitions for player initialization 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 009a2c1 commit 9eade29

File tree

4 files changed

+66
-34
lines changed

4 files changed

+66
-34
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144
"@types/node": "24.10.4",
145145
"@types/wallabyjs": "0.0.15",
146146
"@types/yargs": "17.0.35",
147-
"asciinema-player": "3.13.3",
147+
"asciinema-player": "3.13.5",
148148
"astro": "5.16.5",
149149
"astro-broken-link-checker": "file:./vendor/astro-broken-link-checker",
150150
"ava": "6.4.1",

site/src/components/AsciinemaPlayer.astro

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
2-
import type { HTMLAttributes } from 'astro/types';
2+
import type {HTMLAttributes} from 'astro/types';
3+
import 'asciinema-player/dist/bundle/asciinema-player.css';
34
45
interface Props extends HTMLAttributes<'div'> {
56
src: string;
@@ -29,44 +30,59 @@ const playerId = `player-${Math.random().toString(36).slice(2, 9)}`;
2930
---
3031

3132
<div class="asciinema-player-wrapper">
32-
<div id={playerId}></div>
33+
<div
34+
id={playerId}
35+
data-src={src}
36+
data-options={JSON.stringify({
37+
autoPlay,
38+
loop,
39+
speed,
40+
theme,
41+
fit: terminalFontSize ? false : 'width',
42+
terminalFontSize: terminalFontSize ?? 'medium',
43+
rows,
44+
cols,
45+
})}
46+
>
47+
</div>
3348
</div>
3449

35-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/asciinema-player@3/dist/bundle/asciinema-player.css" />
36-
<script src="https://cdn.jsdelivr.net/npm/asciinema-player@3/dist/bundle/asciinema-player.min.js" defer is:inline></script>
50+
<script>
51+
import * as AsciinemaPlayer from 'asciinema-player';
3752

38-
<script define:vars={{ playerId, src, autoPlay, loop, speed, theme, rows, cols, terminalFontSize }} is:inline>
39-
// Wait for AsciinemaPlayer to be available
40-
function initPlayer() {
41-
const playerDiv = document.getElementById(playerId);
42-
if (!playerDiv) return;
53+
function initPlayers() {
54+
document
55+
.querySelectorAll('.asciinema-player-wrapper > div[data-src]')
56+
.forEach((el) => {
57+
const src = el.getAttribute('data-src');
58+
const options = JSON.parse(el.getAttribute('data-options') || '{}');
4359

44-
if (window.AsciinemaPlayer) {
45-
const options = {
46-
autoPlay,
47-
loop,
48-
speed,
49-
theme,
50-
fit: terminalFontSize ? false : 'width',
51-
terminalFontSize: terminalFontSize ?? 'medium'
52-
};
60+
// Clean up undefined values and parse numbers
61+
if (options.rows) options.rows = parseInt(options.rows);
62+
if (options.cols) options.cols = parseInt(options.cols);
63+
Object.keys(options).forEach((key) => {
64+
if (options[key] === null || options[key] === undefined) {
65+
delete options[key];
66+
}
67+
});
5368

54-
if (rows) options.rows = parseInt(rows);
55-
if (cols) options.cols = parseInt(cols);
69+
// Remove data attributes to prevent re-initialization
70+
el.removeAttribute('data-src');
71+
el.removeAttribute('data-options');
5672

57-
window.AsciinemaPlayer.create(src, playerDiv, options);
58-
} else {
59-
// Retry if player library not loaded yet
60-
setTimeout(initPlayer, 50);
61-
}
73+
AsciinemaPlayer.create(src, el, options);
74+
});
6275
}
6376

64-
// Wait for DOM to be fully loaded
77+
// Initialize on page load and on Astro page transitions
6578
if (document.readyState === 'loading') {
66-
document.addEventListener('DOMContentLoaded', initPlayer);
79+
document.addEventListener('DOMContentLoaded', initPlayers);
6780
} else {
68-
initPlayer();
81+
initPlayers();
6982
}
83+
84+
// Support Astro View Transitions
85+
document.addEventListener('astro:page-load', initPlayers);
7086
</script>
7187

7288
<style>
@@ -76,4 +92,3 @@ const playerId = `player-${Math.random().toString(36).slice(2, 9)}`;
7692
overflow: hidden;
7793
}
7894
</style>
79-

site/src/styles/custom.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,23 @@ h2,
352352
border: 1px solid rgba(255, 1, 154, 0.2);
353353
}
354354

355+
/* asciinema-player workaround: ensure SVG background layer renders properly
356+
See: https://github.com/asciinema/asciinema-player/issues/302 */
357+
.ap-player .ap-term svg.ap-term-bg {
358+
width: 100%;
359+
height: 100%;
360+
}
361+
362+
.ap-player .ap-term pre.ap-term-text {
363+
background-color: transparent;
364+
}
365+
366+
/* Dark mode exception: override our pre styling for asciinema player */
367+
:root[data-theme='dark'] .ap-player .ap-term pre.ap-term-text {
368+
background-color: transparent;
369+
border: none;
370+
}
371+
355372
/* Search button */
356373
:root[data-theme='dark'] .search-button {
357374
background-color: rgba(0, 241, 255, 0.1);

0 commit comments

Comments
 (0)