radiant-docs 0.1.68 → 0.1.70

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.
@@ -62,6 +62,9 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
62
62
  <div
63
63
  class="rd-prose-block rd-component-preview isolate flex w-full max-w-full min-w-0 flex-col"
64
64
  data-rd-component-preview-root="true"
65
+ data-rd-preview-visible-lines={String(visibleLines)}
66
+ data-rd-preview-total-line-count={String(totalLineCount)}
67
+ data-rd-preview-show-all-code={shouldShowAllCode ? "true" : "false"}
65
68
  >
66
69
  <div
67
70
  class="relative z-10 w-full max-w-full min-w-0 rounded-t-xl border-[0.5px] border-b-0 border-(--rd-code-tab-edge-border) bg-(--rd-code-surface) p-2"
@@ -215,27 +218,29 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
215
218
  }
216
219
  </style>
217
220
 
218
- <script
219
- is:inline
220
- data-astro-rerun
221
- define:vars={{
222
- visibleLines,
223
- totalLineCount,
224
- shouldShowAllCode,
225
- }}
226
- >
227
- (() => {
228
- const script = document.currentScript;
229
- if (!(script instanceof HTMLScriptElement)) return;
230
-
231
- let root = script.previousElementSibling;
232
- while (
233
- root &&
234
- (!(root instanceof HTMLElement) ||
235
- !root.hasAttribute("data-rd-component-preview-root"))
236
- ) {
237
- root = root.previousElementSibling;
238
- }
221
+ <script>
222
+ const previewRootSelector = '[data-rd-component-preview-root="true"]';
223
+ const previewControlsKey = "__rdComponentPreviewControls";
224
+
225
+ const parsePositiveInteger = (value, fallback) => {
226
+ const parsed = Number.parseInt(value ?? "", 10);
227
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
228
+ };
229
+
230
+ const syncExpandedHeight = (root) => {
231
+ const codeWrapper = root.querySelector(".rd-component-preview__code");
232
+ if (!(codeWrapper instanceof HTMLElement)) return;
233
+
234
+ const scrollArea = codeWrapper.querySelector("[data-rd-code-scroll-area]");
235
+ if (!(scrollArea instanceof HTMLElement)) return;
236
+
237
+ codeWrapper.style.setProperty(
238
+ "--rd-preview-expanded-height",
239
+ `${scrollArea.scrollHeight}px`,
240
+ );
241
+ };
242
+
243
+ const initComponentPreview = (root) => {
239
244
  if (!(root instanceof HTMLElement)) return;
240
245
 
241
246
  const codeWrapper = root.querySelector(".rd-component-preview__code");
@@ -252,30 +257,66 @@ const isInitiallyExpanded = shouldShowAllCode || totalLineCount <= visibleLines;
252
257
  return;
253
258
  }
254
259
 
255
- const syncExpandedHeight = () => {
256
- codeWrapper.style.setProperty(
257
- "--rd-preview-expanded-height",
258
- `${scrollArea.scrollHeight}px`,
259
- );
260
- };
260
+ syncExpandedHeight(root);
261
+
262
+ if (root.dataset.rdComponentPreviewInitialized === "true") return;
263
+ root.dataset.rdComponentPreviewInitialized = "true";
261
264
 
262
- syncExpandedHeight();
265
+ const visibleLines = parsePositiveInteger(
266
+ root.dataset.rdPreviewVisibleLines,
267
+ 5,
268
+ );
269
+ const totalLineCount = parsePositiveInteger(
270
+ root.dataset.rdPreviewTotalLineCount,
271
+ visibleLines,
272
+ );
273
+ const shouldShowAllCode = root.dataset.rdPreviewShowAllCode === "true";
263
274
 
264
275
  if (shouldShowAllCode || totalLineCount <= visibleLines) {
265
276
  codeWrapper.dataset.rdPreviewExpanded = "true";
266
- window.addEventListener("resize", syncExpandedHeight, { passive: true });
267
277
  return;
268
278
  }
269
279
 
270
280
  const setExpanded = () => {
271
- syncExpandedHeight();
281
+ syncExpandedHeight(root);
272
282
  codeWrapper.dataset.rdPreviewExpanded = "true";
273
283
  };
274
284
 
275
285
  expandButton.addEventListener("click", () => {
276
286
  setExpanded();
277
287
  });
288
+ };
289
+
290
+ const initComponentPreviews = () => {
291
+ document.querySelectorAll(previewRootSelector).forEach((root) => {
292
+ initComponentPreview(root);
293
+ });
294
+ };
295
+
296
+ const schedulePreviewHeightSync = () => {
297
+ if (window[previewControlsKey]?.resizeFrameId) return;
298
+
299
+ window[previewControlsKey].resizeFrameId = window.requestAnimationFrame(
300
+ () => {
301
+ window[previewControlsKey].resizeFrameId = 0;
302
+ document.querySelectorAll(previewRootSelector).forEach((root) => {
303
+ if (root instanceof HTMLElement) syncExpandedHeight(root);
304
+ });
305
+ },
306
+ );
307
+ };
308
+
309
+ window[previewControlsKey] = window[previewControlsKey] || {};
310
+ window[previewControlsKey].init = initComponentPreviews;
311
+
312
+ if (!window[previewControlsKey].installed) {
313
+ window[previewControlsKey].installed = true;
314
+ window[previewControlsKey].resizeFrameId = 0;
315
+ window.addEventListener("resize", schedulePreviewHeightSync, {
316
+ passive: true,
317
+ });
318
+ document.addEventListener("astro:page-load", initComponentPreviews);
319
+ }
278
320
 
279
- window.addEventListener("resize", syncExpandedHeight, { passive: true });
280
- })();
321
+ initComponentPreviews();
281
322
  </script>
@@ -17,6 +17,7 @@ import { resolvePageDescription } from "../lib/page-description";
17
17
  interface Props {
18
18
  pageTitle?: string;
19
19
  pageDescription?: string;
20
+ hasMarkdownAlternate?: boolean;
20
21
  }
21
22
 
22
23
  type TabsPresentation = "topbar" | "sidebar";
@@ -36,7 +37,13 @@ function routePathToOgImagePath(routePath: string): string {
36
37
  return `/_og/images/${normalizedRoutePath.slice(1, -1)}.png`;
37
38
  }
38
39
 
39
- const { pageTitle, pageDescription } = Astro.props as Props;
40
+ function routePathToMarkdownPath(routePath: string): string {
41
+ const normalizedRoutePath = routePath.replace(/^\/+/, "").replace(/\/+$/, "");
42
+ return normalizedRoutePath ? `/${normalizedRoutePath}.md` : "/index.md";
43
+ }
44
+
45
+ const { pageTitle, pageDescription, hasMarkdownAlternate = false } =
46
+ Astro.props as Props;
40
47
  const config = await getConfig();
41
48
  const favicon = getFaviconConfig();
42
49
  const neutralPaletteCss = getDocsThemeCss(config.theme);
@@ -56,6 +63,12 @@ const canonicalUrl = new URL(
56
63
  prependBasePath(routePathname),
57
64
  Astro.site ?? Astro.url,
58
65
  ).toString();
66
+ const markdownUrl = hasMarkdownAlternate
67
+ ? new URL(
68
+ prependBasePath(routePathToMarkdownPath(routePathname)),
69
+ Astro.site ?? Astro.url,
70
+ ).toString()
71
+ : undefined;
59
72
  const ogImageUrl = new URL(
60
73
  resolveStaticAssetUrl(routePathToOgImagePath(routePathname)),
61
74
  Astro.site ?? Astro.url,
@@ -77,6 +90,7 @@ const hasNavigationTabs =
77
90
  const tabsPresentation = navigationTabs?.presentation ?? "topbar";
78
91
  const hasTopbarNavigationTabs =
79
92
  hasNavigationTabs && tabsPresentation === "topbar";
93
+ const hasPagePagination = Astro.slots.has("page-pagination");
80
94
  ---
81
95
 
82
96
  <!doctype html>
@@ -288,6 +302,16 @@ const hasTopbarNavigationTabs =
288
302
  />
289
303
  <meta name="generator" content={Astro.generator} />
290
304
  <link rel="canonical" href={canonicalUrl} />
305
+ {
306
+ markdownUrl && (
307
+ <link
308
+ rel="alternate"
309
+ type="text/markdown"
310
+ href={markdownUrl}
311
+ title="Markdown version"
312
+ />
313
+ )
314
+ }
291
315
  <meta property="og:url" content={canonicalUrl} />
292
316
  <meta property="og:type" content="website" />
293
317
  <meta property="og:site_name" content={config.title} />
@@ -350,10 +374,14 @@ const hasTopbarNavigationTabs =
350
374
  <div
351
375
  x-show="open"
352
376
  x-cloak
377
+ id="mobile-navigation"
353
378
  class="rd-mobile-menu bg-background fixed lg:hidden z-50 overflow-y-auto overscroll-contain [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
354
379
  x-transition.opacity
355
380
  >
356
- <Sidebar askAiEnabled={askAiEnabled} />
381
+ <Sidebar
382
+ askAiEnabled={askAiEnabled}
383
+ showMobileNavbarActions={true}
384
+ />
357
385
  </div>
358
386
 
359
387
  <!-- Main Content -->
@@ -363,9 +391,23 @@ const hasTopbarNavigationTabs =
363
391
  hasTopbarNavigationTabs && "lg:pt-[108px]",
364
392
  ]}
365
393
  >
366
- <main class="mx-auto pt-16 pb-20 min-h-[calc(100vh-64px)]">
394
+ <main
395
+ class:list={[
396
+ "mx-auto min-h-[calc(100dvh-64px)] pt-16",
397
+ hasTopbarNavigationTabs &&
398
+ "lg:min-h-[calc(100dvh-108px)]",
399
+ hasPagePagination ? "pb-16" : "pb-20",
400
+ ]}
401
+ >
367
402
  <slot />
368
403
  </main>
404
+ {
405
+ hasPagePagination ? (
406
+ <div class="pb-20">
407
+ <slot name="page-pagination" />
408
+ </div>
409
+ ) : null
410
+ }
369
411
  <Footer askAiEnabled={askAiEnabled} />
370
412
  </div>
371
413
  {askAiEnabled ? <AssistantDocsWidget /> : null}
@@ -7,10 +7,7 @@ import {
7
7
  } from "./assistant-chrome";
8
8
  import { getDocsBasePath, withBasePath } from "./base-path";
9
9
  import { getFaviconConfig } from "./favicon";
10
- import {
11
- getDocsBaseColorShade,
12
- getThemeForegroundColor,
13
- } from "./theme-css";
10
+ import { getDocsBaseColorShade, getThemeForegroundColor } from "./theme-css";
14
11
  import { type DocsConfig, type ThemeColorByMode } from "./validation";
15
12
 
16
13
  type AssistantColorByMode = {
@@ -141,7 +138,9 @@ function getAssistantButtonColor(
141
138
  config.assistant?.button?.color,
142
139
  mode,
143
140
  );
144
- return configuredAssistantColor ?? getDefaultAssistantButtonColor(config, mode);
141
+ return (
142
+ configuredAssistantColor ?? getDefaultAssistantButtonColor(config, mode)
143
+ );
145
144
  }
146
145
 
147
146
  export function getAssistantLauncherIconConfig(
@@ -905,6 +904,7 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
905
904
  }
906
905
 
907
906
  updatePanelLayout();
907
+ postPanelPageContextMessage();
908
908
 
909
909
  try {
910
910
  panelFrame.contentWindow.postMessage(
@@ -916,6 +916,28 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
916
916
  }
917
917
  }
918
918
 
919
+ function postPanelPageContextMessage(requestId) {
920
+ if (!panelFrame || !panelFrame.contentWindow) {
921
+ return;
922
+ }
923
+
924
+ var message = {
925
+ type: "assistant-embed:set-page-context",
926
+ hostname: window.location.hostname || null,
927
+ pagePath: window.location.pathname || "/",
928
+ };
929
+
930
+ if (typeof requestId === "string" && requestId.length > 0) {
931
+ message.requestId = requestId;
932
+ }
933
+
934
+ try {
935
+ panelFrame.contentWindow.postMessage(message, getPanelTargetOrigin());
936
+ } catch {
937
+ // Ignore cross-window messaging failures.
938
+ }
939
+ }
940
+
919
941
  function getPanelTargetOrigin() {
920
942
  if (!panelFrame || !panelFrame.src) {
921
943
  return "*";
@@ -1154,6 +1176,7 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
1154
1176
  frame.addEventListener("load", function () {
1155
1177
  postPanelThemeMessage();
1156
1178
  postPanelLayoutMessage();
1179
+ postPanelPageContextMessage();
1157
1180
  if (isOpen) {
1158
1181
  notifyPanelOpened();
1159
1182
  }
@@ -1293,6 +1316,11 @@ export function renderAssistantEmbedScript(config: DocsConfig): string {
1293
1316
 
1294
1317
  if (event.data.type === "assistant-embed:get-panel-layout") {
1295
1318
  postPanelLayoutMessage();
1319
+ return;
1320
+ }
1321
+
1322
+ if (event.data.type === "assistant-embed:get-page-context") {
1323
+ postPanelPageContextMessage(event.data.requestId);
1296
1324
  }
1297
1325
  });
1298
1326
 
@@ -4,7 +4,7 @@ import {
4
4
  } from "./assistant-chrome";
5
5
  import { withBasePath } from "./base-path";
6
6
  import { getAssistantLauncherIconConfig } from "./assistant-embed-script";
7
- import type { AssistantShikiRuntimeConfig } from "./assistant-shiki-client";
7
+ import type { AssistantShikiRuntimeConfig } from "@radiant-docs/assistant-shiki";
8
8
  import { getClientShikiRuntimeConfig } from "./client-shiki-config";
9
9
  import type { DocsConfig } from "./validation";
10
10
 
@@ -1,6 +1,8 @@
1
- import type { AssistantShikiRuntimeConfig } from "./assistant-shiki-client";
1
+ import {
2
+ createAssistantShikiRuntimeConfig,
3
+ type AssistantShikiRuntimeConfig,
4
+ } from "@radiant-docs/assistant-shiki";
2
5
  import type { DocsConfig } from "./validation";
3
- import shikiPlatformAssets from "../generated/shiki-platform-assets.json";
4
6
  import {
5
7
  DEFAULT_SHIKI_DARK_THEME,
6
8
  DEFAULT_SHIKI_LIGHT_THEME,
@@ -20,10 +22,6 @@ function normalizeStaticAssetHost(value: unknown): string {
20
22
  : `https://${normalizedHost}`;
21
23
  }
22
24
 
23
- function joinUrl(baseUrl: string, path: string): string {
24
- return `${baseUrl.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
25
- }
26
-
27
25
  function getConfiguredCodeSyntaxThemes(
28
26
  config: DocsConfig,
29
27
  ): ClientShikiRuntimeConfig["syntaxThemes"] {
@@ -53,11 +51,8 @@ export function getClientShikiRuntimeConfig(
53
51
  return undefined;
54
52
  }
55
53
 
56
- return {
57
- assetBaseUrl: joinUrl(
58
- staticAssetHost,
59
- `${shikiPlatformAssets.prefix}/${shikiPlatformAssets.assetVersion}`,
60
- ),
54
+ return createAssistantShikiRuntimeConfig({
55
+ assetHost: staticAssetHost,
61
56
  syntaxThemes: getConfiguredCodeSyntaxThemes(config),
62
- };
57
+ });
63
58
  }
@@ -1,24 +0,0 @@
1
- {
2
- "assetVersion": "shiki-4.2.0-c0d7e21cea71",
3
- "counts": {
4
- "languages": 347,
5
- "themes": 66
6
- },
7
- "manifest": {
8
- "bytes": 172635,
9
- "module": "manifest.json",
10
- "sha256": "1840b6f21a79266d9bf3a74d5e6973d407fb06b96d71decd5542ca37eebf182d"
11
- },
12
- "packageVersions": {
13
- "@shikijs/core": "4.2.0",
14
- "@shikijs/engine-javascript": "4.2.0",
15
- "@shikijs/langs": "4.2.0",
16
- "@shikijs/themes": "4.2.0",
17
- "shiki": "4.2.0"
18
- },
19
- "prefix": "_platform/shiki",
20
- "runtime": {
21
- "engine": "javascript-regexp",
22
- "module": "runtime.mjs"
23
- }
24
- }