sized to 1em so existing * font-size rules (.navbar .nav-link .bd-icon, .metadata .bd-icon, …) scale it. * * Theme-picker icons (sun/moon/snow/droplet/cup/half) are duplicated in * blowdit.js so the toggle can swap them client-side; keep the two in sync. */ if (!function_exists('blowdit_icon')) { function blowdit_icon($name) { static $paths = array( // --- UI --- 'calendar' => '', 'clock' => '', 'folder' => '', 'tag' => '', 'chevron-left' => '', 'chevron-right' => '', 'house' => '', 'link' => '', 'search' => '', 'share' => '', // --- Theme picker (mirror in blowdit.js) --- 'sun' => '', 'moon' => '', 'snow' => '', 'droplet' => '', 'cup' => '', 'half' => '', ); if (!isset($paths[$name])) { return ''; } return ''; } // Bludit already HTML-escapes titles/names on save (Sanitize::html), so a // plain htmlspecialchars() in the theme double-encodes ("&" -> "&", // shown as "&"). blowdit_text() decodes any existing entities first, then // encodes exactly once — correct whether the value is pre-encoded or raw, and // always output-safe. blowdit_plain() returns decoded text (for JSON-LD etc.). function blowdit_plain($s) { return html_entity_decode((string) $s, ENT_QUOTES, 'UTF-8'); } function blowdit_text($s) { return htmlspecialchars(blowdit_plain($s), ENT_QUOTES, 'UTF-8'); } // Theme asset URL with an mtime cache-buster (so edited images/SVGs refetch). function blowdit_asset($rel) { $v = @filemtime(THEME_DIR . $rel); return DOMAIN_THEME . $rel . ($v ? '?v=' . $v : ''); } // Map a theme key to its toggle icon name. function blowdit_theme_icon($theme) { $map = array( 'light' => 'sun', 'dark' => 'moon', 'nord' => 'snow', 'dracula' => 'droplet', 'catppuccin' => 'cup', ); return isset($map[$theme]) ? $map[$theme] : 'half'; } }