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
|
-
|
|
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
|
|
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 !
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
@@ -68,8 +68,13 @@ const headingAnchorContent = {
|
|
|
68
68
|
],
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
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();
|
package/template/package.json
CHANGED
|
@@ -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
|
-
|
|
82
|
-
|
|
83
|
-
}`,
|
|
84
|
-
`--assistant-header-foreground-dark: ${
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
-
|
|
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"
|
|
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'
|
|
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'
|
|
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 {
|