radiant-docs 0.1.50 → 0.1.53

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/index.js CHANGED
@@ -36,11 +36,14 @@ var log = {
36
36
  ),
37
37
  blank: () => console.log("")
38
38
  };
39
+ var SUPPORTED_COMMANDS = /* @__PURE__ */ new Set(["dev", "check", "prepare"]);
39
40
  function getUserDocsDir() {
40
41
  return process.cwd();
41
42
  }
42
43
  function getProjectHash(docsDir) {
43
- return crypto.createHash("md5").update(docsDir).digest("hex").slice(0, 8);
44
+ const cacheKey = process.env.RADIANT_CACHE_KEY?.trim();
45
+ const hashInput = cacheKey ? `cache-key:${cacheKey}` : docsDir;
46
+ return crypto.createHash("md5").update(hashInput).digest("hex").slice(0, 8);
44
47
  }
45
48
  function getCacheDir(docsDir) {
46
49
  const projectHash = getProjectHash(docsDir);
@@ -75,6 +78,9 @@ async function getDirectoryFingerprint(dir) {
75
78
  await walk(dir);
76
79
  return hash.digest("hex");
77
80
  }
81
+ function hasFrameworkDependencies(cacheDir) {
82
+ return fs.existsSync(path.join(cacheDir, "node_modules/.bin/astro"));
83
+ }
78
84
  async function validateUserDocs(docsDir) {
79
85
  const docsJsonPath = path.join(docsDir, "docs.json");
80
86
  if (!fs.existsSync(docsJsonPath)) {
@@ -94,7 +100,7 @@ async function validateUserDocs(docsDir) {
94
100
  }
95
101
  async function setupCache(cacheDir) {
96
102
  const templateDir = getTemplateDir();
97
- const nodeModulesExists = fs.existsSync(path.join(cacheDir, "node_modules"));
103
+ const dependenciesInstalled = hasFrameworkDependencies(cacheDir);
98
104
  const cacheExists = fs.existsSync(cacheDir);
99
105
  if (!fs.existsSync(templateDir)) {
100
106
  log.error(
@@ -132,7 +138,7 @@ async function setupCache(cacheDir) {
132
138
  log.success("Framework copied to cache.");
133
139
  return true;
134
140
  }
135
- return !nodeModulesExists;
141
+ return !dependenciesInstalled;
136
142
  }
137
143
  async function installDependencies(cacheDir) {
138
144
  log.info("Installing dependencies (first run only)...");
@@ -142,13 +148,15 @@ async function installDependencies(cacheDir) {
142
148
  }
143
149
  log.info(`Cache location: ${cacheDir}`);
144
150
  try {
145
- execSync("npm install --silent --no-fund --no-audit", {
151
+ const installCommand = fs.existsSync(path.join(cacheDir, "package-lock.json")) ? "npm ci --silent --no-fund --no-audit" : "npm install --silent --no-fund --no-audit";
152
+ execSync(installCommand, {
146
153
  cwd: cacheDir,
147
154
  stdio: "pipe",
148
155
  env: process.env
149
156
  });
150
157
  log.success("Dependencies installed.");
151
158
  } catch (error) {
159
+ await fs.remove(path.join(cacheDir, "node_modules"));
152
160
  log.error("Failed to install dependencies.");
153
161
  log.error(`Error details: ${error.message}`);
154
162
  throw error;
@@ -179,6 +187,66 @@ async function runAstroSync(cacheDir) {
179
187
  } catch {
180
188
  }
181
189
  }
190
+ function toCommandOutput(value) {
191
+ if (!value) return "";
192
+ if (Buffer.isBuffer(value)) return value.toString("utf-8");
193
+ return String(value);
194
+ }
195
+ function getCommandOutput(error) {
196
+ return [
197
+ toCommandOutput(error?.stdout),
198
+ toCommandOutput(error?.stderr),
199
+ toCommandOutput(error?.message)
200
+ ].filter(Boolean).join("\n");
201
+ }
202
+ function extractUserErrors(output) {
203
+ const errors = [];
204
+ for (const line of output.split("\n")) {
205
+ if (!line.includes("[USER_ERROR]")) continue;
206
+ const message = line.split("[USER_ERROR]:")[1]?.trim() || line.trim();
207
+ if (message && !errors.includes(message)) {
208
+ errors.push(message);
209
+ }
210
+ }
211
+ return errors;
212
+ }
213
+ function getOutputTail(output, maxLines = 40) {
214
+ return output.split("\n").map((line) => line.trim()).filter(Boolean).slice(-maxLines).join("\n");
215
+ }
216
+ function runFrameworkCheck(cacheDir) {
217
+ log.info("Checking documentation...");
218
+ try {
219
+ execSync("npm run check", {
220
+ cwd: cacheDir,
221
+ stdio: "pipe",
222
+ env: {
223
+ ...process.env,
224
+ RADIANT_CHECK: "1"
225
+ },
226
+ encoding: "utf-8"
227
+ });
228
+ log.success("Documentation check passed.");
229
+ } catch (error) {
230
+ const output = getCommandOutput(error);
231
+ const userErrors = extractUserErrors(output);
232
+ log.blank();
233
+ log.error("Documentation check failed.");
234
+ if (userErrors.length > 0) {
235
+ log.blank();
236
+ for (const userError of userErrors) {
237
+ log.error(userError);
238
+ }
239
+ } else {
240
+ const outputTail = getOutputTail(output);
241
+ if (outputTail) {
242
+ log.blank();
243
+ console.log(outputTail);
244
+ }
245
+ }
246
+ log.blank();
247
+ process.exit(typeof error?.status === "number" ? error.status : 1);
248
+ }
249
+ }
182
250
  function startDevServer(cacheDir) {
183
251
  const child = spawn("npm", ["run", "dev"], {
184
252
  cwd: cacheDir,
@@ -284,12 +352,14 @@ ${colors.bright}${colors.cyan}\u25C6 Radiant${colors.reset} v${VERSION}
284
352
  ${colors.bright}Usage:${colors.reset}
285
353
  radiant Start the dev server
286
354
  radiant dev Start the dev server
355
+ radiant check Validate and build the docs once
356
+ radiant prepare Prepare cached framework dependencies
287
357
  radiant --help Show this help message
288
358
  radiant --version Show version
289
359
 
290
360
  ${colors.bright}Description:${colors.reset}
291
361
  Run this command from your documentation folder (containing docs.json)
292
- to preview your docs locally with hot reload.
362
+ to preview your docs locally with hot reload, or run a one-time check.
293
363
  `);
294
364
  }
295
365
  async function run() {
@@ -302,8 +372,8 @@ async function run() {
302
372
  console.log(VERSION);
303
373
  process.exit(0);
304
374
  }
305
- const command = args[0];
306
- if (command && command !== "dev") {
375
+ const command = args[0] || "dev";
376
+ if (!SUPPORTED_COMMANDS.has(command)) {
307
377
  log.error(`Unknown command: ${command}`);
308
378
  showHelp();
309
379
  process.exit(1);
@@ -316,15 +386,25 @@ async function run() {
316
386
  const docsDir = getUserDocsDir();
317
387
  const cacheDir = getCacheDir(docsDir);
318
388
  const contentDir = getContentDir(cacheDir);
319
- await validateUserDocs(docsDir);
389
+ if (command !== "prepare") {
390
+ await validateUserDocs(docsDir);
391
+ }
320
392
  const needsInstall = await setupCache(cacheDir);
321
393
  if (needsInstall) {
322
394
  await installDependencies(cacheDir);
323
395
  }
396
+ if (command === "prepare") {
397
+ log.success("Radiant framework cache is ready.");
398
+ return;
399
+ }
324
400
  log.info("Syncing your documentation...");
325
401
  await syncContent(docsDir, contentDir);
326
402
  await runAstroSync(cacheDir);
327
403
  log.success("Content synced.");
404
+ if (command === "check") {
405
+ runFrameworkCheck(cacheDir);
406
+ return;
407
+ }
328
408
  log.info("Starting dev server...");
329
409
  const devServer = startDevServer(cacheDir);
330
410
  const watcher = watchUserContent(docsDir, contentDir, async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "radiant-docs",
3
- "version": "0.1.50",
3
+ "version": "0.1.53",
4
4
  "description": "CLI tool for previewing Radiant documentation locally",
5
5
  "type": "module",
6
6
  "bin": {
@@ -68,8 +68,13 @@ const headingAnchorContent = {
68
68
  ],
69
69
  };
70
70
 
71
- if (process.env.npm_lifecycle_event === "build") {
72
- // Run validation for build before Astro's internal validation
71
+ const shouldValidateDocs =
72
+ process.env.npm_lifecycle_event === "build" ||
73
+ process.env.npm_lifecycle_event === "check" ||
74
+ process.env.RADIANT_CHECK === "1";
75
+
76
+ if (shouldValidateDocs) {
77
+ // Run validation before Astro's internal validation for build/check commands.
73
78
  try {
74
79
  await getConfig();
75
80
  await validateMdxContent();
@@ -5,6 +5,7 @@
5
5
  "scripts": {
6
6
  "dev": "astro dev",
7
7
  "start": "tsx runner.ts",
8
+ "check": "astro build",
8
9
  "prebuild": "rm -rf public/pagefind",
9
10
  "build": "astro build && node scripts/remove-assistant-for-non-pro.mjs && node scripts/generate-og-metadata.mjs && node scripts/generate-og-images.mjs && node scripts/stamp-og-image-versions.mjs && node scripts/stamp-image-versions.mjs && pagefind --site dist && node scripts/stamp-pagefind-runtime-version.mjs && node scripts/generate-proxy-allowed-origins.mjs && node scripts/generate-robots-txt.mjs",
10
11
  "preview": "astro preview",
@@ -77,14 +77,14 @@ const assistantHeaderButtonStyle = assistantHeaderThemeColors
77
77
  ? [
78
78
  `--assistant-header-theme-light: ${assistantHeaderThemeColors.light}`,
79
79
  `--assistant-header-theme-dark: ${assistantHeaderThemeColors.dark}`,
80
- `--assistant-header-foreground-light: ${
81
- config.assistant?.icon?.color ??
82
- getButtonForegroundColor("light", assistantHeaderThemeColors.light)
83
- }`,
84
- `--assistant-header-foreground-dark: ${
85
- config.assistant?.icon?.color ??
86
- getButtonForegroundColor("dark", assistantHeaderThemeColors.dark)
87
- }`,
80
+ `--assistant-header-foreground-light: ${getButtonForegroundColor(
81
+ "light",
82
+ assistantHeaderThemeColors.light,
83
+ )}`,
84
+ `--assistant-header-foreground-dark: ${getButtonForegroundColor(
85
+ "dark",
86
+ assistantHeaderThemeColors.dark,
87
+ )}`,
88
88
  ].join("; ")
89
89
  : "";
90
90
 
@@ -153,18 +153,14 @@ export function getAssistantLauncherIconConfig(
153
153
  dark: getAssistantButtonColor(config, "dark"),
154
154
  };
155
155
  const iconColors = {
156
- light:
157
- assistantConfig?.icon?.color ??
158
- getThemeForegroundColor(
159
- themeColors.light,
160
- getDocsBaseColorShade(config.theme, "light", "900"),
161
- ),
162
- dark:
163
- assistantConfig?.icon?.color ??
164
- getThemeForegroundColor(
165
- themeColors.dark,
166
- getDocsBaseColorShade(config.theme, "dark", "900"),
167
- ),
156
+ light: getThemeForegroundColor(
157
+ themeColors.light,
158
+ getDocsBaseColorShade(config.theme, "light", "900"),
159
+ ),
160
+ dark: getThemeForegroundColor(
161
+ themeColors.dark,
162
+ getDocsBaseColorShade(config.theme, "dark", "900"),
163
+ ),
168
164
  };
169
165
  const icon = resolveLauncherIcon(assistantConfig?.icon?.src);
170
166
 
@@ -297,9 +293,240 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
297
293
  });
298
294
  }
299
295
 
296
+ function normalizePathForMatching(value) {
297
+ var pathname = String(value || "").trim();
298
+ if (!pathname) return "";
299
+ if (pathname === "*") return "*";
300
+
301
+ try {
302
+ if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(pathname)) {
303
+ pathname = new URL(pathname).pathname;
304
+ }
305
+ } catch {
306
+ // Fall back to treating the value as a path pattern.
307
+ }
308
+
309
+ var hashIndex = pathname.indexOf("#");
310
+ if (hashIndex >= 0) {
311
+ pathname = pathname.slice(0, hashIndex);
312
+ }
313
+
314
+ var queryIndex = pathname.indexOf("?");
315
+ if (queryIndex >= 0) {
316
+ pathname = pathname.slice(0, queryIndex);
317
+ }
318
+
319
+ if (!pathname) return "";
320
+ if (pathname.charAt(0) !== "/") {
321
+ pathname = "/" + pathname;
322
+ }
323
+
324
+ pathname = pathname.replace(/\\/{2,}/g, "/");
325
+ if (pathname.length > 1 && !pathname.endsWith("/*")) {
326
+ pathname = pathname.replace(/\\/+$/, "");
327
+ }
328
+
329
+ return pathname || "/";
330
+ }
331
+
332
+ function parsePathPatterns(value) {
333
+ var rawPatterns = [];
334
+
335
+ if (Array.isArray(value)) {
336
+ rawPatterns = value;
337
+ } else if (typeof value === "string") {
338
+ var trimmed = value.trim();
339
+ if (!trimmed) return [];
340
+
341
+ if (trimmed.charAt(0) === "[") {
342
+ try {
343
+ var parsed = JSON.parse(trimmed);
344
+ if (Array.isArray(parsed)) {
345
+ rawPatterns = parsed;
346
+ } else {
347
+ rawPatterns = [trimmed];
348
+ }
349
+ } catch {
350
+ rawPatterns = trimmed.split(/[\\n,]/);
351
+ }
352
+ } else {
353
+ rawPatterns = trimmed.split(/[\\n,]/);
354
+ }
355
+ }
356
+
357
+ var seenPatterns = {};
358
+ return rawPatterns
359
+ .map(normalizePathForMatching)
360
+ .filter(function (pattern) {
361
+ if (!pattern || seenPatterns[pattern]) return false;
362
+ seenPatterns[pattern] = true;
363
+ return true;
364
+ });
365
+ }
366
+
367
+ function escapeRegExp(value) {
368
+ return String(value).replace(/[|\\\\{}()[\\]^$+?.]/g, "\\\\$&");
369
+ }
370
+
371
+ function pathMatchesPattern(pathname, pattern) {
372
+ if (pattern === "*") return true;
373
+
374
+ if (pattern.endsWith("/*")) {
375
+ var basePath = normalizePathForMatching(pattern.slice(0, -2));
376
+ return pathname === basePath || pathname.startsWith(basePath + "/");
377
+ }
378
+
379
+ if (pattern.indexOf("*") >= 0) {
380
+ var patternRegex = new RegExp(
381
+ "^" + pattern.split("*").map(escapeRegExp).join(".*") + "$",
382
+ );
383
+ return patternRegex.test(pathname);
384
+ }
385
+
386
+ return pathname === pattern;
387
+ }
388
+
389
+ function isCurrentPathExcluded() {
390
+ if (!excludedPathPatterns.length) return false;
391
+ var pathname = normalizePathForMatching(window.location.pathname || "/");
392
+ return excludedPathPatterns.some(function (pattern) {
393
+ return pathMatchesPattern(pathname, pattern);
394
+ });
395
+ }
396
+
397
+ function parseDurationMs(value, fallbackMs) {
398
+ var rawValue = String(value || "").trim();
399
+ var match = rawValue.match(/^([0-9]*\\.?[0-9]+)(ms|s)$/);
400
+ if (!match) return fallbackMs;
401
+
402
+ var amount = Number.parseFloat(match[1]);
403
+ if (!Number.isFinite(amount)) return fallbackMs;
404
+
405
+ return match[2] === "s" ? amount * 1000 : amount;
406
+ }
407
+
408
+ function clearRouteVisibilityRemovalTimeout() {
409
+ if (!routeVisibilityRemovalTimeout) return;
410
+ window.clearTimeout(routeVisibilityRemovalTimeout);
411
+ routeVisibilityRemovalTimeout = undefined;
412
+ }
413
+
414
+ function unmountEmbedElements() {
415
+ clearRouteVisibilityRemovalTimeout();
416
+ setOpen(false);
417
+
418
+ if (launcherButton) {
419
+ launcherButton.remove();
420
+ launcherButton = undefined;
421
+ }
422
+
423
+ if (panelShell) {
424
+ panelShell.remove();
425
+ panelShell = undefined;
426
+ }
427
+
428
+ panelFrame = undefined;
429
+ }
430
+
431
+ function hideEmbedElementsForRouteExclusion() {
432
+ if (!panelShell && !launcherButton) {
433
+ return;
434
+ }
435
+
436
+ clearRouteVisibilityRemovalTimeout();
437
+ setOpen(false);
438
+
439
+ if (launcherButton) {
440
+ launcherButton.dataset.routeHidden = "true";
441
+ }
442
+
443
+ routeVisibilityRemovalTimeout = window.setTimeout(function () {
444
+ routeVisibilityRemovalTimeout = undefined;
445
+ if (isCurrentPathExcluded()) {
446
+ unmountEmbedElements();
447
+ }
448
+ }, routeVisibilityRemovalDelayMs);
449
+ }
450
+
451
+ function applyRouteVisibility() {
452
+ if (isCurrentPathExcluded()) {
453
+ hideEmbedElementsForRouteExclusion();
454
+ return;
455
+ }
456
+
457
+ mount();
458
+ }
459
+
460
+ function scheduleRouteVisibilityCheck() {
461
+ window.setTimeout(applyRouteVisibility, 0);
462
+ }
463
+
464
+ function installRouteVisibilityListeners() {
465
+ if (!excludedPathPatterns.length || routeVisibilityListenersInstalled) {
466
+ return;
467
+ }
468
+
469
+ routeVisibilityListenersInstalled = true;
470
+
471
+ if (window.history && typeof window.history.pushState === "function") {
472
+ originalHistoryPushState = window.history.pushState;
473
+ patchedHistoryPushState = function () {
474
+ var result = originalHistoryPushState.apply(this, arguments);
475
+ scheduleRouteVisibilityCheck();
476
+ return result;
477
+ };
478
+ window.history.pushState = patchedHistoryPushState;
479
+ }
480
+
481
+ if (window.history && typeof window.history.replaceState === "function") {
482
+ originalHistoryReplaceState = window.history.replaceState;
483
+ patchedHistoryReplaceState = function () {
484
+ var result = originalHistoryReplaceState.apply(this, arguments);
485
+ scheduleRouteVisibilityCheck();
486
+ return result;
487
+ };
488
+ window.history.replaceState = patchedHistoryReplaceState;
489
+ }
490
+
491
+ window.addEventListener("popstate", scheduleRouteVisibilityCheck);
492
+ window.addEventListener("hashchange", scheduleRouteVisibilityCheck);
493
+ }
494
+
495
+ function restoreRouteVisibilityListeners() {
496
+ if (!routeVisibilityListenersInstalled) {
497
+ return;
498
+ }
499
+
500
+ if (
501
+ window.history &&
502
+ patchedHistoryPushState &&
503
+ window.history.pushState === patchedHistoryPushState
504
+ ) {
505
+ window.history.pushState = originalHistoryPushState;
506
+ }
507
+
508
+ if (
509
+ window.history &&
510
+ patchedHistoryReplaceState &&
511
+ window.history.replaceState === patchedHistoryReplaceState
512
+ ) {
513
+ window.history.replaceState = originalHistoryReplaceState;
514
+ }
515
+
516
+ window.removeEventListener("popstate", scheduleRouteVisibilityCheck);
517
+ window.removeEventListener("hashchange", scheduleRouteVisibilityCheck);
518
+ routeVisibilityListenersInstalled = false;
519
+ }
520
+
300
521
  var docsOrigin = resolveDocsOrigin();
301
522
  var docsBasePath = resolveDocsBasePath();
302
523
  var chrome = generatedConfig.chrome || {};
524
+ var excludedPathPatterns = parsePathPatterns(
525
+ scriptDataset.excludePaths ||
526
+ globalConfig.excludePaths ||
527
+ globalConfig.excludedPaths ||
528
+ "",
529
+ );
303
530
  var zIndex = scriptDataset.zIndex || chrome.zIndex || "2147483000";
304
531
  var configuredMode =
305
532
  scriptDataset.mode ||
@@ -339,6 +566,7 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
339
566
  var panelSizeTiming = chrome.panelSizeTiming || "cubic-bezier(.22,1.18,.36,1)";
340
567
  var panelCloseDuration = chrome.panelCloseDuration || ".2s";
341
568
  var panelCloseTiming = chrome.panelCloseTiming || "cubic-bezier(.25,1,.5,1)";
569
+ var launcherRouteExitDurationMs = 460;
342
570
  var mobileBreakpoint = chrome.mobileBreakpoint || "640px";
343
571
  var panelFullscreenHeightBreakpoint =
344
572
  chrome.panelFullscreenHeightBreakpoint || "560px";
@@ -367,6 +595,17 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
367
595
  var panelSize = readPanelSize();
368
596
  var panelSizeTransitionTimeout;
369
597
  var isPanelFullscreen = false;
598
+ var routeVisibilityRemovalTimeout;
599
+ var routeVisibilityRemovalDelayMs =
600
+ Math.max(
601
+ parseDurationMs(panelCloseDuration, 200),
602
+ launcherRouteExitDurationMs,
603
+ ) + 80;
604
+ var routeVisibilityListenersInstalled = false;
605
+ var originalHistoryPushState;
606
+ var originalHistoryReplaceState;
607
+ var patchedHistoryPushState;
608
+ var patchedHistoryReplaceState;
370
609
  var systemThemeMediaQuery =
371
610
  typeof window.matchMedia === "function"
372
611
  ? window.matchMedia("(prefers-color-scheme: dark)")
@@ -508,9 +747,11 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
508
747
  style.textContent = [
509
748
  ".assistant-embed-frame{display:block;width:100%;height:100%;border:0;background:transparent;color-scheme:normal;}",
510
749
  "@keyframes assistant-embed-launcher-enter{0%{opacity:0;transform:translateY(3px) scale(.96);}46%{opacity:1;transform:translateY(0) scale(1.012);}72%{opacity:1;transform:translateY(0) scale(.998);}100%{opacity:1;transform:translateY(0) scale(1);}}",
750
+ "@keyframes assistant-embed-launcher-exit{0%{opacity:1;transform:translateY(0) scale(1);}28%{opacity:1;transform:translateY(0) scale(.998);}54%{opacity:1;transform:translateY(0) scale(1.012);}100%{opacity:0;transform:translateY(3px) scale(.96);}}",
511
751
  ".assistant-embed-launcher{position:fixed;display:inline-flex;align-items:center;justify-content:center;border:0;padding:0;cursor:pointer;color:var(--assistant-embed-icon-color);background:linear-gradient(to bottom,color-mix(in oklab,var(--assistant-embed-theme) 88%,white),color-mix(in oklab,var(--assistant-embed-theme) 90%,black));animation:assistant-embed-launcher-enter 460ms linear backwards;transition:transform 180ms ease,opacity 160ms ease;transform-origin:center center;}",
512
752
  ".assistant-embed-launcher:hover{opacity:.96;transform:translateY(-1px) scale(1.03);}",
513
753
  ".assistant-embed-launcher:active{transform:translateY(0) scale(.96);}",
754
+ ".assistant-embed-launcher[data-route-hidden='true']{pointer-events:none;animation:assistant-embed-launcher-exit 460ms linear forwards;}",
514
755
  ".assistant-embed-launcher{width:" +
515
756
  launcherSize +
516
757
  ";height:" +
@@ -883,6 +1124,10 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
883
1124
  }
884
1125
 
885
1126
  function setOpen(nextOpen) {
1127
+ if (nextOpen === true && isCurrentPathExcluded()) {
1128
+ return;
1129
+ }
1130
+
886
1131
  var wasOpen = isOpen;
887
1132
  isOpen = nextOpen === true;
888
1133
  setPanelOpen(isOpen);
@@ -972,6 +1217,25 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
972
1217
  return;
973
1218
  }
974
1219
 
1220
+ if (isCurrentPathExcluded()) {
1221
+ hideEmbedElementsForRouteExclusion();
1222
+ return;
1223
+ }
1224
+
1225
+ clearRouteVisibilityRemovalTimeout();
1226
+
1227
+ if (launcherButton) {
1228
+ delete launcherButton.dataset.routeHidden;
1229
+ }
1230
+
1231
+ if (panelShell && launcherButton) {
1232
+ return;
1233
+ }
1234
+
1235
+ if (panelShell || launcherButton) {
1236
+ unmountEmbedElements();
1237
+ }
1238
+
975
1239
  ensureStyle();
976
1240
  updatePanelLayout();
977
1241
 
@@ -1063,16 +1327,12 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
1063
1327
  },
1064
1328
  destroy: function () {
1065
1329
  setSystemThemeListener(false);
1330
+ restoreRouteVisibilityListeners();
1066
1331
  window.removeEventListener("resize", updatePanelLayout);
1067
1332
  if (panelSizeTransitionTimeout) {
1068
1333
  window.clearTimeout(panelSizeTransitionTimeout);
1069
1334
  }
1070
- if (launcherButton) {
1071
- launcherButton.remove();
1072
- }
1073
- if (panelShell) {
1074
- panelShell.remove();
1075
- }
1335
+ unmountEmbedElements();
1076
1336
  var style = document.getElementById(styleId);
1077
1337
  if (style) {
1078
1338
  style.remove();
@@ -1082,6 +1342,7 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
1082
1342
  };
1083
1343
 
1084
1344
  setSystemThemeListener(themeMode === "system");
1345
+ installRouteVisibilityListeners();
1085
1346
  mount();
1086
1347
  })();
1087
1348
  `;
@@ -259,7 +259,6 @@ export type DocsTheme = {
259
259
  };
260
260
  export type AssistantIcon = {
261
261
  src?: string;
262
- color?: string;
263
262
  };
264
263
  export type AssistantButtonSize = "small" | "default";
265
264
  export type AssistantButtonConfig = {
@@ -2405,22 +2404,19 @@ function validateAssistant(assistant: DocsConfig["assistant"]): void {
2405
2404
  ]);
2406
2405
  }
2407
2406
 
2408
- const allowedIconKeys = new Set(["src", "color"]);
2407
+ const allowedIconKeys = new Set(["src"]);
2409
2408
  for (const key of Object.keys(assistant.icon)) {
2410
2409
  if (!allowedIconKeys.has(key)) {
2411
2410
  throwConfigError(
2412
- "Assistant icon only supports 'src' and 'color'.",
2411
+ "Assistant icon only supports 'src'.",
2413
2412
  ["assistant", "icon", key],
2414
2413
  );
2415
2414
  }
2416
2415
  }
2417
2416
 
2418
- if (
2419
- assistant.icon.src === undefined &&
2420
- assistant.icon.color === undefined
2421
- ) {
2417
+ if (assistant.icon.src === undefined) {
2422
2418
  throwConfigError(
2423
- "Assistant icon must include 'src', 'color', or both.",
2419
+ "Assistant icon must include 'src'.",
2424
2420
  ["assistant", "icon"],
2425
2421
  );
2426
2422
  }
@@ -2432,13 +2428,6 @@ function validateAssistant(assistant: DocsConfig["assistant"]): void {
2432
2428
  );
2433
2429
  }
2434
2430
 
2435
- if (assistant.icon.color !== undefined) {
2436
- assistant.icon.color = normalizeHexColor(
2437
- assistant.icon.color,
2438
- ["assistant", "icon", "color"],
2439
- "Assistant icon color",
2440
- );
2441
- }
2442
2431
  }
2443
2432
 
2444
2433
  function validateHome(home: DocsConfig["home"]): string | undefined {