| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- <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>
|