|
1 | 1 | window.ShellDocs = window.ShellDocs || {}; |
2 | 2 |
|
3 | | -// Re-highlight all code blocks. Called from MarkdownContent after render. |
4 | | -window.shelldocsHighlight = function () { |
5 | | - if (window.Prism) { |
6 | | - try { window.Prism.highlightAll(); } catch (e) {} |
| 3 | +/* Shiki-backed highlighters. Both functions replace <pre><code class="language-X"> |
| 4 | + with Shiki's rendered <pre> so we get VSCode-parity colouring. Idempotent — |
| 5 | + a data-shiki flag prevents re-highlighting. */ |
| 6 | + |
| 7 | +function langOf(codeEl) { |
| 8 | + var cls = (codeEl.className || '').split(/\s+/); |
| 9 | + for (var i = 0; i < cls.length; i++) { |
| 10 | + if (cls[i].indexOf('language-') === 0) return cls[i].substring(9); |
7 | 11 | } |
8 | | -}; |
| 12 | + return null; |
| 13 | +} |
9 | 14 |
|
10 | | -// Highlight a specific <pre> element — used by PreviewFrame when the code tab |
11 | | -// mounts, so we don't re-scan the whole page on every tab flip. |
12 | | -window.shelldocsHighlightElement = function (preEl) { |
13 | | - if (!preEl || !window.Prism) return; |
| 15 | +function highlightOne(preEl) { |
| 16 | + if (!preEl || !window.__shiki) return; |
| 17 | + if (preEl.dataset.shiki === 'done') return; |
14 | 18 | var code = preEl.querySelector('code'); |
15 | 19 | if (!code) return; |
16 | | - try { window.Prism.highlightElement(code); } catch (e) {} |
| 20 | + var lang = langOf(code); |
| 21 | + if (!lang) return; |
| 22 | + /* Shiki doesn't know every Prism alias — silently fall back. */ |
| 23 | + if (!window.__shiki.getLoadedLanguages().includes(lang)) return; |
| 24 | + |
| 25 | + var source = code.textContent; |
| 26 | + try { |
| 27 | + var html = window.__shiki.codeToHtml(source, { |
| 28 | + lang: lang, |
| 29 | + themes: { light: 'github-light', dark: 'github-dark' }, |
| 30 | + defaultColor: false |
| 31 | + }); |
| 32 | + var tpl = document.createElement('template'); |
| 33 | + tpl.innerHTML = html.trim(); |
| 34 | + var newPre = tpl.content.firstElementChild; |
| 35 | + if (!newPre) return; |
| 36 | + newPre.dataset.shiki = 'done'; |
| 37 | + preEl.parentNode.replaceChild(newPre, preEl); |
| 38 | + } catch (e) { /* skip on grammar error */ } |
| 39 | +} |
| 40 | + |
| 41 | +window.shelldocsHighlight = function () { |
| 42 | + if (!window.__shiki) return; |
| 43 | + document.querySelectorAll('pre:not([data-shiki]) > code[class*="language-"]') |
| 44 | + .forEach(function (code) { highlightOne(code.parentElement); }); |
17 | 45 | }; |
18 | 46 |
|
| 47 | +window.shelldocsHighlightElement = function (preEl) { highlightOne(preEl); }; |
| 48 | + |
19 | 49 | // Copy-to-clipboard for code blocks. |
20 | 50 | window.shelldocsCopyCode = function (button) { |
21 | 51 | var block = button.closest('.shelldocs-codeblock'); |
|
0 commit comments