| @@ -6,8 +6,33 @@ | ||
| 6 | 6 | if (!defined('ABSPATH')) { |
| 7 | 7 | exit; |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | +if (!function_exists('darkify_js_string')) { | |
| 11 | + /** | |
| 12 | + * Emit a value as a JavaScript string literal (quotes included). | |
| 13 | + * | |
| 14 | + * For anything the browser parses rather than displays — CSS selectors, | |
| 15 | + * above all — esc_attr() is the wrong escaper inside a <script> block: it | |
| 16 | + * HTML-encodes `>`, `&` and `"`, and script bodies are raw text, so those | |
| 17 | + * entities reach the JS engine verbatim and corrupt the value. JSON is the | |
| 18 | + * correct escaping for a JS string; the HEX flags additionally keep `<`, | |
| 19 | + * `>`, `&`, `'` and `"` out of the raw output so the literal can never | |
| 20 | + * close the surrounding <script> tag. | |
| 21 | + * | |
| 22 | + * @param mixed $value Value to emit (cast to string). | |
| 23 | + * @return string A quoted JS string literal, e.g. '"#id, #id *"'. | |
| 24 | + */ | |
| 25 | + function darkify_js_string($value) | |
| 26 | + { | |
| 27 | + $json = wp_json_encode( | |
| 28 | + (string) $value, | |
| 29 | + JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | |
| 30 | + ); | |
| 31 | + return false === $json ? '""' : $json; | |
| 32 | + } | |
| 33 | +} | |
| 34 | + | |
| 10 | 35 | ob_start(); |
| 11 | 36 | $options = get_option('darkify'); |
| 12 | 37 | // Controls |
| 13 | 38 | $enable_default_dark_mode = isset($options['enable_default_dark_mode']) ? $options['enable_default_dark_mode'] : ''; |
| @@ -12,8 +37,9 @@ | ||
| 12 | 37 | // Controls |
| 13 | 38 | $enable_default_dark_mode = isset($options['enable_default_dark_mode']) ? $options['enable_default_dark_mode'] : ''; |
| 14 | 39 | $enable_os_aware = isset($options['enable_os_aware']) ? $options['enable_os_aware'] : true; |
| 15 | 40 | $enable_keyboard_shortcut = isset($options['enable_keyboard_shortcut']) ? $options['enable_keyboard_shortcut'] : true; |
| 41 | +$keyboard_shortcut_keys = isset($options['keyboard_shortcut_keys']) && $options['keyboard_shortcut_keys'] ? $options['keyboard_shortcut_keys'] : 'ctrl+alt+d'; | |
| 16 | 42 | $enable_time = isset($options['enable_time']) ? $options['enable_time'] : ""; |
| 17 | 43 | $enable_time_based_dark = isset($enable_time['enable_time_based_dark']) ? $enable_time['enable_time_based_dark'] : ""; |
| 18 | 44 | $enable_time_fields = isset($enable_time['enable_time_fields']) ? $enable_time['enable_time_fields'] : ''; |
| 19 | 45 | $time_based_dark_start = isset($enable_time_fields['time_based_dark_start']) ? $enable_time_fields['time_based_dark_start'] : ""; |
| @@ -50,8 +76,43 @@ | ||
| 50 | 76 | $low_image_darken_label = isset($darken_background['low_image_darken_label']) ? $darken_background['low_image_darken_label'] : '60'; |
| 51 | 77 | |
| 52 | 78 | $enable_invert_inline_svg = isset($options['enable_invert_inline_svg']) ? $options['enable_invert_inline_svg'] : ""; |
| 53 | 79 | |
| 80 | +/* | |
| 81 | + * The override rows are printed into a <script> as raw JSON (like | |
| 82 | + * darkify_allowed_btn_class below), so each value is reduced to a known-safe | |
| 83 | + * shape here: a hex colour or one of the fixed scope keys. Rows missing either | |
| 84 | + * colour are dropped — a half-filled repeater row is the default state of the | |
| 85 | + * field and means nothing to the engine. | |
| 86 | + */ | |
| 87 | +$darkify_color_overrides = array(); | |
| 88 | +if (!empty($options['color_overrides']) && is_array($options['color_overrides'])) { | |
| 89 | + $darkify_override_scopes = array('all', 'text', 'icon', 'background', 'border', 'shadow'); | |
| 90 | + foreach ($options['color_overrides'] as $darkify_override_row) { | |
| 91 | + if (!is_array($darkify_override_row)) { | |
| 92 | + continue; | |
| 93 | + } | |
| 94 | + | |
| 95 | + $darkify_light = isset($darkify_override_row['light_color']) ? DarkifyUtils::sanitize_css_color($darkify_override_row['light_color']) : ''; | |
| 96 | + $darkify_dark = isset($darkify_override_row['dark_color']) ? DarkifyUtils::sanitize_css_color($darkify_override_row['dark_color']) : ''; | |
| 97 | + | |
| 98 | + if (!$darkify_light || !$darkify_dark) { | |
| 99 | + continue; | |
| 100 | + } | |
| 101 | + | |
| 102 | + $darkify_scope = isset($darkify_override_row['override_scope']) ? $darkify_override_row['override_scope'] : 'all'; | |
| 103 | + if (!in_array($darkify_scope, $darkify_override_scopes, true)) { | |
| 104 | + $darkify_scope = 'all'; | |
| 105 | + } | |
| 106 | + | |
| 107 | + $darkify_color_overrides[] = array( | |
| 108 | + 'light_color' => $darkify_light, | |
| 109 | + 'dark_color' => $darkify_dark, | |
| 110 | + 'override_scope' => $darkify_scope, | |
| 111 | + ); | |
| 112 | + } | |
| 113 | +} | |
| 114 | + | |
| 54 | 115 | $invert = isset($options['invert']) ? $options['invert'] : ""; |
| 55 | 116 | $enable_invert_images = isset($invert['enable_invert_images']) ? $invert['enable_invert_images'] : ""; |
| 56 | 117 | $invert_images_allowed_urls = !empty($invert['invert_images_allowed_urls']) ? DarkifyUtils::normalize_image_urls($invert['invert_images_allowed_urls']) : ""; |
| 57 | 118 | |
| @@ -86,9 +147,54 @@ | ||
| 86 | 147 | } else { |
| 87 | 148 | $video_replacements = "[]"; |
| 88 | 149 | } |
| 89 | 150 | if (!is_admin()) { ?> |
| 90 | - <script type="text/javascript" class="darkify_inline_js">(function(){var s=localStorage.darkify_last_state,t=localStorage.darkify_selected_theme||'set1';if(s==='1'){var h=document.documentElement;h.classList.add('darkify_dark_mode_enabled');h.classList.add('darkify-'+t);}}());</script> | |
| 151 | + <?php | |
| 152 | + /* | |
| 153 | + * Release the pre-paint guard when the engine is done, not on a fixed timer. | |
| 154 | + * | |
| 155 | + * This used to be a flat `setTimeout(..., 800)`. On a warm reload that is | |
| 156 | + * invisible — every asset is in cache, the engine's first walk lands early, | |
| 157 | + * and it drops both classes itself long before the timer. On a HARD reload | |
| 158 | + * it is the flicker: nothing is served from cache, so the engine script and | |
| 159 | + * the stylesheets it reads are re-fetched and the first walk lands well | |
| 160 | + * after 800ms. The timer fired first, un-hid `body` while the page still | |
| 161 | + * carried the theme's LIGHT colours, and the walk then flipped the whole | |
| 162 | + * page to dark a few hundred ms later. That flip is what the visitor sees | |
| 163 | + * flickering. | |
| 164 | + * | |
| 165 | + * The timeout's real job is the failsafe: if the engine never runs (script | |
| 166 | + * 404s, blocked by an optimiser, JS disabled mid-flight) the page must not | |
| 167 | + * stay hidden. So the guard now comes off on a condition rather than a | |
| 168 | + * duration: | |
| 169 | + * | |
| 170 | + * - engine still to paint -> keep waiting; it removes the classes itself | |
| 171 | + * the moment its first walk has real colours on the page. | |
| 172 | + * - parsing finished and `window.darkify_engine_loaded` still unset -> | |
| 173 | + * the engine is not on this page and never will be, so release at once. | |
| 174 | + * That is strictly quicker than the old fixed 800ms in the case the | |
| 175 | + * timer actually existed for. | |
| 176 | + * - 4000ms -> release regardless, so no failure mode can leave the page | |
| 177 | + * hidden. Comfortably above the slowest measured hard reload. | |
| 178 | + * | |
| 179 | + * Parse state is the gate, not the presence of the engine's script tag: on | |
| 180 | + * a large page the tag can sit hundreds of KB into <head> and simply not be | |
| 181 | + * parsed yet at the moment we look, which reads as "no engine" on exactly | |
| 182 | + * the slow load this is meant to protect. | |
| 183 | + * | |
| 184 | + * Only `darkify_fouc_guard` is polled. Once that is gone the engine has | |
| 185 | + * demonstrably painted, so `darkify_prepaint` can be left to it; the two are | |
| 186 | + * still dropped together if the failsafe ever has to fire, which preserves | |
| 187 | + * the original guarantee that neither class can outlive the page load. | |
| 188 | + * | |
| 189 | + * No `>`/`<`/`&` anywhere in the snippet, so the ceiling is counted in | |
| 190 | + * 100ms ticks (40 = 4s) and every test is an `===`/`!==`. wp_kses | |
| 191 | + * entity-encodes all three characters inside script text — `n>=40` reaches | |
| 192 | + * the browser as `n>=40` and dies with a SyntaxError — which is also why | |
| 193 | + * the gates are nested ifs rather than `&&`. | |
| 194 | + */ | |
| 195 | + ?> | |
| 196 | + <script type="text/javascript" class="darkify_inline_js">(function(){var s=localStorage.darkify_last_state,t=localStorage.darkify_selected_theme||'set1';if(s==='1'){var h=document.documentElement;h.classList.add('darkify_dark_mode_enabled');h.classList.add('darkify-'+t);h.classList.add('darkify_prepaint');h.classList.add('darkify_fouc_guard');var r=function(){h.classList.remove('darkify_prepaint');h.classList.remove('darkify_fouc_guard');};var n=0;var p=function(){if(!h.classList.contains('darkify_fouc_guard')){return;}n=n+1;if(n===40){r();return;}if(document.readyState!=='loading'){if(!window.darkify_engine_loaded){r();return;}}setTimeout(p,100);};setTimeout(p,100);}}());</script> | |
| 91 | 197 | <style type="text/css" class="darkify_inline_css"> |
| 92 | 198 | :root { |
| 93 | 199 | <?php |
| 94 | 200 | $dark_mode_color_palettes = [ |
| @@ -105,8 +211,10 @@ | ||
| 105 | 211 | 'btn_text_color' => isset($options["dark_mode_btn_color_set1"]) ? $options["dark_mode_btn_color_set1"]['color'] : '#BEBEBE', |
| 106 | 212 | 'btn_bg' => isset($options["dark_mode_btn_color_set1"]) ? $options["dark_mode_btn_color_set1"]['background'] : '#4A4A4A', |
| 107 | 213 | 'btn_text_hover_color' => isset($options["dark_mode_btn_color_set1"]) ? $options["dark_mode_btn_color_set1"]['hover_color'] : '#BEBEBE', |
| 108 | 214 | 'btn_hover_bg' => isset($options["dark_mode_btn_color_set1"]) ? $options["dark_mode_btn_color_set1"]['hover_background'] : '#2D2D2D', |
| 215 | + 'btn_border_color' => isset($options["dark_mode_btn_color_set1"]['border']) ? $options["dark_mode_btn_color_set1"]['border'] : '#4A4A4A', | |
| 216 | + 'btn_hover_border_color' => isset($options["dark_mode_btn_color_set1"]['hover_border']) ? $options["dark_mode_btn_color_set1"]['hover_border'] : '#2D2D2D', | |
| 109 | 217 | ], |
| 110 | 218 | 'set2' => [ |
| 111 | 219 | 'bg' => isset($options["dark_mode_color_set2"]) ? $options["dark_mode_color_set2"]['background'] : '#092635', |
| 112 | 220 | 'secondary_bg' => isset($options["dark_mode_color_set2"]) ? $options["dark_mode_color_set2"]['secondary_background'] : '#081E29', |
| @@ -120,8 +228,10 @@ | ||
| 120 | 228 | 'btn_text_color' => isset($options["dark_mode_btn_color_set2"]) ? $options["dark_mode_btn_color_set2"]['color'] : '#BEE0F1', |
| 121 | 229 | 'btn_bg' => isset($options["dark_mode_btn_color_set2"]) ? $options["dark_mode_btn_color_set2"]['background'] : '#195979', |
| 122 | 230 | 'btn_text_hover_color' => isset($options["dark_mode_btn_color_set2"]) ? $options["dark_mode_btn_color_set2"]['hover_color'] : '#BEE0F1', |
| 123 | 231 | 'btn_hover_bg' => isset($options["dark_mode_btn_color_set2"]) ? $options["dark_mode_btn_color_set2"]['hover_background'] : '#2D2D2D', |
| 232 | + 'btn_border_color' => isset($options["dark_mode_btn_color_set2"]['border']) ? $options["dark_mode_btn_color_set2"]['border'] : '#195979', | |
| 233 | + 'btn_hover_border_color' => isset($options["dark_mode_btn_color_set2"]['hover_border']) ? $options["dark_mode_btn_color_set2"]['hover_border'] : '#2D2D2D', | |
| 124 | 234 | ], |
| 125 | 235 | 'set3' => [ |
| 126 | 236 | 'bg' => isset($options["dark_mode_color_set3"]) ? $options["dark_mode_color_set3"]['background'] : '#211e3c', |
| 127 | 237 | 'secondary_bg' => isset($options["dark_mode_color_set3"]) ? $options["dark_mode_color_set3"]['secondary_background'] : '#302C57', |
| @@ -135,8 +245,10 @@ | ||
| 135 | 245 | 'btn_text_color' => isset($options["dark_mode_btn_color_set3"]) ? $options["dark_mode_btn_color_set3"]['color'] : '#B1BBD8', |
| 136 | 246 | 'btn_bg' => isset($options["dark_mode_btn_color_set3"]) ? $options["dark_mode_btn_color_set3"]['background'] : '#4E478D', |
| 137 | 247 | 'btn_text_hover_color' => isset($options["dark_mode_btn_color_set3"]) ? $options["dark_mode_btn_color_set3"]['hover_color'] : '#B1BBD8', |
| 138 | 248 | 'btn_hover_bg' => isset($options["dark_mode_btn_color_set3"]) ? $options["dark_mode_btn_color_set3"]['hover_background'] : '#2A264D', |
| 249 | + 'btn_border_color' => isset($options["dark_mode_btn_color_set3"]['border']) ? $options["dark_mode_btn_color_set3"]['border'] : '#4E478D', | |
| 250 | + 'btn_hover_border_color' => isset($options["dark_mode_btn_color_set3"]['hover_border']) ? $options["dark_mode_btn_color_set3"]['hover_border'] : '#2A264D', | |
| 139 | 251 | ], |
| 140 | 252 | 'set4' => [ |
| 141 | 253 | 'bg' => isset($options["dark_mode_color_set4"]) ? $options["dark_mode_color_set4"]['background'] : '#1d253a', |
| 142 | 254 | 'secondary_bg' => isset($options["dark_mode_color_set4"]) ? $options["dark_mode_color_set4"]['secondary_background'] : '#2B3655', |
| @@ -150,8 +262,10 @@ | ||
| 150 | 262 | 'btn_text_color' => isset($options["dark_mode_btn_color_set4"]) ? $options["dark_mode_btn_color_set4"]['color'] : '#B1BBD8', |
| 151 | 263 | 'btn_bg' => isset($options["dark_mode_btn_color_set4"]) ? $options["dark_mode_btn_color_set4"]['background'] : '#46598C', |
| 152 | 264 | 'btn_text_hover_color' => isset($options["dark_mode_btn_color_set4"]) ? $options["dark_mode_btn_color_set4"]['hover_color'] : '#B1BBD8', |
| 153 | 265 | 'btn_hover_bg' => isset($options["dark_mode_btn_color_set4"]) ? $options["dark_mode_btn_color_set4"]['hover_background'] : '#303D60', |
| 266 | + 'btn_border_color' => isset($options["dark_mode_btn_color_set4"]['border']) ? $options["dark_mode_btn_color_set4"]['border'] : '#46598C', | |
| 267 | + 'btn_hover_border_color' => isset($options["dark_mode_btn_color_set4"]['hover_border']) ? $options["dark_mode_btn_color_set4"]['hover_border'] : '#303D60', | |
| 154 | 268 | ], |
| 155 | 269 | 'set5' => [ |
| 156 | 270 | 'bg' => isset($options["dark_mode_color_set5"]) ? $options["dark_mode_color_set5"]['background'] : '#1b1823', |
| 157 | 271 | 'secondary_bg' => isset($options["dark_mode_color_set5"]) ? $options["dark_mode_color_set5"]['secondary_background'] : '#352f44', |
| @@ -165,8 +279,10 @@ | ||
| 165 | 279 | 'btn_text_color' => isset($options["dark_mode_btn_color_set5"]) ? $options["dark_mode_btn_color_set5"]['color'] : '#C6C1D5', |
| 166 | 280 | 'btn_bg' => isset($options["dark_mode_btn_color_set5"]) ? $options["dark_mode_btn_color_set5"]['background'] : '#54496f', |
| 167 | 281 | 'btn_text_hover_color' => isset($options["dark_mode_btn_color_set5"]) ? $options["dark_mode_btn_color_set5"]['hover_color'] : '#C6C1D5', |
| 168 | 282 | 'btn_hover_bg' => isset($options["dark_mode_btn_color_set5"]) ? $options["dark_mode_btn_color_set5"]['hover_background'] : '#403953', |
| 283 | + 'btn_border_color' => isset($options["dark_mode_btn_color_set5"]['border']) ? $options["dark_mode_btn_color_set5"]['border'] : '#54496f', | |
| 284 | + 'btn_hover_border_color' => isset($options["dark_mode_btn_color_set5"]['hover_border']) ? $options["dark_mode_btn_color_set5"]['hover_border'] : '#403953', | |
| 169 | 285 | ], |
| 170 | 286 | 'set6' => [ |
| 171 | 287 | 'bg' => isset($options["dark_mode_color_set6"]) ? $options["dark_mode_color_set6"]['background'] : '#082032', |
| 172 | 288 | 'secondary_bg' => isset($options["dark_mode_color_set6"]) ? $options["dark_mode_color_set6"]['secondary_background'] : '#061825', |
| @@ -180,8 +296,10 @@ | ||
| 180 | 296 | 'btn_text_color' => isset($options["dark_mode_btn_color_set6"]) ? $options["dark_mode_btn_color_set6"]['color'] : '#B5D9F3', |
| 181 | 297 | 'btn_bg' => isset($options["dark_mode_btn_color_set6"]) ? $options["dark_mode_btn_color_set6"]['background'] : '#144E78', |
| 182 | 298 | 'btn_text_hover_color' => isset($options["dark_mode_btn_color_set6"]) ? $options["dark_mode_btn_color_set6"]['hover_color'] : '#B5D9F3', |
| 183 | 299 | 'btn_hover_bg' => isset($options["dark_mode_btn_color_set6"]) ? $options["dark_mode_btn_color_set6"]['hover_background'] : '#0E3755', |
| 300 | + 'btn_border_color' => isset($options["dark_mode_btn_color_set6"]['border']) ? $options["dark_mode_btn_color_set6"]['border'] : '#144E78', | |
| 301 | + 'btn_hover_border_color' => isset($options["dark_mode_btn_color_set6"]['hover_border']) ? $options["dark_mode_btn_color_set6"]['hover_border'] : '#0E3755', | |
| 184 | 302 | ], |
| 185 | 303 | 'set7' => [ |
| 186 | 304 | 'bg' => isset($options["dark_mode_color_set7"]) ? $options["dark_mode_color_set7"]['background'] : '#07161b', |
| 187 | 305 | 'secondary_bg' => isset($options["dark_mode_color_set7"]) ? $options["dark_mode_color_set7"]['secondary_background'] : '#0d242e', |
| @@ -195,8 +313,10 @@ | ||
| 195 | 313 | 'btn_text_color' => isset($options["dark_mode_btn_color_set7"]) ? $options["dark_mode_btn_color_set7"]['color'] : '#C5E6F0', |
| 196 | 314 | 'btn_bg' => isset($options["dark_mode_btn_color_set7"]) ? $options["dark_mode_btn_color_set7"]['background'] : '#286F8D', |
| 197 | 315 | 'btn_text_hover_color' => isset($options["dark_mode_btn_color_set7"]) ? $options["dark_mode_btn_color_set7"]['hover_color'] : '#C5E6F0', |
| 198 | 316 | 'btn_hover_bg' => isset($options["dark_mode_btn_color_set7"]) ? $options["dark_mode_btn_color_set7"]['hover_background'] : '#19495A', |
| 317 | + 'btn_border_color' => isset($options["dark_mode_btn_color_set7"]['border']) ? $options["dark_mode_btn_color_set7"]['border'] : '#286F8D', | |
| 318 | + 'btn_hover_border_color' => isset($options["dark_mode_btn_color_set7"]['hover_border']) ? $options["dark_mode_btn_color_set7"]['hover_border'] : '#19495A', | |
| 199 | 319 | ], |
| 200 | 320 | 'set8' => [ |
| 201 | 321 | 'bg' => isset($options["dark_mode_color_set8"]) ? $options["dark_mode_color_set8"]['background'] : '#15274C', |
| 202 | 322 | 'secondary_bg' => isset($options["dark_mode_color_set8"]) ? $options["dark_mode_color_set8"]['secondary_background'] : '#112244', |
| @@ -210,8 +330,10 @@ | ||
| 210 | 330 | 'btn_text_color' => isset($options["dark_mode_btn_color_set8"]) ? $options["dark_mode_btn_color_set8"]['color'] : '#ACC1EA', |
| 211 | 331 | 'btn_bg' => isset($options["dark_mode_btn_color_set8"]) ? $options["dark_mode_btn_color_set8"]['background'] : '#244892', |
| 212 | 332 | 'btn_text_hover_color' => isset($options["dark_mode_btn_color_set8"]) ? $options["dark_mode_btn_color_set8"]['hover_color'] : '#ACC1EA', |
| 213 | 333 | 'btn_hover_bg' => isset($options["dark_mode_btn_color_set8"]) ? $options["dark_mode_btn_color_set8"]['hover_background'] : '#1a2f5c', |
| 334 | + 'btn_border_color' => isset($options["dark_mode_btn_color_set8"]['border']) ? $options["dark_mode_btn_color_set8"]['border'] : '#244892', | |
| 335 | + 'btn_hover_border_color' => isset($options["dark_mode_btn_color_set8"]['hover_border']) ? $options["dark_mode_btn_color_set8"]['hover_border'] : '#1a2f5c', | |
| 214 | 336 | ], |
| 215 | 337 | 'set9' => [ |
| 216 | 338 | 'bg' => isset($options["dark_mode_color_set9"]) ? $options["dark_mode_color_set9"]['background'] : '#04261d', |
| 217 | 339 | 'secondary_bg' => isset($options["dark_mode_color_set9"]) ? $options["dark_mode_color_set9"]['secondary_background'] : '#021e16', |
| @@ -225,8 +347,10 @@ | ||
| 225 | 347 | 'btn_text_color' => isset($options["dark_mode_btn_color_set9"]) ? $options["dark_mode_btn_color_set9"]['color'] : '#C1D2BB', |
| 226 | 348 | 'btn_bg' => isset($options["dark_mode_btn_color_set9"]) ? $options["dark_mode_btn_color_set9"]['background'] : '#095541', |
| 227 | 349 | 'btn_text_hover_color' => isset($options["dark_mode_btn_color_set9"]) ? $options["dark_mode_btn_color_set9"]['hover_color'] : '#C1D2BB', |
| 228 | 350 | 'btn_hover_bg' => isset($options["dark_mode_btn_color_set9"]) ? $options["dark_mode_btn_color_set9"]['hover_background'] : '#073d2f', |
| 351 | + 'btn_border_color' => isset($options["dark_mode_btn_color_set9"]['border']) ? $options["dark_mode_btn_color_set9"]['border'] : '#095541', | |
| 352 | + 'btn_hover_border_color' => isset($options["dark_mode_btn_color_set9"]['hover_border']) ? $options["dark_mode_btn_color_set9"]['hover_border'] : '#073d2f', | |
| 229 | 353 | ], |
| 230 | 354 | 'set10' => [ |
| 231 | 355 | 'bg' => isset($options["dark_mode_color_set10"]) ? $options["dark_mode_color_set10"]['background'] : '#171004', |
| 232 | 356 | 'secondary_bg' => isset($options["dark_mode_color_set10"]) ? $options["dark_mode_color_set10"]['secondary_background'] : '#211706', |
| @@ -240,8 +364,10 @@ | ||
| 240 | 364 | 'btn_text_color' => isset($options["dark_mode_btn_color_set10"]) ? $options["dark_mode_btn_color_set10"]['color'] : '#E0D2BD', |
| 241 | 365 | 'btn_bg' => isset($options["dark_mode_btn_color_set10"]) ? $options["dark_mode_btn_color_set10"]['background'] : '#5D4010', |
| 242 | 366 | 'btn_text_hover_color' => isset($options["dark_mode_btn_color_set10"]) ? $options["dark_mode_btn_color_set10"]['hover_color'] : '#E0D2BD', |
| 243 | 367 | 'btn_hover_bg' => isset($options["dark_mode_btn_color_set10"]) ? $options["dark_mode_btn_color_set10"]['hover_background'] : '#372911', |
| 368 | + 'btn_border_color' => isset($options["dark_mode_btn_color_set10"]['border']) ? $options["dark_mode_btn_color_set10"]['border'] : '#5D4010', | |
| 369 | + 'btn_hover_border_color' => isset($options["dark_mode_btn_color_set10"]['hover_border']) ? $options["dark_mode_btn_color_set10"]['hover_border'] : '#372911', | |
| 244 | 370 | ], |
| 245 | 371 | 'set11' => [ |
| 246 | 372 | 'bg' => isset($options["dark_mode_color_set11"]) ? $options["dark_mode_color_set11"]['background'] : '#19081b', |
| 247 | 373 | 'secondary_bg' => isset($options["dark_mode_color_set11"]) ? $options["dark_mode_color_set11"]['secondary_background'] : '#210a24', |
| @@ -255,8 +381,10 @@ | ||
| 255 | 381 | 'btn_text_color' => isset($options["dark_mode_btn_color_set11"]) ? $options["dark_mode_btn_color_set11"]['color'] : '#c09dc2', |
| 256 | 382 | 'btn_bg' => isset($options["dark_mode_btn_color_set11"]) ? $options["dark_mode_btn_color_set11"]['background'] : '#440649', |
| 257 | 383 | 'btn_text_hover_color' => isset($options["dark_mode_btn_color_set11"]) ? $options["dark_mode_btn_color_set11"]['hover_color'] : '#c09dc2', |
| 258 | 384 | 'btn_hover_bg' => isset($options["dark_mode_btn_color_set11"]) ? $options["dark_mode_btn_color_set11"]['hover_background'] : '#2c082f', |
| 385 | + 'btn_border_color' => isset($options["dark_mode_btn_color_set11"]['border']) ? $options["dark_mode_btn_color_set11"]['border'] : '#440649', | |
| 386 | + 'btn_hover_border_color' => isset($options["dark_mode_btn_color_set11"]['hover_border']) ? $options["dark_mode_btn_color_set11"]['hover_border'] : '#2c082f', | |
| 259 | 387 | ], |
| 260 | 388 | ]; |
| 261 | 389 | |
| 262 | 390 | $selected_set_key = isset($options['color_pallets']) ? $options['color_pallets'] : 'set1'; |
| @@ -268,10 +396,55 @@ | ||
| 268 | 396 | } |
| 269 | 397 | ?> |
| 270 | 398 | } |
| 271 | 399 | </style> |
| 272 | -<?php } else { ?> | |
| 273 | - <script type="text/javascript" class="darkify_inline_js">(function(){var s=localStorage.darkify_admin_panel_last_state,t=localStorage.darkify_selected_theme||'set1';if(s==='1'){var h=document.documentElement;h.classList.add('darkify_dark_mode_enabled');h.classList.add('darkify-'+t);}}());</script> | |
| 400 | +<?php } else { | |
| 401 | + /* | |
| 402 | + * `dark` on <html> is the de-facto convention a React admin themes itself | |
| 403 | + * off — Tailwind's class strategy, shadcn/ui, and Darkify's own React admin | |
| 404 | + * (`@custom-variant dark (&:is(.dark *))`) all key on exactly this class. | |
| 405 | + * | |
| 406 | + * It used to be added only on Darkify's own SPA pages, which is why a | |
| 407 | + * React-based admin screen from ANOTHER plugin stayed stubbornly light while | |
| 408 | + * the rest of wp-admin went dark: such an app doesn't take its colours from | |
| 409 | + * the cascade at all, it reads design tokens that only switch when `dark` is | |
| 410 | + * present, and that class never arrived. Mirroring Admin Panel Dark Mode | |
| 411 | + * onto it here — on every admin screen, not just ours — lets any app | |
| 412 | + * following the convention inherit the theme with no plugin-specific | |
| 413 | + * handling on either side. | |
| 414 | + * | |
| 415 | + * Setting it in <head> means the very first paint is already dark; the | |
| 416 | + * runtime half of the mirror lives in client_main.js so the admin-bar switch | |
| 417 | + * re-themes those screens live too. The `h.classList.add('dark')` call is | |
| 418 | + * emitted as a static literal in the snippet below. | |
| 419 | + */ | |
| 420 | + /* | |
| 421 | + * `d` gates this FOUC snippet on Admin Panel Dark Mode actually being ON. | |
| 422 | + * It used to be implicit: with the option off this template was never | |
| 423 | + * included on an admin screen. Darkify's own SPA screens now always | |
| 424 | + * include it (so the admin-bar icon can toggle without a reload), so | |
| 425 | + * without this check a stale `darkify_admin_panel_last_state = "1"` would | |
| 426 | + * darken the screen even though the option is off. | |
| 427 | + * | |
| 428 | + * Nested ifs, NOT `s==='1'&&d==='1'`: this whole template is printed | |
| 429 | + * through wp_kses() (see the bottom of the file), whose entity | |
| 430 | + * normalization rewrites a bare `&` to `&` — script content is raw | |
| 431 | + * text, so `&&` would reach the browser as `&&` and kill the | |
| 432 | + * snippet with a SyntaxError. Keep this snippet free of `&` (and `<`). | |
| 433 | + */ | |
| 434 | + /* | |
| 435 | + * Effective admin darkening for THIS screen. Block Editor Dark Mode is | |
| 436 | + * independent of Admin Panel Dark Mode: the block editor darkens when Block | |
| 437 | + * Editor Dark Mode is on even if Admin Panel Dark Mode is off. Reused for the | |
| 438 | + * runtime gate (darkify_admin_panel_dark_enabled) below. | |
| 439 | + */ | |
| 440 | + $darkify_screen = \function_exists('get_current_screen') ? \get_current_screen() : null; | |
| 441 | + $darkify_is_block_editor = $darkify_screen && \method_exists($darkify_screen, 'is_block_editor') && $darkify_screen->is_block_editor(); | |
| 442 | + $darkify_block_editor_dark = !empty($options['block_editor_dark_mode']); | |
| 443 | + $darkify_effective_admin_dark = (!empty($options['enable_admin_panel_dark_mode']) || ($darkify_is_block_editor && $darkify_block_editor_dark)) ? '1' : '0'; | |
| 444 | + $darkify_admin_dark_on = $darkify_effective_admin_dark; | |
| 445 | + ?> | |
| 446 | + <script type="text/javascript" class="darkify_inline_js">(function(){var s=localStorage.darkify_admin_panel_last_state,t=localStorage.darkify_selected_theme||'set1',d='<?php echo esc_attr($darkify_admin_dark_on); ?>';if(s==='1'){if(d==='1'){var h=document.documentElement;h.classList.add('darkify_dark_mode_enabled');h.classList.add('darkify-'+t);h.classList.add('dark');}}}());</script> | |
| 274 | 447 | <style type="text/css" class="darkify_inline_css"> |
| 275 | 448 | :root { |
| 276 | 449 | --darkify_dark_mode_bg: #181a1b; |
| 277 | 450 | --darkify_dark_mode_secondary_bg: #202324; |
| @@ -285,8 +458,10 @@ | ||
| 285 | 458 | --darkify_dark_mode_btn_bg: #2D2D2D; |
| 286 | 459 | --darkify_dark_mode_btn_text_color: #BEBEBE; |
| 287 | 460 | --darkify_dark_mode_btn_hover_bg: #BEBEBE; |
| 288 | 461 | --darkify_dark_mode_btn_text_hover_color: #2D2D2D; |
| 462 | + --darkify_dark_mode_btn_border_color: #2D2D2D; | |
| 463 | + --darkify_dark_mode_btn_hover_border_color: #BEBEBE; | |
| 289 | 464 | } |
| 290 | 465 | </style> |
| 291 | 466 | <?php } |
| 292 | 467 | if ($enable_scrollbar_dark) { |
| @@ -298,11 +473,35 @@ | ||
| 298 | 473 | |
| 299 | 474 | <script type="text/javascript" class="darkify_inline_js"> |
| 300 | 475 | var darkify_switch_unique_id = "<?php echo esc_attr($this->unique_id); ?>"; |
| 301 | 476 | var darkify_is_this_admin_panel = "<?php echo esc_attr(is_admin() ? "1" : "0"); ?>"; |
| 477 | + <?php | |
| 478 | + /* | |
| 479 | + * Admin Panel Dark Mode, exposed so the admin engine can refuse to darken | |
| 480 | + * while the option is off. Darkify's own SPA screens load the engine even | |
| 481 | + * then, so the admin-bar icon can be toggled without a reload, which means | |
| 482 | + * the engine has to honour the option itself rather than relying on simply | |
| 483 | + * not being enqueued. | |
| 484 | + */ | |
| 485 | + ?> | |
| 486 | + var darkify_admin_panel_dark_enabled = "<?php echo esc_attr(isset($darkify_effective_admin_dark) ? $darkify_effective_admin_dark : (!empty($options['enable_admin_panel_dark_mode']) ? '1' : '0')); ?>"; | |
| 487 | + <?php | |
| 488 | + /* | |
| 489 | + * Site-wide palette defaults for the Dark Reader admin engine, one for the | |
| 490 | + * block editor and one for everything else. "auto" means "let Dark Reader | |
| 491 | + * derive every colour", which is the default and the recommended value. | |
| 492 | + * | |
| 493 | + * These are defaults, not overrides: the editor's toolbar dropdown writes a | |
| 494 | + * per-user choice to localStorage and that still wins, which is how that | |
| 495 | + * control has always behaved. | |
| 496 | + */ | |
| 497 | + ?> | |
| 498 | + var darkify_admin_palette_default = "<?php echo esc_attr(!empty($options['admin_panel_palette']) ? $options['admin_panel_palette'] : 'auto'); ?>"; | |
| 499 | + var darkify_editor_palette_default = "<?php echo esc_attr(!empty($options['block_editor_palette']) ? $options['block_editor_palette'] : 'auto'); ?>"; | |
| 302 | 500 | var darkify_enable_default_dark_mode = "<?php echo esc_attr($enable_default_dark_mode); ?>"; |
| 303 | 501 | var darkify_enable_os_aware = "<?php echo esc_attr($enable_os_aware); ?>"; |
| 304 | 502 | var darkify_enable_keyboard_shortcut = "<?php echo esc_attr($enable_keyboard_shortcut); ?>"; |
| 503 | + var darkify_keyboard_shortcut_keys = "<?php echo esc_attr($keyboard_shortcut_keys); ?>"; | |
| 305 | 504 | var darkify_enable_time_based_dark = "<?php echo esc_attr($enable_time_based_dark); ?>"; |
| 306 | 505 | var darkify_time_based_dark_start = "<?php echo esc_attr($time_based_dark_start ? $time_based_dark_start : "19:00"); ?>"; |
| 307 | 506 | var darkify_time_based_dark_stop = "<?php echo esc_attr($time_based_dark_stop ? $time_based_dark_stop : "07:00"); ?>"; |
| 308 | 507 | var darkify_enable_switch_dragging = "<?php echo esc_attr($enable_switch_dragging); ?>"; |
| @@ -327,17 +526,35 @@ | ||
| 327 | 526 | var darkify_video_brightness_to = "<?php echo esc_attr($low_video_brightness_label); ?>"; |
| 328 | 527 | var darkify_enable_video_grayscale = "<?php echo esc_attr($enable_video_grayscale); ?>"; |
| 329 | 528 | var darkify_video_grayscale_to = "<?php echo esc_attr($video_grayscale_label); ?>"; |
| 330 | 529 | var darkify_video_replacements = "<?PHP echo esc_attr($video_replacements); ?>"; |
| 331 | - var darkify_allowed_elements = "<?php echo esc_attr($this->utils->generateAllowedElementsStr($options)); ?>"; | |
| 332 | - var darkify_allowed_elements_raw = "<?php echo esc_attr($allowed_elements); ?>"; | |
| 530 | + <?php | |
| 531 | + /* | |
| 532 | + * These four carry CSS selectors, not display text, and they are read back | |
| 533 | + * by element.matches() in client_main.js. esc_attr() would HTML-encode the | |
| 534 | + * selector combinators (`>` becomes `>`, `&` becomes `&`), and a | |
| 535 | + * <script> body is raw text — the browser never decodes those back. One | |
| 536 | + * encoded combinator anywhere in the list makes the whole comma-joined | |
| 537 | + * selector a SyntaxError, matches() throws, and Disallowed Elements | |
| 538 | + * silently stops restricting anything. Custom CSS selectors are folded into | |
| 539 | + * the disallowed list automatically (see generateDisallowedElementsStr), so | |
| 540 | + * a perfectly ordinary `.card > .title` rule was enough to trigger it. | |
| 541 | + * darkify_js_string() emits a proper JSON string literal instead, which | |
| 542 | + * keeps the selector intact and is still safe to sit inside <script> | |
| 543 | + * (tags/ampersands are \u-escaped). | |
| 544 | + */ | |
| 545 | + ?> | |
| 546 | + var darkify_allowed_elements = <?php echo darkify_js_string($this->utils->generateAllowedElementsStr($options)); ?>; | |
| 547 | + var darkify_allowed_elements_raw = <?php echo darkify_js_string($allowed_elements); ?>; | |
| 333 | 548 | var darkify_allowed_elements_force_to_correct = "<?php echo esc_attr($allowed_elements_force_to_correct); ?>"; |
| 334 | 549 | |
| 335 | - var darkify_disallowed_elements = "<?php echo esc_attr($this->utils->generateDisallowedElementsStr($options, $this->external_support)); ?>"; | |
| 336 | - var darkify_disallowed_elements_raw = "<?php echo esc_attr($disallowed_elements); ?>"; | |
| 550 | + var darkify_disallowed_elements = <?php echo darkify_js_string($this->utils->generateDisallowedElementsStr($options, $this->external_support)); ?>; | |
| 551 | + var darkify_disallowed_elements_raw = <?php echo darkify_js_string($disallowed_elements); ?>; | |
| 337 | 552 | var darkify_disallowed_elements_force_to_correct = "<?php echo esc_attr($disallowed_elements_force_to_correct); ?>"; |
| 338 | 553 | |
| 339 | 554 | var darkify_allowed_btn_class = <?php echo json_encode($this->utils->addButtonClassByDarkify($options)); ?>; |
| 555 | + | |
| 556 | + var darkify_color_overrides = <?php echo wp_json_encode($darkify_color_overrides); ?>; | |
| 340 | 557 | </script> |
| 341 | 558 | <?php |
| 342 | 559 | $output = ob_get_clean(); |
| 343 | 560 | $tags_allowed_in_output = array( |