refactor(serialization): 重构颜色模块的序列化实现
将手动实现的序列化逻辑替换为派生宏实现 添加foreign_serializer模块处理特殊序列化需求 优化代码结构并减少重复代码
This commit is contained in:
		@@ -1,10 +1,10 @@
 | 
			
		||||
use std::str::FromStr;
 | 
			
		||||
 | 
			
		||||
use palette::{
 | 
			
		||||
    FromColor, Hsl, IntoColor, IsWithinBounds, Lab, Oklch, Srgb,
 | 
			
		||||
    cam16::{Cam16Jch, Parameters},
 | 
			
		||||
    color_difference::Wcag21RelativeContrast,
 | 
			
		||||
    convert::FromColorUnclamped,
 | 
			
		||||
    FromColor, Hsl, IntoColor, IsWithinBounds, Lab, Oklch, Srgb,
 | 
			
		||||
};
 | 
			
		||||
use wasm_bindgen::prelude::*;
 | 
			
		||||
 | 
			
		||||
@@ -14,6 +14,7 @@ mod color_differ;
 | 
			
		||||
mod color_shifting;
 | 
			
		||||
mod convert;
 | 
			
		||||
mod errors;
 | 
			
		||||
mod foreign_serializer;
 | 
			
		||||
mod palettes;
 | 
			
		||||
mod reversing;
 | 
			
		||||
mod schemes;
 | 
			
		||||
@@ -139,10 +140,6 @@ pub fn wacg_relative_contrast(fg_color: &str, bg_color: &str) -> Result<f32, err
 | 
			
		||||
#[macro_export]
 | 
			
		||||
macro_rules! cond {
 | 
			
		||||
    ($s: expr, $a: expr, $b: expr) => {
 | 
			
		||||
        if $s {
 | 
			
		||||
            $a
 | 
			
		||||
        } else {
 | 
			
		||||
            $b
 | 
			
		||||
        }
 | 
			
		||||
        if $s { $a } else { $b }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,12 @@
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
 | 
			
		||||
use internment::Intern;
 | 
			
		||||
use material_design_2::MaterialDesign2Scheme;
 | 
			
		||||
use material_design_3::MaterialDesign3Scheme;
 | 
			
		||||
use material_design_3_dynamic::{build_baseline, build_dynamic_scheme, build_swatches, Variant};
 | 
			
		||||
use material_design_3_dynamic::{Variant, build_baseline, build_dynamic_scheme, build_swatches};
 | 
			
		||||
use q_style::{QScheme, SchemeSetting};
 | 
			
		||||
use swatch_style::{SwatchEntry, SwatchSchemeSetting};
 | 
			
		||||
use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
 | 
			
		||||
use wasm_bindgen::{JsValue, prelude::wasm_bindgen};
 | 
			
		||||
 | 
			
		||||
use crate::{errors, schemes::q_style_2::QScheme2};
 | 
			
		||||
 | 
			
		||||
@@ -23,6 +24,10 @@ pub trait SchemeExport {
 | 
			
		||||
    fn output_javascript_object(&self) -> String;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn get_static_str(s: &str) -> &'static str {
 | 
			
		||||
    Intern::new(s.to_string()).as_ref()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[wasm_bindgen]
 | 
			
		||||
pub fn generate_material_design_3_scheme(
 | 
			
		||||
    source_color: &str,
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@ use palette::{
 | 
			
		||||
    Oklch, ShiftHue,
 | 
			
		||||
    color_theory::{Analogous, Complementary, SplitComplementary, Tetradic, Triadic},
 | 
			
		||||
};
 | 
			
		||||
use serde::{Serialize, ser::SerializeStruct};
 | 
			
		||||
use serde::Serialize;
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    convert::map_oklch_to_srgb_hex,
 | 
			
		||||
@@ -16,7 +16,8 @@ use crate::{
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
#[derive(Debug, Clone, Serialize)]
 | 
			
		||||
#[serde(rename_all = "camelCase")]
 | 
			
		||||
pub struct ColorUnit {
 | 
			
		||||
    pub root: ColorSet,
 | 
			
		||||
    pub surface: ColorSet,
 | 
			
		||||
@@ -82,20 +83,8 @@ impl ColorUnit {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Serialize for ColorUnit {
 | 
			
		||||
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 | 
			
		||||
    where
 | 
			
		||||
        S: serde::Serializer,
 | 
			
		||||
    {
 | 
			
		||||
        let mut state = serializer.serialize_struct("ColorUnit", 3)?;
 | 
			
		||||
        state.serialize_field("root", &self.root)?;
 | 
			
		||||
        state.serialize_field("surface", &self.surface)?;
 | 
			
		||||
        state.serialize_field("swatch", &self.swatch)?;
 | 
			
		||||
        state.end()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
#[derive(Debug, Clone, Serialize)]
 | 
			
		||||
#[serde(rename_all = "camelCase")]
 | 
			
		||||
pub struct Baseline {
 | 
			
		||||
    pub primary: ColorUnit,
 | 
			
		||||
    pub secondary: Option<ColorUnit>,
 | 
			
		||||
@@ -105,18 +94,26 @@ pub struct Baseline {
 | 
			
		||||
    pub neutral_variant: ColorSet,
 | 
			
		||||
    pub surface: ColorSet,
 | 
			
		||||
    pub surface_variant: ColorSet,
 | 
			
		||||
    #[serde(serialize_with = "crate::schemes::q_style_2::swatch::serialize_neutral_swatch")]
 | 
			
		||||
    pub neutral_swatch: Arc<NeutralSwatch>,
 | 
			
		||||
    pub danger: ColorUnit,
 | 
			
		||||
    pub success: ColorUnit,
 | 
			
		||||
    pub warn: ColorUnit,
 | 
			
		||||
    pub info: ColorUnit,
 | 
			
		||||
    pub custom_colors: HashMap<String, ColorUnit>,
 | 
			
		||||
    #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
 | 
			
		||||
    pub shadow: Oklch,
 | 
			
		||||
    #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
 | 
			
		||||
    pub overlay: Oklch,
 | 
			
		||||
    #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
 | 
			
		||||
    pub outline: Oklch,
 | 
			
		||||
    #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
 | 
			
		||||
    pub outline_variant: Oklch,
 | 
			
		||||
    #[serde(skip)]
 | 
			
		||||
    pub neutral_lightness: f32,
 | 
			
		||||
    #[serde(skip)]
 | 
			
		||||
    pub scheme_settings: Arc<SchemeSetting>,
 | 
			
		||||
    #[serde(skip)]
 | 
			
		||||
    pub is_dark: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -514,35 +511,3 @@ impl Baseline {
 | 
			
		||||
        javascript_fields
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Serialize for Baseline {
 | 
			
		||||
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 | 
			
		||||
    where
 | 
			
		||||
        S: serde::Serializer,
 | 
			
		||||
    {
 | 
			
		||||
        let mut state = serializer.serialize_struct("Baseline", 17)?;
 | 
			
		||||
 | 
			
		||||
        state.serialize_field("primary", &self.primary)?;
 | 
			
		||||
        state.serialize_field("secondary", &self.secondary)?;
 | 
			
		||||
        state.serialize_field("tertiary", &self.tertiary)?;
 | 
			
		||||
        state.serialize_field("accent", &self.accent)?;
 | 
			
		||||
        state.serialize_field("neutral", &self.neutral)?;
 | 
			
		||||
        state.serialize_field("neutralVariant", &self.neutral_variant)?;
 | 
			
		||||
        state.serialize_field("surface", &self.surface)?;
 | 
			
		||||
        state.serialize_field("surfaceVariant", &self.surface_variant)?;
 | 
			
		||||
        state.serialize_field("danger", &self.danger)?;
 | 
			
		||||
        state.serialize_field("success", &self.success)?;
 | 
			
		||||
        state.serialize_field("warn", &self.warn)?;
 | 
			
		||||
        state.serialize_field("info", &self.info)?;
 | 
			
		||||
        state.serialize_field("shadow", &map_oklch_to_srgb_hex(&self.shadow))?;
 | 
			
		||||
        state.serialize_field("overlay", &map_oklch_to_srgb_hex(&self.overlay))?;
 | 
			
		||||
        state.serialize_field("outline", &map_oklch_to_srgb_hex(&self.outline))?;
 | 
			
		||||
        state.serialize_field(
 | 
			
		||||
            "outlineVariant",
 | 
			
		||||
            &map_oklch_to_srgb_hex(&self.outline_variant),
 | 
			
		||||
        )?;
 | 
			
		||||
        state.serialize_field("custom", &self.custom_colors)?;
 | 
			
		||||
 | 
			
		||||
        state.end()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ use std::sync::Arc;
 | 
			
		||||
 | 
			
		||||
use linked_hash_map::LinkedHashMap;
 | 
			
		||||
use palette::{Oklch, color_difference::Wcag21RelativeContrast, luma::Luma};
 | 
			
		||||
use serde::{Serialize, ser::SerializeStruct};
 | 
			
		||||
use serde::Serialize;
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    convert::{map_oklch_to_luma, map_oklch_to_srgb_hex},
 | 
			
		||||
@@ -13,17 +13,28 @@ use crate::{
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
#[derive(Debug, Clone, Serialize)]
 | 
			
		||||
#[serde(rename_all = "camelCase")]
 | 
			
		||||
pub struct ColorSet {
 | 
			
		||||
    #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
 | 
			
		||||
    pub root: Oklch,
 | 
			
		||||
    #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
 | 
			
		||||
    pub active: Oklch,
 | 
			
		||||
    #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
 | 
			
		||||
    pub focus: Oklch,
 | 
			
		||||
    #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
 | 
			
		||||
    pub hover: Oklch,
 | 
			
		||||
    #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
 | 
			
		||||
    pub disabled: Oklch,
 | 
			
		||||
    #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
 | 
			
		||||
    pub on_root: Oklch,
 | 
			
		||||
    #[serde(serialize_with = "crate::foreign_serializer::serialize_oklch_to_hex")]
 | 
			
		||||
    pub on_disabled: Oklch,
 | 
			
		||||
    #[serde(skip)]
 | 
			
		||||
    pub neutral_swatch: Arc<NeutralSwatch>,
 | 
			
		||||
    #[serde(skip)]
 | 
			
		||||
    pub neutral_lightness: f32,
 | 
			
		||||
    #[serde(skip)]
 | 
			
		||||
    pub scheme_settings: Arc<SchemeSetting>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -266,28 +277,3 @@ impl ColorSet {
 | 
			
		||||
        variables
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Serialize for ColorSet {
 | 
			
		||||
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 | 
			
		||||
    where
 | 
			
		||||
        S: serde::Serializer,
 | 
			
		||||
    {
 | 
			
		||||
        let root = map_oklch_to_srgb_hex(&self.root);
 | 
			
		||||
        let hover = map_oklch_to_srgb_hex(&self.hover);
 | 
			
		||||
        let active = map_oklch_to_srgb_hex(&self.active);
 | 
			
		||||
        let focus = map_oklch_to_srgb_hex(&self.focus);
 | 
			
		||||
        let disabled = map_oklch_to_srgb_hex(&self.disabled);
 | 
			
		||||
        let on_root = map_oklch_to_srgb_hex(&self.on_root);
 | 
			
		||||
        let on_disabled = map_oklch_to_srgb_hex(&self.on_disabled);
 | 
			
		||||
 | 
			
		||||
        let mut state = serializer.serialize_struct("ColorSet", 6)?;
 | 
			
		||||
        state.serialize_field("root", &root)?;
 | 
			
		||||
        state.serialize_field("hover", &hover)?;
 | 
			
		||||
        state.serialize_field("active", &active)?;
 | 
			
		||||
        state.serialize_field("focus", &focus)?;
 | 
			
		||||
        state.serialize_field("disabled", &disabled)?;
 | 
			
		||||
        state.serialize_field("onRoot", &on_root)?;
 | 
			
		||||
        state.serialize_field("onDisabled", &on_disabled)?;
 | 
			
		||||
        state.end()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ use serde::Serialize;
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    errors, parse_option_to_oklch, parse_to_oklch,
 | 
			
		||||
    schemes::{q_style::SchemeSetting, q_style_2::baseline::Baseline, SchemeExport},
 | 
			
		||||
    schemes::{SchemeExport, q_style::SchemeSetting, q_style_2::baseline::Baseline},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
mod baseline;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,13 @@
 | 
			
		||||
use internment::Intern;
 | 
			
		||||
use std::sync::Arc;
 | 
			
		||||
 | 
			
		||||
use linked_hash_map::LinkedHashMap;
 | 
			
		||||
use palette::Oklch;
 | 
			
		||||
use serde::{Serialize, ser::SerializeStruct};
 | 
			
		||||
use serde::{Serialize, Serializer, ser::SerializeStruct};
 | 
			
		||||
 | 
			
		||||
use crate::convert::map_oklch_to_srgb_hex;
 | 
			
		||||
use crate::{
 | 
			
		||||
    convert::map_oklch_to_srgb_hex,
 | 
			
		||||
    schemes::{get_static_str, q_style::NeutralSwatch},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static SWATCH_LIGHTINGS: [u8; 16] = [
 | 
			
		||||
    10, 15, 20, 25, 30, 35, 40, 50, 60, 70, 75, 80, 85, 90, 95, 98,
 | 
			
		||||
@@ -77,10 +81,6 @@ impl Swatch {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn get_static_str(s: &str) -> &'static str {
 | 
			
		||||
    Intern::new(s.to_string()).as_ref()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Serialize for Swatch {
 | 
			
		||||
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 | 
			
		||||
    where
 | 
			
		||||
@@ -97,3 +97,23 @@ impl Serialize for Swatch {
 | 
			
		||||
        state.end()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn serialize_neutral_swatch<S>(
 | 
			
		||||
    swatch: &Arc<NeutralSwatch>,
 | 
			
		||||
    serailizer: S,
 | 
			
		||||
) -> Result<S::Ok, S::Error>
 | 
			
		||||
where
 | 
			
		||||
    S: Serializer,
 | 
			
		||||
{
 | 
			
		||||
    let swatch = swatch.clone();
 | 
			
		||||
    let mut swatch_struct = serailizer.serialize_struct("NeutralSwatch", SWATCH_LIGHTINGS.len())?;
 | 
			
		||||
 | 
			
		||||
    for l in SWATCH_LIGHTINGS {
 | 
			
		||||
        let color = swatch.get((l as f32) / 100.0);
 | 
			
		||||
        let color = map_oklch_to_srgb_hex(&color);
 | 
			
		||||
        let key: &'static str = get_static_str(&format!("{l:02}"));
 | 
			
		||||
        swatch_struct.serialize_field(key, &color)?;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    swatch_struct.end()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user