radiant-docs 0.1.61 → 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 +2858 -1140
- package/template/package.json +18 -13
- package/template/scripts/generate-proxy-allowed-origins.mjs +10 -179
- package/template/scripts/publish-shiki-platform-assets.mjs +1177 -0
- package/template/src/components/Header.astro +6 -1
- package/template/src/components/NavigationTabList.astro +65 -0
- package/template/src/components/NavigationTabs.astro +109 -0
- package/template/src/components/OpenApiPage.astro +17 -1
- package/template/src/components/Sidebar.astro +2 -2
- package/template/src/components/SidebarDropdown.astro +105 -44
- package/template/src/components/SidebarMenu.astro +3 -0
- package/template/src/components/SidebarSegmented.astro +87 -52
- package/template/src/components/SidebarTabs.astro +86 -0
- package/template/src/components/chat/AssistantDocsWidget.tsx +127 -2
- package/template/src/components/chat/AssistantEmbedPanel.tsx +401 -283
- package/template/src/components/endpoint/PlaygroundForm.astro +69 -55
- package/template/src/components/endpoint/ResponseDisplay.astro +2 -2
- package/template/src/components/user/Accordion.astro +1 -1
- package/template/src/components/user/Callout.astro +2 -2
- package/template/src/components/user/CodeBlock.astro +58 -7
- package/template/src/components/user/CodeGroup.astro +52 -1
- package/template/src/components/user/Column.astro +1 -1
- package/template/src/components/user/Step.astro +1 -1
- package/template/src/components/user/Tabs.astro +1 -1
- package/template/src/generated/shiki-platform-assets.json +24 -0
- package/template/src/layouts/Layout.astro +111 -8
- package/template/src/lib/assistant-panel-config.ts +4 -0
- package/template/src/lib/assistant-shiki-client.ts +522 -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/mdx/remark-resolve-internal-links.ts +334 -17
- package/template/src/lib/proxy-allowed-origins.mjs +189 -0
- package/template/src/lib/routes.ts +66 -24
- package/template/src/styles/global.css +16 -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
|
@@ -1,34 +1,18 @@
|
|
|
1
1
|
import type { JSX } from "preact";
|
|
2
2
|
import { useEffect, useRef, useState } from "preact/hooks";
|
|
3
3
|
import { Icon } from "@iconify/react";
|
|
4
|
-
import Prism from "prismjs";
|
|
5
|
-
import "prismjs/components/prism-markup.js";
|
|
6
|
-
import "prismjs/components/prism-clike.js";
|
|
7
|
-
import "prismjs/components/prism-javascript.js";
|
|
8
|
-
import "prismjs/components/prism-typescript.js";
|
|
9
|
-
import "prismjs/components/prism-jsx.js";
|
|
10
|
-
import "prismjs/components/prism-tsx.js";
|
|
11
|
-
import "prismjs/components/prism-json.js";
|
|
12
|
-
import "prismjs/components/prism-markdown.js";
|
|
13
|
-
import "prismjs/components/prism-bash.js";
|
|
14
|
-
import "prismjs/components/prism-python.js";
|
|
15
|
-
import "prismjs/components/prism-yaml.js";
|
|
16
|
-
import "prismjs/components/prism-sql.js";
|
|
17
|
-
import "prismjs/components/prism-rust.js";
|
|
18
|
-
import "prismjs/components/prism-go.js";
|
|
19
|
-
import "prismjs/components/prism-java.js";
|
|
20
|
-
import "prismjs/components/prism-markup-templating.js";
|
|
21
|
-
import "prismjs/components/prism-php.js";
|
|
22
|
-
import "prismjs/components/prism-ruby.js";
|
|
23
|
-
import "prismjs/components/prism-css.js";
|
|
24
|
-
import "prismjs/components/prism-diff.js";
|
|
25
|
-
import "prism-themes/themes/prism-one-light.css";
|
|
26
4
|
import { type Plugin, unified } from "unified";
|
|
27
5
|
import remarkParse from "remark-parse";
|
|
28
6
|
import remarkGfm from "remark-gfm";
|
|
29
7
|
import remarkRehype from "remark-rehype";
|
|
30
8
|
import rehypeStringify from "rehype-stringify";
|
|
31
9
|
import { getDocsBasePath, withBasePath } from "../../lib/base-path";
|
|
10
|
+
import {
|
|
11
|
+
highlightAssistantCodeToHtml,
|
|
12
|
+
normalizeAssistantCodeLanguage,
|
|
13
|
+
warmAssistantShikiRuntime,
|
|
14
|
+
type AssistantShikiRuntimeConfig,
|
|
15
|
+
} from "../../lib/assistant-shiki-client";
|
|
32
16
|
|
|
33
17
|
type AssistantLinkTarget = "current" | "blank";
|
|
34
18
|
export type AssistantPanelSize = "default" | "expanded";
|
|
@@ -59,10 +43,13 @@ type AssistantEmbedPanelProps = {
|
|
|
59
43
|
allowApiPathQueryOverride?: boolean;
|
|
60
44
|
openSignal?: number;
|
|
61
45
|
panelSize?: AssistantPanelSize;
|
|
46
|
+
mobileBreakpoint?: string;
|
|
47
|
+
panelFullscreenHeightBreakpoint?: string;
|
|
62
48
|
onRequestOpen?: () => void;
|
|
63
49
|
onRequestClose?: () => void;
|
|
64
50
|
onRequestPanelSizeToggle?: (size: AssistantPanelSize) => void;
|
|
65
51
|
onCurrentLinkNavigate?: (href: string, sourceElement?: Element) => void;
|
|
52
|
+
shiki?: AssistantShikiRuntimeConfig;
|
|
66
53
|
};
|
|
67
54
|
|
|
68
55
|
type AssistantColorByMode = {
|
|
@@ -70,15 +57,22 @@ type AssistantColorByMode = {
|
|
|
70
57
|
dark: string;
|
|
71
58
|
};
|
|
72
59
|
|
|
60
|
+
type AssistantMessageSource = {
|
|
61
|
+
href: string;
|
|
62
|
+
label: string;
|
|
63
|
+
};
|
|
64
|
+
|
|
73
65
|
type ChatMessage = {
|
|
74
66
|
id: string;
|
|
75
67
|
role: "user" | "assistant";
|
|
76
68
|
content: string;
|
|
69
|
+
sources?: AssistantMessageSource[];
|
|
77
70
|
};
|
|
78
71
|
|
|
79
72
|
type AssistantStreamEvent = {
|
|
80
73
|
type?: string;
|
|
81
74
|
delta?: string;
|
|
75
|
+
sources?: unknown;
|
|
82
76
|
};
|
|
83
77
|
|
|
84
78
|
type ChatInputKeyEvent = JSX.TargetedKeyboardEvent<HTMLTextAreaElement>;
|
|
@@ -120,41 +114,50 @@ const HANDOFF_ACK_TYPE = "assistant-handoff:ack";
|
|
|
120
114
|
const IN_FLIGHT_STALE_MS = 10000;
|
|
121
115
|
const IN_FLIGHT_HEARTBEAT_MS = 3000;
|
|
122
116
|
const MARKDOWN_HTML_CACHE_LIMIT = 300;
|
|
117
|
+
const DEFAULT_ASSISTANT_MOBILE_BREAKPOINT = "640px";
|
|
118
|
+
const DEFAULT_ASSISTANT_PANEL_FULLSCREEN_HEIGHT_BREAKPOINT = "560px";
|
|
123
119
|
const markdownHtmlCache = new Map<string, string>();
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
mdx: "markdown",
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
const PRISM_LANGUAGE_LABEL: Record<string, string> = {
|
|
120
|
+
const markdownHtmlPromiseCache = new Map<string, Promise<string>>();
|
|
121
|
+
const ASSISTANT_LANGUAGE_LABEL: Record<string, string> = {
|
|
122
|
+
bash: "Bash",
|
|
123
|
+
css: "CSS",
|
|
124
|
+
diff: "Diff",
|
|
125
|
+
go: "Go",
|
|
126
|
+
html: "HTML",
|
|
127
|
+
java: "Java",
|
|
136
128
|
javascript: "JavaScript",
|
|
137
|
-
typescript: "TypeScript",
|
|
138
129
|
jsx: "JSX",
|
|
139
|
-
tsx: "TSX",
|
|
140
130
|
json: "JSON",
|
|
141
131
|
markdown: "Markdown",
|
|
142
|
-
|
|
143
|
-
|
|
132
|
+
mdx: "MDX",
|
|
133
|
+
php: "PHP",
|
|
134
|
+
plaintext: "Text",
|
|
144
135
|
python: "Python",
|
|
145
|
-
|
|
146
|
-
sql: "SQL",
|
|
136
|
+
ruby: "Ruby",
|
|
147
137
|
rust: "Rust",
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
mdx: "MDX",
|
|
138
|
+
shell: "Shell",
|
|
139
|
+
sql: "SQL",
|
|
140
|
+
tsx: "TSX",
|
|
141
|
+
typescript: "TypeScript",
|
|
142
|
+
yaml: "YAML",
|
|
154
143
|
};
|
|
155
144
|
|
|
156
145
|
const EXTERNAL_PROTOCOL_REGEX = /^[a-zA-Z][a-zA-Z\d+\-.]*:/;
|
|
157
146
|
|
|
147
|
+
function buildMarkdownCacheKey(
|
|
148
|
+
normalizedMarkdown: string,
|
|
149
|
+
linkTarget: AssistantLinkTarget,
|
|
150
|
+
shiki: AssistantShikiRuntimeConfig | undefined,
|
|
151
|
+
): string {
|
|
152
|
+
return [
|
|
153
|
+
linkTarget,
|
|
154
|
+
shiki?.assetBaseUrl ?? "",
|
|
155
|
+
shiki?.syntaxThemes.light ?? "",
|
|
156
|
+
shiki?.syntaxThemes.dark ?? "",
|
|
157
|
+
normalizedMarkdown,
|
|
158
|
+
].join("\0");
|
|
159
|
+
}
|
|
160
|
+
|
|
158
161
|
function normalizeRelTokens(value: unknown): string[] {
|
|
159
162
|
if (Array.isArray(value)) {
|
|
160
163
|
return value
|
|
@@ -356,6 +359,33 @@ function createMessageId(): string {
|
|
|
356
359
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
357
360
|
}
|
|
358
361
|
|
|
362
|
+
function normalizeAssistantMessageSources(
|
|
363
|
+
rawSources: unknown,
|
|
364
|
+
): AssistantMessageSource[] {
|
|
365
|
+
if (!Array.isArray(rawSources)) {
|
|
366
|
+
return [];
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
return rawSources.flatMap((rawSource) => {
|
|
370
|
+
if (!rawSource || typeof rawSource !== "object") {
|
|
371
|
+
return [];
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const source = rawSource as Partial<AssistantMessageSource>;
|
|
375
|
+
const href = typeof source.href === "string" ? source.href.trim() : "";
|
|
376
|
+
const label =
|
|
377
|
+
typeof source.label === "string" && source.label.trim()
|
|
378
|
+
? source.label.trim()
|
|
379
|
+
: href;
|
|
380
|
+
|
|
381
|
+
if (!href || !label) {
|
|
382
|
+
return [];
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return [{ href, label }];
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
|
|
359
389
|
function normalizePersistedMessages(rawMessages: unknown): ChatMessage[] {
|
|
360
390
|
if (!Array.isArray(rawMessages)) {
|
|
361
391
|
return [];
|
|
@@ -377,6 +407,7 @@ function normalizePersistedMessages(rawMessages: unknown): ChatMessage[] {
|
|
|
377
407
|
id: message.id,
|
|
378
408
|
role: message.role,
|
|
379
409
|
content: message.content,
|
|
410
|
+
sources: normalizeAssistantMessageSources(message.sources),
|
|
380
411
|
}));
|
|
381
412
|
}
|
|
382
413
|
|
|
@@ -395,6 +426,13 @@ function normalizePanelSize(value: unknown): AssistantPanelSize {
|
|
|
395
426
|
return value === "expanded" ? "expanded" : "default";
|
|
396
427
|
}
|
|
397
428
|
|
|
429
|
+
function getPanelFullscreenMediaQuery(
|
|
430
|
+
mobileBreakpoint: string,
|
|
431
|
+
panelFullscreenHeightBreakpoint: string,
|
|
432
|
+
): string {
|
|
433
|
+
return `(max-width: ${mobileBreakpoint}), (max-height: ${panelFullscreenHeightBreakpoint})`;
|
|
434
|
+
}
|
|
435
|
+
|
|
398
436
|
function normalizePersistedPanelState(rawState: unknown): PersistedPanelState {
|
|
399
437
|
if (!rawState || typeof rawState !== "object") {
|
|
400
438
|
return createEmptyPersistedPanelState();
|
|
@@ -574,32 +612,20 @@ function escapeHtml(value: string): string {
|
|
|
574
612
|
.replaceAll("'", "'");
|
|
575
613
|
}
|
|
576
614
|
|
|
577
|
-
function
|
|
578
|
-
const normalized = rawLanguage.trim().toLowerCase();
|
|
579
|
-
return PRISM_LANGUAGE_ALIAS[normalized] ?? normalized;
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
function resolvePrismLanguageLabel(language: string): string {
|
|
615
|
+
function resolveAssistantLanguageLabel(language: string): string {
|
|
583
616
|
const normalized = language.trim().toLowerCase();
|
|
584
617
|
if (!normalized) {
|
|
585
618
|
return "";
|
|
586
619
|
}
|
|
587
620
|
|
|
588
621
|
return (
|
|
589
|
-
|
|
622
|
+
ASSISTANT_LANGUAGE_LABEL[normalized] ??
|
|
590
623
|
normalized
|
|
591
624
|
.replace(/[-_]+/g, " ")
|
|
592
625
|
.replace(/\b\w/g, (char) => char.toUpperCase())
|
|
593
626
|
);
|
|
594
627
|
}
|
|
595
628
|
|
|
596
|
-
function resolvePrismGrammar(language: string) {
|
|
597
|
-
return (
|
|
598
|
-
Prism.languages[language] ??
|
|
599
|
-
Prism.languages[PRISM_LANGUAGE_ALIAS[language] ?? ""]
|
|
600
|
-
);
|
|
601
|
-
}
|
|
602
|
-
|
|
603
629
|
function ensureCodeBlockCopyButton(preElement: HTMLPreElement): void {
|
|
604
630
|
const existingButton = Array.from(preElement.children).find(
|
|
605
631
|
(child) =>
|
|
@@ -697,12 +723,23 @@ function unwrapEscapedFenceCodeBlock(rawCode: string): {
|
|
|
697
723
|
}
|
|
698
724
|
|
|
699
725
|
return {
|
|
700
|
-
language:
|
|
726
|
+
language: normalizeAssistantCodeLanguage(languageToken),
|
|
701
727
|
code: lines.slice(1, -1).join("\n"),
|
|
702
728
|
};
|
|
703
729
|
}
|
|
704
730
|
|
|
705
|
-
function
|
|
731
|
+
function stripSerializedCodeBlockTrailingNewline(rawCode: string): string {
|
|
732
|
+
if (rawCode.endsWith("\n")) {
|
|
733
|
+
return rawCode.slice(0, -1);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
return rawCode;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
async function highlightCodeBlocksInHtml(
|
|
740
|
+
html: string,
|
|
741
|
+
shiki: AssistantShikiRuntimeConfig | undefined,
|
|
742
|
+
): Promise<string> {
|
|
706
743
|
if (typeof document === "undefined" || !html.trim()) {
|
|
707
744
|
return html;
|
|
708
745
|
}
|
|
@@ -711,8 +748,8 @@ function highlightCodeBlocksInHtml(html: string): string {
|
|
|
711
748
|
const container = document.createElement("div");
|
|
712
749
|
container.innerHTML = html;
|
|
713
750
|
|
|
714
|
-
const codeNodes = container.querySelectorAll("pre > code");
|
|
715
|
-
|
|
751
|
+
const codeNodes = Array.from(container.querySelectorAll("pre > code"));
|
|
752
|
+
for (const codeNode of codeNodes) {
|
|
716
753
|
const getLanguageClassName = (element: Element | null) =>
|
|
717
754
|
Array.from(element?.classList ?? []).find(
|
|
718
755
|
(className) =>
|
|
@@ -741,13 +778,14 @@ function highlightCodeBlocksInHtml(html: string): string {
|
|
|
741
778
|
}
|
|
742
779
|
});
|
|
743
780
|
preParent.classList.add(`language-${language}`);
|
|
744
|
-
const languageLabel =
|
|
781
|
+
const languageLabel = resolveAssistantLanguageLabel(language);
|
|
745
782
|
if (languageLabel) {
|
|
746
783
|
preParent.setAttribute("data-language", languageLabel);
|
|
747
784
|
} else {
|
|
748
785
|
preParent.removeAttribute("data-language");
|
|
749
786
|
}
|
|
750
787
|
|
|
788
|
+
codeNode.setAttribute("data-rd-code-theme", "");
|
|
751
789
|
ensureCodeBlockCopyButton(preParent);
|
|
752
790
|
}
|
|
753
791
|
};
|
|
@@ -759,7 +797,9 @@ function highlightCodeBlocksInHtml(html: string): string {
|
|
|
759
797
|
preLanguageClassName?.replace(/^(language-|lang-)/, "") ??
|
|
760
798
|
"";
|
|
761
799
|
|
|
762
|
-
let rawCode =
|
|
800
|
+
let rawCode = stripSerializedCodeBlockTrailingNewline(
|
|
801
|
+
codeNode.textContent ?? "",
|
|
802
|
+
);
|
|
763
803
|
if (!rawLanguage) {
|
|
764
804
|
const unwrappedFence = unwrapEscapedFenceCodeBlock(rawCode);
|
|
765
805
|
if (unwrappedFence) {
|
|
@@ -769,28 +809,37 @@ function highlightCodeBlocksInHtml(html: string): string {
|
|
|
769
809
|
}
|
|
770
810
|
|
|
771
811
|
if (!rawLanguage) {
|
|
772
|
-
|
|
812
|
+
const preParent = codeNode.parentElement;
|
|
813
|
+
if (preParent instanceof HTMLPreElement) {
|
|
814
|
+
ensureCodeBlockCopyButton(preParent);
|
|
815
|
+
}
|
|
816
|
+
continue;
|
|
773
817
|
}
|
|
774
818
|
|
|
775
|
-
const resolvedLanguage =
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
819
|
+
const resolvedLanguage = normalizeAssistantCodeLanguage(rawLanguage);
|
|
820
|
+
setLanguageClass(resolvedLanguage);
|
|
821
|
+
|
|
822
|
+
if (!shiki) {
|
|
823
|
+
codeNode.textContent = rawCode;
|
|
824
|
+
continue;
|
|
781
825
|
}
|
|
782
826
|
|
|
783
|
-
setLanguageClass(resolvedLanguage);
|
|
784
827
|
try {
|
|
785
|
-
const highlighted =
|
|
786
|
-
|
|
828
|
+
const highlighted = await highlightAssistantCodeToHtml({
|
|
829
|
+
code: rawCode,
|
|
830
|
+
config: shiki,
|
|
831
|
+
language: resolvedLanguage,
|
|
832
|
+
});
|
|
833
|
+
setLanguageClass(highlighted.language);
|
|
834
|
+
codeNode.innerHTML = highlighted.html;
|
|
787
835
|
} catch (error) {
|
|
788
836
|
console.error("Assistant embed code highlighting failed", {
|
|
789
837
|
language: resolvedLanguage,
|
|
790
838
|
error,
|
|
791
839
|
});
|
|
840
|
+
codeNode.textContent = rawCode;
|
|
792
841
|
}
|
|
793
|
-
}
|
|
842
|
+
}
|
|
794
843
|
|
|
795
844
|
return container.innerHTML;
|
|
796
845
|
} catch (error) {
|
|
@@ -805,45 +854,176 @@ function highlightCodeBlocksInHtml(html: string): string {
|
|
|
805
854
|
function renderMarkdownToHtml(
|
|
806
855
|
markdown: string,
|
|
807
856
|
linkTarget: AssistantLinkTarget,
|
|
808
|
-
|
|
857
|
+
shiki: AssistantShikiRuntimeConfig | undefined,
|
|
858
|
+
): Promise<string> {
|
|
809
859
|
const normalizedMarkdown = markdown.replaceAll("\r\n", "\n");
|
|
810
|
-
const cacheKey =
|
|
860
|
+
const cacheKey = buildMarkdownCacheKey(normalizedMarkdown, linkTarget, shiki);
|
|
811
861
|
const cached = markdownHtmlCache.get(cacheKey);
|
|
812
862
|
if (cached !== undefined) {
|
|
813
|
-
return cached;
|
|
863
|
+
return Promise.resolve(cached);
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
const cachedPromise = markdownHtmlPromiseCache.get(cacheKey);
|
|
867
|
+
if (cachedPromise) {
|
|
868
|
+
return cachedPromise;
|
|
814
869
|
}
|
|
815
870
|
|
|
816
|
-
|
|
871
|
+
const renderPromise = (async () => {
|
|
872
|
+
let html = "";
|
|
817
873
|
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
874
|
+
try {
|
|
875
|
+
const processor = unified()
|
|
876
|
+
.use(remarkParse)
|
|
877
|
+
.use(remarkGfm)
|
|
878
|
+
.use(remarkRehype, { allowDangerousHtml: false })
|
|
879
|
+
.use(rehypeRebaseInternalLinks);
|
|
880
|
+
|
|
881
|
+
if (linkTarget === "blank") {
|
|
882
|
+
processor.use(rehypeOpenLinksInNewTab);
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
html = String(
|
|
886
|
+
processor.use(rehypeStringify).processSync(normalizedMarkdown),
|
|
887
|
+
);
|
|
888
|
+
} catch {
|
|
889
|
+
html = escapeHtml(normalizedMarkdown).replaceAll("\n", "<br/>");
|
|
827
890
|
}
|
|
828
891
|
|
|
829
|
-
html =
|
|
830
|
-
processor.use(rehypeStringify).processSync(normalizedMarkdown),
|
|
831
|
-
);
|
|
832
|
-
} catch {
|
|
833
|
-
html = escapeHtml(normalizedMarkdown).replaceAll("\n", "<br/>");
|
|
834
|
-
}
|
|
892
|
+
html = await highlightCodeBlocksInHtml(html, shiki);
|
|
835
893
|
|
|
836
|
-
|
|
894
|
+
markdownHtmlCache.set(cacheKey, html);
|
|
895
|
+
if (markdownHtmlCache.size > MARKDOWN_HTML_CACHE_LIMIT) {
|
|
896
|
+
const oldestKey = markdownHtmlCache.keys().next().value;
|
|
897
|
+
if (oldestKey) {
|
|
898
|
+
markdownHtmlCache.delete(oldestKey);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
837
901
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
902
|
+
markdownHtmlPromiseCache.delete(cacheKey);
|
|
903
|
+
return html;
|
|
904
|
+
})();
|
|
905
|
+
|
|
906
|
+
markdownHtmlPromiseCache.set(cacheKey, renderPromise);
|
|
907
|
+
return renderPromise;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
function getCachedMarkdownHtml(
|
|
911
|
+
markdown: string,
|
|
912
|
+
linkTarget: AssistantLinkTarget,
|
|
913
|
+
shiki: AssistantShikiRuntimeConfig | undefined,
|
|
914
|
+
): string | undefined {
|
|
915
|
+
return markdownHtmlCache.get(
|
|
916
|
+
buildMarkdownCacheKey(markdown.replaceAll("\r\n", "\n"), linkTarget, shiki),
|
|
917
|
+
);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
function AssistantMarkdownBlock({
|
|
921
|
+
className,
|
|
922
|
+
linkTarget,
|
|
923
|
+
markdown,
|
|
924
|
+
onClick,
|
|
925
|
+
onRendered,
|
|
926
|
+
shiki,
|
|
927
|
+
}: {
|
|
928
|
+
className: string;
|
|
929
|
+
linkTarget: AssistantLinkTarget;
|
|
930
|
+
markdown: string;
|
|
931
|
+
onClick: (event: JSX.TargetedMouseEvent<HTMLDivElement>) => void;
|
|
932
|
+
onRendered?: () => void;
|
|
933
|
+
shiki?: AssistantShikiRuntimeConfig;
|
|
934
|
+
}) {
|
|
935
|
+
const onRenderedRef = useRef(onRendered);
|
|
936
|
+
const [html, setHtml] = useState(
|
|
937
|
+
() => getCachedMarkdownHtml(markdown, linkTarget, shiki) ?? "",
|
|
938
|
+
);
|
|
939
|
+
|
|
940
|
+
useEffect(() => {
|
|
941
|
+
onRenderedRef.current = onRendered;
|
|
942
|
+
}, [onRendered]);
|
|
943
|
+
|
|
944
|
+
useEffect(() => {
|
|
945
|
+
let isCancelled = false;
|
|
946
|
+
const cached = getCachedMarkdownHtml(markdown, linkTarget, shiki);
|
|
947
|
+
if (cached !== undefined) {
|
|
948
|
+
setHtml(cached);
|
|
949
|
+
onRenderedRef.current?.();
|
|
950
|
+
return () => {
|
|
951
|
+
isCancelled = true;
|
|
952
|
+
};
|
|
843
953
|
}
|
|
954
|
+
|
|
955
|
+
void renderMarkdownToHtml(markdown, linkTarget, shiki)
|
|
956
|
+
.then((nextHtml) => {
|
|
957
|
+
if (isCancelled) return;
|
|
958
|
+
setHtml((previousHtml) =>
|
|
959
|
+
previousHtml === nextHtml ? previousHtml : nextHtml,
|
|
960
|
+
);
|
|
961
|
+
onRenderedRef.current?.();
|
|
962
|
+
})
|
|
963
|
+
.catch((error) => {
|
|
964
|
+
if (isCancelled) return;
|
|
965
|
+
console.error("Assistant embed markdown rendering failed", error);
|
|
966
|
+
setHtml(escapeHtml(markdown).replaceAll("\n", "<br/>"));
|
|
967
|
+
onRenderedRef.current?.();
|
|
968
|
+
});
|
|
969
|
+
|
|
970
|
+
return () => {
|
|
971
|
+
isCancelled = true;
|
|
972
|
+
};
|
|
973
|
+
}, [
|
|
974
|
+
linkTarget,
|
|
975
|
+
markdown,
|
|
976
|
+
shiki?.assetBaseUrl,
|
|
977
|
+
shiki?.syntaxThemes.dark,
|
|
978
|
+
shiki?.syntaxThemes.light,
|
|
979
|
+
]);
|
|
980
|
+
|
|
981
|
+
return (
|
|
982
|
+
<div
|
|
983
|
+
className={className}
|
|
984
|
+
onClick={onClick}
|
|
985
|
+
dangerouslySetInnerHTML={{
|
|
986
|
+
__html: html,
|
|
987
|
+
}}
|
|
988
|
+
/>
|
|
989
|
+
);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
function AssistantSourcesBlock({
|
|
993
|
+
linkTarget,
|
|
994
|
+
onClick,
|
|
995
|
+
sources,
|
|
996
|
+
}: {
|
|
997
|
+
linkTarget: AssistantLinkTarget;
|
|
998
|
+
onClick: (event: JSX.TargetedMouseEvent<HTMLDivElement>) => void;
|
|
999
|
+
sources: AssistantMessageSource[] | undefined;
|
|
1000
|
+
}) {
|
|
1001
|
+
const visibleSources = normalizeAssistantMessageSources(sources);
|
|
1002
|
+
if (visibleSources.length === 0) {
|
|
1003
|
+
return null;
|
|
844
1004
|
}
|
|
845
1005
|
|
|
846
|
-
return
|
|
1006
|
+
return (
|
|
1007
|
+
<div
|
|
1008
|
+
className="ask-ai-sources ask-ai-markdown prose-rules mt-3 max-w-full min-w-0 wrap-break-word text-[15px]!"
|
|
1009
|
+
onClick={onClick}
|
|
1010
|
+
>
|
|
1011
|
+
<p>Sources:</p>
|
|
1012
|
+
<ul>
|
|
1013
|
+
{visibleSources.map((source) => (
|
|
1014
|
+
<li key={`${source.href}\0${source.label}`}>
|
|
1015
|
+
<a
|
|
1016
|
+
href={source.href}
|
|
1017
|
+
target={linkTarget === "blank" ? "_blank" : undefined}
|
|
1018
|
+
rel={linkTarget === "blank" ? "noopener noreferrer" : undefined}
|
|
1019
|
+
>
|
|
1020
|
+
{source.label}
|
|
1021
|
+
</a>
|
|
1022
|
+
</li>
|
|
1023
|
+
))}
|
|
1024
|
+
</ul>
|
|
1025
|
+
</div>
|
|
1026
|
+
);
|
|
847
1027
|
}
|
|
848
1028
|
|
|
849
1029
|
function extractErrorMessage(rawBody: string): string {
|
|
@@ -944,11 +1124,18 @@ export default function AssistantEmbedPanel({
|
|
|
944
1124
|
allowApiPathQueryOverride = true,
|
|
945
1125
|
openSignal = 0,
|
|
946
1126
|
panelSize,
|
|
1127
|
+
mobileBreakpoint = DEFAULT_ASSISTANT_MOBILE_BREAKPOINT,
|
|
1128
|
+
panelFullscreenHeightBreakpoint = DEFAULT_ASSISTANT_PANEL_FULLSCREEN_HEIGHT_BREAKPOINT,
|
|
947
1129
|
onRequestOpen,
|
|
948
1130
|
onRequestClose,
|
|
949
1131
|
onRequestPanelSizeToggle,
|
|
950
1132
|
onCurrentLinkNavigate,
|
|
1133
|
+
shiki,
|
|
951
1134
|
}: AssistantEmbedPanelProps) {
|
|
1135
|
+
const panelFullscreenMediaQuery = getPanelFullscreenMediaQuery(
|
|
1136
|
+
mobileBreakpoint,
|
|
1137
|
+
panelFullscreenHeightBreakpoint,
|
|
1138
|
+
);
|
|
952
1139
|
const [initialPanelState] = useState<PersistedPanelState>(() =>
|
|
953
1140
|
canSendChatRequest
|
|
954
1141
|
? readPersistedPanelState()
|
|
@@ -969,7 +1156,17 @@ export default function AssistantEmbedPanel({
|
|
|
969
1156
|
const [localPanelSize, setLocalPanelSize] = useState<AssistantPanelSize>(
|
|
970
1157
|
panelSize ?? initialPanelState.panelSize,
|
|
971
1158
|
);
|
|
972
|
-
const [isShellFullscreen, setIsShellFullscreen] = useState(
|
|
1159
|
+
const [isShellFullscreen, setIsShellFullscreen] = useState(() => {
|
|
1160
|
+
if (
|
|
1161
|
+
panelSurface !== "inline" ||
|
|
1162
|
+
typeof window === "undefined" ||
|
|
1163
|
+
typeof window.matchMedia !== "function"
|
|
1164
|
+
) {
|
|
1165
|
+
return false;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
return window.matchMedia(panelFullscreenMediaQuery).matches;
|
|
1169
|
+
});
|
|
973
1170
|
const activeRequestAbortRef = useRef<AbortController | null>(null);
|
|
974
1171
|
const scrollViewportRef = useRef<HTMLDivElement | null>(null);
|
|
975
1172
|
const savedScrollTopRef = useRef(initialPanelState.scrollTop);
|
|
@@ -986,6 +1183,7 @@ export default function AssistantEmbedPanel({
|
|
|
986
1183
|
const panelSizeRef = useRef<AssistantPanelSize>(
|
|
987
1184
|
panelSize ?? initialPanelState.panelSize,
|
|
988
1185
|
);
|
|
1186
|
+
const hasPrewarmedShikiRef = useRef(false);
|
|
989
1187
|
const skipNextMessagesPersistRef = useRef(false);
|
|
990
1188
|
const inputRef = useRef<HTMLTextAreaElement | null>(null);
|
|
991
1189
|
const resolvedApiPathRef = useRef(
|
|
@@ -1541,6 +1739,27 @@ export default function AssistantEmbedPanel({
|
|
|
1541
1739
|
notifyPanelSizeChange(resolvedPanelSize);
|
|
1542
1740
|
}, [resolvedPanelSize]);
|
|
1543
1741
|
|
|
1742
|
+
useEffect(() => {
|
|
1743
|
+
if (
|
|
1744
|
+
panelSurface !== "inline" ||
|
|
1745
|
+
typeof window === "undefined" ||
|
|
1746
|
+
typeof window.matchMedia !== "function"
|
|
1747
|
+
) {
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
const mediaQuery = window.matchMedia(panelFullscreenMediaQuery);
|
|
1752
|
+
const updateShellLayout = () => {
|
|
1753
|
+
setIsShellFullscreen(mediaQuery.matches);
|
|
1754
|
+
};
|
|
1755
|
+
|
|
1756
|
+
updateShellLayout();
|
|
1757
|
+
mediaQuery.addEventListener("change", updateShellLayout);
|
|
1758
|
+
return () => {
|
|
1759
|
+
mediaQuery.removeEventListener("change", updateShellLayout);
|
|
1760
|
+
};
|
|
1761
|
+
}, [panelFullscreenMediaQuery, panelSurface]);
|
|
1762
|
+
|
|
1544
1763
|
useEffect(() => {
|
|
1545
1764
|
if (typeof window === "undefined") {
|
|
1546
1765
|
return;
|
|
@@ -1654,6 +1873,13 @@ export default function AssistantEmbedPanel({
|
|
|
1654
1873
|
setMessages(nextConversation);
|
|
1655
1874
|
queueThreadScrollToBottom(nextConversation);
|
|
1656
1875
|
|
|
1876
|
+
if (shiki && !hasPrewarmedShikiRef.current) {
|
|
1877
|
+
hasPrewarmedShikiRef.current = true;
|
|
1878
|
+
void warmAssistantShikiRuntime(shiki).catch((error) => {
|
|
1879
|
+
console.warn("Assistant embed Shiki runtime prewarm failed", error);
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1657
1883
|
activeRequestAbortRef.current?.abort();
|
|
1658
1884
|
const abortController = new AbortController();
|
|
1659
1885
|
activeRequestAbortRef.current = abortController;
|
|
@@ -1771,6 +1997,49 @@ export default function AssistantEmbedPanel({
|
|
|
1771
1997
|
: message,
|
|
1772
1998
|
);
|
|
1773
1999
|
});
|
|
2000
|
+
continue;
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
if (parsed.type === "sources") {
|
|
2004
|
+
const nextSources = normalizeAssistantMessageSources(
|
|
2005
|
+
parsed.sources,
|
|
2006
|
+
);
|
|
2007
|
+
if (nextSources.length === 0) {
|
|
2008
|
+
continue;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
if (!hasReceivedFirstTextDelta) {
|
|
2012
|
+
hasReceivedFirstTextDelta = true;
|
|
2013
|
+
setSharedAwaitingFirstToken(false);
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
setMessages((previous) => {
|
|
2017
|
+
const existingAssistantMessage = previous.find(
|
|
2018
|
+
(message) => message.id === assistantId,
|
|
2019
|
+
);
|
|
2020
|
+
|
|
2021
|
+
const nextMessages = existingAssistantMessage
|
|
2022
|
+
? previous.map((message) =>
|
|
2023
|
+
message.id === assistantId
|
|
2024
|
+
? {
|
|
2025
|
+
...message,
|
|
2026
|
+
sources: nextSources,
|
|
2027
|
+
}
|
|
2028
|
+
: message,
|
|
2029
|
+
)
|
|
2030
|
+
: [
|
|
2031
|
+
...previous,
|
|
2032
|
+
{
|
|
2033
|
+
id: assistantId,
|
|
2034
|
+
role: "assistant" as const,
|
|
2035
|
+
content: "",
|
|
2036
|
+
sources: nextSources,
|
|
2037
|
+
},
|
|
2038
|
+
];
|
|
2039
|
+
|
|
2040
|
+
queueThreadScrollToBottom(nextMessages);
|
|
2041
|
+
return nextMessages;
|
|
2042
|
+
});
|
|
1774
2043
|
}
|
|
1775
2044
|
}
|
|
1776
2045
|
}
|
|
@@ -1949,6 +2218,12 @@ export default function AssistantEmbedPanel({
|
|
|
1949
2218
|
});
|
|
1950
2219
|
};
|
|
1951
2220
|
|
|
2221
|
+
const handleMarkdownRendered = () => {
|
|
2222
|
+
if (isBusyRef.current) {
|
|
2223
|
+
queueThreadScrollToBottom(messagesRef.current);
|
|
2224
|
+
}
|
|
2225
|
+
};
|
|
2226
|
+
|
|
1952
2227
|
const panelClassName = [
|
|
1953
2228
|
"relative flex min-h-0 flex-col overflow-hidden text-neutral-900 shadow-2xl dark:text-neutral-50",
|
|
1954
2229
|
panelSurface === "inline"
|
|
@@ -2041,7 +2316,7 @@ export default function AssistantEmbedPanel({
|
|
|
2041
2316
|
{messages.length === 0 ? (
|
|
2042
2317
|
<div
|
|
2043
2318
|
key={emptyStateAnimationKey}
|
|
2044
|
-
className="flex min-h-full flex-col items-center justify-center
|
|
2319
|
+
className="flex min-h-full flex-col items-center justify-center py-8 text-center"
|
|
2045
2320
|
>
|
|
2046
2321
|
<AssistantPanelIcon
|
|
2047
2322
|
color={launcherIconColor}
|
|
@@ -2069,7 +2344,7 @@ export default function AssistantEmbedPanel({
|
|
|
2069
2344
|
<button
|
|
2070
2345
|
key={question}
|
|
2071
2346
|
type="button"
|
|
2072
|
-
className="assistant-empty-state-item w-fit rounded-full border-neutral-900/8 bg-white/90 px-3.5 py-2 text-
|
|
2347
|
+
className="assistant-empty-state-item w-fit rounded-full border-neutral-900/8 bg-white/90 px-3.5 py-2 text-center text-[13px] leading-5 text-neutral-700 shadow-[0px_1px_3px_0px_rgba(0,0,0,0.04),0px_0px_0px_1px_rgba(0,0,0,0.06)_inset,0px_-1px_0px_0px_rgba(0,0,0,0.06)_inset] transition hover:bg-white dark:bg-white/4 dark:text-neutral-200 dark:hover:bg-white/8 cursor-pointer dark:shadow-[0_1px_3px_0_rgba(0,0,0,0.04),inset_0_1px_0_0_rgba(255,255,255,0.04),inset_0_0_0_1px_rgba(0,0,0,0.06),inset_0_-1px_0_0_rgba(0,0,0,0.06),inset_0_0_0_1px_rgba(196,196,196,0.07)]"
|
|
2073
2348
|
style={
|
|
2074
2349
|
{
|
|
2075
2350
|
"--assistant-empty-state-delay": `${400 + index * 100}ms`,
|
|
@@ -2091,7 +2366,8 @@ export default function AssistantEmbedPanel({
|
|
|
2091
2366
|
{messages.map((message) => {
|
|
2092
2367
|
if (
|
|
2093
2368
|
message.role === "assistant" &&
|
|
2094
|
-
message.content.length === 0
|
|
2369
|
+
message.content.length === 0 &&
|
|
2370
|
+
normalizeAssistantMessageSources(message.sources).length === 0
|
|
2095
2371
|
) {
|
|
2096
2372
|
return null;
|
|
2097
2373
|
}
|
|
@@ -2101,18 +2377,26 @@ export default function AssistantEmbedPanel({
|
|
|
2101
2377
|
key={message.id}
|
|
2102
2378
|
className={isUser ? "text-right" : "text-left"}
|
|
2103
2379
|
>
|
|
2104
|
-
<
|
|
2380
|
+
<AssistantMarkdownBlock
|
|
2105
2381
|
className={[
|
|
2106
2382
|
"ask-ai-markdown prose-rules text-[15px]! max-w-full min-w-0 wrap-break-word prose-code:text-neutral-700 dark:prose-code:text-neutral-200 prose-pre:shadow-xs prose-pre:text-neutral-700! dark:prose-pre:text-neutral-100! prose-pre:border prose-pre:border-neutral-200 dark:prose-pre:border-neutral-800 prose-pre:rounded-xl!",
|
|
2107
2383
|
isUser
|
|
2108
2384
|
? "inline-block ml-2 px-3 py-1.5 rounded-2xl rounded-br-sm bg-neutral-900/5 text-neutral-700/85 dark:bg-neutral-800 dark:text-neutral-100 *:text-left"
|
|
2109
2385
|
: "block w-full bg-transparent text-neutral-900 dark:text-neutral-100",
|
|
2110
2386
|
].join(" ")}
|
|
2387
|
+
linkTarget={linkTarget}
|
|
2388
|
+
markdown={message.content}
|
|
2111
2389
|
onClick={handleRenderedMarkdownClick}
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
}}
|
|
2390
|
+
onRendered={handleMarkdownRendered}
|
|
2391
|
+
shiki={shiki}
|
|
2115
2392
|
/>
|
|
2393
|
+
{!isUser ? (
|
|
2394
|
+
<AssistantSourcesBlock
|
|
2395
|
+
linkTarget={linkTarget}
|
|
2396
|
+
onClick={handleRenderedMarkdownClick}
|
|
2397
|
+
sources={message.sources}
|
|
2398
|
+
/>
|
|
2399
|
+
) : null}
|
|
2116
2400
|
</div>
|
|
2117
2401
|
);
|
|
2118
2402
|
})}
|
|
@@ -2152,7 +2436,10 @@ export default function AssistantEmbedPanel({
|
|
|
2152
2436
|
}}
|
|
2153
2437
|
onKeyDown={handleChatInputKeyDown}
|
|
2154
2438
|
placeholder="Ask a question..."
|
|
2155
|
-
className=
|
|
2439
|
+
className={[
|
|
2440
|
+
"assistant-embed-input my-auto min-w-0 flex-1 bg-transparent pl-4 py-2.5 text-neutral-900 placeholder:text-neutral-400 focus:outline-none dark:text-white dark:placeholder:text-neutral-400 leading-5 resize-none [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
2441
|
+
isShellFullscreen ? "text-base" : "text-sm",
|
|
2442
|
+
].join(" ")}
|
|
2156
2443
|
disabled={isBusy}
|
|
2157
2444
|
rows={1}
|
|
2158
2445
|
/>
|
|
@@ -2261,7 +2548,7 @@ export default function AssistantEmbedPanel({
|
|
|
2261
2548
|
max-width: 100%;
|
|
2262
2549
|
min-width: 0;
|
|
2263
2550
|
box-sizing: border-box;
|
|
2264
|
-
padding
|
|
2551
|
+
padding: 2.25rem 0 0 !important;
|
|
2265
2552
|
background: var(--color-neutral-50) !important;
|
|
2266
2553
|
overflow-x: hidden;
|
|
2267
2554
|
overflow-y: hidden;
|
|
@@ -2326,10 +2613,6 @@ export default function AssistantEmbedPanel({
|
|
|
2326
2613
|
justify-content: center;
|
|
2327
2614
|
width: 1.75rem;
|
|
2328
2615
|
height: 1.75rem;
|
|
2329
|
-
border: 1px solid
|
|
2330
|
-
color-mix(in oklab, var(--color-neutral-200) 80%, transparent);
|
|
2331
|
-
background: color-mix(in oklab, #fff 80%, transparent);
|
|
2332
|
-
backdrop-filter: blur(4px);
|
|
2333
2616
|
color: color-mix(
|
|
2334
2617
|
in oklab,
|
|
2335
2618
|
var(--color-neutral-500) 80%,
|
|
@@ -2344,22 +2627,14 @@ export default function AssistantEmbedPanel({
|
|
|
2344
2627
|
}
|
|
2345
2628
|
|
|
2346
2629
|
.dark .ask-ai-markdown .ask-ai-copy-code-button {
|
|
2347
|
-
border-color: color-mix(
|
|
2348
|
-
in oklab,
|
|
2349
|
-
var(--color-neutral-700) 50%,
|
|
2350
|
-
transparent
|
|
2351
|
-
);
|
|
2352
|
-
background: var(--rd-code-surface);
|
|
2353
2630
|
color: var(--color-neutral-400);
|
|
2354
2631
|
}
|
|
2355
2632
|
|
|
2356
2633
|
.ask-ai-markdown .ask-ai-copy-code-button:hover {
|
|
2357
|
-
background: var(--color-neutral-50);
|
|
2358
2634
|
color: var(--color-neutral-600);
|
|
2359
2635
|
}
|
|
2360
2636
|
|
|
2361
2637
|
.dark .ask-ai-markdown .ask-ai-copy-code-button:hover {
|
|
2362
|
-
background: var(--color-neutral-800);
|
|
2363
2638
|
color: var(--color-neutral-200);
|
|
2364
2639
|
}
|
|
2365
2640
|
|
|
@@ -2437,6 +2712,7 @@ export default function AssistantEmbedPanel({
|
|
|
2437
2712
|
display: block;
|
|
2438
2713
|
width: 100%;
|
|
2439
2714
|
min-width: 100%;
|
|
2715
|
+
padding-block: 0.625rem;
|
|
2440
2716
|
background: transparent !important;
|
|
2441
2717
|
white-space: inherit;
|
|
2442
2718
|
word-break: normal;
|
|
@@ -2482,164 +2758,6 @@ export default function AssistantEmbedPanel({
|
|
|
2482
2758
|
background: var(--color-neutral-800);
|
|
2483
2759
|
}
|
|
2484
2760
|
|
|
2485
|
-
.dark .ask-ai-markdown .token.comment,
|
|
2486
|
-
.dark .ask-ai-markdown .token.prolog,
|
|
2487
|
-
.dark .ask-ai-markdown .token.doctype,
|
|
2488
|
-
.dark .ask-ai-markdown .token.cdata {
|
|
2489
|
-
color: #7f848e;
|
|
2490
|
-
}
|
|
2491
|
-
|
|
2492
|
-
.dark .ask-ai-markdown .token.punctuation {
|
|
2493
|
-
color: #abb2bf;
|
|
2494
|
-
}
|
|
2495
|
-
|
|
2496
|
-
.dark .ask-ai-markdown .token.property,
|
|
2497
|
-
.dark .ask-ai-markdown .token.tag,
|
|
2498
|
-
.dark .ask-ai-markdown .token.boolean,
|
|
2499
|
-
.dark .ask-ai-markdown .token.number,
|
|
2500
|
-
.dark .ask-ai-markdown .token.constant,
|
|
2501
|
-
.dark .ask-ai-markdown .token.symbol,
|
|
2502
|
-
.dark .ask-ai-markdown .token.deleted {
|
|
2503
|
-
color: #d19a66;
|
|
2504
|
-
}
|
|
2505
|
-
|
|
2506
|
-
.dark .ask-ai-markdown .token.selector,
|
|
2507
|
-
.dark .ask-ai-markdown .token.attr-name,
|
|
2508
|
-
.dark .ask-ai-markdown .token.string,
|
|
2509
|
-
.dark .ask-ai-markdown .token.char,
|
|
2510
|
-
.dark .ask-ai-markdown .token.builtin,
|
|
2511
|
-
.dark .ask-ai-markdown .token.inserted {
|
|
2512
|
-
color: #98c379;
|
|
2513
|
-
}
|
|
2514
|
-
|
|
2515
|
-
.dark .ask-ai-markdown .token.operator,
|
|
2516
|
-
.dark .ask-ai-markdown .token.entity,
|
|
2517
|
-
.dark .ask-ai-markdown .token.url,
|
|
2518
|
-
.dark .ask-ai-markdown .language-css .token.string,
|
|
2519
|
-
.dark .ask-ai-markdown .style .token.string {
|
|
2520
|
-
color: #56b6c2;
|
|
2521
|
-
}
|
|
2522
|
-
|
|
2523
|
-
.dark .ask-ai-markdown .token.atrule,
|
|
2524
|
-
.dark .ask-ai-markdown .token.attr-value,
|
|
2525
|
-
.dark .ask-ai-markdown .token.keyword {
|
|
2526
|
-
color: #c678dd;
|
|
2527
|
-
}
|
|
2528
|
-
|
|
2529
|
-
.dark .ask-ai-markdown .token.function,
|
|
2530
|
-
.dark .ask-ai-markdown .token.class-name {
|
|
2531
|
-
color: #e5c07b;
|
|
2532
|
-
}
|
|
2533
|
-
|
|
2534
|
-
.dark .ask-ai-markdown .token.regex,
|
|
2535
|
-
.dark .ask-ai-markdown .token.important,
|
|
2536
|
-
.dark .ask-ai-markdown .token.variable {
|
|
2537
|
-
color: #e06c75;
|
|
2538
|
-
}
|
|
2539
|
-
|
|
2540
|
-
.dark .ask-ai-markdown .token.attr-value > .token.punctuation.attr-equals,
|
|
2541
|
-
.dark
|
|
2542
|
-
.ask-ai-markdown
|
|
2543
|
-
.token.special-attr
|
|
2544
|
-
> .token.attr-value
|
|
2545
|
-
> .token.value.css {
|
|
2546
|
-
color: #abb2bf;
|
|
2547
|
-
}
|
|
2548
|
-
|
|
2549
|
-
.dark .ask-ai-markdown .language-css .token.selector {
|
|
2550
|
-
color: #d19a66;
|
|
2551
|
-
}
|
|
2552
|
-
|
|
2553
|
-
.dark .ask-ai-markdown .language-css .token.property {
|
|
2554
|
-
color: #abb2bf;
|
|
2555
|
-
}
|
|
2556
|
-
|
|
2557
|
-
.dark .ask-ai-markdown .language-css .token.function,
|
|
2558
|
-
.dark .ask-ai-markdown .language-css .token.url > .token.function {
|
|
2559
|
-
color: #56b6c2;
|
|
2560
|
-
}
|
|
2561
|
-
|
|
2562
|
-
.dark .ask-ai-markdown .language-css .token.url > .token.string.url {
|
|
2563
|
-
color: #98c379;
|
|
2564
|
-
}
|
|
2565
|
-
|
|
2566
|
-
.dark .ask-ai-markdown .language-css .token.important,
|
|
2567
|
-
.dark .ask-ai-markdown .language-css .token.atrule .token.rule {
|
|
2568
|
-
color: #c678dd;
|
|
2569
|
-
}
|
|
2570
|
-
|
|
2571
|
-
.dark .ask-ai-markdown .language-javascript .token.operator {
|
|
2572
|
-
color: #c678dd;
|
|
2573
|
-
}
|
|
2574
|
-
|
|
2575
|
-
.dark
|
|
2576
|
-
.ask-ai-markdown
|
|
2577
|
-
.language-javascript
|
|
2578
|
-
.token.template-string
|
|
2579
|
-
> .token.interpolation
|
|
2580
|
-
> .token.interpolation-punctuation.punctuation {
|
|
2581
|
-
color: #e06c75;
|
|
2582
|
-
}
|
|
2583
|
-
|
|
2584
|
-
.dark .ask-ai-markdown .language-json .token.operator {
|
|
2585
|
-
color: #abb2bf;
|
|
2586
|
-
}
|
|
2587
|
-
|
|
2588
|
-
.dark .ask-ai-markdown .language-json .token.null.keyword {
|
|
2589
|
-
color: #d19a66;
|
|
2590
|
-
}
|
|
2591
|
-
|
|
2592
|
-
.dark .ask-ai-markdown .language-markdown .token.url,
|
|
2593
|
-
.dark .ask-ai-markdown .language-markdown .token.url > .token.operator,
|
|
2594
|
-
.dark
|
|
2595
|
-
.ask-ai-markdown
|
|
2596
|
-
.language-markdown
|
|
2597
|
-
.token.url-reference.url
|
|
2598
|
-
> .token.string {
|
|
2599
|
-
color: #abb2bf;
|
|
2600
|
-
}
|
|
2601
|
-
|
|
2602
|
-
.dark .ask-ai-markdown .language-markdown .token.url > .token.content {
|
|
2603
|
-
color: #56b6c2;
|
|
2604
|
-
}
|
|
2605
|
-
|
|
2606
|
-
.dark .ask-ai-markdown .language-markdown .token.url > .token.url,
|
|
2607
|
-
.dark .ask-ai-markdown .language-markdown .token.url-reference.url {
|
|
2608
|
-
color: #98c379;
|
|
2609
|
-
}
|
|
2610
|
-
|
|
2611
|
-
.dark .ask-ai-markdown .language-markdown .token.blockquote.punctuation,
|
|
2612
|
-
.dark .ask-ai-markdown .language-markdown .token.hr.punctuation {
|
|
2613
|
-
color: #7f848e;
|
|
2614
|
-
}
|
|
2615
|
-
|
|
2616
|
-
.dark .ask-ai-markdown .language-markdown .token.code-snippet {
|
|
2617
|
-
color: #98c379;
|
|
2618
|
-
}
|
|
2619
|
-
|
|
2620
|
-
.dark .ask-ai-markdown .language-markdown .token.bold .token.content {
|
|
2621
|
-
color: #e5c07b;
|
|
2622
|
-
}
|
|
2623
|
-
|
|
2624
|
-
.dark .ask-ai-markdown .language-markdown .token.italic .token.content {
|
|
2625
|
-
color: #c678dd;
|
|
2626
|
-
}
|
|
2627
|
-
|
|
2628
|
-
.dark .ask-ai-markdown .language-markdown .token.strike .token.content,
|
|
2629
|
-
.dark
|
|
2630
|
-
.ask-ai-markdown
|
|
2631
|
-
.language-markdown
|
|
2632
|
-
.token.strike
|
|
2633
|
-
.token.punctuation,
|
|
2634
|
-
.dark .ask-ai-markdown .language-markdown .token.list.punctuation,
|
|
2635
|
-
.dark
|
|
2636
|
-
.ask-ai-markdown
|
|
2637
|
-
.language-markdown
|
|
2638
|
-
.token.title.important
|
|
2639
|
-
> .token.punctuation {
|
|
2640
|
-
color: #e06c75;
|
|
2641
|
-
}
|
|
2642
|
-
|
|
2643
2761
|
.ask-ai-markdown pre > code::-webkit-scrollbar {
|
|
2644
2762
|
width: 0;
|
|
2645
2763
|
height: 0;
|