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 @@
+
-
-
-
-
- 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: