diff options
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.svelte | 97 |
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, '&').replace(/</g, '<').replace(/>/g, '>'); + } + }); +</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> |
