Loading src/theme.cpp +72 −7 Original line number Diff line number Diff line Loading @@ -825,6 +825,53 @@ static std::string extractCssVar(const std::string &css, const std::string &varN return ""; } // Extracts the lowercase directory-name of a theme (e.g. ".../data/themes/schimmelfuchs" -> "schimmelfuchs"), // used to key theme-specific palette overrides below. static std::string themeBaseName(const std::string &themePath){ std::string name = std::filesystem::path(themePath).filename().string(); std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c){ return std::tolower(c); }); return name; } // Per-theme brand palettes. A theme not listed here just falls back to the generic // dark/lightDefault pairs baked into each ColorVar/ColorDef table below. Kept separate // from those generic tables so shipping a themed palette never changes the fallback // look for every other theme/tenant. static bool getThemePaletteOverride(const std::string &themeName, const std::string &cssVar, std::string &outDark, std::string &outLight){ struct Entry { const char *theme; const char *cssVar; const char *dark; const char *light; }; static const Entry table[] = { // "schimmelfuchs" -- light values sourced from bautenschutz-wetzlar.de's brand kit // (green #5CB310 / coral #EC6643 / body text #444); dark values are a soft graphite // (not near-black) using the same brand accents. {"schimmelfuchs", "--blogi-bg", "#3a3d40", "rgba(236,238,240,1)"}, {"schimmelfuchs", "--blogi-surface", "#45484b", "rgba(255,255,255,1)"}, {"schimmelfuchs", "--blogi-surface-a", "rgba(69,72,75,0.75)", "rgba(255,255,255,0.9)"}, {"schimmelfuchs", "--blogi-text", "#eceef0", "rgba(68,68,68,1)"}, {"schimmelfuchs", "--blogi-text-muted", "#aeb3a6", "rgba(106,112,96,1)"}, {"schimmelfuchs", "--blogi-accent", "#83bb32", "rgba(92,179,16,1)"}, {"schimmelfuchs", "--blogi-accent-dark", "#6dbb28", "rgba(69,134,12,1)"}, {"schimmelfuchs", "--blogi-border", "#55585b", "rgba(234,234,234,1)"}, {"schimmelfuchs", "--blogi-bg-alt", "#33363a", "rgba(247,248,245,1)"}, {"schimmelfuchs", "--blogi-error", "#ec6643", "rgba(236,102,67,1)"}, {"schimmelfuchs", "--blogi-error-bg", "#4a332c", "rgba(253,240,235,1)"}, {"schimmelfuchs", "--blogi-error-text", "#ff9a7a", "rgba(179,64,31,1)"}, {"schimmelfuchs", "--blogi-success-bg", "#38402c", "rgba(238,247,230,1)"}, {"schimmelfuchs", "--blogi-success-text", "#a8d878", "rgba(69,134,12,1)"}, {"schimmelfuchs", "--blogi-nav-active", "#83bb32", "rgba(92,179,16,1)"}, {"schimmelfuchs", "--blogi-nav-hover", "#3f4245", "rgba(225,228,230,1)"}, {"schimmelfuchs", "--blogi-nav-border", "#2f3234", "rgba(189,195,199,1)"}, }; for(const auto &e : table){ if(themeName == e.theme && cssVar == e.cssVar){ outDark = e.dark; outLight = e.light; return true; } } return false; } void blogi::Theme::injectThemeColors(const int tid, libhtmlpp::HtmlElement *index){ libhtmlpp::HtmlElement *head = index->getElementbyTag("head"); if(!head) Loading Loading @@ -859,6 +906,8 @@ void blogi::Theme::injectThemeColors(const int tid, libhtmlpp::HtmlElement *inde {"NAV_BORDER", "--blogi-nav-border", "#222529", "rgba(189,195,199,1)"}, }; std::string themeName = themeBaseName(_Config.Theme); // Build dark values std::string darkPrefix = "THEME_DARK_"; libhtmlpp::HtmlString css; Loading @@ -872,7 +921,9 @@ void blogi::Theme::injectThemeColors(const int tid, libhtmlpp::HtmlElement *inde std::string altVar = "--color-" + std::string(v.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ddef = dynamicDef.empty() ? v.darkDefault : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, v.cssVar, pDark, pLight); std::string ddef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pDark : v.darkDefault); std::string val; try { getConfig(*_Config.TDatabase[tid], darkPrefix + v.dbSuffix, val); } catch(...) {} Loading @@ -891,7 +942,9 @@ void blogi::Theme::injectThemeColors(const int tid, libhtmlpp::HtmlElement *inde std::string altVar = "--color-" + std::string(v.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ldef = dynamicDef.empty() ? v.lightDefault : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, v.cssVar, pDark, pLight); std::string ldef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pLight : v.lightDefault); std::string val; try { getConfig(*_Config.TDatabase[tid], lightPrefix + v.dbSuffix, val); } catch(...) {} Loading @@ -909,7 +962,9 @@ void blogi::Theme::injectThemeColors(const int tid, libhtmlpp::HtmlElement *inde std::string altVar = "--color-" + std::string(v.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ldef = dynamicDef.empty() ? v.lightDefault : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, v.cssVar, pDark, pLight); std::string ldef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pLight : v.lightDefault); std::string val; try { getConfig(*_Config.TDatabase[tid], lightPrefix + v.dbSuffix, val); } catch(...) {} Loading Loading @@ -954,6 +1009,8 @@ json_object* blogi::Theme::getThemeColors(const int tid){ {"NAV_BORDER", "--blogi-nav-border", "#222529", "rgba(189,195,199,1)"}, }; std::string themeName = themeBaseName(_Config.Theme); json_object *root = json_object_new_object(); json_object *dark = json_object_new_object(); json_object *light = json_object_new_object(); Loading @@ -964,8 +1021,10 @@ json_object* blogi::Theme::getThemeColors(const int tid){ std::string altVar = "--color-" + std::string(v.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ddef = dynamicDef.empty() ? v.darkDefault : dynamicDef; std::string ldef = dynamicDef.empty() ? v.lightDefault : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, v.cssVar, pDark, pLight); std::string ddef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pDark : v.darkDefault); std::string ldef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pLight : v.lightDefault); std::string dval; try { getConfig(*_Config.TDatabase[tid], std::string("THEME_DARK_") + v.dbSuffix, dval); } catch(...) {} Loading Loading @@ -1079,6 +1138,8 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & {"NAV_BORDER", "--blogi-nav-border", "Nav Border", "#222529", "rgba(189,195,199,1)"}, }; std::string themeName = themeBaseName(_Config.Theme); if(reset){ // Batch reset: delete all theme color keys (do NOT insert hardcoded defaults, let getThemeColors extract from style.css) dbpp::SQL rsql; Loading Loading @@ -1200,7 +1261,9 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & std::string altVar = "--color-" + std::string(c.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ddef = dynamicDef.empty() ? c.darkDef : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, c.cssVar, pDark, pLight); std::string ddef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pDark : c.darkDef); std::string val; try { getConfig(*_Config.TDatabase[tid], std::string("THEME_DARK_") + c.suffix, val); } catch(...) {} Loading Loading @@ -1235,7 +1298,9 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & std::string altVar = "--color-" + std::string(c.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ldef = dynamicDef.empty() ? c.lightDef : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, c.cssVar, pDark, pLight); std::string ldef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pLight : c.lightDef); std::string val; try { getConfig(*_Config.TDatabase[tid], std::string("THEME_LIGHT_") + c.suffix, val); } catch(...) {} Loading Loading
src/theme.cpp +72 −7 Original line number Diff line number Diff line Loading @@ -825,6 +825,53 @@ static std::string extractCssVar(const std::string &css, const std::string &varN return ""; } // Extracts the lowercase directory-name of a theme (e.g. ".../data/themes/schimmelfuchs" -> "schimmelfuchs"), // used to key theme-specific palette overrides below. static std::string themeBaseName(const std::string &themePath){ std::string name = std::filesystem::path(themePath).filename().string(); std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c){ return std::tolower(c); }); return name; } // Per-theme brand palettes. A theme not listed here just falls back to the generic // dark/lightDefault pairs baked into each ColorVar/ColorDef table below. Kept separate // from those generic tables so shipping a themed palette never changes the fallback // look for every other theme/tenant. static bool getThemePaletteOverride(const std::string &themeName, const std::string &cssVar, std::string &outDark, std::string &outLight){ struct Entry { const char *theme; const char *cssVar; const char *dark; const char *light; }; static const Entry table[] = { // "schimmelfuchs" -- light values sourced from bautenschutz-wetzlar.de's brand kit // (green #5CB310 / coral #EC6643 / body text #444); dark values are a soft graphite // (not near-black) using the same brand accents. {"schimmelfuchs", "--blogi-bg", "#3a3d40", "rgba(236,238,240,1)"}, {"schimmelfuchs", "--blogi-surface", "#45484b", "rgba(255,255,255,1)"}, {"schimmelfuchs", "--blogi-surface-a", "rgba(69,72,75,0.75)", "rgba(255,255,255,0.9)"}, {"schimmelfuchs", "--blogi-text", "#eceef0", "rgba(68,68,68,1)"}, {"schimmelfuchs", "--blogi-text-muted", "#aeb3a6", "rgba(106,112,96,1)"}, {"schimmelfuchs", "--blogi-accent", "#83bb32", "rgba(92,179,16,1)"}, {"schimmelfuchs", "--blogi-accent-dark", "#6dbb28", "rgba(69,134,12,1)"}, {"schimmelfuchs", "--blogi-border", "#55585b", "rgba(234,234,234,1)"}, {"schimmelfuchs", "--blogi-bg-alt", "#33363a", "rgba(247,248,245,1)"}, {"schimmelfuchs", "--blogi-error", "#ec6643", "rgba(236,102,67,1)"}, {"schimmelfuchs", "--blogi-error-bg", "#4a332c", "rgba(253,240,235,1)"}, {"schimmelfuchs", "--blogi-error-text", "#ff9a7a", "rgba(179,64,31,1)"}, {"schimmelfuchs", "--blogi-success-bg", "#38402c", "rgba(238,247,230,1)"}, {"schimmelfuchs", "--blogi-success-text", "#a8d878", "rgba(69,134,12,1)"}, {"schimmelfuchs", "--blogi-nav-active", "#83bb32", "rgba(92,179,16,1)"}, {"schimmelfuchs", "--blogi-nav-hover", "#3f4245", "rgba(225,228,230,1)"}, {"schimmelfuchs", "--blogi-nav-border", "#2f3234", "rgba(189,195,199,1)"}, }; for(const auto &e : table){ if(themeName == e.theme && cssVar == e.cssVar){ outDark = e.dark; outLight = e.light; return true; } } return false; } void blogi::Theme::injectThemeColors(const int tid, libhtmlpp::HtmlElement *index){ libhtmlpp::HtmlElement *head = index->getElementbyTag("head"); if(!head) Loading Loading @@ -859,6 +906,8 @@ void blogi::Theme::injectThemeColors(const int tid, libhtmlpp::HtmlElement *inde {"NAV_BORDER", "--blogi-nav-border", "#222529", "rgba(189,195,199,1)"}, }; std::string themeName = themeBaseName(_Config.Theme); // Build dark values std::string darkPrefix = "THEME_DARK_"; libhtmlpp::HtmlString css; Loading @@ -872,7 +921,9 @@ void blogi::Theme::injectThemeColors(const int tid, libhtmlpp::HtmlElement *inde std::string altVar = "--color-" + std::string(v.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ddef = dynamicDef.empty() ? v.darkDefault : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, v.cssVar, pDark, pLight); std::string ddef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pDark : v.darkDefault); std::string val; try { getConfig(*_Config.TDatabase[tid], darkPrefix + v.dbSuffix, val); } catch(...) {} Loading @@ -891,7 +942,9 @@ void blogi::Theme::injectThemeColors(const int tid, libhtmlpp::HtmlElement *inde std::string altVar = "--color-" + std::string(v.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ldef = dynamicDef.empty() ? v.lightDefault : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, v.cssVar, pDark, pLight); std::string ldef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pLight : v.lightDefault); std::string val; try { getConfig(*_Config.TDatabase[tid], lightPrefix + v.dbSuffix, val); } catch(...) {} Loading @@ -909,7 +962,9 @@ void blogi::Theme::injectThemeColors(const int tid, libhtmlpp::HtmlElement *inde std::string altVar = "--color-" + std::string(v.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ldef = dynamicDef.empty() ? v.lightDefault : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, v.cssVar, pDark, pLight); std::string ldef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pLight : v.lightDefault); std::string val; try { getConfig(*_Config.TDatabase[tid], lightPrefix + v.dbSuffix, val); } catch(...) {} Loading Loading @@ -954,6 +1009,8 @@ json_object* blogi::Theme::getThemeColors(const int tid){ {"NAV_BORDER", "--blogi-nav-border", "#222529", "rgba(189,195,199,1)"}, }; std::string themeName = themeBaseName(_Config.Theme); json_object *root = json_object_new_object(); json_object *dark = json_object_new_object(); json_object *light = json_object_new_object(); Loading @@ -964,8 +1021,10 @@ json_object* blogi::Theme::getThemeColors(const int tid){ std::string altVar = "--color-" + std::string(v.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ddef = dynamicDef.empty() ? v.darkDefault : dynamicDef; std::string ldef = dynamicDef.empty() ? v.lightDefault : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, v.cssVar, pDark, pLight); std::string ddef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pDark : v.darkDefault); std::string ldef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pLight : v.lightDefault); std::string dval; try { getConfig(*_Config.TDatabase[tid], std::string("THEME_DARK_") + v.dbSuffix, dval); } catch(...) {} Loading Loading @@ -1079,6 +1138,8 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & {"NAV_BORDER", "--blogi-nav-border", "Nav Border", "#222529", "rgba(189,195,199,1)"}, }; std::string themeName = themeBaseName(_Config.Theme); if(reset){ // Batch reset: delete all theme color keys (do NOT insert hardcoded defaults, let getThemeColors extract from style.css) dbpp::SQL rsql; Loading Loading @@ -1200,7 +1261,9 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & std::string altVar = "--color-" + std::string(c.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ddef = dynamicDef.empty() ? c.darkDef : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, c.cssVar, pDark, pLight); std::string ddef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pDark : c.darkDef); std::string val; try { getConfig(*_Config.TDatabase[tid], std::string("THEME_DARK_") + c.suffix, val); } catch(...) {} Loading Loading @@ -1235,7 +1298,9 @@ json_object* blogi::Theme::SettingsTheme(const int tid, libhttppp::HttpRequest & std::string altVar = "--color-" + std::string(c.cssVar).substr(8); dynamicDef = extractCssVar(styleCss, altVar); } std::string ldef = dynamicDef.empty() ? c.lightDef : dynamicDef; std::string pDark, pLight; bool hasOverride = dynamicDef.empty() && getThemePaletteOverride(themeName, c.cssVar, pDark, pLight); std::string ldef = !dynamicDef.empty() ? dynamicDef : (hasOverride ? pLight : c.lightDef); std::string val; try { getConfig(*_Config.TDatabase[tid], std::string("THEME_LIGHT_") + c.suffix, val); } catch(...) {} Loading