@remix-run/cli 0.1.0 → 0.2.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.
- package/README.md +0 -3
- package/bootstrap/.agents/skills/remix/SKILL.md +501 -0
- package/bootstrap/.agents/skills/remix/references/animate-elements.md +195 -0
- package/bootstrap/.agents/skills/remix/references/assets-and-browser-modules.md +122 -0
- package/bootstrap/.agents/skills/remix/references/auth-and-sessions.md +420 -0
- package/bootstrap/.agents/skills/remix/references/component-model.md +282 -0
- package/bootstrap/.agents/skills/remix/references/create-mixins.md +158 -0
- package/bootstrap/.agents/skills/remix/references/data-and-validation.md +363 -0
- package/bootstrap/.agents/skills/remix/references/hydration-frames-navigation.md +297 -0
- package/bootstrap/.agents/skills/remix/references/middleware-and-server.md +243 -0
- package/bootstrap/.agents/skills/remix/references/mixins-styling-events.md +213 -0
- package/bootstrap/.agents/skills/remix/references/routing-and-controllers.md +324 -0
- package/bootstrap/.agents/skills/remix/references/testing-patterns.md +156 -0
- package/bootstrap/AGENTS.md +4 -0
- package/bootstrap/app/assets/entry.ts +19 -0
- package/bootstrap/app/assets.ts +18 -0
- package/bootstrap/app/controllers/auth.tsx +2 -2
- package/bootstrap/app/controllers/home.tsx +3 -18
- package/bootstrap/app/router.ts +6 -0
- package/bootstrap/app/routes.ts +2 -1
- package/bootstrap/app/ui/document.tsx +6 -1
- package/bootstrap/app/ui/prompt-button.tsx +162 -0
- package/bootstrap/app/ui/scaffold-home-page.tsx +526 -0
- package/bootstrap/app/utils/render.tsx +22 -3
- package/bootstrap/server.ts +13 -13
- package/bootstrap/tsconfig.json +0 -1
- package/dist/lib/cli.d.ts.map +1 -1
- package/dist/lib/cli.js +7 -10
- package/dist/lib/commands/help.d.ts.map +1 -1
- package/dist/lib/commands/help.js +9 -33
- package/dist/lib/commands/test.d.ts +1 -1
- package/dist/lib/commands/test.d.ts.map +1 -1
- package/dist/lib/commands/test.js +8 -4
- package/dist/lib/completion.d.ts.map +1 -1
- package/dist/lib/completion.js +3 -101
- package/dist/lib/errors.d.ts +0 -6
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +0 -11
- package/package.json +3 -4
- package/src/lib/cli.ts +7 -11
- package/src/lib/commands/help.ts +9 -43
- package/src/lib/commands/test.ts +10 -4
- package/src/lib/completion.ts +3 -146
- package/src/lib/errors.ts +0 -12
- package/dist/lib/commands/skills.d.ts +0 -6
- package/dist/lib/commands/skills.d.ts.map +0 -1
- package/dist/lib/commands/skills.js +0 -222
- package/dist/lib/skills-cache.d.ts +0 -19
- package/dist/lib/skills-cache.d.ts.map +0 -1
- package/dist/lib/skills-cache.js +0 -89
- package/dist/lib/skills.d.ts +0 -30
- package/dist/lib/skills.d.ts.map +0 -1
- package/dist/lib/skills.js +0 -441
- package/src/lib/commands/skills.ts +0 -306
- package/src/lib/skills-cache.ts +0 -140
- package/src/lib/skills.ts +0 -706
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
// Delete this file and put your own home page in app/controllers/home.tsx
|
|
2
|
+
import { css, type RemixNode } from 'remix/ui'
|
|
3
|
+
|
|
4
|
+
import { PromptButton } from './prompt-button.tsx'
|
|
5
|
+
import { routes } from '../routes.ts'
|
|
6
|
+
|
|
7
|
+
const APP_DISPLAY_NAME = decodeURIComponent('%%RMX_APP_DISPLAY_NAME_URI_COMPONENT%%')
|
|
8
|
+
|
|
9
|
+
const FONT_STACK =
|
|
10
|
+
"'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace"
|
|
11
|
+
|
|
12
|
+
export function HomePage() {
|
|
13
|
+
return () => (
|
|
14
|
+
<html lang="en">
|
|
15
|
+
<head>
|
|
16
|
+
<meta charSet="utf-8" />
|
|
17
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
18
|
+
<meta name="color-scheme" content="light dark" />
|
|
19
|
+
<title>Welcome to {APP_DISPLAY_NAME}</title>
|
|
20
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
21
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
|
22
|
+
<link
|
|
23
|
+
rel="stylesheet"
|
|
24
|
+
href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap"
|
|
25
|
+
/>
|
|
26
|
+
<script type="module" src={routes.assets.href({ path: 'app/assets/entry.ts' })}></script>
|
|
27
|
+
</head>
|
|
28
|
+
<body
|
|
29
|
+
mix={css({
|
|
30
|
+
// Light-mode design tokens (default).
|
|
31
|
+
'--surface-0': '#dee2e6',
|
|
32
|
+
'--surface-3': '#f0f4f7',
|
|
33
|
+
'--surface-4': '#f7fbff',
|
|
34
|
+
'--text-primary': '#313539',
|
|
35
|
+
'--text-tertiary': '#94989c',
|
|
36
|
+
'--brand-blue': '#2dacf9',
|
|
37
|
+
// Dark-mode overrides.
|
|
38
|
+
'@media (prefers-color-scheme: dark)': {
|
|
39
|
+
'--surface-0': '#1e2226',
|
|
40
|
+
'--surface-3': '#313539',
|
|
41
|
+
'--surface-4': '#363a3e',
|
|
42
|
+
'--text-primary': '#dee2e6',
|
|
43
|
+
'--text-tertiary': '#94989c',
|
|
44
|
+
},
|
|
45
|
+
'& *, & *::before, & *::after': { boxSizing: 'border-box' },
|
|
46
|
+
margin: 0,
|
|
47
|
+
padding: '48px 24px',
|
|
48
|
+
minHeight: '100vh',
|
|
49
|
+
background: 'var(--surface-0)',
|
|
50
|
+
color: 'var(--text-primary)',
|
|
51
|
+
fontFamily: FONT_STACK,
|
|
52
|
+
fontSize: '14px',
|
|
53
|
+
lineHeight: 1.5,
|
|
54
|
+
WebkitFontSmoothing: 'antialiased',
|
|
55
|
+
MozOsxFontSmoothing: 'grayscale',
|
|
56
|
+
display: 'flex',
|
|
57
|
+
alignItems: 'center',
|
|
58
|
+
justifyContent: 'center',
|
|
59
|
+
})}
|
|
60
|
+
>
|
|
61
|
+
<main
|
|
62
|
+
mix={css({
|
|
63
|
+
width: '100%',
|
|
64
|
+
maxWidth: '820px',
|
|
65
|
+
display: 'flex',
|
|
66
|
+
flexDirection: 'column',
|
|
67
|
+
alignItems: 'center',
|
|
68
|
+
gap: '72px',
|
|
69
|
+
})}
|
|
70
|
+
>
|
|
71
|
+
<Masthead />
|
|
72
|
+
<Columns />
|
|
73
|
+
<Footer />
|
|
74
|
+
</main>
|
|
75
|
+
</body>
|
|
76
|
+
</html>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function Masthead() {
|
|
81
|
+
return () => (
|
|
82
|
+
<section
|
|
83
|
+
aria-label="Welcome"
|
|
84
|
+
mix={css({
|
|
85
|
+
display: 'flex',
|
|
86
|
+
flexDirection: 'column',
|
|
87
|
+
alignItems: 'center',
|
|
88
|
+
justifyContent: 'center',
|
|
89
|
+
gap: '36px',
|
|
90
|
+
width: '100%',
|
|
91
|
+
})}
|
|
92
|
+
>
|
|
93
|
+
<p
|
|
94
|
+
mix={css({
|
|
95
|
+
margin: 0,
|
|
96
|
+
fontWeight: 700,
|
|
97
|
+
fontSize: '14px',
|
|
98
|
+
lineHeight: 1.33,
|
|
99
|
+
textTransform: 'uppercase',
|
|
100
|
+
letterSpacing: '0.1em',
|
|
101
|
+
color: 'var(--text-primary)',
|
|
102
|
+
textAlign: 'center',
|
|
103
|
+
})}
|
|
104
|
+
>
|
|
105
|
+
Welcome to
|
|
106
|
+
</p>
|
|
107
|
+
<RemixWordmarkHero />
|
|
108
|
+
</section>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function Columns() {
|
|
113
|
+
return () => (
|
|
114
|
+
<section
|
|
115
|
+
aria-label="Getting started"
|
|
116
|
+
mix={css({
|
|
117
|
+
display: 'flex',
|
|
118
|
+
gap: '16px',
|
|
119
|
+
alignItems: 'stretch',
|
|
120
|
+
justifyContent: 'center',
|
|
121
|
+
width: 'auto',
|
|
122
|
+
'@media (max-width: 720px)': {
|
|
123
|
+
flexDirection: 'column',
|
|
124
|
+
width: '100%',
|
|
125
|
+
},
|
|
126
|
+
})}
|
|
127
|
+
>
|
|
128
|
+
<GetStartedCard />
|
|
129
|
+
<CodingWithAiCard />
|
|
130
|
+
</section>
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function GetStartedCard() {
|
|
135
|
+
return () => (
|
|
136
|
+
<div mix={css({ ...CARD_STYLES, flex: '0 0 auto' })}>
|
|
137
|
+
<h2 mix={css(CARD_HEADER_STYLES)}>Get started</h2>
|
|
138
|
+
<ul
|
|
139
|
+
mix={css({
|
|
140
|
+
listStyle: 'none',
|
|
141
|
+
margin: 0,
|
|
142
|
+
padding: 0,
|
|
143
|
+
display: 'flex',
|
|
144
|
+
flexDirection: 'column',
|
|
145
|
+
alignItems: 'stretch',
|
|
146
|
+
width: '100%',
|
|
147
|
+
})}
|
|
148
|
+
>
|
|
149
|
+
<li>
|
|
150
|
+
<CardLink href="https://remix.run/docs" icon={<AtomIcon />} label="Remix Docs" />
|
|
151
|
+
</li>
|
|
152
|
+
<li>
|
|
153
|
+
<CardLink
|
|
154
|
+
href="https://discord.gg/xwx7mMzVkA"
|
|
155
|
+
icon={<DiscordFaceIcon />}
|
|
156
|
+
label="Join Discord"
|
|
157
|
+
/>
|
|
158
|
+
</li>
|
|
159
|
+
</ul>
|
|
160
|
+
</div>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function CodingWithAiCard() {
|
|
165
|
+
return () => (
|
|
166
|
+
<div
|
|
167
|
+
mix={css({
|
|
168
|
+
...CARD_STYLES,
|
|
169
|
+
width: '540px',
|
|
170
|
+
justifyContent: 'center',
|
|
171
|
+
'@media (max-width: 720px)': { width: '100%' },
|
|
172
|
+
})}
|
|
173
|
+
>
|
|
174
|
+
<h2 mix={css(CARD_HEADER_STYLES)}>Coding with AI?</h2>
|
|
175
|
+
<div
|
|
176
|
+
mix={css({
|
|
177
|
+
width: '100%',
|
|
178
|
+
display: 'flex',
|
|
179
|
+
flexDirection: 'column',
|
|
180
|
+
alignItems: 'stretch',
|
|
181
|
+
})}
|
|
182
|
+
>
|
|
183
|
+
<p
|
|
184
|
+
mix={css({
|
|
185
|
+
margin: 0,
|
|
186
|
+
padding: '0 16px 16px',
|
|
187
|
+
fontSize: '14px',
|
|
188
|
+
lineHeight: 1.67,
|
|
189
|
+
color: 'var(--text-primary)',
|
|
190
|
+
})}
|
|
191
|
+
>
|
|
192
|
+
Navigate to this project folder using your preferred AI-powered tool, and try copying any
|
|
193
|
+
of these prompts into the agent chat:
|
|
194
|
+
</p>
|
|
195
|
+
<PromptButton text="I want to build a simple headless Shopify store, what does Remix have available to help scaffold this?" />
|
|
196
|
+
<PromptButton text="Add a sqlite database with a users table and scaffold a signup flow" />
|
|
197
|
+
<PromptButton text="Make a copy to clipboard component that confirms to the user it was copied then resets after a few seconds" />
|
|
198
|
+
<PromptButton text="Add RMX-01 theme and a page with a remix/ui/select component and remix/ui/button variants" />
|
|
199
|
+
<PromptButton text="Add compression middleware" />
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function CardLink() {
|
|
206
|
+
return ({ href, icon, label }: { href: string; icon: RemixNode; label: string }) => (
|
|
207
|
+
<a
|
|
208
|
+
href={href}
|
|
209
|
+
mix={css({
|
|
210
|
+
display: 'flex',
|
|
211
|
+
gap: '16px',
|
|
212
|
+
alignItems: 'center',
|
|
213
|
+
padding: '16px',
|
|
214
|
+
borderRadius: '12px',
|
|
215
|
+
color: 'var(--text-primary)',
|
|
216
|
+
textDecoration: 'none',
|
|
217
|
+
background: 'transparent',
|
|
218
|
+
transition: 'background-color 150ms ease, color 150ms ease',
|
|
219
|
+
'&:hover, &:focus-visible': {
|
|
220
|
+
background: 'var(--surface-4)',
|
|
221
|
+
color: 'var(--brand-blue)',
|
|
222
|
+
outline: 'none',
|
|
223
|
+
},
|
|
224
|
+
})}
|
|
225
|
+
>
|
|
226
|
+
<IconSlot>{icon}</IconSlot>
|
|
227
|
+
<span mix={css({ fontSize: '14px', lineHeight: 1.5, whiteSpace: 'nowrap' })}>{label}</span>
|
|
228
|
+
</a>
|
|
229
|
+
)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function IconSlot() {
|
|
233
|
+
return ({ children, rotated = false }: { children: RemixNode; rotated?: boolean }) => (
|
|
234
|
+
<span
|
|
235
|
+
aria-hidden="true"
|
|
236
|
+
mix={css({
|
|
237
|
+
flex: '0 0 24px',
|
|
238
|
+
width: '24px',
|
|
239
|
+
display: 'flex',
|
|
240
|
+
alignItems: 'center',
|
|
241
|
+
justifyContent: rotated ? 'center' : 'flex-start',
|
|
242
|
+
'& svg': {
|
|
243
|
+
width: '20px',
|
|
244
|
+
height: '20px',
|
|
245
|
+
display: 'block',
|
|
246
|
+
...(rotated ? { transform: 'rotate(180deg)' } : {}),
|
|
247
|
+
},
|
|
248
|
+
})}
|
|
249
|
+
>
|
|
250
|
+
{children}
|
|
251
|
+
</span>
|
|
252
|
+
)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function Footer() {
|
|
256
|
+
return () => (
|
|
257
|
+
<footer
|
|
258
|
+
mix={css({
|
|
259
|
+
display: 'flex',
|
|
260
|
+
flexDirection: 'column',
|
|
261
|
+
alignItems: 'center',
|
|
262
|
+
justifyContent: 'center',
|
|
263
|
+
gap: '10px',
|
|
264
|
+
})}
|
|
265
|
+
>
|
|
266
|
+
<div
|
|
267
|
+
mix={css({
|
|
268
|
+
display: 'flex',
|
|
269
|
+
gap: '24px',
|
|
270
|
+
alignItems: 'center',
|
|
271
|
+
justifyContent: 'center',
|
|
272
|
+
})}
|
|
273
|
+
>
|
|
274
|
+
<FooterWordmark />
|
|
275
|
+
<nav
|
|
276
|
+
aria-label="Remix social links"
|
|
277
|
+
mix={css({
|
|
278
|
+
display: 'flex',
|
|
279
|
+
gap: '16px',
|
|
280
|
+
alignItems: 'center',
|
|
281
|
+
justifyContent: 'flex-end',
|
|
282
|
+
color: 'var(--text-tertiary)',
|
|
283
|
+
'& a': {
|
|
284
|
+
width: '20px',
|
|
285
|
+
height: '20px',
|
|
286
|
+
display: 'inline-flex',
|
|
287
|
+
alignItems: 'center',
|
|
288
|
+
justifyContent: 'center',
|
|
289
|
+
color: 'inherit',
|
|
290
|
+
transition: 'color 150ms ease',
|
|
291
|
+
},
|
|
292
|
+
'& a:hover, & a:focus-visible': {
|
|
293
|
+
color: 'var(--text-primary)',
|
|
294
|
+
outline: 'none',
|
|
295
|
+
},
|
|
296
|
+
'& svg': { width: '100%', height: '100%', display: 'block' },
|
|
297
|
+
})}
|
|
298
|
+
>
|
|
299
|
+
<a href="https://github.com/remix-run/remix" aria-label="GitHub">
|
|
300
|
+
<GitHubIcon />
|
|
301
|
+
</a>
|
|
302
|
+
<a href="https://x.com/remix_run" aria-label="X">
|
|
303
|
+
<XIcon />
|
|
304
|
+
</a>
|
|
305
|
+
<a href="https://www.youtube.com/@Remix-Run" aria-label="YouTube">
|
|
306
|
+
<YouTubeIcon />
|
|
307
|
+
</a>
|
|
308
|
+
<a href="https://discord.gg/xwx7mMzVkA" aria-label="Discord">
|
|
309
|
+
<DiscordIcon />
|
|
310
|
+
</a>
|
|
311
|
+
</nav>
|
|
312
|
+
</div>
|
|
313
|
+
<div
|
|
314
|
+
mix={css({
|
|
315
|
+
display: 'flex',
|
|
316
|
+
flexDirection: 'column',
|
|
317
|
+
alignItems: 'center',
|
|
318
|
+
justifyContent: 'center',
|
|
319
|
+
gap: '12px',
|
|
320
|
+
fontSize: '10px',
|
|
321
|
+
lineHeight: 1.6,
|
|
322
|
+
letterSpacing: '0.05em',
|
|
323
|
+
color: 'var(--text-tertiary)',
|
|
324
|
+
textAlign: 'center',
|
|
325
|
+
'& p': { margin: 0, whiteSpace: 'nowrap' },
|
|
326
|
+
})}
|
|
327
|
+
>
|
|
328
|
+
<p>DOCS AND EXAMPLES LICENSED UNDER MIT</p>
|
|
329
|
+
<p>©2026 SHOPIFY, INC.</p>
|
|
330
|
+
</div>
|
|
331
|
+
</footer>
|
|
332
|
+
)
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const CARD_STYLES = {
|
|
336
|
+
background: 'var(--surface-3)',
|
|
337
|
+
borderRadius: '20px',
|
|
338
|
+
padding: '32px 16px 16px',
|
|
339
|
+
display: 'flex',
|
|
340
|
+
flexDirection: 'column',
|
|
341
|
+
alignItems: 'center',
|
|
342
|
+
gap: '32px',
|
|
343
|
+
} as const
|
|
344
|
+
|
|
345
|
+
const CARD_HEADER_STYLES = {
|
|
346
|
+
margin: 0,
|
|
347
|
+
width: '100%',
|
|
348
|
+
padding: '0 16px',
|
|
349
|
+
display: 'flex',
|
|
350
|
+
alignItems: 'flex-start',
|
|
351
|
+
fontSize: '14px',
|
|
352
|
+
fontWeight: 700,
|
|
353
|
+
lineHeight: 1.5,
|
|
354
|
+
textTransform: 'uppercase',
|
|
355
|
+
letterSpacing: '0.1em',
|
|
356
|
+
color: 'var(--text-primary)',
|
|
357
|
+
} as const
|
|
358
|
+
|
|
359
|
+
// ----- SVG icons -----
|
|
360
|
+
// Inline so the page is fully self-contained with no external icon assets.
|
|
361
|
+
|
|
362
|
+
function AtomIcon() {
|
|
363
|
+
return () => (
|
|
364
|
+
<svg viewBox="0 0 17.5 17.5" fill="none">
|
|
365
|
+
<path
|
|
366
|
+
d="M8.75 8.825V8.75M16.219 16.219C14.639 17.798 10.014 15.735 5.89 11.61C1.765 7.485 -0.299 2.861 1.281 1.281C2.861 -0.299 7.485 1.765 11.61 5.89C15.735 10.014 17.798 14.639 16.219 16.219ZM1.281 16.219C-0.299 14.639 1.765 10.014 5.89 5.89C10.014 1.765 14.639 -0.299 16.219 1.281C17.799 2.861 15.735 7.485 11.61 11.61C7.486 15.735 2.861 17.798 1.281 16.219Z"
|
|
367
|
+
stroke="currentColor"
|
|
368
|
+
stroke-width="1.5"
|
|
369
|
+
stroke-linecap="round"
|
|
370
|
+
/>
|
|
371
|
+
</svg>
|
|
372
|
+
)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function DiscordFaceIcon() {
|
|
376
|
+
return () => (
|
|
377
|
+
<svg viewBox="0 0 25.5 19.4" fill="none">
|
|
378
|
+
<path
|
|
379
|
+
d="M15.068 0.911C16.442 1.137 17.766 1.53 19.04 2.061L19.583 2.297L19.776 2.384L19.894 2.559C22.358 6.185 23.587 10.304 23.152 15.044L23.122 15.375L22.855 15.575C21.187 16.827 19.305 17.756 17.311 18.368L16.805 18.524L16.489 18.099C16.029 17.479 15.626 16.834 15.282 16.146H15.281C13.127 16.699 10.864 16.698 8.711 16.141L8.709 16.146C8.365 16.834 7.962 17.479 7.502 18.099L7.188 18.52L6.685 18.37C4.68 17.775 2.818 16.823 1.139 15.578L0.869 15.378L0.838 15.044C0.463 10.957 1.238 6.816 4.074 2.582L4.19 2.409L4.378 2.32C5.807 1.645 7.336 1.169 8.903 0.911L9.414 0.827L9.674 1.276C9.804 1.501 9.927 1.734 10.043 1.972C11.339 1.817 12.645 1.817 13.941 1.972C14.054 1.735 14.175 1.496 14.291 1.287L14.548 0.825L15.068 0.911ZM8.494 9.064C7.954 9.064 7.364 9.601 7.364 10.44C7.364 11.269 7.946 11.796 8.494 11.796C9.055 11.796 9.625 11.275 9.641 10.432C9.637 9.588 9.06 9.064 8.494 9.064ZM15.478 9.064C14.938 9.064 14.35 9.601 14.35 10.44C14.35 11.269 14.93 11.796 15.478 11.796C16.021 11.796 16.593 11.292 16.607 10.427C16.621 9.59 16.047 9.064 15.478 9.064Z"
|
|
380
|
+
stroke="currentColor"
|
|
381
|
+
stroke-width="1.5"
|
|
382
|
+
/>
|
|
383
|
+
</svg>
|
|
384
|
+
)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function GitHubIcon() {
|
|
388
|
+
return () => (
|
|
389
|
+
<svg viewBox="0 0 20 19.67" fill="none">
|
|
390
|
+
<path
|
|
391
|
+
fill-rule="evenodd"
|
|
392
|
+
clip-rule="evenodd"
|
|
393
|
+
d="M10.008 0C4.474 0 0 4.507 0 10.083C0 14.54 2.867 18.312 6.843 19.648C7.341 19.748 7.523 19.431 7.523 19.164C7.523 18.93 7.506 18.129 7.506 17.294C4.722 17.895 4.142 16.092 4.142 16.092C3.695 14.924 3.032 14.623 3.032 14.623C2.121 14.006 3.099 14.006 3.099 14.006C4.109 14.072 4.64 15.041 4.64 15.041C5.534 16.576 6.976 16.142 7.556 15.875C7.639 15.224 7.904 14.773 8.186 14.523C5.965 14.289 3.629 13.421 3.629 9.548C3.629 8.447 4.026 7.545 4.656 6.844C4.557 6.594 4.209 5.559 4.756 4.173C4.756 4.173 5.601 3.906 7.506 5.208C8.322 4.987 9.163 4.875 10.008 4.874C10.853 4.874 11.715 4.991 12.51 5.208C14.416 3.906 15.261 4.173 15.261 4.173C15.808 5.559 15.46 6.594 15.36 6.844C16.007 7.545 16.388 8.447 16.388 9.548C16.388 13.421 14.051 14.273 11.814 14.523C12.179 14.84 12.494 15.441 12.494 16.393C12.494 17.745 12.477 18.83 12.477 19.164C12.477 19.431 12.66 19.748 13.157 19.648C17.133 18.312 20 14.54 20 10.083C20.016 4.507 15.526 0 10.008 0Z"
|
|
394
|
+
fill="currentColor"
|
|
395
|
+
/>
|
|
396
|
+
</svg>
|
|
397
|
+
)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
function XIcon() {
|
|
401
|
+
return () => (
|
|
402
|
+
<svg viewBox="0 0 18.33 16.57" fill="none">
|
|
403
|
+
<path
|
|
404
|
+
d="M14.439 0H17.25L11.108 7.02L18.333 16.572H12.676L8.245 10.778L3.175 16.572H0.362L6.931 9.063L0 0H5.801L9.806 5.295L14.439 0ZM13.452 14.889H15.01L4.955 1.594H3.283L13.452 14.889Z"
|
|
405
|
+
fill="currentColor"
|
|
406
|
+
/>
|
|
407
|
+
</svg>
|
|
408
|
+
)
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function YouTubeIcon() {
|
|
412
|
+
return () => (
|
|
413
|
+
<svg viewBox="0 0 20 14.07" fill="none">
|
|
414
|
+
<path
|
|
415
|
+
d="M19.801 3.035C19.801 3.035 19.605 1.656 19.004 1.051C18.242 0.254 17.391 0.25 17 0.203C14.203 0 10.004 0 10.004 0H9.996C9.996 0 5.797 0 3 0.203C2.609 0.25 1.758 0.254 0.996 1.051C0.395 1.656 0.203 3.035 0.203 3.035C0.203 3.035 0 4.656 0 6.273V7.789C0 9.406 0.199 11.027 0.199 11.027C0.199 11.027 0.395 12.406 0.992 13.012C1.754 13.809 2.754 13.781 3.199 13.867C4.801 14.02 10 14.066 10 14.066C10 14.066 14.203 14.059 17 13.859C17.391 13.813 18.242 13.809 19.004 13.012C19.605 12.406 19.801 11.027 19.801 11.027C19.801 11.027 20 9.41 20 7.789V6.273C20 4.656 19.801 3.035 19.801 3.035ZM7.934 9.629V4.008L13.336 6.828L7.934 9.629Z"
|
|
416
|
+
fill="currentColor"
|
|
417
|
+
/>
|
|
418
|
+
</svg>
|
|
419
|
+
)
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function DiscordIcon() {
|
|
423
|
+
return () => (
|
|
424
|
+
<svg viewBox="0 0 20 15.24" fill="none">
|
|
425
|
+
<path
|
|
426
|
+
d="M16.931 1.264C15.656 0.679 14.289 0.248 12.86 0.001C12.834 -0.004 12.808 0.008 12.795 0.032C12.619 0.345 12.424 0.753 12.288 1.073C10.75 0.843 9.221 0.843 7.715 1.073C7.579 0.745 7.377 0.345 7.2 0.032C7.187 0.009 7.161 -0.003 7.135 0.001C5.707 0.247 4.34 0.678 3.064 1.264C3.053 1.268 3.044 1.276 3.037 1.287C0.445 5.16 -0.266 8.939 0.083 12.67C0.084 12.689 0.094 12.706 0.109 12.717C1.819 13.973 3.476 14.736 5.103 15.242C5.129 15.25 5.156 15.24 5.173 15.219C5.558 14.693 5.901 14.139 6.195 13.557C6.212 13.523 6.195 13.482 6.16 13.469C5.616 13.262 5.098 13.011 4.6 12.725C4.56 12.702 4.557 12.646 4.593 12.619C4.698 12.54 4.803 12.458 4.903 12.376C4.921 12.361 4.947 12.358 4.968 12.367C8.241 13.862 11.785 13.862 15.019 12.367C15.04 12.357 15.066 12.36 15.085 12.375C15.185 12.458 15.29 12.54 15.395 12.619C15.431 12.646 15.429 12.702 15.39 12.725C14.891 13.016 14.374 13.262 13.829 13.468C13.793 13.481 13.778 13.523 13.795 13.557C14.095 14.139 14.438 14.692 14.816 15.218C14.831 15.24 14.86 15.25 14.886 15.242C16.52 14.736 18.177 13.973 19.888 12.717C19.903 12.706 19.912 12.689 19.914 12.671C20.331 8.357 19.215 4.61 16.957 1.287C16.951 1.276 16.942 1.268 16.931 1.264ZM6.683 10.398C5.698 10.398 4.886 9.493 4.886 8.382C4.886 7.271 5.682 6.367 6.683 6.367C7.692 6.367 8.497 7.279 8.481 8.382C8.481 9.493 7.685 10.398 6.683 10.398ZM13.329 10.398C12.343 10.398 11.532 9.493 11.532 8.382C11.532 7.271 12.328 6.367 13.329 6.367C14.338 6.367 15.142 7.279 15.126 8.382C15.126 9.493 14.338 10.398 13.329 10.398Z"
|
|
427
|
+
stroke="currentColor"
|
|
428
|
+
stroke-width="1.5"
|
|
429
|
+
/>
|
|
430
|
+
</svg>
|
|
431
|
+
)
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function FooterWordmark() {
|
|
435
|
+
// Same wordmark used for both light and dark mode; the text paths use
|
|
436
|
+
// currentColor so they inherit `--text-primary` from <body>.
|
|
437
|
+
return () => (
|
|
438
|
+
<span
|
|
439
|
+
role="img"
|
|
440
|
+
aria-label="Remix"
|
|
441
|
+
mix={css({
|
|
442
|
+
display: 'block',
|
|
443
|
+
height: '8px',
|
|
444
|
+
width: 'calc(8px * 163 / 16)',
|
|
445
|
+
color: 'var(--text-primary)',
|
|
446
|
+
opacity: 0.55,
|
|
447
|
+
'& svg': { display: 'block', width: '100%', height: '100%' },
|
|
448
|
+
})}
|
|
449
|
+
>
|
|
450
|
+
<svg viewBox="0 0 163 16" fill="currentColor" aria-hidden="true">
|
|
451
|
+
<path d="M11.5566 11.5024C11.9535 11.5025 12.2424 11.8811 12.1396 12.2661L11.1846 15.8481H0.0673828L1.22656 11.5024H11.5566ZM30.1533 0.0180664V0.019043C34.3663 0.0191833 37.2765 1.9102 36.6543 4.24268L36.2324 5.82178C35.6099 8.15428 31.6907 10.0454 27.4775 10.0454H27.0469L35.8965 15.8481H21.6875L14.5332 10.3257C14.247 10.1423 13.9147 10.0454 13.5752 10.0454H1.61523L2.74219 5.8208H23.6904C24.4776 5.82071 25.2104 5.4677 25.3271 5.03174C25.4436 4.59555 24.8992 4.2417 24.1113 4.2417H3.16406L4.29102 0.0180664H30.1533Z" />
|
|
452
|
+
<path d="M113.897 15.9271L118.132 0.124207H129.313L125.052 15.9271H113.897Z" />
|
|
453
|
+
<path d="M71.7284 0.124207H107.931C112.785 0.124207 116.142 2.29324 115.419 4.9787L112.475 15.9271H101.32L102.844 10.2722L103.722 7.04445L104.057 5.805C104.264 5.00452 103.257 4.33316 101.785 4.33316H98.6089C98.5831 4.53973 98.5831 4.74631 98.5056 4.9787L95.5877 15.9271H84.4069L85.9304 10.2722L86.8083 7.04445L87.144 5.805C87.3506 5.00452 86.3436 4.33316 84.8717 4.33316H81.7731L78.6487 15.9271H67.4937L71.7284 0.124207Z" />
|
|
454
|
+
<path d="M145.926 2.73926L149.765 0.219727H162.734L150.971 7.93848L158.611 15.8135H145.642L143.047 13.1387L138.971 15.8135H126.002L138.002 7.93848L130.513 0.219727H143.482L145.926 2.73926Z" />
|
|
455
|
+
<path d="M70.4294 0.124146L69.319 4.33313H48.6296L48.2175 5.9054H48.2233L48.2224 5.90833H68.8796L67.7692 10.1427H47.0856L47.0603 10.2726C46.8284 11.0727 47.8351 11.7177 49.3063 11.7179H67.3308L66.194 15.9269H43.1608C38.3069 15.9267 34.95 13.7581 35.6726 11.0988L37.2995 4.97864C37.3359 4.84353 37.384 4.71053 37.4392 4.57825L37.4372 4.57922L38.6042 0.124146H70.4294Z" />
|
|
456
|
+
</svg>
|
|
457
|
+
</span>
|
|
458
|
+
)
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function RemixWordmarkHero() {
|
|
462
|
+
// Single SVG used for both themes: bracket characters keep their decorative
|
|
463
|
+
// colors; the "REMIX" letterforms use currentColor so they inherit
|
|
464
|
+
// `--text-primary` from <body> (light or dark).
|
|
465
|
+
return () => (
|
|
466
|
+
<svg
|
|
467
|
+
role="img"
|
|
468
|
+
aria-label="Remix"
|
|
469
|
+
viewBox="0 0 820 73"
|
|
470
|
+
mix={css({
|
|
471
|
+
width: '100%',
|
|
472
|
+
height: 'auto',
|
|
473
|
+
display: 'block',
|
|
474
|
+
color: 'var(--text-primary)',
|
|
475
|
+
})}
|
|
476
|
+
>
|
|
477
|
+
<path d="M53.1347 52.3526H37.3303L32.0532 72.1341H47.8519L53.1347 52.3526Z" fill="#FFDF5F" />
|
|
478
|
+
<path d="M44.2314 26.4861L39.1011 45.7148H54.9079L60.0431 26.4861H44.2314Z" fill="#FFDF5F" />
|
|
479
|
+
<path
|
|
480
|
+
d="M61.9637 19.2947L67.0981 0.0684052H51.2799L46.1504 19.2947H61.9637Z"
|
|
481
|
+
fill="#FFDF5F"
|
|
482
|
+
/>
|
|
483
|
+
<path d="M37.3365 52.3526H21.5321L16.2559 72.1341H32.0537L37.3365 52.3526Z" fill="#80E464" />
|
|
484
|
+
<path d="M46.1656 19.2947L51.3 0.0684052H35.4818L30.3523 19.2947H46.1656Z" fill="#80E464" />
|
|
485
|
+
<path d="M28.4333 26.4861L23.303 45.7148H39.1098L44.245 26.4861H28.4333Z" fill="#80E464" />
|
|
486
|
+
<path d="M21.54 52.3526H5.73559L0.458496 72.1341H16.2572L21.54 52.3526Z" fill="#20AAFF" />
|
|
487
|
+
<path d="M12.6359 26.4861L7.50635 45.7148H23.3124L28.4476 26.4861H12.6359Z" fill="#20AAFF" />
|
|
488
|
+
<path
|
|
489
|
+
d="M30.3683 19.2947L35.5035 0.0684052H19.6844L14.5549 19.2947H30.3683Z"
|
|
490
|
+
fill="#20AAFF"
|
|
491
|
+
/>
|
|
492
|
+
<path d="M68.7538 52.3526H52.9495L47.6724 72.1341H63.471L68.7538 52.3526Z" fill="#FF65DB" />
|
|
493
|
+
<path d="M59.8513 26.4861L54.7209 45.7148H70.527L75.6622 26.4861H59.8513Z" fill="#FF65DB" />
|
|
494
|
+
<path d="M77.583 19.2947L82.7174 0.0684052H66.8991L61.7688 19.2947H77.583Z" fill="#FF65DB" />
|
|
495
|
+
<path d="M84.5487 52.3526H68.7443L63.468 72.1341H79.2659L84.5487 52.3526Z" fill="#FF5148" />
|
|
496
|
+
<path d="M75.6455 26.4861L70.5151 45.7148H86.322L91.4572 26.4861H75.6455Z" fill="#FF5148" />
|
|
497
|
+
<path d="M93.3778 19.2947L98.5122 0.0684052H82.694L77.5645 19.2947H93.3778Z" fill="#FF5148" />
|
|
498
|
+
<path
|
|
499
|
+
fill-rule="evenodd"
|
|
500
|
+
clip-rule="evenodd"
|
|
501
|
+
d="M216.245 0.0681458L216.243 0.0700989V0.072052C235.424 0.072052 248.674 8.67951 245.842 19.2986L243.923 26.489C241.089 37.1082 223.245 45.7166 204.064 45.7166H202.103L242.393 72.1355H177.706L145.137 46.9959C143.833 46.1598 142.319 45.7156 140.772 45.7156H86.3262L91.4561 26.4871H186.821C190.406 26.4871 193.744 24.877 194.274 22.8914H194.276C194.806 20.9057 192.328 19.2958 188.741 19.2957H93.375L98.5039 0.0681458H216.245ZM131.582 52.3523C133.389 52.3523 134.705 54.0738 134.237 55.8269L129.888 72.1336H79.2783L84.5557 52.3523H131.582Z"
|
|
502
|
+
fill="currentColor"
|
|
503
|
+
/>
|
|
504
|
+
<path
|
|
505
|
+
d="M597.362 72.4945L616.641 0.550888H667.543L648.146 72.4945H597.362Z"
|
|
506
|
+
fill="currentColor"
|
|
507
|
+
/>
|
|
508
|
+
<path
|
|
509
|
+
d="M405.385 0.550934H570.197C592.298 0.550934 607.58 10.4256 604.288 22.6513L590.887 72.4946H540.103L547.039 46.75L551.036 32.0557L552.564 26.413C553.504 22.7688 548.92 19.7124 542.219 19.7124H527.76C527.642 20.6528 527.642 21.5933 527.29 22.6513L514.006 72.4946H463.105L470.04 46.75L474.037 32.0557L475.566 26.413C476.506 22.7688 471.921 19.7124 465.221 19.7124H451.114L436.89 72.4946H386.106L405.385 0.550934Z"
|
|
510
|
+
fill="currentColor"
|
|
511
|
+
/>
|
|
512
|
+
<path
|
|
513
|
+
fill-rule="evenodd"
|
|
514
|
+
clip-rule="evenodd"
|
|
515
|
+
d="M743.176 12.4551L760.652 0.986328H819.692L766.143 36.1279L800.923 71.9785H741.884L730.069 59.8008L711.513 71.9785H652.474L707.104 36.1279L673.009 0.986328H732.049L743.176 12.4551Z"
|
|
516
|
+
fill="currentColor"
|
|
517
|
+
/>
|
|
518
|
+
<path
|
|
519
|
+
fill-rule="evenodd"
|
|
520
|
+
clip-rule="evenodd"
|
|
521
|
+
d="M399.467 0.551117L394.413 19.7122H312.242C312.196 19.7122 312.151 19.7139 312.105 19.7142H300.223L298.349 26.8685H298.375L298.371 26.8831H392.415L387.36 46.1624H293.198L293.081 46.7503C292.023 50.3944 296.607 53.3332 303.307 53.3333H385.361L380.189 72.4945H275.33C253.23 72.4945 237.948 62.6201 241.239 50.5121L248.644 22.6517C248.809 22.0384 249.02 21.4319 249.27 20.8314L254.585 0.551117H399.467Z"
|
|
522
|
+
fill="currentColor"
|
|
523
|
+
/>
|
|
524
|
+
</svg>
|
|
525
|
+
)
|
|
526
|
+
}
|
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
import type { RemixNode } from 'remix/ui'
|
|
2
2
|
import { renderToStream } from 'remix/ui/server'
|
|
3
|
-
import { createHtmlResponse } from 'remix/response/html'
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { router } from '../router.ts'
|
|
5
|
+
|
|
6
|
+
export function render(node: RemixNode, request: Request, init?: ResponseInit) {
|
|
7
|
+
let stream = renderToStream(node, {
|
|
8
|
+
frameSrc: request.url,
|
|
9
|
+
async resolveFrame(src, target) {
|
|
10
|
+
let headers = new Headers({ accept: 'text/html' })
|
|
11
|
+
let cookie = request.headers.get('cookie')
|
|
12
|
+
if (cookie) headers.set('cookie', cookie)
|
|
13
|
+
if (target) headers.set('x-remix-target', target)
|
|
14
|
+
|
|
15
|
+
let response = await router.fetch(new Request(new URL(src, request.url), { headers }))
|
|
16
|
+
return response.body ?? response.text()
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
let headers = new Headers(init?.headers)
|
|
21
|
+
if (!headers.has('Content-Type')) {
|
|
22
|
+
headers.set('Content-Type', 'text/html; charset=utf-8')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return new Response(stream, { ...init, headers })
|
|
7
26
|
}
|
package/bootstrap/server.ts
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { createRequestListener } from 'remix/node-fetch-server'
|
|
1
|
+
import { serve } from 'remix/node-serve'
|
|
3
2
|
|
|
4
3
|
import { router } from './app/router.ts'
|
|
5
4
|
|
|
6
|
-
const
|
|
7
|
-
|
|
5
|
+
const port = process.env.PORT ? Number.parseInt(process.env.PORT, 10) : 44100
|
|
6
|
+
|
|
7
|
+
const server = serve(
|
|
8
|
+
async (request) => {
|
|
8
9
|
try {
|
|
9
10
|
return await router.fetch(request)
|
|
10
11
|
} catch (error) {
|
|
11
12
|
console.error(error)
|
|
12
13
|
return new Response('Internal Server Error', { status: 500 })
|
|
13
14
|
}
|
|
14
|
-
}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
port,
|
|
18
|
+
},
|
|
15
19
|
)
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
server.listen(port, () => {
|
|
20
|
-
console.log(`Server listening on http://localhost:${port}`)
|
|
21
|
-
})
|
|
21
|
+
await server.ready
|
|
22
|
+
console.log(`Server listening on http://localhost:${server.port}`)
|
|
22
23
|
|
|
23
24
|
let shuttingDown = false
|
|
24
25
|
|
|
@@ -28,9 +29,8 @@ function shutdown() {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
shuttingDown = true
|
|
31
|
-
server.close(
|
|
32
|
-
|
|
33
|
-
})
|
|
32
|
+
server.close()
|
|
33
|
+
process.exit(0)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
process.on('SIGINT', shutdown)
|
package/bootstrap/tsconfig.json
CHANGED
package/dist/lib/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/lib/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/lib/cli.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAsB,QAAQ,CAC5B,IAAI,GAAE,MAAM,EAA0B,EACtC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CA4BjB"}
|
package/dist/lib/cli.js
CHANGED
|
@@ -1,12 +1,5 @@
|
|
|
1
1
|
import * as process from 'node:process';
|
|
2
|
-
import { runCompletionCommand } from "./commands/completion.js";
|
|
3
|
-
import { runDoctorCommand } from "./commands/doctor.js";
|
|
4
2
|
import { getCliHelpText, runHelpCommand } from "./commands/help.js";
|
|
5
|
-
import { runNewCommand } from "./commands/new.js";
|
|
6
|
-
import { runRoutesCommand } from "./commands/routes.js";
|
|
7
|
-
import { runSkillsCommand } from "./commands/skills.js";
|
|
8
|
-
import { runTestCommand } from "./commands/test.js";
|
|
9
|
-
import { runVersionCommand } from "./commands/version.js";
|
|
10
3
|
import { resolveCliContext } from "./cli-context.js";
|
|
11
4
|
import { renderCliError, unknownCommand } from "./errors.js";
|
|
12
5
|
import { configureColors, restoreTerminalFormatting } from "./terminal.js";
|
|
@@ -39,27 +32,31 @@ async function runCommand(command, argv, context) {
|
|
|
39
32
|
return runHelpCommand(argv);
|
|
40
33
|
}
|
|
41
34
|
if (command === '-v' || command === '--version') {
|
|
35
|
+
let { runVersionCommand } = await import("./commands/version.js");
|
|
42
36
|
return runVersionCommand([], context);
|
|
43
37
|
}
|
|
44
38
|
if (command === 'new') {
|
|
39
|
+
let { runNewCommand } = await import("./commands/new.js");
|
|
45
40
|
return runNewCommand(argv, context);
|
|
46
41
|
}
|
|
47
42
|
if (command === 'completion') {
|
|
43
|
+
let { runCompletionCommand } = await import("./commands/completion.js");
|
|
48
44
|
return runCompletionCommand(argv);
|
|
49
45
|
}
|
|
50
46
|
if (command === 'doctor') {
|
|
47
|
+
let { runDoctorCommand } = await import("./commands/doctor.js");
|
|
51
48
|
return runDoctorCommand(argv, context);
|
|
52
49
|
}
|
|
53
|
-
if (command === 'skills') {
|
|
54
|
-
return runSkillsCommand(argv, context);
|
|
55
|
-
}
|
|
56
50
|
if (command === 'routes') {
|
|
51
|
+
let { runRoutesCommand } = await import("./commands/routes.js");
|
|
57
52
|
return runRoutesCommand(argv, context);
|
|
58
53
|
}
|
|
59
54
|
if (command === 'test') {
|
|
55
|
+
let { runTestCommand } = await import("./commands/test.js");
|
|
60
56
|
return runTestCommand(argv, context);
|
|
61
57
|
}
|
|
62
58
|
if (command === 'version') {
|
|
59
|
+
let { runVersionCommand } = await import("./commands/version.js");
|
|
63
60
|
return runVersionCommand(argv, context);
|
|
64
61
|
}
|
|
65
62
|
process.stderr.write(renderCliError(unknownCommand(command), { helpText: getCliHelpText(process.stderr) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/help.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/help.ts"],"names":[],"mappings":"AAKA,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAepE;AAED,wBAAgB,cAAc,CAAC,MAAM,GAAE,MAAM,CAAC,WAA4B,GAAG,MAAM,CAiClF;AAED,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,MAAM,CAAC,WAA4B,GAAG,MAAM,CAiB1F"}
|