wowchemy-theming.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*************************************************
  2. * Wowchemy
  3. * https://github.com/wowchemy/wowchemy-hugo-modules
  4. *
  5. * Wowchemy Theming System
  6. * Supported Modes: {0: Day, 1: Night, 2: Auto}
  7. **************************************************/
  8. import {fadeIn} from './wowchemy-animation';
  9. function getThemeMode() {
  10. return parseInt(localStorage.getItem('dark_mode') || 2);
  11. }
  12. function canChangeTheme() {
  13. // If var is set, then user is allowed to change the theme variation.
  14. return Boolean(window.wc.darkLightEnabled);
  15. }
  16. function initThemeVariation() {
  17. if (!canChangeTheme()) {
  18. return;
  19. }
  20. let currentThemeMode = getThemeMode();
  21. let isDarkTheme;
  22. switch (currentThemeMode) {
  23. case 0:
  24. isDarkTheme = false;
  25. break;
  26. case 1:
  27. isDarkTheme = true;
  28. break;
  29. default:
  30. if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
  31. // The visitor prefers dark themes and switching to the dark variation is allowed by admin.
  32. isDarkTheme = true;
  33. } else if (window.matchMedia('(prefers-color-scheme: light)').matches) {
  34. // The visitor prefers light themes and switching to the dark variation is allowed by admin.
  35. isDarkTheme = false;
  36. } else {
  37. // Use the site's default theme variation based on `light` in the theme file.
  38. isDarkTheme = window.wc.isSiteThemeDark;
  39. }
  40. break;
  41. }
  42. if (isDarkTheme) {
  43. document.body.classList.add("dark");
  44. } else {
  45. document.body.classList.remove("dark");
  46. }
  47. }
  48. function changeThemeModeClick(newMode) {
  49. if (!canChangeTheme()) {
  50. console.info('Cannot set theme - admin disabled theme selector.');
  51. return;
  52. }
  53. let isDarkTheme;
  54. switch (newMode) {
  55. case 0:
  56. localStorage.setItem('dark_mode', '1');
  57. isDarkTheme = true;
  58. console.info('User changed theme variation to Dark.');
  59. showActiveTheme(0);
  60. break;
  61. case 1:
  62. localStorage.setItem('dark_mode', '2');
  63. if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
  64. // The visitor prefers dark themes and switching to the dark variation is allowed by admin.
  65. isDarkTheme = true;
  66. } else if (window.matchMedia('(prefers-color-scheme: light)').matches) {
  67. // The visitor prefers light themes and switching to the dark variation is allowed by admin.
  68. isDarkTheme = false;
  69. } else {
  70. isDarkTheme = window.wc.isSiteThemeDark; // Use the site's default theme variation based on `light` in the theme file.
  71. }
  72. console.info('User changed theme variation to Auto.');
  73. showActiveTheme(1);
  74. break;
  75. default:
  76. localStorage.setItem('dark_mode', '0');
  77. isDarkTheme = false;
  78. console.info('User changed theme variation to Light.');
  79. showActiveTheme(2);
  80. break;
  81. }
  82. renderThemeVariation(isDarkTheme);
  83. }
  84. function showActiveTheme(mode) {
  85. let linkLight = document.querySelector('.js-set-theme-light');
  86. let linkDark = document.querySelector('.js-set-theme-dark');
  87. let linkAuto = document.querySelector('.js-set-theme-auto');
  88. switch (mode) {
  89. case 0:
  90. // Dark.
  91. linkLight.classList.remove('dropdown-item-active');
  92. linkDark.classList.add('dropdown-item-active');
  93. linkAuto.classList.remove('dropdown-item-active');
  94. break;
  95. case 1:
  96. // Auto.
  97. linkLight.classList.remove('dropdown-item-active');
  98. linkDark.classList.remove('dropdown-item-active');
  99. linkAuto.classList.add('dropdown-item-active');
  100. break;
  101. default:
  102. // Light.
  103. linkLight.classList.add('dropdown-item-active');
  104. linkDark.classList.remove('dropdown-item-active');
  105. linkAuto.classList.remove('dropdown-item-active');
  106. break;
  107. }
  108. }
  109. /**
  110. * Render theme variation (day or night).
  111. *
  112. * @param {boolean} isDarkTheme
  113. * @param {boolean} init
  114. * @returns {undefined}
  115. */
  116. function renderThemeVariation(isDarkTheme, init = false) {
  117. // Is code highlighting enabled in site config?
  118. const codeHlLight = document.querySelector('link[title=hl-light]');
  119. const codeHlDark = document.querySelector('link[title=hl-dark]');
  120. const codeHlEnabled = codeHlLight || codeHlDark;
  121. const diagramEnabled = document.querySelector('script[title=mermaid]');
  122. const body = document.body;
  123. // Check if re-render required.
  124. if (!init) {
  125. // If request to render light when light variation already rendered, return.
  126. // If request to render dark when dark variation already rendered, return.
  127. if ((isDarkTheme === false && !body.classList.contains('dark')) || (isDarkTheme === true && body.classList.contains('dark'))) {
  128. return;
  129. }
  130. }
  131. if (isDarkTheme === false) {
  132. if (!init) {
  133. // Only fade in the page when changing the theme variation.
  134. //$('body').css({opacity: 0, visibility: 'visible'}).animate({opacity: 1}, 500);
  135. Object.assign(document.body.style, {opacity: 0, visibility: 'visible'});
  136. fadeIn(document.body, 600);
  137. }
  138. body.classList.remove('dark');
  139. if (codeHlEnabled) {
  140. codeHlLight.disabled = false;
  141. codeHlDark.disabled = true;
  142. }
  143. if (diagramEnabled) {
  144. if (init) {
  145. /** @namespace window.mermaid **/
  146. window.mermaid.initialize({theme: 'default', securityLevel: 'loose'});
  147. } else {
  148. // Have to reload to re-initialise Mermaid with the new theme and re-parse the Mermaid code blocks.
  149. location.reload();
  150. }
  151. }
  152. } else if (isDarkTheme === true) {
  153. if (!init) {
  154. // Only fade in the page when changing the theme variation.
  155. Object.assign(document.body.style, {opacity: 0, visibility: 'visible'});
  156. fadeIn(document.body, 600);
  157. }
  158. body.classList.add("dark");
  159. if (codeHlEnabled) {
  160. codeHlLight.disabled = true;
  161. codeHlDark.disabled = false;
  162. }
  163. if (diagramEnabled) {
  164. if (init) {
  165. /** @namespace window.mermaid **/
  166. window.mermaid.initialize({theme: 'dark', securityLevel: 'loose'});
  167. } else {
  168. // Have to reload to re-initialise Mermaid with the new theme and re-parse the Mermaid code blocks.
  169. location.reload();
  170. }
  171. }
  172. }
  173. }
  174. export {
  175. canChangeTheme,
  176. initThemeVariation,
  177. changeThemeModeClick,
  178. renderThemeVariation,
  179. };