diff --git a/docs/_document.html b/docs/_document.html index b76588947c..57be559114 100644 --- a/docs/_document.html +++ b/docs/_document.html @@ -6,10 +6,11 @@ + -
- - logo - -

Marked Documentation

+
+ + logo + +

Marked Documentation

+
+
+
Loading...
@@ -76,6 +92,7 @@

You'll need to enable Javascript to use this tool.

+ diff --git a/docs/demo/preview.html b/docs/demo/preview.html index 7e8c89fec5..445ecd8206 100644 --- a/docs/demo/preview.html +++ b/docs/demo/preview.html @@ -5,7 +5,16 @@ marked.js preview + + diff --git a/docs/js/index.js b/docs/js/index.js index 2f896564a1..983c676905 100644 --- a/docs/js/index.js +++ b/docs/js/index.js @@ -1,3 +1,124 @@ +// Theme functionality +function initTheme() { + // SVG icon constants for better maintainability + const SUN_ICON_SVG = ''; + const MOON_ICON_SVG = ''; + + // Get stored theme preference or default to 'auto' + const storedTheme = localStorage.getItem('theme') || 'auto'; + const html = document.documentElement; + const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)'); + + function applyThemeToIframes(theme) { + const effectiveTheme = theme === 'auto' + ? (darkModeQuery.matches ? 'dark' : 'light') + : theme; + + const iframes = document.querySelectorAll('iframe'); + iframes.forEach(iframe => { + try { + const iframeDocument = iframe.contentDocument || (iframe.contentWindow && iframe.contentWindow.document); + if (!iframeDocument || !iframeDocument.documentElement) { + return; + } + + if (theme === 'auto') { + iframeDocument.documentElement.removeAttribute('data-theme'); + } else { + iframeDocument.documentElement.setAttribute('data-theme', theme); + } + + if (iframeDocument.documentElement.style) { + iframeDocument.documentElement.style.colorScheme = effectiveTheme; + } + } catch { + // Ignore errors, iframe might be from another origin + } + }); + } + + // Expose helper for other scripts (e.g., demo page) to reapply theme on iframe load + window.__markedApplyThemeToIframes = applyThemeToIframes; + + function setTheme(theme) { + if (theme === 'auto') { + html.removeAttribute('data-theme'); + } else { + html.setAttribute('data-theme', theme); + } + localStorage.setItem('theme', theme); + updateToggleButton(theme); + + applyThemeToIframes(theme); + } + + function updateToggleButton(theme) { + const button = document.getElementById('theme-toggle'); + if (!button) return; + + const icon = button.querySelector('.icon'); + const text = button.querySelector('.text'); + + if (theme === 'auto') { + // Auto mode: show icon based on system preference + const isDarkMode = darkModeQuery.matches; + icon.innerHTML = isDarkMode ? MOON_ICON_SVG : SUN_ICON_SVG; + text.textContent = 'Dark'; + } else if (theme === 'dark') { + // Manual dark mode: show 'Light' (next action is to go to manual light) + icon.innerHTML = MOON_ICON_SVG; + text.textContent = 'Light'; + } else { + // Manual light mode: show 'System' (next action is to go back to auto) + icon.innerHTML = SUN_ICON_SVG; + text.textContent = 'System'; + } + } + + function cycleTheme() { + const currentTheme = localStorage.getItem('theme') || 'auto'; + let nextTheme; + + switch (currentTheme) { + case 'auto': + nextTheme = 'dark'; + break; + case 'dark': + nextTheme = 'light'; + break; + case 'light': + nextTheme = 'auto'; + break; + default: + nextTheme = 'dark'; + } + + setTheme(nextTheme); + } + + // Initialize theme + setTheme(storedTheme); + + // Listen for system theme changes + darkModeQuery.addEventListener('change', () => { + if (localStorage.getItem('theme') === 'auto') { + updateToggleButton('auto'); + applyThemeToIframes('auto'); + } + }); + + // Add click handler for toggle button + document.addEventListener('DOMContentLoaded', () => { + const toggleButton = document.getElementById('theme-toggle'); + if (toggleButton) { + toggleButton.addEventListener('click', cycleTheme); + } + }); +} + +// Initialize theme as early as possible +initTheme(); + const match = /#\/(.+)\\.md(.*)/g.exec(window.location.hash); if (match && match[1]) { // Redirect from URL format to new URL, for example: