radiant-docs 0.1.62 → 0.1.63
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/package.json +1 -1
- package/template/astro.config.mjs +38 -27
- package/template/package-lock.json +2857 -1145
- package/template/package.json +16 -20
- package/template/scripts/generate-proxy-allowed-origins.mjs +10 -187
- package/template/scripts/publish-shiki-platform-assets.mjs +32 -6
- package/template/src/components/chat/AssistantEmbedPanel.tsx +133 -1
- package/template/src/components/endpoint/PlaygroundForm.astro +69 -55
- package/template/src/components/endpoint/ResponseDisplay.astro +2 -2
- package/template/src/generated/shiki-platform-assets.json +8 -8
- package/template/src/lib/assistant-panel-config.ts +2 -57
- package/template/src/lib/assistant-shiki-client.ts +16 -0
- package/template/src/lib/client-shiki-config.ts +60 -0
- package/template/src/lib/dev-playground-proxy.mjs +597 -0
- package/template/src/lib/proxy-allowed-origins.mjs +189 -0
- package/template/src/styles/global.css +4 -4
- package/template/src/components/ui/demo/CodeDemo.astro +0 -15
- package/template/src/components/ui/demo/Demo.astro +0 -3
- package/template/src/components/ui/demo/UiDisplay.astro +0 -13
|
@@ -4,6 +4,7 @@ import { withBasePath } from "../../lib/base-path";
|
|
|
4
4
|
import type { OpenApiRoute } from "../../lib/routes";
|
|
5
5
|
import { getConfig } from "../../lib/validation";
|
|
6
6
|
import { renderMarkdown } from "../../lib/utils";
|
|
7
|
+
import { getClientShikiRuntimeConfig } from "../../lib/client-shiki-config";
|
|
7
8
|
import {
|
|
8
9
|
OPENAPI_REQUEST_SECTION_LABELS,
|
|
9
10
|
type OpenApiRequestFields,
|
|
@@ -38,6 +39,7 @@ const {
|
|
|
38
39
|
} = Astro.props;
|
|
39
40
|
const headers: Record<string, string> = OPENAPI_REQUEST_SECTION_LABELS;
|
|
40
41
|
const config = await getConfig();
|
|
42
|
+
const shikiRuntimeConfig = getClientShikiRuntimeConfig(config);
|
|
41
43
|
const configuredProxyUrl =
|
|
42
44
|
typeof import.meta.env.PUBLIC_PROXY_URL === "string"
|
|
43
45
|
? import.meta.env.PUBLIC_PROXY_URL.trim()
|
|
@@ -77,6 +79,7 @@ const sectionVariantFieldNames = Object.fromEntries(
|
|
|
77
79
|
queryFieldMeta: ${JSON.stringify(queryFieldMeta)},
|
|
78
80
|
sectionVariantFieldNames: ${JSON.stringify(sectionVariantFieldNames)},
|
|
79
81
|
bodyDefaultKind: ${JSON.stringify(bodyDefaultKind ?? null)},
|
|
82
|
+
shiki: ${JSON.stringify(shikiRuntimeConfig ?? null)},
|
|
80
83
|
selectedSectionVariants: {},
|
|
81
84
|
inputs: {
|
|
82
85
|
header: {},
|
|
@@ -476,7 +479,7 @@ const sectionVariantFieldNames = Object.fromEntries(
|
|
|
476
479
|
}
|
|
477
480
|
};
|
|
478
481
|
}
|
|
479
|
-
|
|
482
|
+
|
|
480
483
|
// 6. Execute Request
|
|
481
484
|
const res = await fetch(finalUrl, finalOptions);
|
|
482
485
|
|
|
@@ -487,11 +490,12 @@ const sectionVariantFieldNames = Object.fromEntries(
|
|
|
487
490
|
responseHeaders[key] = value;
|
|
488
491
|
});
|
|
489
492
|
|
|
490
|
-
let
|
|
491
|
-
|
|
493
|
+
let responseDataText;
|
|
494
|
+
let responseDataLanguage = 'plaintext';
|
|
495
|
+
const highlightedHeaders = await window.RadiantPlaygroundHighlightCode(
|
|
492
496
|
JSON.stringify(responseHeaders, null, 2),
|
|
493
|
-
|
|
494
|
-
|
|
497
|
+
'json',
|
|
498
|
+
this.shiki,
|
|
495
499
|
);
|
|
496
500
|
const contentType = res.headers.get('content-type') || '';
|
|
497
501
|
const responseText = await res.text();
|
|
@@ -500,25 +504,19 @@ const sectionVariantFieldNames = Object.fromEntries(
|
|
|
500
504
|
try {
|
|
501
505
|
const parsed =
|
|
502
506
|
responseText.trim().length > 0 ? JSON.parse(responseText) : null;
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
Prism.languages.json,
|
|
506
|
-
'json'
|
|
507
|
-
);
|
|
507
|
+
responseDataText = JSON.stringify(parsed, null, 2);
|
|
508
|
+
responseDataLanguage = 'json';
|
|
508
509
|
} catch (parseError) {
|
|
509
|
-
|
|
510
|
-
responseText || '(empty response)',
|
|
511
|
-
Prism.languages.plaintext,
|
|
512
|
-
'plaintext'
|
|
513
|
-
);
|
|
510
|
+
responseDataText = responseText || '(empty response)';
|
|
514
511
|
}
|
|
515
512
|
} else {
|
|
516
|
-
|
|
517
|
-
responseText || '(empty response)',
|
|
518
|
-
Prism.languages.plaintext,
|
|
519
|
-
'plaintext'
|
|
520
|
-
);
|
|
513
|
+
responseDataText = responseText || '(empty response)';
|
|
521
514
|
}
|
|
515
|
+
const highlightedData = await window.RadiantPlaygroundHighlightCode(
|
|
516
|
+
responseDataText,
|
|
517
|
+
responseDataLanguage,
|
|
518
|
+
this.shiki,
|
|
519
|
+
);
|
|
522
520
|
|
|
523
521
|
this.response = {
|
|
524
522
|
status,
|
|
@@ -682,45 +680,61 @@ const sectionVariantFieldNames = Object.fromEntries(
|
|
|
682
680
|
</div>
|
|
683
681
|
|
|
684
682
|
<script>
|
|
685
|
-
import
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
683
|
+
import {
|
|
684
|
+
highlightAssistantCodeToHtml,
|
|
685
|
+
type AssistantShikiRuntimeConfig,
|
|
686
|
+
} from "../../lib/assistant-shiki-client";
|
|
687
|
+
|
|
688
|
+
type PlaygroundShikiConfig = AssistantShikiRuntimeConfig | null | undefined;
|
|
689
|
+
|
|
690
|
+
function escapeHtml(value: string): string {
|
|
691
|
+
return value
|
|
692
|
+
.replaceAll("&", "&")
|
|
693
|
+
.replaceAll("<", "<")
|
|
694
|
+
.replaceAll(">", ">")
|
|
695
|
+
.replaceAll('"', """)
|
|
696
|
+
.replaceAll("'", "'");
|
|
698
697
|
}
|
|
699
698
|
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
699
|
+
function renderPlainCodeToHtml(code: string): string {
|
|
700
|
+
const lines = code.split("\n");
|
|
701
|
+
const normalizedLines = lines.length > 0 ? lines : [""];
|
|
703
702
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
703
|
+
return normalizedLines
|
|
704
|
+
.map((line) => {
|
|
705
|
+
const lineHtml = line.length > 0 ? escapeHtml(line) : " ";
|
|
706
|
+
return `<span class="flex w-max min-w-full"><span class="flex-1 whitespace-pre pl-3 pr-3">${lineHtml}</span></span>`;
|
|
707
|
+
})
|
|
708
|
+
.join("");
|
|
709
709
|
}
|
|
710
710
|
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
:
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
711
|
+
async function highlightPlaygroundCodeToHtml(
|
|
712
|
+
code: unknown,
|
|
713
|
+
language: string,
|
|
714
|
+
config: PlaygroundShikiConfig,
|
|
715
|
+
): Promise<string> {
|
|
716
|
+
const normalizedCode = String(code ?? "");
|
|
717
|
+
if (!config) return renderPlainCodeToHtml(normalizedCode);
|
|
718
|
+
|
|
719
|
+
try {
|
|
720
|
+
const highlighted = await highlightAssistantCodeToHtml({
|
|
721
|
+
code: normalizedCode,
|
|
722
|
+
config,
|
|
723
|
+
language,
|
|
724
|
+
});
|
|
725
|
+
return highlighted.html;
|
|
726
|
+
} catch (error) {
|
|
727
|
+
console.error("Playground code highlighting failed", {
|
|
728
|
+
error,
|
|
729
|
+
language,
|
|
730
|
+
});
|
|
731
|
+
return renderPlainCodeToHtml(normalizedCode);
|
|
732
|
+
}
|
|
721
733
|
}
|
|
722
734
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
735
|
+
(
|
|
736
|
+
window as typeof window & {
|
|
737
|
+
RadiantPlaygroundHighlightCode?: typeof highlightPlaygroundCodeToHtml;
|
|
738
|
+
}
|
|
739
|
+
).RadiantPlaygroundHighlightCode = highlightPlaygroundCodeToHtml;
|
|
740
|
+
</script>
|
|
@@ -161,7 +161,7 @@ import { Icon } from "astro-icon/components";
|
|
|
161
161
|
</div>
|
|
162
162
|
<div x-show="response && response.highlightedData">
|
|
163
163
|
<pre
|
|
164
|
-
class="relative m-0 min-w-full p-0 text-[13px] leading-6"><code data-rd-code-theme class="block min-w-full
|
|
164
|
+
class="relative m-0 min-w-full p-0 text-[13px] leading-6"><code data-rd-code-theme class="block min-w-full py-2.5 font-mono text-neutral-800 dark:text-neutral-200" x-html="response?.highlightedData" /></pre>
|
|
165
165
|
</div>
|
|
166
166
|
</div>
|
|
167
167
|
|
|
@@ -185,7 +185,7 @@ import { Icon } from "astro-icon/components";
|
|
|
185
185
|
</div>
|
|
186
186
|
<div x-show="response && response.highlightedHeaders">
|
|
187
187
|
<pre
|
|
188
|
-
class="relative m-0 min-w-full bg-(--rd-code-surface) p-0 text-[13px] leading-6"><code data-rd-code-theme class="block min-w-full
|
|
188
|
+
class="relative m-0 min-w-full bg-(--rd-code-surface) p-0 text-[13px] leading-6"><code data-rd-code-theme class="block min-w-full py-2.5 font-mono text-neutral-800 dark:text-neutral-200" x-html="response?.highlightedHeaders" /></pre>
|
|
189
189
|
</div>
|
|
190
190
|
</div>
|
|
191
191
|
</div>
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
|
-
"assetVersion": "shiki-
|
|
2
|
+
"assetVersion": "shiki-4.2.0-c0d7e21cea71",
|
|
3
3
|
"counts": {
|
|
4
4
|
"languages": 347,
|
|
5
5
|
"themes": 66
|
|
6
6
|
},
|
|
7
7
|
"manifest": {
|
|
8
|
-
"bytes":
|
|
8
|
+
"bytes": 172635,
|
|
9
9
|
"module": "manifest.json",
|
|
10
|
-
"sha256": "
|
|
10
|
+
"sha256": "1840b6f21a79266d9bf3a74d5e6973d407fb06b96d71decd5542ca37eebf182d"
|
|
11
11
|
},
|
|
12
12
|
"packageVersions": {
|
|
13
|
-
"@shikijs/core": "
|
|
14
|
-
"@shikijs/engine-javascript": "
|
|
15
|
-
"@shikijs/langs": "
|
|
16
|
-
"@shikijs/themes": "
|
|
17
|
-
"shiki": "
|
|
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
18
|
},
|
|
19
19
|
"prefix": "_platform/shiki",
|
|
20
20
|
"runtime": {
|
|
@@ -5,12 +5,8 @@ import {
|
|
|
5
5
|
import { withBasePath } from "./base-path";
|
|
6
6
|
import { getAssistantLauncherIconConfig } from "./assistant-embed-script";
|
|
7
7
|
import type { AssistantShikiRuntimeConfig } from "./assistant-shiki-client";
|
|
8
|
+
import { getClientShikiRuntimeConfig } from "./client-shiki-config";
|
|
8
9
|
import type { DocsConfig } from "./validation";
|
|
9
|
-
import shikiPlatformAssets from "../generated/shiki-platform-assets.json";
|
|
10
|
-
import {
|
|
11
|
-
DEFAULT_SHIKI_DARK_THEME,
|
|
12
|
-
DEFAULT_SHIKI_LIGHT_THEME,
|
|
13
|
-
} from "radiant-docs-validator/shiki-theme-config";
|
|
14
10
|
|
|
15
11
|
export type AssistantPanelRuntimeConfig = {
|
|
16
12
|
apiPath: string;
|
|
@@ -35,57 +31,6 @@ export type AssistantPanelRuntimeConfig = {
|
|
|
35
31
|
shiki?: AssistantShikiRuntimeConfig;
|
|
36
32
|
};
|
|
37
33
|
|
|
38
|
-
function normalizeStaticAssetHost(value: unknown): string {
|
|
39
|
-
const rawValue = typeof value === "string" ? value.trim() : "";
|
|
40
|
-
if (!rawValue) return "";
|
|
41
|
-
|
|
42
|
-
const normalizedHost = rawValue.replace(/\/+$/, "");
|
|
43
|
-
return /^https?:\/\//i.test(normalizedHost)
|
|
44
|
-
? normalizedHost
|
|
45
|
-
: `https://${normalizedHost}`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function joinUrl(baseUrl: string, path: string): string {
|
|
49
|
-
return `${baseUrl.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function getConfiguredCodeSyntaxThemes(
|
|
53
|
-
config: DocsConfig,
|
|
54
|
-
): AssistantShikiRuntimeConfig["syntaxThemes"] {
|
|
55
|
-
const configuredSyntaxTheme = config.theme?.code?.syntaxTheme;
|
|
56
|
-
|
|
57
|
-
if (typeof configuredSyntaxTheme === "string") {
|
|
58
|
-
return {
|
|
59
|
-
light: configuredSyntaxTheme,
|
|
60
|
-
dark: configuredSyntaxTheme,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return {
|
|
65
|
-
light: configuredSyntaxTheme?.light ?? DEFAULT_SHIKI_LIGHT_THEME,
|
|
66
|
-
dark: configuredSyntaxTheme?.dark ?? DEFAULT_SHIKI_DARK_THEME,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function getAssistantShikiRuntimeConfig(
|
|
71
|
-
config: DocsConfig,
|
|
72
|
-
): AssistantShikiRuntimeConfig | undefined {
|
|
73
|
-
const staticAssetHost = normalizeStaticAssetHost(
|
|
74
|
-
import.meta.env.STATIC_ASSET_HOST ?? process.env.STATIC_ASSET_HOST,
|
|
75
|
-
);
|
|
76
|
-
if (!staticAssetHost) {
|
|
77
|
-
return undefined;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
assetBaseUrl: joinUrl(
|
|
82
|
-
staticAssetHost,
|
|
83
|
-
`${shikiPlatformAssets.prefix}/${shikiPlatformAssets.assetVersion}`,
|
|
84
|
-
),
|
|
85
|
-
syntaxThemes: getConfiguredCodeSyntaxThemes(config),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
34
|
export function getAssistantPanelRuntimeConfig(
|
|
90
35
|
config: DocsConfig,
|
|
91
36
|
): AssistantPanelRuntimeConfig {
|
|
@@ -134,6 +79,6 @@ export function getAssistantPanelRuntimeConfig(
|
|
|
134
79
|
emptyStateQuestions: assistantConfig?.questions,
|
|
135
80
|
devProxyToken: isDev ? assistantDevProxySecret : undefined,
|
|
136
81
|
chrome: getAssistantChromeConfig(config),
|
|
137
|
-
shiki:
|
|
82
|
+
shiki: getClientShikiRuntimeConfig(config),
|
|
138
83
|
};
|
|
139
84
|
}
|
|
@@ -175,9 +175,20 @@ async function loadRuntime(
|
|
|
175
175
|
})();
|
|
176
176
|
|
|
177
177
|
runtimePromiseByKey.set(runtimeCacheKey, runtimePromise);
|
|
178
|
+
runtimePromise.catch(() => {
|
|
179
|
+
if (runtimePromiseByKey.get(runtimeCacheKey) === runtimePromise) {
|
|
180
|
+
runtimePromiseByKey.delete(runtimeCacheKey);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
178
183
|
return runtimePromise;
|
|
179
184
|
}
|
|
180
185
|
|
|
186
|
+
export async function warmAssistantShikiRuntime(
|
|
187
|
+
config: AssistantShikiRuntimeConfig,
|
|
188
|
+
): Promise<void> {
|
|
189
|
+
await loadRuntime(config);
|
|
190
|
+
}
|
|
191
|
+
|
|
181
192
|
function normalizeLanguageToken(rawLanguage: string): string {
|
|
182
193
|
const normalized = rawLanguage.trim().toLowerCase();
|
|
183
194
|
if (!normalized) return "";
|
|
@@ -254,6 +265,11 @@ async function ensureLanguageLoaded({
|
|
|
254
265
|
await highlighter.loadLanguage(...registrations);
|
|
255
266
|
})();
|
|
256
267
|
languageLoadPromiseByKey.set(cacheKey, loadPromise);
|
|
268
|
+
loadPromise.catch(() => {
|
|
269
|
+
if (languageLoadPromiseByKey.get(cacheKey) === loadPromise) {
|
|
270
|
+
languageLoadPromiseByKey.delete(cacheKey);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
257
273
|
}
|
|
258
274
|
|
|
259
275
|
await loadPromise;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { AssistantShikiRuntimeConfig } from "./assistant-shiki-client";
|
|
2
|
+
import type { DocsConfig } from "./validation";
|
|
3
|
+
import shikiPlatformAssets from "../generated/shiki-platform-assets.json";
|
|
4
|
+
import {
|
|
5
|
+
DEFAULT_SHIKI_DARK_THEME,
|
|
6
|
+
DEFAULT_SHIKI_LIGHT_THEME,
|
|
7
|
+
} from "radiant-docs-validator/shiki-theme-config";
|
|
8
|
+
|
|
9
|
+
export type ClientShikiRuntimeConfig = AssistantShikiRuntimeConfig;
|
|
10
|
+
|
|
11
|
+
function normalizeStaticAssetHost(value: unknown): string {
|
|
12
|
+
const rawValue = typeof value === "string" ? value.trim() : "";
|
|
13
|
+
if (!rawValue) return "";
|
|
14
|
+
|
|
15
|
+
const normalizedHost = rawValue.replace(/\/+$/, "");
|
|
16
|
+
return /^https?:\/\//i.test(normalizedHost)
|
|
17
|
+
? normalizedHost
|
|
18
|
+
: `https://${normalizedHost}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function joinUrl(baseUrl: string, path: string): string {
|
|
22
|
+
return `${baseUrl.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getConfiguredCodeSyntaxThemes(
|
|
26
|
+
config: DocsConfig,
|
|
27
|
+
): ClientShikiRuntimeConfig["syntaxThemes"] {
|
|
28
|
+
const configuredSyntaxTheme = config.theme?.code?.syntaxTheme;
|
|
29
|
+
|
|
30
|
+
if (typeof configuredSyntaxTheme === "string") {
|
|
31
|
+
return {
|
|
32
|
+
light: configuredSyntaxTheme,
|
|
33
|
+
dark: configuredSyntaxTheme,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
light: configuredSyntaxTheme?.light ?? DEFAULT_SHIKI_LIGHT_THEME,
|
|
39
|
+
dark: configuredSyntaxTheme?.dark ?? DEFAULT_SHIKI_DARK_THEME,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function getClientShikiRuntimeConfig(
|
|
44
|
+
config: DocsConfig,
|
|
45
|
+
): ClientShikiRuntimeConfig | undefined {
|
|
46
|
+
const staticAssetHost = normalizeStaticAssetHost(
|
|
47
|
+
import.meta.env.STATIC_ASSET_HOST ?? process.env.STATIC_ASSET_HOST,
|
|
48
|
+
);
|
|
49
|
+
if (!staticAssetHost) {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
assetBaseUrl: joinUrl(
|
|
55
|
+
staticAssetHost,
|
|
56
|
+
`${shikiPlatformAssets.prefix}/${shikiPlatformAssets.assetVersion}`,
|
|
57
|
+
),
|
|
58
|
+
syntaxThemes: getConfiguredCodeSyntaxThemes(config),
|
|
59
|
+
};
|
|
60
|
+
}
|