summaryrefslogtreecommitdiff
path: root/llama.cpp/tools/server/webui/src/lib/components/app/misc/SyntaxHighlightedCode.svelte
diff options
context:
space:
mode:
Diffstat (limited to 'llama.cpp/tools/server/webui/src/lib/components/app/misc/SyntaxHighlightedCode.svelte')
-rw-r--r--llama.cpp/tools/server/webui/src/lib/components/app/misc/SyntaxHighlightedCode.svelte97
1 files changed, 97 insertions, 0 deletions
diff --git a/llama.cpp/tools/server/webui/src/lib/components/app/misc/SyntaxHighlightedCode.svelte b/llama.cpp/tools/server/webui/src/lib/components/app/misc/SyntaxHighlightedCode.svelte
new file mode 100644
index 0000000..bc42f9d
--- /dev/null
+++ b/llama.cpp/tools/server/webui/src/lib/components/app/misc/SyntaxHighlightedCode.svelte
@@ -0,0 +1,97 @@
+<script lang="ts">
+ import hljs from 'highlight.js';
+ import { browser } from '$app/environment';
+ import { mode } from 'mode-watcher';
+
+ import githubDarkCss from 'highlight.js/styles/github-dark.css?inline';
+ import githubLightCss from 'highlight.js/styles/github.css?inline';
+
+ interface Props {
+ code: string;
+ language?: string;
+ class?: string;
+ maxHeight?: string;
+ maxWidth?: string;
+ }
+
+ let {
+ code,
+ language = 'text',
+ class: className = '',
+ maxHeight = '60vh',
+ maxWidth = ''
+ }: Props = $props();
+
+ let highlightedHtml = $state('');
+
+ function loadHighlightTheme(isDark: boolean) {
+ if (!browser) return;
+
+ const existingThemes = document.querySelectorAll('style[data-highlight-theme-preview]');
+ existingThemes.forEach((style) => style.remove());
+
+ const style = document.createElement('style');
+ style.setAttribute('data-highlight-theme-preview', 'true');
+ style.textContent = isDark ? githubDarkCss : githubLightCss;
+
+ document.head.appendChild(style);
+ }
+
+ $effect(() => {
+ const currentMode = mode.current;
+ const isDark = currentMode === 'dark';
+
+ loadHighlightTheme(isDark);
+ });
+
+ $effect(() => {
+ if (!code) {
+ highlightedHtml = '';
+ return;
+ }
+
+ try {
+ // Check if the language is supported
+ const lang = language.toLowerCase();
+ const isSupported = hljs.getLanguage(lang);
+
+ if (isSupported) {
+ const result = hljs.highlight(code, { language: lang });
+ highlightedHtml = result.value;
+ } else {
+ // Try auto-detection or fallback to plain text
+ const result = hljs.highlightAuto(code);
+ highlightedHtml = result.value;
+ }
+ } catch {
+ // Fallback to escaped plain text
+ highlightedHtml = code.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+ }
+ });
+</script>
+
+<div
+ class="code-preview-wrapper overflow-auto rounded-lg border border-border bg-muted {className}"
+ style="max-height: {maxHeight}; max-width: {maxWidth};"
+>
+ <!-- Needs to be formatted as single line for proper rendering -->
+ <pre class="m-0 overflow-x-auto p-4"><code class="hljs text-sm leading-relaxed"
+ >{@html highlightedHtml}</code
+ ></pre>
+</div>
+
+<style>
+ .code-preview-wrapper {
+ font-family:
+ ui-monospace, SFMono-Regular, 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas,
+ 'Liberation Mono', Menlo, monospace;
+ }
+
+ .code-preview-wrapper pre {
+ background: transparent;
+ }
+
+ .code-preview-wrapper code {
+ background: transparent;
+ }
+</style>