/** * repo-page.ts — universal initialiser for every repo-scoped page. * * Pages that only need repo-nav hydration register `{ "page": "repo" }` (or * include `"repo_id"` in their page_json block). More complex pages extend * this and register their own key in MusePages. * * Also runs highlight.js over any .rh-readme-body code blocks so that fenced * code in READMEs gets syntax highlighting without a separate page module. * * Registered as: window.MusePages['repo'] */ import hljs from 'highlight.js/lib/core'; import python from 'highlight.js/lib/languages/python'; import typescript from 'highlight.js/lib/languages/typescript'; import javascript from 'highlight.js/lib/languages/javascript'; import bash from 'highlight.js/lib/languages/bash'; import rust from 'highlight.js/lib/languages/rust'; import go from 'highlight.js/lib/languages/go'; import yaml from 'highlight.js/lib/languages/yaml'; import json from 'highlight.js/lib/languages/json'; import toml from 'highlight.js/lib/languages/ini'; // toml ~= ini hljs.registerLanguage('python', python); hljs.registerLanguage('typescript', typescript); hljs.registerLanguage('javascript', javascript); hljs.registerLanguage('bash', bash); hljs.registerLanguage('sh', bash); hljs.registerLanguage('shell', bash); hljs.registerLanguage('rust', rust); hljs.registerLanguage('go', go); hljs.registerLanguage('yaml', yaml); hljs.registerLanguage('json', json); hljs.registerLanguage('toml', toml); export interface RepoPageData { page?: string; repo_id?: string; clone_url?: string; [key: string]: unknown; } function highlightReadme(): void { document.querySelectorAll('.rh-readme-body pre code').forEach((block) => { if (block.dataset['highlighted'] !== 'yes') { hljs.highlightElement(block); } }); } function initReadmeAnchors(): void { document.querySelectorAll('.rh-readme-body h1,.rh-readme-body h2,.rh-readme-body h3,.rh-readme-body h4,.rh-readme-body h5,.rh-readme-body h6').forEach((heading) => { if (heading.querySelector('.rh-md-anchor')) return; const slug = heading.id; if (!slug) return; const anchor = document.createElement('a'); anchor.href = '#' + slug; anchor.className = 'rh-md-anchor'; anchor.textContent = '#'; anchor.setAttribute('aria-hidden', 'true'); heading.appendChild(anchor); }); } function initCloneCopyButtons(): void { document.querySelectorAll('.clone-copy-btn').forEach((btn) => { btn.addEventListener('click', () => { const input = btn.previousElementSibling as HTMLInputElement | null; if (input?.value) void navigator.clipboard.writeText(input.value); }); }); } export function initRepoPage(data: RepoPageData): void { const repoId = data.repo_id; if (repoId && typeof window.initRepoNav === 'function') { window.initRepoNav(String(repoId)); } highlightReadme(); initReadmeAnchors(); initCloneCopyButtons(); }