Support setting custom background color for syntax highlighting (#12400)

Danielle Maywood created

Release Notes:

- Added support for `background_color` in `syntax` map in `theme.json`.

This adds support for setting a `background_color` for styles inside the
`syntax` map for themes defined in `theme.json`. The field is optional
so there should be no backwards compatibility issues.

It is worth noting that the current behaviour for selecting text is that
the background colours will mix/blend (I'm not sure the correct term
here). Changing this behaviour, or making it configurable, looks to be a
far more complex issue and I'm not sure I know how to do it.

Change summary

crates/theme/src/registry.rs                  |  4 ++++
crates/theme/src/schema.rs                    | 12 +++++++++++-
crates/theme_importer/src/vscode/converter.rs |  1 +
3 files changed, 16 insertions(+), 1 deletion(-)

Detailed changes

crates/theme/src/registry.rs 🔗

@@ -137,6 +137,10 @@ impl ThemeRegistry {
                                 .color
                                 .as_ref()
                                 .and_then(|color| try_parse_color(color).ok()),
+                            background_color: highlight
+                                .background_color
+                                .as_ref()
+                                .and_then(|color| try_parse_color(color).ok()),
                             font_style: highlight.font_style.map(Into::into),
                             font_weight: highlight.font_weight.map(Into::into),
                             ..Default::default()

crates/theme/src/schema.rs 🔗

@@ -117,6 +117,10 @@ impl ThemeStyleContent {
                             .color
                             .as_ref()
                             .and_then(|color| try_parse_color(color).ok()),
+                        background_color: style
+                            .background_color
+                            .as_ref()
+                            .and_then(|color| try_parse_color(color).ok()),
                         font_style: style
                             .font_style
                             .map(|font_style| FontStyle::from(font_style)),
@@ -1304,6 +1308,9 @@ impl From<FontWeightContent> for FontWeight {
 pub struct HighlightStyleContent {
     pub color: Option<String>,
 
+    #[serde(deserialize_with = "treat_error_as_none")]
+    pub background_color: Option<String>,
+
     #[serde(deserialize_with = "treat_error_as_none")]
     pub font_style: Option<FontStyleContent>,
 
@@ -1313,7 +1320,10 @@ pub struct HighlightStyleContent {
 
 impl HighlightStyleContent {
     pub fn is_empty(&self) -> bool {
-        self.color.is_none() && self.font_style.is_none() && self.font_weight.is_none()
+        self.color.is_none()
+            && self.background_color.is_none()
+            && self.font_style.is_none()
+            && self.font_weight.is_none()
     }
 }
 

crates/theme_importer/src/vscode/converter.rs 🔗

@@ -241,6 +241,7 @@ impl VsCodeThemeConverter {
 
             let highlight_style = HighlightStyleContent {
                 color: token_color.settings.foreground.clone(),
+                background_color: token_color.settings.background.clone(),
                 font_style: token_color
                     .settings
                     .font_style