1---
2/**
3 * Renders styled terminal output matching Alchemy CLI colors.
4 *
5 * Pass content as a `content` prop (string) to avoid MDX processing.
6 * Use simple markup tags for styling:
7 * [g]...[/g] green [r]...[/r] red
8 * [y]...[/y] yellow [c]...[/c] cyan
9 * [b]...[/b] bold [d]...[/d] dim
10 * [u]...[/u] underline
11 */
12
13interface Props {
14 title?: string;
15 content: string;
16}
17
18const { title, content } = Astro.props;
19
20const html = content
21 .replace(/^\n/, '')
22 .replace(/\[g\]([\s\S]*?)\[\/g\]/g, '<span class="t-g">$1</span>')
23 .replace(/\[r\]([\s\S]*?)\[\/r\]/g, '<span class="t-r">$1</span>')
24 .replace(/\[y\]([\s\S]*?)\[\/y\]/g, '<span class="t-y">$1</span>')
25 .replace(/\[c\]([\s\S]*?)\[\/c\]/g, '<span class="t-c">$1</span>')
26 .replace(/\[b\]([\s\S]*?)\[\/b\]/g, '<span class="t-b">$1</span>')
27 .replace(/\[d\]([\s\S]*?)\[\/d\]/g, '<span class="t-d">$1</span>')
28 .replace(/\[u\]([\s\S]*?)\[\/u\]/g, '<span class="t-u">$1</span>')
29 .replace(/\[s2\]/g, ' ')
30 .replace(/\[s4\]/g, ' ');
31---
32
33<div class="terminal not-content" data-nosnippet>
34 <div class="terminal-header">
35 <span class="terminal-dot" style="background:#ff5f57"></span>
36 <span class="terminal-dot" style="background:#febc2e"></span>
37 <span class="terminal-dot" style="background:#28c840"></span>
38 {title && <span class="terminal-title">{title}</span>}
39 </div>
40 <pre class="terminal-body" set:html={html} />
41</div>
42
43<style>
44 .terminal {
45 background: var(--alc-bg-code);
46 border: 1px solid var(--alc-walnut-700);
47 border-radius: var(--alc-radius);
48 overflow: hidden;
49 margin: 1rem 0;
50 font-family: var(--alc-font-mono, 'JetBrains Mono', monospace);
51 font-size: 0.85rem;
52 line-height: 1.6;
53 box-shadow: var(--alc-shadow);
54 }
55 .terminal-header {
56 display: flex;
57 align-items: center;
58 gap: 6px;
59 padding: 10px 14px;
60 background: var(--alc-walnut-950);
61 border-bottom: 1px solid var(--alc-walnut-700);
62 }
63 .terminal-dot {
64 width: 12px;
65 height: 12px;
66 border-radius: 50%;
67 }
68 .terminal-title {
69 margin-left: 8px;
70 color: var(--alc-walnut-400);
71 font-size: 0.8rem;
72 font-family: var(--alc-font-mono);
73 }
74 .terminal-body {
75 padding: 16px 20px;
76 margin: 0;
77 color: var(--alc-fg-invert);
78 overflow-x: auto;
79 white-space: pre;
80 background: transparent;
81 border: none;
82 }
83 .terminal-body :global(.t-g) { color: var(--alc-accent-bright); }
84 .terminal-body :global(.t-r) { color: #e07a5f; }
85 .terminal-body :global(.t-y) { color: var(--alc-warn); }
86 .terminal-body :global(.t-c) { color: var(--alc-code-type); }
87 .terminal-body :global(.t-b) { font-weight: 700; color: var(--alc-fg-invert); }
88 .terminal-body :global(.t-d) { color: var(--alc-walnut-400); }
89 .terminal-body :global(.t-u) { text-decoration: underline; }
90</style>