From fa4dab4e3ede216202306f270fbe448b1a08e5aa Mon Sep 17 00:00:00 2001 From: zhaowenkai <799480165@qq.com> Date: Thu, 7 Dec 2023 10:19:17 +0800 Subject: [PATCH 1/6] fix the accuracy of number type mapping --- src/Styles/StyleHelper.cs | 10 ++++++++++ src/Styles/StyleOutlet.cs | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/src/Styles/StyleHelper.cs b/src/Styles/StyleHelper.cs index 8c695b0..aa96f21 100644 --- a/src/Styles/StyleHelper.cs +++ b/src/Styles/StyleHelper.cs @@ -40,5 +40,15 @@ public static RenderFragment UseStyleRegister(StyleInfo style) builder.CloseComponent(); }; } + + public static RenderFragment UseStyleRegister(StyleInfo style) + { + StyleOutlet.Register(style); + return builder => + { + builder.OpenComponent(0); + builder.CloseComponent(); + }; + } } } diff --git a/src/Styles/StyleOutlet.cs b/src/Styles/StyleOutlet.cs index 9446299..f70b8cb 100644 --- a/src/Styles/StyleOutlet.cs +++ b/src/Styles/StyleOutlet.cs @@ -12,6 +12,12 @@ public sealed class StyleOutlet : ComponentBase internal const string StyeSectionOutletName = "cssincsharp_style"; internal const string InternalStyeSectionOutletName = "cssincsharp_style_internal"; + internal static void Register(StyleInfo style) + { + var path = $"{style.TokenKey}|{string.Join("|", style.Path)}"; + Styles.TryAdd(path, style); + } + /* * using SectionOutlet to render style tag * note: From 84d69966e8c004f50b595b00cf9b6ba0ddcd44b9 Mon Sep 17 00:00:00 2001 From: zhaowenkai <799480165@qq.com> Date: Mon, 11 Dec 2023 15:29:16 +0800 Subject: [PATCH 2/6] add internal style content component --- src/Styles/StyleOutlet.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Styles/StyleOutlet.cs b/src/Styles/StyleOutlet.cs index f70b8cb..9446299 100644 --- a/src/Styles/StyleOutlet.cs +++ b/src/Styles/StyleOutlet.cs @@ -12,12 +12,6 @@ public sealed class StyleOutlet : ComponentBase internal const string StyeSectionOutletName = "cssincsharp_style"; internal const string InternalStyeSectionOutletName = "cssincsharp_style_internal"; - internal static void Register(StyleInfo style) - { - var path = $"{style.TokenKey}|{string.Join("|", style.Path)}"; - Styles.TryAdd(path, style); - } - /* * using SectionOutlet to render style tag * note: From 8f70923d5695b35dad3b1c064192d01d4a8e90ac Mon Sep 17 00:00:00 2001 From: zhaowenkai <799480165@qq.com> Date: Tue, 12 Dec 2023 18:58:04 +0800 Subject: [PATCH 3/6] cssobject support css variable --- src/CSSObject.cs | 19 ++++++++++++++++++- src/Types/CSSInterpolation.cs | 11 ++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/CSSObject.cs b/src/CSSObject.cs index d179675..166230d 100644 --- a/src/CSSObject.cs +++ b/src/CSSObject.cs @@ -30,7 +30,7 @@ public string SerializeCss(string hashId) return Serialize(Compile(ParseStyle(true, hashId)), Stringify); } - public string ParseStyle(bool root, string hashId) + internal string ParseStyle(bool root, string hashId) { var sb = new StringBuilder(); @@ -93,6 +93,23 @@ public CSSObject Merge(CSSObject[] objects) private void SetStyle(string key, CSSInterpolation value) { if (key == null) return; + /* + * If is css variable, + * eg: + * new CSSObject + * { + * ["--font-size"] = "12px" // here is string value. + * } + */ + if (value.IsT2) + { + _properties[key] = (Property)value.AsT2; // cast to Property type. + return; + } + + /* + * if is CSSObject or CSSObject[] + */ var cssObject = value.IsT0 ? value.AsT0 : new CSSObject().Merge(value.ToCssArray()); if (cssObject == null) return; if (key == MERGE_OPERATOR) diff --git a/src/Types/CSSInterpolation.cs b/src/Types/CSSInterpolation.cs index d26435c..655435b 100644 --- a/src/Types/CSSInterpolation.cs +++ b/src/Types/CSSInterpolation.cs @@ -7,21 +7,25 @@ public struct CSSInterpolation private readonly int _index; private readonly CSSObject _value0; private readonly CSSInterpolation[] _value1; + private readonly string _value2; public CSSObject this[string key] => _value0; - private CSSInterpolation(int index, CSSObject value0 = default, CSSInterpolation[] value1 = default) + private CSSInterpolation(int index, CSSObject value0 = default, CSSInterpolation[] value1 = default, string value2 = default) { _index = index; _value0 = value0; _value1 = value1; + _value2 = value2; } public static implicit operator CSSInterpolation(CSSObject t) => new(0, value0: t); public static implicit operator CSSInterpolation(CSSInterpolation[] t) => new(1, value1: t); + public static implicit operator CSSInterpolation(string t) => new(2, value2: t); public bool IsT0 => _index == 0; public bool IsT1 => _index == 1; + public bool IsT2 => _index == 2; public CSSObject AsT0 => _index == 0 ? @@ -31,5 +35,10 @@ private CSSInterpolation(int index, CSSObject value0 = default, CSSInterpolation _index == 1 ? _value1 : throw new InvalidOperationException($"Cannot return as T1 as result is T{_index}"); + + public string AsT2 => + _index == 2 ? + _value2 : + throw new InvalidOperationException($"Cannot return as T1 as result is T{_index}"); } } From e0f20d8b5a2cf02620e81ede61df44b02128744d Mon Sep 17 00:00:00 2001 From: yoli Date: Tue, 12 Dec 2023 22:13:39 +0800 Subject: [PATCH 4/6] fix media type hashId error --- src/CSSObject.cs | 8 ++- src/Types/Functions.cs | 10 ++-- test/CssInCSharp.Tests/CSSObjectTests.cs | 63 ++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 test/CssInCSharp.Tests/CSSObjectTests.cs diff --git a/src/CSSObject.cs b/src/CSSObject.cs index 166230d..fce91e3 100644 --- a/src/CSSObject.cs +++ b/src/CSSObject.cs @@ -9,7 +9,7 @@ namespace CssInCSharp { public sealed partial class CSSObject { - private readonly Dictionary _styles = new (); + private readonly Dictionary _styles = new(); private readonly Dictionary _properties = new(); public Dictionary GetProperties() => _properties; public Dictionary GetStyles() => _styles; @@ -41,6 +41,12 @@ internal string ParseStyle(bool root, string hashId) foreach (var subStyle in _styles) { var nextRoot = false; + if (subStyle.Key.StartsWith("@")) + { + // if is media type, skip and insert hashId from subStyle. + root = false; + nextRoot = true; + } sb.Append($"{subStyle.Key}{{{subStyle.Value.ParseStyle(nextRoot, hashId)}}}"); } diff --git a/src/Types/Functions.cs b/src/Types/Functions.cs index bc0452e..551bdd6 100644 --- a/src/Types/Functions.cs +++ b/src/Types/Functions.cs @@ -7,18 +7,18 @@ internal static string FormatValue(string key, T value) return value switch { string v => v, - int v => Wrap(key, v), - float v => Wrap(key, v), - double v => Wrap(key, v), + int v => Wrap(key, v, v != 0), + float v => Wrap(key, v, v != 0), + double v => Wrap(key, v, v != 0), Keyframe v => v.ToString(), _ => value?.ToString() }; } - internal static string Wrap(string key, T value) + internal static string Wrap(string key, T value, bool hasValue) { // All number types need to be px-wrapped and unwanted parts of Unitless should be ignored. - if (!string.IsNullOrEmpty(key) && !Unitless.Keys.ContainsKey(key)) + if (!string.IsNullOrEmpty(key) && !Unitless.Keys.ContainsKey(key) && hasValue) { return $"{value}px"; } diff --git a/test/CssInCSharp.Tests/CSSObjectTests.cs b/test/CssInCSharp.Tests/CSSObjectTests.cs new file mode 100644 index 0000000..9b56d49 --- /dev/null +++ b/test/CssInCSharp.Tests/CSSObjectTests.cs @@ -0,0 +1,63 @@ +using Shouldly; +using Xunit; + +namespace CssInCSharp.Tests +{ + public class CSSObjectTests + { + [Fact] + public void Number_Without_Pxwrap() + { + new CSSObject + { + [".test"] = new CSSObject + { + AnimationIterationCount = 1, + AspectRatio = 1, + BorderImageOutset = 1, + BorderImageSlice = 1, + BorderImageWidth = 1, + ColumnCount = 1, + Columns = 1, + Flex = 1, + FlexGrow = 1, + MsFlexPositive = 1, + FlexShrink = 1, + FontWeight = 1, + LineHeight = 1, + Opacity = 1, + Order = 1, + Orphans = 1, + TabSize = 1, + Widows = 1, + ZIndex = 1, + Zoom = 1, + WebkitLineClamp = 1, + } + } + .ToString() + .ShouldBe(".test{animation-iteration-count:1;aspect-ratio:1;border-image-outset:1;border-image-slice:1;border-image-width:1;column-count:1;columns:1;flex:1;flex-grow:1;-ms-flex-positive:1px;flex-shrink:1;font-weight:1;line-height:1;opacity:1;order:1;orphans:1;tab-size:1;widows:1;z-index:1;zoom:1;-webkit-line-clamp:1;}"); + } + + [Fact] + public void Media() + { + var css = new CSSObject + { + ["@media (min-width: 500px)"] = new CSSObject + { + [".grid-sm"] = new CSSObject + { + Display = "none", + InsetInlineStart = "auto", + InsetInlineEnd = "auto", + MarginInlineStart = 0, + Order = 0 + } + } + }; + css.ToString().ShouldBe("@media (min-width: 500px){.grid-sm{display:none;inset-inline-start:auto;inset-inline-end:auto;margin-inline-start:0;order:0;}}"); + css.SerializeCss("1iw360o").ShouldBe("@media (min-width: 500px){:where(.1iw360o).grid-sm{display:none;inset-inline-start:auto;inset-inline-end:auto;margin-inline-start:0;order:0;}}"); + } + } +} From 48ea3df1aa75c723b28198456d8d022f959f1584 Mon Sep 17 00:00:00 2001 From: yoli Date: Tue, 12 Dec 2023 22:27:02 +0800 Subject: [PATCH 5/6] remove useless code --- src/Styles/StyleHelper.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Styles/StyleHelper.cs b/src/Styles/StyleHelper.cs index aa96f21..8c695b0 100644 --- a/src/Styles/StyleHelper.cs +++ b/src/Styles/StyleHelper.cs @@ -40,15 +40,5 @@ public static RenderFragment UseStyleRegister(StyleInfo style) builder.CloseComponent(); }; } - - public static RenderFragment UseStyleRegister(StyleInfo style) - { - StyleOutlet.Register(style); - return builder => - { - builder.OpenComponent(0); - builder.CloseComponent(); - }; - } } } From cf23784a2a50aab3aaa84850c3cf6fe95b9b8558 Mon Sep 17 00:00:00 2001 From: yoli Date: Tue, 12 Dec 2023 22:31:43 +0800 Subject: [PATCH 6/6] update InvalidOperationException message --- src/Types/CSSInterpolation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Types/CSSInterpolation.cs b/src/Types/CSSInterpolation.cs index 655435b..f469a7e 100644 --- a/src/Types/CSSInterpolation.cs +++ b/src/Types/CSSInterpolation.cs @@ -39,6 +39,6 @@ private CSSInterpolation(int index, CSSObject value0 = default, CSSInterpolation public string AsT2 => _index == 2 ? _value2 : - throw new InvalidOperationException($"Cannot return as T1 as result is T{_index}"); + throw new InvalidOperationException($"Cannot return as T2 as result is T{_index}"); } }