@rangojs/router 0.0.0-experimental.f2337aef → 0.0.0-experimental.fa8a383a
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/dist/bin/rango.js +8 -3
- package/dist/vite/index.js +139 -200
- package/package.json +1 -1
- package/skills/caching/SKILL.md +37 -4
- package/skills/parallel/SKILL.md +59 -0
- package/src/browser/event-controller.ts +5 -0
- package/src/browser/navigation-bridge.ts +1 -3
- package/src/browser/navigation-client.ts +60 -27
- package/src/browser/navigation-transaction.ts +11 -9
- package/src/browser/partial-update.ts +39 -9
- package/src/browser/prefetch/cache.ts +57 -5
- package/src/browser/prefetch/fetch.ts +30 -21
- package/src/browser/prefetch/queue.ts +53 -13
- package/src/browser/react/Link.tsx +9 -1
- package/src/browser/react/NavigationProvider.tsx +27 -0
- package/src/browser/rsc-router.tsx +109 -57
- package/src/browser/scroll-restoration.ts +20 -7
- package/src/browser/segment-reconciler.ts +6 -1
- package/src/browser/types.ts +9 -0
- package/src/build/route-types/router-processing.ts +12 -2
- package/src/cache/cache-scope.ts +2 -2
- package/src/cache/cf/cf-cache-store.ts +453 -11
- package/src/cache/cf/index.ts +5 -1
- package/src/cache/document-cache.ts +17 -7
- package/src/cache/index.ts +1 -0
- package/src/debug.ts +2 -2
- package/src/route-definition/dsl-helpers.ts +32 -7
- package/src/route-definition/redirect.ts +2 -2
- package/src/router/lazy-includes.ts +4 -1
- package/src/router/logging.ts +1 -1
- package/src/router/manifest.ts +9 -3
- package/src/router/match-middleware/background-revalidation.ts +18 -1
- package/src/router/match-middleware/cache-lookup.ts +20 -3
- package/src/router/match-middleware/cache-store.ts +32 -6
- package/src/router/match-middleware/intercept-resolution.ts +9 -7
- package/src/router/match-middleware/segment-resolution.ts +7 -5
- package/src/router/match-result.ts +11 -1
- package/src/router/middleware.ts +2 -1
- package/src/router/segment-resolution/fresh.ts +104 -14
- package/src/router/segment-resolution/loader-cache.ts +1 -0
- package/src/router/segment-resolution/revalidation.ts +307 -272
- package/src/router.ts +5 -1
- package/src/rsc/handler.ts +9 -0
- package/src/segment-system.tsx +140 -4
- package/src/server/context.ts +90 -13
- package/src/server/request-context.ts +10 -4
- package/src/ssr/index.tsx +1 -0
- package/src/types/route-entry.ts +7 -0
- package/src/types/segments.ts +2 -0
- package/src/urls/path-helper.ts +1 -1
- package/src/vite/discovery/state.ts +0 -2
- package/src/vite/plugin-types.ts +0 -83
- package/src/vite/plugins/expose-action-id.ts +1 -3
- package/src/vite/plugins/version-plugin.ts +13 -1
- package/src/vite/rango.ts +144 -209
- package/src/vite/router-discovery.ts +0 -8
- package/src/vite/utils/banner.ts +3 -3
package/src/vite/rango.ts
CHANGED
|
@@ -13,10 +13,7 @@ import {
|
|
|
13
13
|
getExcludeDeps,
|
|
14
14
|
getPackageAliases,
|
|
15
15
|
} from "./utils/package-resolution.js";
|
|
16
|
-
import {
|
|
17
|
-
createScanFilter,
|
|
18
|
-
findRouterFiles,
|
|
19
|
-
} from "../build/generate-route-types.js";
|
|
16
|
+
import { findRouterFiles } from "../build/generate-route-types.js";
|
|
20
17
|
import { createVersionPlugin } from "./plugins/version-plugin.js";
|
|
21
18
|
import {
|
|
22
19
|
sharedEsbuildOptions,
|
|
@@ -24,11 +21,7 @@ import {
|
|
|
24
21
|
onwarn,
|
|
25
22
|
getManualChunks,
|
|
26
23
|
} from "./utils/shared-utils.js";
|
|
27
|
-
import type {
|
|
28
|
-
RangoOptions,
|
|
29
|
-
RangoNodeOptions,
|
|
30
|
-
RscPluginOptions,
|
|
31
|
-
} from "./plugin-types.js";
|
|
24
|
+
import type { RangoOptions } from "./plugin-types.js";
|
|
32
25
|
import { printBanner, rangoVersion } from "./utils/banner.js";
|
|
33
26
|
import { createVersionInjectorPlugin } from "./plugins/version-injector.js";
|
|
34
27
|
import { createCjsToEsmPlugin } from "./plugins/cjs-to-esm.js";
|
|
@@ -43,7 +36,7 @@ import { createRouterDiscoveryPlugin } from "./router-discovery.js";
|
|
|
43
36
|
* @example Node.js (default)
|
|
44
37
|
* ```ts
|
|
45
38
|
* export default defineConfig({
|
|
46
|
-
* plugins: [react(), rango(
|
|
39
|
+
* plugins: [react(), rango()],
|
|
47
40
|
* });
|
|
48
41
|
* ```
|
|
49
42
|
*
|
|
@@ -69,9 +62,6 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
69
62
|
const rangoAliases = getPackageAliases();
|
|
70
63
|
const excludeDeps = getExcludeDeps();
|
|
71
64
|
|
|
72
|
-
// Track RSC entry path for version injection
|
|
73
|
-
let rscEntryPath: string | null = null;
|
|
74
|
-
|
|
75
65
|
// Mutable ref for router path (node preset only).
|
|
76
66
|
// Set immediately when user-specified, or populated by the auto-discover
|
|
77
67
|
// config() hook using Vite's resolved root.
|
|
@@ -207,198 +197,148 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
207
197
|
// packages that are also imported directly by client components.
|
|
208
198
|
plugins.push(clientRefDedup());
|
|
209
199
|
} else {
|
|
210
|
-
//
|
|
211
|
-
|
|
200
|
+
// Auto-discover router using Vite's resolved root (not process.cwd())
|
|
201
|
+
plugins.push({
|
|
202
|
+
name: "@rangojs/router:auto-discover",
|
|
203
|
+
config(userConfig) {
|
|
204
|
+
if (routerRef.path) return;
|
|
205
|
+
const root = userConfig.root
|
|
206
|
+
? resolve(process.cwd(), userConfig.root)
|
|
207
|
+
: process.cwd();
|
|
208
|
+
const candidates = findRouterFiles(root);
|
|
209
|
+
if (candidates.length === 1) {
|
|
210
|
+
const abs = candidates[0];
|
|
211
|
+
routerRef.path = (
|
|
212
|
+
abs.startsWith(root) ? "./" + abs.slice(root.length + 1) : abs
|
|
213
|
+
).replaceAll("\\", "/");
|
|
214
|
+
} else if (candidates.length > 1) {
|
|
215
|
+
const list = candidates
|
|
216
|
+
.map(
|
|
217
|
+
(f) =>
|
|
218
|
+
" - " + (f.startsWith(root) ? f.slice(root.length + 1) : f),
|
|
219
|
+
)
|
|
220
|
+
.join("\n");
|
|
221
|
+
throw new Error(`[rsc-router] Multiple routers found:\n${list}`);
|
|
222
|
+
}
|
|
223
|
+
// 0 found: routerRef.path stays undefined, warn at startup via discovery plugin
|
|
224
|
+
},
|
|
225
|
+
});
|
|
212
226
|
|
|
213
|
-
|
|
227
|
+
// Always use virtual entries for client, ssr, and rsc
|
|
228
|
+
const finalEntries = {
|
|
229
|
+
client: VIRTUAL_IDS.browser,
|
|
230
|
+
ssr: VIRTUAL_IDS.ssr,
|
|
231
|
+
rsc: VIRTUAL_IDS.rsc,
|
|
232
|
+
};
|
|
214
233
|
|
|
215
|
-
//
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
`[rsc-router] Multiple routers found. Specify \`router\` to choose one:\n${list}`,
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
// 0 found: routerRef.path stays undefined, warn at startup via discovery plugin
|
|
246
|
-
},
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const rscOption = nodeOptions.rsc ?? true;
|
|
251
|
-
|
|
252
|
-
// Add RSC plugin by default (can be disabled with rsc: false)
|
|
253
|
-
if (rscOption !== false) {
|
|
254
|
-
// Dynamically import @vitejs/plugin-rsc
|
|
255
|
-
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
256
|
-
|
|
257
|
-
// Resolve entry paths: use explicit config or virtual modules
|
|
258
|
-
const userEntries =
|
|
259
|
-
typeof rscOption === "boolean" ? {} : rscOption.entries || {};
|
|
260
|
-
const finalEntries = {
|
|
261
|
-
client: userEntries.client ?? VIRTUAL_IDS.browser,
|
|
262
|
-
ssr: userEntries.ssr ?? VIRTUAL_IDS.ssr,
|
|
263
|
-
rsc: userEntries.rsc ?? VIRTUAL_IDS.rsc,
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
// Track RSC entry for version injection (only if custom entry provided)
|
|
267
|
-
rscEntryPath = userEntries.rsc ?? null;
|
|
268
|
-
|
|
269
|
-
// Create wrapper plugin that checks for duplicates
|
|
270
|
-
let hasWarnedDuplicate = false;
|
|
271
|
-
|
|
272
|
-
plugins.push({
|
|
273
|
-
name: "@rangojs/router:rsc-integration",
|
|
274
|
-
enforce: "pre",
|
|
275
|
-
|
|
276
|
-
config() {
|
|
277
|
-
// Configure environments for RSC
|
|
278
|
-
// When using virtual entries, we need to explicitly configure optimizeDeps
|
|
279
|
-
// so Vite pre-bundles React before processing the virtual modules.
|
|
280
|
-
// Without this, the dep optimizer may run multiple times with different hashes,
|
|
281
|
-
// causing React instance mismatches.
|
|
282
|
-
const useVirtualClient = finalEntries.client === VIRTUAL_IDS.browser;
|
|
283
|
-
const useVirtualSSR = finalEntries.ssr === VIRTUAL_IDS.ssr;
|
|
284
|
-
const useVirtualRSC = finalEntries.rsc === VIRTUAL_IDS.rsc;
|
|
285
|
-
|
|
286
|
-
return {
|
|
287
|
-
// Exclude rsc-router modules from optimization to prevent module duplication
|
|
288
|
-
// This ensures the same Context instance is used by both browser entry and RSC proxy modules
|
|
289
|
-
optimizeDeps: {
|
|
290
|
-
exclude: excludeDeps,
|
|
291
|
-
esbuildOptions: sharedEsbuildOptions,
|
|
292
|
-
},
|
|
293
|
-
build: {
|
|
294
|
-
rollupOptions: { onwarn },
|
|
295
|
-
},
|
|
296
|
-
resolve: {
|
|
297
|
-
alias: rangoAliases,
|
|
298
|
-
},
|
|
299
|
-
environments: {
|
|
300
|
-
client: {
|
|
301
|
-
build: {
|
|
302
|
-
rollupOptions: {
|
|
303
|
-
output: {
|
|
304
|
-
manualChunks: getManualChunks,
|
|
305
|
-
},
|
|
234
|
+
// Dynamically import @vitejs/plugin-rsc
|
|
235
|
+
const { default: rsc } = await import("@vitejs/plugin-rsc");
|
|
236
|
+
|
|
237
|
+
let hasWarnedDuplicate = false;
|
|
238
|
+
|
|
239
|
+
plugins.push({
|
|
240
|
+
name: "@rangojs/router:rsc-integration",
|
|
241
|
+
enforce: "pre",
|
|
242
|
+
|
|
243
|
+
config() {
|
|
244
|
+
return {
|
|
245
|
+
optimizeDeps: {
|
|
246
|
+
exclude: excludeDeps,
|
|
247
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
248
|
+
},
|
|
249
|
+
build: {
|
|
250
|
+
rollupOptions: { onwarn },
|
|
251
|
+
},
|
|
252
|
+
resolve: {
|
|
253
|
+
alias: rangoAliases,
|
|
254
|
+
},
|
|
255
|
+
environments: {
|
|
256
|
+
client: {
|
|
257
|
+
build: {
|
|
258
|
+
rollupOptions: {
|
|
259
|
+
output: {
|
|
260
|
+
manualChunks: getManualChunks,
|
|
306
261
|
},
|
|
307
262
|
},
|
|
308
|
-
// Always exclude rsc-router modules, conditionally add virtual entry
|
|
309
|
-
optimizeDeps: {
|
|
310
|
-
// Pre-bundle React and rsc-html-stream to prevent late discovery
|
|
311
|
-
// triggering ERR_OUTDATED_OPTIMIZED_DEP on cold starts
|
|
312
|
-
include: [
|
|
313
|
-
"react",
|
|
314
|
-
"react-dom",
|
|
315
|
-
"react/jsx-runtime",
|
|
316
|
-
"react/jsx-dev-runtime",
|
|
317
|
-
"rsc-html-stream/client",
|
|
318
|
-
],
|
|
319
|
-
exclude: excludeDeps,
|
|
320
|
-
esbuildOptions: sharedEsbuildOptions,
|
|
321
|
-
...(useVirtualClient && {
|
|
322
|
-
// Tell Vite to scan the virtual entry for dependencies
|
|
323
|
-
entries: [VIRTUAL_IDS.browser],
|
|
324
|
-
}),
|
|
325
|
-
},
|
|
326
263
|
},
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
264
|
+
optimizeDeps: {
|
|
265
|
+
include: [
|
|
266
|
+
"react",
|
|
267
|
+
"react-dom",
|
|
268
|
+
"react/jsx-runtime",
|
|
269
|
+
"react/jsx-dev-runtime",
|
|
270
|
+
"rsc-html-stream/client",
|
|
271
|
+
],
|
|
272
|
+
exclude: excludeDeps,
|
|
273
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
274
|
+
entries: [VIRTUAL_IDS.browser],
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
ssr: {
|
|
278
|
+
optimizeDeps: {
|
|
279
|
+
entries: [VIRTUAL_IDS.ssr],
|
|
280
|
+
include: [
|
|
281
|
+
"react",
|
|
282
|
+
"react-dom",
|
|
283
|
+
"react-dom/server.edge",
|
|
284
|
+
"react-dom/static.edge",
|
|
285
|
+
"react/jsx-runtime",
|
|
286
|
+
"react/jsx-dev-runtime",
|
|
287
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/client.edge",
|
|
288
|
+
],
|
|
289
|
+
exclude: excludeDeps,
|
|
290
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
rsc: {
|
|
294
|
+
optimizeDeps: {
|
|
295
|
+
entries: [VIRTUAL_IDS.rsc],
|
|
296
|
+
include: [
|
|
297
|
+
"react",
|
|
298
|
+
"react/jsx-runtime",
|
|
299
|
+
"react/jsx-dev-runtime",
|
|
300
|
+
"@vitejs/plugin-rsc/vendor/react-server-dom/server.edge",
|
|
301
|
+
],
|
|
302
|
+
esbuildOptions: sharedEsbuildOptions,
|
|
303
|
+
},
|
|
361
304
|
},
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
: "
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
}) as PluginOption,
|
|
400
|
-
);
|
|
401
|
-
}
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
configResolved(config) {
|
|
310
|
+
if (showBanner) {
|
|
311
|
+
const mode =
|
|
312
|
+
config.command === "serve"
|
|
313
|
+
? process.argv.includes("preview")
|
|
314
|
+
? "preview"
|
|
315
|
+
: "dev"
|
|
316
|
+
: "build";
|
|
317
|
+
printBanner(mode, "node", rangoVersion);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const rscMinimalCount = config.plugins.filter(
|
|
321
|
+
(p) => p.name === "rsc:minimal",
|
|
322
|
+
).length;
|
|
323
|
+
|
|
324
|
+
if (rscMinimalCount > 1 && !hasWarnedDuplicate) {
|
|
325
|
+
hasWarnedDuplicate = true;
|
|
326
|
+
console.warn(
|
|
327
|
+
"[rsc-router] Duplicate @vitejs/plugin-rsc detected. " +
|
|
328
|
+
"Remove rsc() from your vite config — rango() includes it automatically.",
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Add virtual entries plugin (RSC entry generated lazily from routerRef)
|
|
335
|
+
plugins.push(createVirtualEntriesPlugin(finalEntries, routerRef));
|
|
336
|
+
|
|
337
|
+
plugins.push(
|
|
338
|
+
rsc({
|
|
339
|
+
entries: finalEntries,
|
|
340
|
+
}) as PluginOption,
|
|
341
|
+
);
|
|
402
342
|
|
|
403
343
|
// Deduplicate client references from third-party packages in dev mode.
|
|
404
344
|
// Prevents module duplication when server components import "use client"
|
|
@@ -479,14 +419,11 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
479
419
|
// Ref for deferred auto-discovery (node preset only, undefined for cloudflare)
|
|
480
420
|
const discoveryRouterRef = preset !== "cloudflare" ? routerRef : undefined;
|
|
481
421
|
|
|
482
|
-
// Version injector: auto-injects VERSION and routes-manifest into
|
|
483
|
-
//
|
|
484
|
-
//
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
rscEntryPath ?? (preset === "cloudflare" ? undefined : null);
|
|
488
|
-
if (injectorEntryPath !== null) {
|
|
489
|
-
plugins.push(createVersionInjectorPlugin(injectorEntryPath));
|
|
422
|
+
// Version injector: auto-injects VERSION and routes-manifest into the RSC entry.
|
|
423
|
+
// For cloudflare preset, the entry is resolved lazily in configResolved.
|
|
424
|
+
// For node preset, the virtual entry already includes these imports.
|
|
425
|
+
if (preset === "cloudflare") {
|
|
426
|
+
plugins.push(createVersionInjectorPlugin(undefined));
|
|
490
427
|
}
|
|
491
428
|
|
|
492
429
|
// Transform CJS vendor files to ESM for browser compatibility
|
|
@@ -501,8 +438,6 @@ export async function rango(options?: RangoOptions): Promise<PluginOption[]> {
|
|
|
501
438
|
routerPathRef: discoveryRouterRef,
|
|
502
439
|
enableBuildPrerender: prerenderEnabled,
|
|
503
440
|
staticRouteTypesGeneration: resolvedOptions.staticRouteTypesGeneration,
|
|
504
|
-
include: resolvedOptions.include,
|
|
505
|
-
exclude: resolvedOptions.exclude,
|
|
506
441
|
}),
|
|
507
442
|
);
|
|
508
443
|
|
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
formatNestedRouterConflictError,
|
|
15
15
|
findNestedRouterConflict,
|
|
16
16
|
findRouterFiles,
|
|
17
|
-
createScanFilter,
|
|
18
17
|
} from "../build/generate-route-types.js";
|
|
19
18
|
import { createVersionPlugin } from "./plugins/version-plugin.js";
|
|
20
19
|
import { createVirtualStubPlugin } from "./plugins/virtual-stub-plugin.js";
|
|
@@ -168,13 +167,6 @@ export function createRouterDiscoveryPlugin(
|
|
|
168
167
|
s.resolvedEntryPath = entries[0];
|
|
169
168
|
}
|
|
170
169
|
}
|
|
171
|
-
// Compile include/exclude patterns into a scan filter
|
|
172
|
-
if (opts?.include || opts?.exclude) {
|
|
173
|
-
s.scanFilter = createScanFilter(s.projectRoot, {
|
|
174
|
-
include: opts.include,
|
|
175
|
-
exclude: opts.exclude,
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
170
|
// Generate combined named-routes.gen.ts from static source parsing.
|
|
179
171
|
// Runs before the dev server starts so the gen file exists immediately for IDE.
|
|
180
172
|
// In build mode, the runtime discovery in buildStart produces the definitive
|
package/src/vite/utils/banner.ts
CHANGED
|
@@ -23,11 +23,11 @@ ${dim} ╱${reset} ${bold}╔═╗${reset}${dim} * ╱
|
|
|
23
23
|
${dim} ${reset}${bold}║ ║${reset} ${bold}╔═╗${reset}${dim} * ✧. ╱${reset}
|
|
24
24
|
${dim} ${reset}${bold}╔╗ ║ ║ ║ ║${reset}${dim} * ╱${reset}
|
|
25
25
|
${dim} ${reset}${bold}║║ ║ ║ ║ ║ ╦═╗╔═╗╔╗╔╔═╗╔═╗${reset}${dim} ✧ ✦${reset}
|
|
26
|
-
${dim}
|
|
26
|
+
${dim} ${reset}${bold}║║ ║ ╠═╝ ║ ╠╦╝╠═╣║║║║ ╦║ ║${reset}${dim} * ✧${reset}
|
|
27
27
|
${dim} ${reset}${bold}║╚═╝ ╔═══╝ ╩╚═╩ ╩╝╚╝╚═╝╚═╝${reset}${dim} ✦ . *${reset}
|
|
28
28
|
${dim} ${reset}${bold}╚══╗ ║${reset}${dim} * RSC Wrangler ✧ ✦${reset}
|
|
29
|
-
${dim} * ${reset}${bold}║
|
|
30
|
-
${bold}
|
|
29
|
+
${dim} * ${reset}${bold}║ ║${reset}${dim} * ✧. ╱${reset}
|
|
30
|
+
${dim} ${reset}${bold}═══╝ ╚════${reset}${dim} ✦ *${reset}
|
|
31
31
|
|
|
32
32
|
v${version} · ${preset} · ${mode}
|
|
33
33
|
`;
|