Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: CSSObject support css variable #11

Merged
merged 6 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions src/CSSObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace CssInCSharp
{
public sealed partial class CSSObject
{
private readonly Dictionary<string, CSSObject> _styles = new ();
private readonly Dictionary<string, CSSObject> _styles = new();
private readonly Dictionary<string, IProperty> _properties = new();
public Dictionary<string, IProperty> GetProperties() => _properties;
public Dictionary<string, CSSObject> GetStyles() => _styles;
Expand All @@ -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();

Expand All @@ -41,6 +41,12 @@ public 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)}}}");
}

Expand Down Expand Up @@ -93,6 +99,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<string>)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)
Expand Down
11 changes: 10 additions & 1 deletion src/Types/CSSInterpolation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 ?
Expand All @@ -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 T2 as result is T{_index}");
}
}
10 changes: 5 additions & 5 deletions src/Types/Functions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ internal static string FormatValue<T>(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<T>(string key, T value)
internal static string Wrap<T>(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";
}
Expand Down
63 changes: 63 additions & 0 deletions test/CssInCSharp.Tests/CSSObjectTests.cs
Original file line number Diff line number Diff line change
@@ -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;}}");
}
}
}
Loading