From 9122ab3f244a0531ca6a32648af41866d30ad75f Mon Sep 17 00:00:00 2001 From: owjs3901 Date: Tue, 7 Apr 2026 13:24:02 +0900 Subject: [PATCH] Support variable on typography --- .../changepack_log_qcHsL3xvZLwwNPSMXNdfv.json | 1 + Cargo.lock | 84 +++++++++---------- libs/extractor/Cargo.toml | 18 ++-- libs/sheet/src/theme.rs | 82 ++++++++++++++++-- 4 files changed, 129 insertions(+), 56 deletions(-) create mode 100644 .changepacks/changepack_log_qcHsL3xvZLwwNPSMXNdfv.json diff --git a/.changepacks/changepack_log_qcHsL3xvZLwwNPSMXNdfv.json b/.changepacks/changepack_log_qcHsL3xvZLwwNPSMXNdfv.json new file mode 100644 index 00000000..f001363e --- /dev/null +++ b/.changepacks/changepack_log_qcHsL3xvZLwwNPSMXNdfv.json @@ -0,0 +1 @@ +{"changes":{"bindings/devup-ui-wasm/package.json":"Patch"},"note":"Support variable on typography","date":"2026-04-07T04:23:57.883285900Z"} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index c8b9991e..413b29f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1319,9 +1319,9 @@ dependencies = [ [[package]] name = "oxc-miette" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a7ba54c704edefead1f44e9ef09c43e5cfae666bdc33516b066011f0e6ebf7" +checksum = "4356a61f2ed4c9b3610245215fbf48970eb277126919f87db9d0efa93a74245c" dependencies = [ "cfg-if", "owo-colors", @@ -1334,9 +1334,9 @@ dependencies = [ [[package]] name = "oxc-miette-derive" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4faecb54d0971f948fbc1918df69b26007e6f279a204793669542e1e8b75eb3" +checksum = "b237422b014f8f8fff75bb9379e697d13f8d57551a22c88bebb39f073c1bf696" dependencies = [ "proc-macro2", "quote", @@ -1345,9 +1345,9 @@ dependencies = [ [[package]] name = "oxc_allocator" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6fc6ce99f6a28fd477c6df500bbc9bf1c39db166952e15bea218459cc0db0c" +checksum = "7cce9493fc18c7f2b9274baba258555d88cc1fab3ac3c4b293433b4f85ad097b" dependencies = [ "allocator-api2", "hashbrown 0.16.1", @@ -1357,9 +1357,9 @@ dependencies = [ [[package]] name = "oxc_ast" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fa0813bf9fcff5a4e48fc186ee15a0d276b30b0b575389a34a530864567819" +checksum = "29366258930c55e2578e231995d2079cba12793429454fa892f01d985821a554" dependencies = [ "bitflags", "oxc_allocator", @@ -1374,9 +1374,9 @@ dependencies = [ [[package]] name = "oxc_ast_macros" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a2b2a2e09ff0dd4790a5ceb4a93349e0ea769d4d98d778946de48decb763b18" +checksum = "617bf2f55d04db8d6fea9583569c7e4d9052297f76f2f8ae31b1f4ef8bcfd98e" dependencies = [ "phf", "proc-macro2", @@ -1386,9 +1386,9 @@ dependencies = [ [[package]] name = "oxc_ast_visit" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef6d2304cb25dbbd028440591bf289ef16e3df98517930e79dcc304be64b3045" +checksum = "4344952280d3e8cbfed93da2775c460bbded12f388404daa662dc0ee731e051f" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1398,9 +1398,9 @@ dependencies = [ [[package]] name = "oxc_codegen" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce92b24319ee9fbfa14a5cc488a5ba91bb04bac070c4bad0ba18c772060d19c0" +checksum = "fb16cc717d020bff40a1ef4da006da23b24990c277eec39586a454110c2ad628" dependencies = [ "bitflags", "cow-utils", @@ -1419,9 +1419,9 @@ dependencies = [ [[package]] name = "oxc_compat" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5a3de8c67c960a20bc0177d54498d1a96275c38eb78a0975b4ffdc5a1fb13a" +checksum = "31b7f19adf1f6b67312fc3ac1003d995c55b51fc6a77be17fc597139300aab24" dependencies = [ "cow-utils", "oxc-browserslist", @@ -1432,18 +1432,18 @@ dependencies = [ [[package]] name = "oxc_data_structures" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e8f59bed9522098da177d894dc8635fb3eae218ff97d9c695900cb11fd10a2" +checksum = "a3a309fcc491b31039bd2a77d8517278c198f566c284e9a18977dab801c05681" dependencies = [ "ropey", ] [[package]] name = "oxc_diagnostics" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0476859d4319f2b063f7c4a3120ee5b7e3e48032865ca501f8545ff44badcff" +checksum = "a1c0f18571aac10db23d1ab681108102ac735c50142c5418ec8272e1d861219f" dependencies = [ "cow-utils", "oxc-miette", @@ -1452,9 +1452,9 @@ dependencies = [ [[package]] name = "oxc_ecmascript" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bcf46e5b1a6f8ea3797e887a9db4c79ed15894ca8685eb628da462d4c4e913f" +checksum = "4eaddc891449b4c7d8720714d6939c99fc531054c8f7decba9ffdd1c70a7b67b" dependencies = [ "cow-utils", "num-bigint", @@ -1468,9 +1468,9 @@ dependencies = [ [[package]] name = "oxc_estree" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2251e6b61eab7b96f0e9d140b68b0f0d8a851c7d260725433e18b1babdcb9430" +checksum = "8dd0f39cc6f2014fc1a60a563903c6c6c88f856772d44f390fe876a575bd7c97" [[package]] name = "oxc_index" @@ -1484,9 +1484,9 @@ dependencies = [ [[package]] name = "oxc_parser" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439d2580047b77faf6e60d358b48e5292e0e026b9cfc158d46ddd0175244bb26" +checksum = "ecf347b9ba5fd251f215f0c44602fbec98c01ea4cf13ae2682167f33d8a8d0b4" dependencies = [ "bitflags", "cow-utils", @@ -1507,9 +1507,9 @@ dependencies = [ [[package]] name = "oxc_regular_expression" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fb5669d3298a92d440afec516943745794cb4cf977911728cd73e3438db87b9" +checksum = "922016d2def4d0a2b17c907bda16d6eb20516622ae818eb8662f69b353ba9f20" dependencies = [ "bitflags", "oxc_allocator", @@ -1523,9 +1523,9 @@ dependencies = [ [[package]] name = "oxc_semantic" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487e9ef54375b23b159eef73746a02b505c3ae70b9c302610680d3c68a3bb62c" +checksum = "4cb5b9082935c4b0e076bc9c2add9f335fed1be4e6ae5e580747a33808348318" dependencies = [ "itertools 0.14.0", "memchr", @@ -1556,9 +1556,9 @@ dependencies = [ [[package]] name = "oxc_span" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d452f6a664627bdd0f1f1586f9258f81cd7edc5c83e9ef50019f701ef1722d" +checksum = "9b4413a552b443c777dd2782bc49e719a20cb36434c9b196e9021259028ca74c" dependencies = [ "compact_str", "oxc-miette", @@ -1570,9 +1570,9 @@ dependencies = [ [[package]] name = "oxc_str" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7a27c4371f69387f3d6f8fa56f70e4c6fa6aedc399285de6ec02bb9fd148d7" +checksum = "321abe830f84ab9c13ac43eadb625f7e8ccddab6a150732d1e5bf9dde043ef4f" dependencies = [ "compact_str", "hashbrown 0.16.1", @@ -1582,9 +1582,9 @@ dependencies = [ [[package]] name = "oxc_syntax" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d60d91023aafc256ab99c3dbf6181473e495695029c0152d2093e87df18ffe2" +checksum = "11919498c468e21e0688d6c99e37c15f2825a64cfa2f9a0c99d6f767076011d8" dependencies = [ "bitflags", "cow-utils", @@ -1601,9 +1601,9 @@ dependencies = [ [[package]] name = "oxc_transformer" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226d77c70778860c4b4888e4aa52f1b4799bfc67093aa5070f367848ff8df09b" +checksum = "80da5fe1be7e026fb17d3b948712d5d53b6257fa9806c851f405b842dcf761b8" dependencies = [ "base64", "compact_str", @@ -1630,9 +1630,9 @@ dependencies = [ [[package]] name = "oxc_traverse" -version = "0.123.0" +version = "0.124.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31aba1910999e2f9a1cc9c47a490caaed828bb119351abe20a2a7851d554963" +checksum = "d8cbebcd5777218246cd65c540c4792600ba2bf3467671c068f6dc4da963cdd2" dependencies = [ "itoa", "oxc_allocator", @@ -2267,9 +2267,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simd-adler32" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "similar" diff --git a/libs/extractor/Cargo.toml b/libs/extractor/Cargo.toml index 1947bb24..7ebca084 100644 --- a/libs/extractor/Cargo.toml +++ b/libs/extractor/Cargo.toml @@ -4,15 +4,15 @@ version = "0.1.0" edition = "2024" [dependencies] -oxc_parser = "0.123.0" -oxc_syntax = "0.123.0" -oxc_span = "0.123.0" -oxc_allocator = "0.123.0" -oxc_ast = "0.123.0" -oxc_ast_visit = "0.123.0" -oxc_codegen = "0.123.0" -oxc_transformer = "0.123.0" -oxc_semantic = "0.123.0" +oxc_parser = "0.124.0" +oxc_syntax = "0.124.0" +oxc_span = "0.124.0" +oxc_allocator = "0.124.0" +oxc_ast = "0.124.0" +oxc_ast_visit = "0.124.0" +oxc_codegen = "0.124.0" +oxc_transformer = "0.124.0" +oxc_semantic = "0.124.0" css = { path = "../css" } phf = "0.13" strum = "0.28.0" diff --git a/libs/sheet/src/theme.rs b/libs/sheet/src/theme.rs index f9f1a587..2b878922 100644 --- a/libs/sheet/src/theme.rs +++ b/libs/sheet/src/theme.rs @@ -675,26 +675,33 @@ impl Theme { for ty in self.typography.iter() { for (idx, t) in ty.1.0.iter().enumerate() { if let Some(t) = t { + let resolve = |v: &str| -> String { + if let Some(token) = v.strip_prefix('$') { + format!("var(--{})", token) + } else { + optimize_value(v) + } + }; let css_content = [ t.font_family .as_ref() - .map(|v| format!("font-family:{}", optimize_value(v))) + .map(|v| format!("font-family:{}", resolve(v))) .unwrap_or_default(), t.font_size .as_ref() - .map(|v| format!("font-size:{}", optimize_value(v))) + .map(|v| format!("font-size:{}", resolve(v))) .unwrap_or_default(), t.font_weight .as_ref() - .map(|v| format!("font-weight:{}", optimize_value(v))) + .map(|v| format!("font-weight:{}", resolve(v))) .unwrap_or_default(), t.line_height .as_ref() - .map(|v| format!("line-height:{}", optimize_value(v))) + .map(|v| format!("line-height:{}", resolve(v))) .unwrap_or_default(), t.letter_spacing .as_ref() - .map(|v| format!("letter-spacing:{}", optimize_value(v))) + .map(|v| format!("letter-spacing:{}", resolve(v))) .unwrap_or_default(), ] .iter() @@ -1380,6 +1387,71 @@ mod tests { assert!(err.contains("cannot start with an array")); } + #[test] + fn test_typography_variable_reference() { + let theme: Theme = serde_json::from_str( + r##"{ + "typography": { + "body": { + "fontSize": "$text", + "lineHeight": "$leading", + "fontWeight": 400 + } + } + }"##, + ) + .unwrap(); + + let css = theme.to_css(); + assert!( + css.contains("font-size:var(--text)"), + "Expected font-size:var(--text), got: {}", + css + ); + assert!( + css.contains("line-height:var(--leading)"), + "Expected line-height:var(--leading), got: {}", + css + ); + assert!(css.contains("font-weight:400")); + } + + #[test] + fn test_typography_variable_reference_responsive() { + let theme: Theme = serde_json::from_str( + r##"{ + "typography": { + "heading": [ + { + "fontSize": "$textSm", + "fontWeight": 700 + }, + null, + null, + null, + { + "fontSize": "$textLg", + "fontWeight": 700 + } + ] + } + }"##, + ) + .unwrap(); + + let css = theme.to_css(); + assert!( + css.contains("font-size:var(--textSm)"), + "Expected font-size:var(--textSm), got: {}", + css + ); + assert!( + css.contains("font-size:var(--textLg)"), + "Expected font-size:var(--textLg), got: {}", + css + ); + } + #[test] fn test_mixed_typography_formats() { // Test that both formats can coexist in the same theme