@@ -8,4 +8,128 @@ const myTimeline = new MastodonTimeline.Init({
88 maxNbPostFetch : '10' ,
99 insistSearchContainer : true , // This helps with timing issues
1010 insistSearchContainerTime : '5000' // Wait up to 5 seconds for container
11- } ) ;
11+ } ) ;
12+
13+ // Function to detect current Quarto theme
14+ function detectQuartoTheme ( ) {
15+ // Method 1: Check for Quarto's theme class on html or body
16+ if ( document . documentElement . getAttribute ( 'data-bs-theme' ) === 'dark' ||
17+ document . body . classList . contains ( 'quarto-dark' ) ||
18+ document . documentElement . classList . contains ( 'quarto-dark' ) ) {
19+ return 'dark' ;
20+ }
21+
22+ // Method 2: Check for dark mode in CSS custom properties
23+ const computedStyle = getComputedStyle ( document . documentElement ) ;
24+ const bgColor = computedStyle . getPropertyValue ( '--bs-body-bg' ) ||
25+ computedStyle . getPropertyValue ( 'background-color' ) ;
26+
27+ // If background is dark, assume dark theme
28+ if ( bgColor && ( bgColor . includes ( 'rgb(' ) || bgColor . includes ( '#' ) ) ) {
29+ // Simple heuristic: convert to grayscale and check brightness
30+ const isDark = isColorDark ( bgColor ) ;
31+ return isDark ? 'dark' : 'light' ;
32+ }
33+
34+ // Method 3: Check CSS media query preference
35+ if ( window . matchMedia && window . matchMedia ( '(prefers-color-scheme: dark)' ) . matches ) {
36+ return 'dark' ;
37+ }
38+
39+ return 'light' ;
40+ }
41+
42+ // Helper function to determine if a color is dark
43+ function isColorDark ( color ) {
44+ // Convert color to RGB values
45+ let r , g , b ;
46+
47+ if ( color . startsWith ( '#' ) ) {
48+ // Hex color
49+ const hex = color . slice ( 1 ) ;
50+ r = parseInt ( hex . substr ( 0 , 2 ) , 16 ) ;
51+ g = parseInt ( hex . substr ( 2 , 2 ) , 16 ) ;
52+ b = parseInt ( hex . substr ( 4 , 2 ) , 16 ) ;
53+ } else if ( color . startsWith ( 'rgb' ) ) {
54+ // RGB color
55+ const matches = color . match ( / \d + / g) ;
56+ if ( matches && matches . length >= 3 ) {
57+ r = parseInt ( matches [ 0 ] ) ;
58+ g = parseInt ( matches [ 1 ] ) ;
59+ b = parseInt ( matches [ 2 ] ) ;
60+ } else {
61+ return false ; // Default to light if can't parse
62+ }
63+ } else {
64+ return false ; // Unknown format, default to light
65+ }
66+
67+ // Calculate luminance
68+ const luminance = ( 0.299 * r + 0.587 * g + 0.114 * b ) / 255 ;
69+ return luminance < 0.5 ; // Dark if luminance is less than 50%
70+ }
71+
72+ // Function to sync timeline theme with Quarto theme
73+ function syncTimelineTheme ( ) {
74+ const currentTheme = detectQuartoTheme ( ) ;
75+ myTimeline . mtColorTheme ( currentTheme ) ;
76+ }
77+
78+ // Set up theme synchronization
79+ function setupThemeSync ( ) {
80+ // Initial sync
81+ syncTimelineTheme ( ) ;
82+
83+ // Method 1: Watch for changes to data-bs-theme attribute (Bootstrap-based Quarto)
84+ if ( document . documentElement . hasAttribute ( 'data-bs-theme' ) ) {
85+ const observer = new MutationObserver ( ( mutations ) => {
86+ mutations . forEach ( ( mutation ) => {
87+ if ( mutation . type === 'attributes' &&
88+ mutation . attributeName === 'data-bs-theme' ) {
89+ syncTimelineTheme ( ) ;
90+ }
91+ } ) ;
92+ } ) ;
93+
94+ observer . observe ( document . documentElement , {
95+ attributes : true ,
96+ attributeFilter : [ 'data-bs-theme' ]
97+ } ) ;
98+ }
99+
100+ // Method 2: Watch for class changes on body or html
101+ const classObserver = new MutationObserver ( ( mutations ) => {
102+ mutations . forEach ( ( mutation ) => {
103+ if ( mutation . type === 'attributes' &&
104+ mutation . attributeName === 'class' ) {
105+ syncTimelineTheme ( ) ;
106+ }
107+ } ) ;
108+ } ) ;
109+
110+ classObserver . observe ( document . body , {
111+ attributes : true ,
112+ attributeFilter : [ 'class' ]
113+ } ) ;
114+
115+ classObserver . observe ( document . documentElement , {
116+ attributes : true ,
117+ attributeFilter : [ 'class' ]
118+ } ) ;
119+
120+ // Method 3: Listen for custom events (if your Quarto site dispatches them)
121+ document . addEventListener ( 'quartoThemeChanged' , syncTimelineTheme ) ;
122+
123+ // Method 4: Poll for changes (fallback method)
124+ let lastTheme = detectQuartoTheme ( ) ;
125+ setInterval ( ( ) => {
126+ const currentTheme = detectQuartoTheme ( ) ;
127+ if ( currentTheme !== lastTheme ) {
128+ syncTimelineTheme ( ) ;
129+ lastTheme = currentTheme ;
130+ }
131+ } , 1000 ) ; // Check every second
132+ }
133+
134+ // Initialize theme synchronization when the timeline is ready
135+ setTimeout ( setupThemeSync , 1000 ) ;
0 commit comments