Skip to content

feat: add color customization support for templates with validation#35

Merged
twangodev merged 5 commits intomainfrom
feat/colors
Nov 3, 2025
Merged

feat: add color customization support for templates with validation#35
twangodev merged 5 commits intomainfrom
feat/colors

Conversation

@twangodev
Copy link
Owner

@twangodev twangodev commented Nov 3, 2025

Summary by CodeRabbit

  • New Features

    • Added custom color override support for SVG templates; invalid colors return a clear 400 error.
    • Templates now include predefined per-template color palettes for richer default styling.
    • Color overrides are applied at generation time so requests can customize template colors.
  • Bug Fixes

    • Improved validation to ensure color values are exactly 6‑hex digits.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 3, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Templates now include per-template color definitions. Request parameters can supply validated color overrides; generate_svg requires an explicit template name and applies overrides to template content before parsing to produce the final SVG.

Changes

Cohort / File(s) Summary
SVG Generation Engine
src/generator/svg.rs
Replaced optional template param with mandatory template_name: &str; added private override_colors() to apply provided color overrides to template content; generate_svg() now applies overrides before parsing and reports errors using explicit template_name.
Parameters & Color Validation
src/params.rs
Added use std::collections::HashMap;, pub extra: HashMap<String, String> (serde flattened) to OgParams; added is_valid_hex_color() and pub fn extract_colors(...) -> Result<HashMap<String,String>, String> to validate/normalize color overrides.
Route Integration
src/routes/index.rs
Determine template_name (with default fallback), call extract_colors() and return 400 on validation failure; pass template_name and color_overrides into generator::generate_svg() instead of previous optional template usage.
Template Management
src/templates.rs
Added colors: HashMap<String, HashMap<String, String>> to TemplateMap; introduced parse_template_colors() and load_template() logic to read per-template colors from YAML and populate TemplateMap.colors during load_templates().
Template Configuration
templates.yaml
Added colors: mappings to multiple template entries (keys like background, text, accents, borders, etc.), providing default color definitions for templates.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Client
    participant Route as routes/index.rs
    participant Params as params.rs
    participant Templates as templates.rs
    participant Generator as generator/svg.rs

    Client->>Route: Request with OgParams (+extra color params)
    Route->>Params: extract_colors(template_name, state)
    Params->>Templates: lookup template color definitions
    Templates-->>Params: allowed color keys & defaults
    alt Colors valid
        Params-->>Route: color_overrides (normalized, `#`-prefixed)
        Route->>Generator: generate_svg(..., template_name, color_overrides)
        Generator->>Templates: fetch template content by name
        Generator->>Generator: override_colors(content, template_name, templates, color_overrides)
        Generator->>Generator: parse SVG from overridden content
        Generator-->>Route: SVG string
        Route-->>Client: 200 OK with SVG
    else Colors invalid
        Params-->>Route: Err (invalid hex / unknown key)
        Route-->>Client: 400 Bad Request with error
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Areas needing extra attention:
    • src/templates.rs — YAML parsing and merging of colors into TemplateMap.
    • src/generator/svg.rs — correctness and safety of override_colors() (ensure replacements target intended attributes).
    • src/params.rs — validation and normalization logic in extract_colors() and is_valid_hex_color().

Possibly related PRs

Poem

🐰 In a burrow I nibble on code so bright,
Swapping hex for hues in the soft moonlight.
Templates bloom in colors I chose,
Overrides whisper — the artwork glows! 🎨✨

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "feat: add color customization support for templates with validation" accurately and specifically describes the main changes across the changeset. The modifications introduce color override functionality in src/generator/svg.rs with an override_colors() function, add color validation logic in src/params.rs via extract_colors() and is_valid_hex_color(), integrate this validation into the routes in src/routes/index.rs, extend the template system with color definitions in src/templates.rs, and include color mappings in templates.yaml. The title is clear, concise, and directly related to the primary objective of enabling color customization with validation rather than being vague or overly broad.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/colors

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b1faa18 and 1c1798b.

📒 Files selected for processing (1)
  • src/params.rs (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/params.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@twangodev twangodev marked this pull request as ready for review November 3, 2025 08:11
Copilot AI review requested due to automatic review settings November 3, 2025 08:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for dynamic color customization in SVG templates. Users can now override template colors via query parameters, enabling personalized branding without creating new templates.

  • Added color definitions to all templates in templates.yaml
  • Implemented color extraction, validation, and override functionality
  • Modified SVG generation to apply color replacements

Reviewed Changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
templates.yaml Added color definitions for each template (background, text colors, accents, etc.)
src/templates.rs Added color parsing and storage logic to load color definitions from template YAML
src/params.rs Added extra field for color parameters with validation logic using regex
src/routes/index.rs Integrated color extraction and validation into the request pipeline
src/generator/svg.rs Implemented color override logic using string replacement
Cargo.toml Added regex dependency (version 1.11)
Cargo.lock Updated lock file with regex dependency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/params.rs (1)

3-101: Avoid recompiling the hex regex on every request.

Regex::new runs for each call to extract_colors, which adds measurable overhead on hot paths. A OnceLock keeps the pattern compiled once and reuses it safely across requests.

Apply this diff to cache the regex:

 use axum::http::StatusCode;
 use axum::response::{IntoResponse, Response};
 use regex::Regex;
 use serde::Deserialize;
 use std::collections::HashMap;
+use std::sync::OnceLock;
 use utoipa::{IntoParams, ToSchema};

 use crate::AppState;
 use crate::config::ImageFallbackBehavior;
 use crate::image::ValidatedImage;
 
+static HEX_COLOR_REGEX: OnceLock<Regex> =
+    OnceLock::new(|| Regex::new(r"^[0-9A-Fa-f]{6}$").unwrap());
+
 impl OgParams {
@@
-        let template_colors = state.templates.colors.get(template_name);
-        let hex_regex = Regex::new(r"^[0-9A-Fa-f]{6}$").unwrap();
+        let template_colors = state.templates.colors.get(template_name);
+        let hex_regex = HEX_COLOR_REGEX.get_or_init(|| {
+            Regex::new(r"^[0-9A-Fa-f]{6}$").expect("hex color regex should compile")
+        });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e708c07 and 288e691.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • Cargo.toml (1 hunks)
  • src/generator/svg.rs (1 hunks)
  • src/params.rs (3 hunks)
  • src/routes/index.rs (1 hunks)
  • src/templates.rs (3 hunks)
  • templates.yaml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/generator/svg.rs (1)
src/templates.rs (2)
  • available_templates (13-19)
  • templates (14-17)
src/routes/index.rs (1)
src/generator/svg.rs (1)
  • generate_svg (46-104)
src/templates.rs (1)
src/yaml_loader.rs (2)
  • load_text (34-40)
  • load_yaml (7-16)
🔇 Additional comments (6)
Cargo.toml (1)

20-20: Dependency addition looks good.

Adding regex = "1.11" cleanly supports the new validation path in params without affecting existing deps.

templates.yaml (1)

6-70: Palette definitions align with the override workflow.

The quoted hex literals ensure YAML keeps the #, and the keys match the validator expectations—nicely coordinated.

src/routes/index.rs (1)

145-175: Color override integration looks solid.

Nice job threading template_name and the validated color_overrides through to the generator while preserving existing error handling and logging.

src/templates.rs (1)

22-115: Template color parsing is well integrated.

The helper cleanly filters non-string entries and only stores non-empty palettes, keeping TemplateMap consistent with the new override flow.

src/generator/svg.rs (2)

12-24: LGTM: Clean template lookup with helpful error messages.

The refactoring to require an explicit template_name parameter removes ambiguity and provides clear error messages when templates are not found.


46-57: All call sites updated correctly.

The call at src/routes/index.rs:166-175 matches the new signature exactly, passing all 8 arguments in the correct order and types. No other files call generate_svg. Signature change is fully integrated.

Copilot AI review requested due to automatic review settings November 3, 2025 08:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/params.rs:55

  • The is_empty() method should also check self.template and self.extra fields. Currently, a request with only color parameters or only a template parameter would be considered 'empty', which could lead to incorrect default value application.
    fn is_empty(&self) -> bool {
        self.title.is_none()
            && self.description.is_none()
            && self.subtitle.is_none()
            && self.logo.is_none()
            && self.image.is_none()

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@twangodev twangodev merged commit fc68375 into main Nov 3, 2025
9 checks passed
@twangodev twangodev deleted the feat/colors branch November 3, 2025 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants