From 641937a5cfb2f21b6eaddb0dae5279c4dbc226aa Mon Sep 17 00:00:00 2001 From: Chanan Braunstein Date: Wed, 5 Jun 2019 21:09:29 -0600 Subject: [PATCH] Full port is done --- Polished.net.sln | 7 +- readme.md | 11 + .../Mixins/LinearGradient.cs | 17 + src/Polished.net.tests/Mixins/Normalize.cs | 18 + .../Mixins/RadialGradient.cs | 88 +++++ src/Polished.net.tests/Mixins/RetinaImage.cs | 58 +++ .../Mixins/TimingFunctions.cs | 202 ++++++++++ src/Polished.net.tests/Mixins/Triangle.cs | 207 ++++++++++ src/Polished.net.tests/Mixins/WordWrap.cs | 26 ++ src/Polished.net/IMixins.cs | 60 +++ src/Polished.net/Mixins.cs | 374 +++++++++++++++++- src/Polished.net/Polished.net.csproj | 2 +- .../RadialGradientConfiguration.cs | 13 + src/Polished.net/Side.cs | 6 +- src/Polished.net/TimingFunction.cs | 30 ++ src/Polished.net/TriangleConfiguration.cs | 11 + 16 files changed, 1124 insertions(+), 6 deletions(-) create mode 100644 readme.md create mode 100644 src/Polished.net.tests/Mixins/Normalize.cs create mode 100644 src/Polished.net.tests/Mixins/RadialGradient.cs create mode 100644 src/Polished.net.tests/Mixins/RetinaImage.cs create mode 100644 src/Polished.net.tests/Mixins/TimingFunctions.cs create mode 100644 src/Polished.net.tests/Mixins/Triangle.cs create mode 100644 src/Polished.net.tests/Mixins/WordWrap.cs create mode 100644 src/Polished.net/RadialGradientConfiguration.cs create mode 100644 src/Polished.net/TimingFunction.cs create mode 100644 src/Polished.net/TriangleConfiguration.cs diff --git a/Polished.net.sln b/Polished.net.sln index d686de8..29bbaeb 100644 --- a/Polished.net.sln +++ b/Polished.net.sln @@ -5,7 +5,12 @@ VisualStudioVersion = 16.0.28917.182 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Polished.net", "src\Polished.net\Polished.net.csproj", "{837A1FFD-D7C5-4EF4-BCA4-91CCB228201B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Polished.net.tests", "src\Polished.net.tests\Polished.net.tests.csproj", "{53BA05F1-DDC6-4C6D-BF43-125E2F2CAC01}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Polished.net.tests", "src\Polished.net.tests\Polished.net.tests.csproj", "{53BA05F1-DDC6-4C6D-BF43-125E2F2CAC01}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7D0A702B-44A7-4929-AE59-78EBC74F7686}" + ProjectSection(SolutionItems) = preProject + readme.md = readme.md + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..b298b07 --- /dev/null +++ b/readme.md @@ -0,0 +1,11 @@ +Polished.net +============ + +_A lightweight toolset for writing styles in C#_ + +Polished.net is a port of https://github.com/styled-components/polished (version 3.4.0) to C#. + +Docs +==== + +There are no docs yet for this version but the polished js docs maybe helpful: https://polished.js.org/ \ No newline at end of file diff --git a/src/Polished.net.tests/Mixins/LinearGradient.cs b/src/Polished.net.tests/Mixins/LinearGradient.cs index 3939d2a..418123b 100644 --- a/src/Polished.net.tests/Mixins/LinearGradient.cs +++ b/src/Polished.net.tests/Mixins/LinearGradient.cs @@ -31,5 +31,22 @@ public void Fallback() string expected = "background-color:#FFF;background-image:linear-gradient(to top right, #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%);"; Assert.AreEqual(expected, actual); } + + [TestMethod] + public void ThrowsIfColorStopsAreNull() + { + Assert.ThrowsException( + () => _mixins.LinearGradient(null, "#FFF") + ); + + } + + [TestMethod] + public void ThrowsIfColorStopsAreLessThan2() + { + Assert.ThrowsException( + () => _mixins.LinearGradient(new List { "#fff" }, "#fff") + ); + } } } diff --git a/src/Polished.net.tests/Mixins/Normalize.cs b/src/Polished.net.tests/Mixins/Normalize.cs new file mode 100644 index 0000000..17c1915 --- /dev/null +++ b/src/Polished.net.tests/Mixins/Normalize.cs @@ -0,0 +1,18 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Polished.Tests.Mixins +{ + [TestClass] + public class Normalize + { + private readonly IMixins _mixins = new Polished.Mixins(); + + [TestMethod] + public void NormalizeCss() + { + string actual = _mixins.Normalize(); + string expected = @"html { line-height: 1.15; -webkit-text-size-adjust: 100%; } body { margin: 0; } main { display: block; } h1 { font-size: 2em; margin: 0.67em 0; } hr { box-sizing: content-box; height: 0; overflow: visible; } pre { font-family: monospace, monospace; font-size: 1em; } a { background-color: transparent; } abbr[title] { border-bottom: none; text-decoration: underline; text-decoration: underline dotted; } b, strong { font-weight: bolder; } code, kbd, samp { font-family: monospace, monospace; font-size: 1em; } small { font-size: 80%; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } img { border-style: none; } button, input, optgroup, select, textarea { font-family: inherit; font-size: 100%; line-height: 1.15; margin: 0; } button, input { overflow: visible; } button, select { text-transform: none; } button, [type=""button""], [type=""reset""], [type=""submit""] { -webkit-appearance: button; } button::-moz-focus-inner, [type=""button""]::-moz-focus-inner, [type=""reset""]::-moz-focus-inner, [type=""submit""]::-moz-focus-inner { border-style: none; padding: 0; } button:-moz-focusring, [type=""button""]:-moz-focusring, [type=""reset""]:-moz-focusring, [type=""submit""]:-moz-focusring { outline: 1px dotted ButtonText; } fieldset { padding: 0.35em 0.75em 0.625em; } legend { box-sizing: border-box; color: inherit; display: table; max-width: 100%; padding: 0; white-space: normal; } progress { vertical-align: baseline; } textarea { overflow: auto; } [type=""checkbox""], [type=""radio""] { box-sizing: border-box; padding: 0; } [type=""number""]::-webkit-inner-spin-button, [type=""number""]::-webkit-outer-spin-button { height: auto; } [type=""search""] { -webkit-appearance: textfield; outline-offset: -2px; } [type=""search""]::-webkit-search-decoration { -webkit-appearance: none; } ::-webkit-file-upload-button { -webkit-appearance: button; font: inherit; } details { display: block; } summary { display: list-item; } template { display: none; } [hidden] { display: none; } "; + Assert.AreEqual(expected, actual); + } + } +} diff --git a/src/Polished.net.tests/Mixins/RadialGradient.cs b/src/Polished.net.tests/Mixins/RadialGradient.cs new file mode 100644 index 0000000..86b254f --- /dev/null +++ b/src/Polished.net.tests/Mixins/RadialGradient.cs @@ -0,0 +1,88 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Collections.Generic; + +namespace Polished.Tests.Mixins +{ + [TestClass] + public class RadialGradient + { + private readonly IMixins _mixins = new Polished.Mixins(); + + [TestMethod] + public void TwoColorStops() + { + string actual = _mixins.RadialGradient(new RadialGradientConfiguration { ColorStops = new List { "#fff", "#000" } }); + string expected = "background-color:#fff;background-image:radial-gradient(#fff, #000);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ExtentShapeAndPosition() + { + string actual = _mixins.RadialGradient(new RadialGradientConfiguration + { + ColorStops = new List { "#00FFFF 0%", "rgba(0, 0, 255, 0) 50%", "#0000FF 95%" }, + Extent = "farthest-corner at 45px 45px", + Position = "center", + Shape = "ellipse" + }); + string expected = "background-color:#00FFFF;background-image:radial-gradient(center ellipse farthest-corner at 45px 45px, #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ExtentAndShape() + { + string actual = _mixins.RadialGradient(new RadialGradientConfiguration + { + ColorStops = new List { "#00FFFF 0%", "rgba(0, 0, 255, 0) 50%", "#0000FF 95%" }, + Extent = "farthest-corner at 45px 45px", + Shape = "ellipse" + }); + string expected = "background-color:#00FFFF;background-image:radial-gradient(ellipse farthest-corner at 45px 45px, #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void Extent() + { + string actual = _mixins.RadialGradient(new RadialGradientConfiguration + { + ColorStops = new List { "#00FFFF 0%", "rgba(0, 0, 255, 0) 50%", "#0000FF 95%" }, + Extent = "farthest-corner at 45px 45px" + }); + string expected = "background-color:#00FFFF;background-image:radial-gradient(farthest-corner at 45px 45px, #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ExtentAndFallback() + { + string actual = _mixins.RadialGradient(new RadialGradientConfiguration + { + ColorStops = new List { "#00FFFF 0%", "rgba(0, 0, 255, 0) 50%", "#0000FF 95%" }, + Extent = "farthest-corner at 45px 45px", + Fallback = "#FFF" + }); + string expected = "background-color:#FFF;background-image:radial-gradient(farthest-corner at 45px 45px, #00FFFF 0%, rgba(0, 0, 255, 0) 50%, #0000FF 95%);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ThrowsIfColorStopsAreNull() + { + Assert.ThrowsException( + () => _mixins.RadialGradient(null, null, null, null, null) + ); + + } + + [TestMethod] + public void ThrowsIfColorStopsAreLessThan2() + { + Assert.ThrowsException( + () => _mixins.RadialGradient(new List { "#fff" }, null, null, null, null) + ); + } + } +} diff --git a/src/Polished.net.tests/Mixins/RetinaImage.cs b/src/Polished.net.tests/Mixins/RetinaImage.cs new file mode 100644 index 0000000..50729d1 --- /dev/null +++ b/src/Polished.net.tests/Mixins/RetinaImage.cs @@ -0,0 +1,58 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Polished.Tests.Mixins +{ + [TestClass] + public class RetinaImage + { + private readonly IMixins _mixins = new Polished.Mixins(); + + [TestMethod] + public void ShowThrowIfNoFilename() + { + Assert.ThrowsException( + () => _mixins.RetinaImage(null, null) + ); + } + + [TestMethod] + public void Filename() + { + string actual = _mixins.RetinaImage("img", null); + string expected = "background-image:url(img.png);@media only screen and (-webkit-min-device-pixel-ratio: 1.3),only screen and (min--moz-device-pixel-ratio: 1.3),only screen and (-o-min-device-pixel-ratio: 1.3/1),only screen and (min-resolution: 125dpi),only screen and (min-resolution: 1.3dppx){background-image:url(img_2x.png);}"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void FilenameAndCover() + { + string actual = _mixins.RetinaImage("img", "cover"); + string expected = "background-image:url(img.png);@media only screen and (-webkit-min-device-pixel-ratio: 1.3),only screen and (min--moz-device-pixel-ratio: 1.3),only screen and (-o-min-device-pixel-ratio: 1.3/1),only screen and (min-resolution: 125dpi),only screen and (min-resolution: 1.3dppx){background-image:url(img_2x.png);background-size:cover;}"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void FilenameAndExtension() + { + string actual = _mixins.RetinaImage("img", null, "jpg"); + string expected = "background-image:url(img.jpg);@media only screen and (-webkit-min-device-pixel-ratio: 1.3),only screen and (min--moz-device-pixel-ratio: 1.3),only screen and (-o-min-device-pixel-ratio: 1.3/1),only screen and (min-resolution: 125dpi),only screen and (min-resolution: 1.3dppx){background-image:url(img_2x.jpg);}"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void FilenameAndRetinaFilename() + { + string actual = _mixins.RetinaImage("img", null, null, "retina_img"); + string expected = "background-image:url(img.png);@media only screen and (-webkit-min-device-pixel-ratio: 1.3),only screen and (min--moz-device-pixel-ratio: 1.3),only screen and (-o-min-device-pixel-ratio: 1.3/1),only screen and (min-resolution: 125dpi),only screen and (min-resolution: 1.3dppx){background-image:url(retina_img.png);}"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void FilenameAndSuffix() + { + string actual = _mixins.RetinaImage("img", null, null, null, "_5x"); + string expected = "background-image:url(img.png);@media only screen and (-webkit-min-device-pixel-ratio: 1.3),only screen and (min--moz-device-pixel-ratio: 1.3),only screen and (-o-min-device-pixel-ratio: 1.3/1),only screen and (min-resolution: 125dpi),only screen and (min-resolution: 1.3dppx){background-image:url(img_5x.png);}"; + Assert.AreEqual(expected, actual); + } + } +} diff --git a/src/Polished.net.tests/Mixins/TimingFunctions.cs b/src/Polished.net.tests/Mixins/TimingFunctions.cs new file mode 100644 index 0000000..d44e880 --- /dev/null +++ b/src/Polished.net.tests/Mixins/TimingFunctions.cs @@ -0,0 +1,202 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Polished.Tests.Mixins +{ + [TestClass] + public class TimingFunctions + { + private readonly IMixins _mixins = new Polished.Mixins(); + + [TestMethod] + public void EaseInBack() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInBack)};"; + string expected = "transition-timing-function:cubic-bezier(0.600, -0.280, 0.735, 0.045);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInCirc() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInCirc)};"; + string expected = "transition-timing-function:cubic-bezier(0.600, 0.040, 0.980, 0.335);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInCubic() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInCubic)};"; + string expected = "transition-timing-function:cubic-bezier(0.550, 0.055, 0.675, 0.190);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInExpo() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInExpo)};"; + string expected = "transition-timing-function:cubic-bezier(0.950, 0.050, 0.795, 0.035);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInQuad() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInQuad)};"; + string expected = "transition-timing-function:cubic-bezier(0.550, 0.085, 0.680, 0.530);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInQuart() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInQuart)};"; + string expected = "transition-timing-function:cubic-bezier(0.895, 0.030, 0.685, 0.220);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInQuint() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInQuint)};"; + string expected = "transition-timing-function:cubic-bezier(0.755, 0.050, 0.855, 0.060);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInSine() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInSine)};"; + string expected = "transition-timing-function:cubic-bezier(0.470, 0.000, 0.745, 0.715);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseOutBack() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseOutBack)};"; + string expected = "transition-timing-function:cubic-bezier(0.175, 0.885, 0.320, 1.275);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseOutCubic() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseOutCubic)};"; + string expected = "transition-timing-function:cubic-bezier(0.215, 0.610, 0.355, 1.000);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseOutCirc() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseOutCirc)};"; + string expected = "transition-timing-function:cubic-bezier(0.075, 0.820, 0.165, 1.000);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseOutExpo() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseOutExpo)};"; + string expected = "transition-timing-function:cubic-bezier(0.190, 1.000, 0.220, 1.000);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseOutQuad() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseOutQuad)};"; + string expected = "transition-timing-function:cubic-bezier(0.250, 0.460, 0.450, 0.940);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseOutQuart() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseOutQuart)};"; + string expected = "transition-timing-function:cubic-bezier(0.165, 0.840, 0.440, 1.000);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseOutQuint() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseOutQuint)};"; + string expected = "transition-timing-function:cubic-bezier(0.230, 1.000, 0.320, 1.000);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseOutSine() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseOutSine)};"; + string expected = "transition-timing-function:cubic-bezier(0.390, 0.575, 0.565, 1.000);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInOutBack() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInOutBack)};"; + string expected = "transition-timing-function:cubic-bezier(0.680, -0.550, 0.265, 1.550);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInOutCirc() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInOutCirc)};"; + string expected = "transition-timing-function:cubic-bezier(0.785, 0.135, 0.150, 0.860);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInOutCubic() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInOutCubic)};"; + string expected = "transition-timing-function:cubic-bezier(0.645, 0.045, 0.355, 1.000);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInOutExpo() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInOutExpo)};"; + string expected = "transition-timing-function:cubic-bezier(1.000, 0.000, 0.000, 1.000);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInOutQuad() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInOutQuad)};"; + string expected = "transition-timing-function:cubic-bezier(0.455, 0.030, 0.515, 0.955);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInOutQuart() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInOutQuart)};"; + string expected = "transition-timing-function:cubic-bezier(0.770, 0.000, 0.175, 1.000);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInOutQuint() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInOutQuint)};"; + string expected = "transition-timing-function:cubic-bezier(0.860, 0.000, 0.070, 1.000);"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void EaseInOutSine() + { + string actual = $"transition-timing-function:{_mixins.TimingFunctions(TimingFunction.EaseInOutSine)};"; + string expected = "transition-timing-function:cubic-bezier(0.445, 0.050, 0.550, 0.950);"; + Assert.AreEqual(expected, actual); + } + } +} diff --git a/src/Polished.net.tests/Mixins/Triangle.cs b/src/Polished.net.tests/Mixins/Triangle.cs new file mode 100644 index 0000000..1d4102d --- /dev/null +++ b/src/Polished.net.tests/Mixins/Triangle.cs @@ -0,0 +1,207 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Polished.Tests.Mixins +{ + [TestClass] + public class Triangle + { + private readonly IMixins _mixins = new Polished.Mixins(); + + [TestMethod] + public void AllParamsNoUnits() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "red", + BackgroundColor = "black", + PointingDirection = Side.Right, + Height = "10", + Width = "20" + } + ); + string expected = "width:0;height:0;border-color:black black black red;border-style:solid;border-width:5 0 5 20;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void AllParamsWithUnits() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "red", + BackgroundColor = "black", + PointingDirection = Side.Right, + Height = "10em", + Width = "20em" + } + ); + string expected = "width:0;height:0;border-color:black black black red;border-style:solid;border-width:5em 0 5em 20em;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void AllParamsWithDoublesAndUnits() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "red", + BackgroundColor = "black", + PointingDirection = Side.Right, + Height = "10.5em", + Width = "20.5em" + } + ); + string expected = "width:0;height:0;border-color:black black black red;border-style:solid;border-width:5.25em 0 5.25em 20.5em;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void DefaultsToTransparent() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "red", + PointingDirection = Side.Right, + Height = "10px", + Width = "20px" + } + ); + string expected = "width:0;height:0;border-color:transparent transparent transparent red;border-style:solid;border-width:5px 0 5px 20px;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void TopArrow() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "green", + PointingDirection = Side.Top, + Height = "20px", + Width = "20px" + } + ); + string expected = "width:0;height:0;border-color:transparent transparent green transparent;border-style:solid;border-width:0 10px 20px 10px;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void RightArrow() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "red", + PointingDirection = Side.Right, + Height = "10px", + Width = "20px" + } + ); + string expected = "width:0;height:0;border-color:transparent transparent transparent red;border-style:solid;border-width:5px 0 5px 20px;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void BottomArrow() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "red", + PointingDirection = Side.Bottom, + Height = "20px", + Width = "10px" + } + ); + string expected = "width:0;height:0;border-color:red transparent transparent transparent;border-style:solid;border-width:20px 5px 0 5px;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void LeftArrow() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "blue", + PointingDirection = Side.Left, + Height = "20px", + Width = "10px" + } + ); + string expected = "width:0;height:0;border-color:transparent blue transparent transparent;border-style:solid;border-width:10px 10px 10px 0;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void TopRightArrow() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "blue", + PointingDirection = Side.TopRight, + Height = "20px", + Width = "20px" + } + ); + string expected = "width:0;height:0;border-color:transparent blue transparent transparent;border-style:solid;border-width:0 20px 20px 0;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void BottomRightArrow() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "blue", + PointingDirection = Side.BottomRight, + Height = "20px", + Width = "20px" + } + ); + string expected = "width:0;height:0;border-color:transparent transparent blue transparent;border-style:solid;border-width:0 0 20px 20px;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void BottomLeftArrow() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "blue", + PointingDirection = Side.BottomLeft, + Height = "20px", + Width = "20px" + } + ); + string expected = "width:0;height:0;border-color:transparent transparent transparent blue;border-style:solid;border-width:20px 0 0 20px;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void TopLeftArrow() + { + string actual = _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "blue", + PointingDirection = Side.TopLeft, + Height = "20px", + Width = "20px" + } + ); + string expected = "width:0;height:0;border-color:blue transparent transparent transparent;border-style:solid;border-width:20px 20px 0 0;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ThrowsWhenHeightOrWidthNotNumbers() + { + Assert.ThrowsException( + () => _mixins.Triangle(new TriangleConfiguration + { + ForegroundColor = "blue", + PointingDirection = Side.TopLeft, + Height = "inherit", + Width = "inherit" + }) + ); + } + } +} diff --git a/src/Polished.net.tests/Mixins/WordWrap.cs b/src/Polished.net.tests/Mixins/WordWrap.cs new file mode 100644 index 0000000..b860e93 --- /dev/null +++ b/src/Polished.net.tests/Mixins/WordWrap.cs @@ -0,0 +1,26 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Polished.Tests.Mixins +{ + [TestClass] + public class WordWrap + { + private readonly IMixins _mixins = new Polished.Mixins(); + + [TestMethod] + public void Default() + { + string actual = _mixins.WordWrap(); + string expected = "overflow-wrap:break-word;word-wrap:break-word;word-break:break-all;"; + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void BreakAll() + { + string actual = _mixins.WordWrap("break-all"); + string expected = "overflow-wrap:break-all;word-wrap:break-all;word-break:break-all;"; + Assert.AreEqual(expected, actual); + } + } +} diff --git a/src/Polished.net/IMixins.cs b/src/Polished.net/IMixins.cs index f9189fa..ab9ae95 100644 --- a/src/Polished.net/IMixins.cs +++ b/src/Polished.net/IMixins.cs @@ -115,5 +115,65 @@ public interface IMixins /// /// string LinearGradient(System.Collections.Generic.List colorStops, string fallback, string toDirection = ""); + + /// + /// CSS to normalize abnormalities across browsers (normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css) + /// + /// + string Normalize(); + + /// + /// CSS for declaring a radial gradient, including a fallback background-color. + /// The fallback is either the first color-stop or an explicitly passed fallback color. + /// + /// + /// + string RadialGradient(RadialGradientConfiguration radialGradientConfiguration); + + /// + /// CSS for declaring a radial gradient, including a fallback background-color. + /// The fallback is either the first color-stop or an explicitly passed fallback color. + /// + /// + /// + /// + /// + /// + /// + string RadialGradient(System.Collections.Generic.List colorStops, string extent, string fallback, string position, string shape); + + /// + /// A helper to generate a retina background image and non-retina + /// background image.The retina background image will output to a HiDPI media query. The mixin uses + /// a _2x.png filename suffix by default. + /// + /// + /// + /// + /// + /// + /// + string RetinaImage(string filename, string backgroundSize, string extension = "png", string retinaFilename = "", string retinaSuffix = "_2x"); + + /// + /// String to represent common easing functions as demonstrated here: (github.com/jaukia/easie). + /// + /// + /// + string TimingFunctions(TimingFunction timingFunction); + + /// + /// CSS to represent triangle with any pointing direction with an optional background color. + /// + /// + /// + string Triangle(TriangleConfiguration triangleConfiguration); + + /// + /// Provides an easy way to change the `wordWrap` property. + /// + /// + /// + string WordWrap(string wrap = "break-word"); } } \ No newline at end of file diff --git a/src/Polished.net/Mixins.cs b/src/Polished.net/Mixins.cs index 8410b5b..3251fba 100644 --- a/src/Polished.net/Mixins.cs +++ b/src/Polished.net/Mixins.cs @@ -1,4 +1,5 @@ -using System; +using Polished.Internal; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -20,6 +21,34 @@ public class Mixins : IMixins { "svgz", "svg" }, }; + private readonly Dictionary _timingMap = new Dictionary + { + {TimingFunction.EaseInBack,"cubic-bezier(0.600, -0.280, 0.735, 0.045)"}, + {TimingFunction.EaseInCirc,"cubic-bezier(0.600, 0.040, 0.980, 0.335)"}, + {TimingFunction.EaseInCubic,"cubic-bezier(0.550, 0.055, 0.675, 0.190)"}, + {TimingFunction.EaseInExpo,"cubic-bezier(0.950, 0.050, 0.795, 0.035)"}, + {TimingFunction.EaseInQuad,"cubic-bezier(0.550, 0.085, 0.680, 0.530)"}, + {TimingFunction.EaseInQuart,"cubic-bezier(0.895, 0.030, 0.685, 0.220)"}, + {TimingFunction.EaseInQuint,"cubic-bezier(0.755, 0.050, 0.855, 0.060)"}, + {TimingFunction.EaseInSine,"cubic-bezier(0.470, 0.000, 0.745, 0.715)"}, + {TimingFunction.EaseOutBack,"cubic-bezier(0.175, 0.885, 0.320, 1.275)"}, + {TimingFunction.EaseOutCubic,"cubic-bezier(0.215, 0.610, 0.355, 1.000)"}, + {TimingFunction.EaseOutCirc,"cubic-bezier(0.075, 0.820, 0.165, 1.000)"}, + {TimingFunction.EaseOutExpo,"cubic-bezier(0.190, 1.000, 0.220, 1.000)"}, + {TimingFunction.EaseOutQuad,"cubic-bezier(0.250, 0.460, 0.450, 0.940)"}, + {TimingFunction.EaseOutQuart,"cubic-bezier(0.165, 0.840, 0.440, 1.000)"}, + {TimingFunction.EaseOutQuint,"cubic-bezier(0.230, 1.000, 0.320, 1.000)"}, + {TimingFunction.EaseOutSine,"cubic-bezier(0.390, 0.575, 0.565, 1.000)"}, + {TimingFunction.EaseInOutBack,"cubic-bezier(0.680, -0.550, 0.265, 1.550)"}, + {TimingFunction.EaseInOutCirc,"cubic-bezier(0.785, 0.135, 0.150, 0.860)"}, + {TimingFunction.EaseInOutCubic,"cubic-bezier(0.645, 0.045, 0.355, 1.000)"}, + {TimingFunction.EaseInOutExpo,"cubic-bezier(1.000, 0.000, 0.000, 1.000)"}, + {TimingFunction.EaseInOutQuad,"cubic-bezier(0.455, 0.030, 0.515, 0.955)"}, + {TimingFunction.EaseInOutQuart,"cubic-bezier(0.770, 0.000, 0.175, 1.000)"}, + {TimingFunction.EaseInOutQuint,"cubic-bezier(0.860, 0.000, 0.070, 1.000)"}, + {TimingFunction.EaseInOutSine,"cubic-bezier(0.445, 0.050, 0.550, 0.950)"} + }; + /// public string Between(string fromSize, string toSize, string minScreen = "320px", string maxScreen = "1200px") { @@ -241,8 +270,6 @@ public string LinearGradient(List colorStops, string fallback, string to throw PolishedException.GetPolishedException(56); } - //TODO: Not sure how constructGradientValue https://github.com/styled-components/polished/blob/master/src/internalHelpers/_constructGradientValue.js - //fits in here. StringBuilder sb = new StringBuilder(); sb.Append("background-color:").Append(fallback ?? colorStops[0].Split(' ')[0]).Append(";"); sb.Append("background-image:").Append("linear-gradient("); @@ -256,6 +283,347 @@ public string LinearGradient(List colorStops, string fallback, string to return sb.ToString(); } + /// + public string Normalize() + { + return @"html { + line-height: 1.15; + -webkit-text-size-adjust: 100%; + } + + body { + margin: 0; + } + + main { + display: block; + } + + h1 { + font-size: 2em; + margin: 0.67em 0; + } + + hr { + box-sizing: content-box; + height: 0; + overflow: visible; + } + + pre { + font-family: monospace, monospace; + font-size: 1em; + } + + a { + background-color: transparent; + } + + abbr[title] { + border-bottom: none; + text-decoration: underline; + text-decoration: underline dotted; + } + + b, + strong { + font-weight: bolder; + } + + code, + kbd, + samp { + font-family: monospace, monospace; + font-size: 1em; + } + + small { + font-size: 80%; + } + + sub, + sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; + } + + sub { + bottom: -0.25em; + } + + sup { + top: -0.5em; + } + + img { + border-style: none; + } + + button, + input, + optgroup, + select, + textarea { + font-family: inherit; + font-size: 100%; + line-height: 1.15; + margin: 0; + } + + button, + input { + overflow: visible; + } + + button, + select { + text-transform: none; + } + + button, + [type=""button""], + [type=""reset""], + [type=""submit""] { + -webkit-appearance: button; + } + + button::-moz-focus-inner, + [type=""button""]::-moz-focus-inner, + [type=""reset""]::-moz-focus-inner, + [type=""submit""]::-moz-focus-inner { + border-style: none; + padding: 0; + } + + button:-moz-focusring, + [type=""button""]:-moz-focusring, + [type=""reset""]:-moz-focusring, + [type=""submit""]:-moz-focusring { + outline: 1px dotted ButtonText; + } + + fieldset { + padding: 0.35em 0.75em 0.625em; + } + + legend { + box-sizing: border-box; + color: inherit; + display: table; + max-width: 100%; + padding: 0; + white-space: normal; + } + + progress { + vertical-align: baseline; + } + + textarea { + overflow: auto; + } + + [type=""checkbox""], + [type=""radio""] { + box-sizing: border-box; + padding: 0; + } + + [type=""number""]::-webkit-inner-spin-button, + [type=""number""]::-webkit-outer-spin-button { + height: auto; + } + + [type=""search""] { + -webkit-appearance: textfield; + outline-offset: -2px; + } + + [type=""search""]::-webkit-search-decoration { + -webkit-appearance: none; + } + + ::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; + } + + details { + display: block; + } + + summary { + display: list-item; + } + + template { + display: none; + } + + [hidden] { + display: none; + } + ".StripWhitespace(); + } + + /// + public string RadialGradient(RadialGradientConfiguration radialGradientConfiguration) + { + return RadialGradient(radialGradientConfiguration.ColorStops, radialGradientConfiguration.Extent, + radialGradientConfiguration.Fallback, radialGradientConfiguration.Position, radialGradientConfiguration.Shape); + } + + /// + public string RadialGradient(List colorStops, string extent, string fallback, string position, string shape) + { + if (colorStops == null || colorStops.Count < 2) + { + throw PolishedException.GetPolishedException(57); + } + + StringBuilder sb = new StringBuilder(); + sb.Append("background-color:").Append(fallback ?? colorStops[0].Split(' ')[0]).Append(";"); + sb.Append("background-image:").Append("radial-gradient("); + sb.Append(RadialGradientFirstValue(position, shape, extent)); + sb.Append(string.Join(", ", colorStops)); + sb.Append(");"); + return sb.ToString(); + } + + /// + public string RetinaImage(string filename, string backgroundSize, string extension = "png", string retinaFilename = "", string retinaSuffix = "_2x") + { + if (string.IsNullOrWhiteSpace(filename)) + { + throw PolishedException.GetPolishedException(58); + } + + string ext = string.IsNullOrWhiteSpace(extension) ? "png" : extension.Replace(".", ""); + string rFilename = !string.IsNullOrWhiteSpace(retinaFilename) ? $"{retinaFilename}.{ext}" : $"{filename}{retinaSuffix}.{ext}"; + string rBackgroundSize = !string.IsNullOrWhiteSpace(backgroundSize) ? $"background-size:{backgroundSize};" : ""; + return $"background-image:url({filename}.{ext});{HiDPI()}{{background-image:url({rFilename});{rBackgroundSize}}}"; + } + + /// + public string TimingFunctions(TimingFunction timingFunction) + { + return _timingMap[timingFunction]; + } + + /// + public string Triangle(TriangleConfiguration triangleConfiguration) + { + return Triangle(triangleConfiguration.PointingDirection, triangleConfiguration.Height, triangleConfiguration.Width, + triangleConfiguration.ForegroundColor, triangleConfiguration.BackgroundColor); + } + + /// + public string Triangle(Side pointingDirection, string height, string width, string foregroundColor, string backgroundColor = "transparent") + { + ValueAndUnit heightAndUnit = _helpers.GetValueAndUnit(height); + ValueAndUnit widthAndUnit = _helpers.GetValueAndUnit(width); + if (!double.TryParse(heightAndUnit.Value, out double h) || !double.TryParse(widthAndUnit.Value, out double w)) + { + throw PolishedException.GetPolishedException(60); + } + string backgourndColorDefault = !string.IsNullOrWhiteSpace(backgroundColor) ? backgroundColor : "transparent"; + StringBuilder sb = new StringBuilder(); + sb.Append("width:0;"); + sb.Append("height:0;"); + sb.Append("border-color:").Append(GetBorderColor(pointingDirection, foregroundColor, backgourndColorDefault)).Append(";"); + sb.Append("border-style:solid;"); + sb.Append("border-width:").Append(GetBorderWidth(pointingDirection, heightAndUnit, widthAndUnit)).Append(";"); + return sb.ToString(); + } + + /// + public string WordWrap(string wrap = "break-word") + { + string wrapDefault = !string.IsNullOrWhiteSpace(wrap) ? wrap : "break-word"; + string wordBreak = wrapDefault == "break-word" ? "break-all" : wrapDefault; + return $"overflow-wrap:{wrapDefault};word-wrap:{wrapDefault};word-break:{wordBreak};"; + } + + private string GetBorderWidth(Side pointingDirection, ValueAndUnit heightAndUnit, ValueAndUnit widthAndUnit) + { + string fullWidth = $"{widthAndUnit.Value}{widthAndUnit.Unit}"; + string halfWidth = $"{double.Parse(widthAndUnit.Value) / 2}{widthAndUnit.Unit}"; + string fullHeight = $"{heightAndUnit.Value}{heightAndUnit.Unit}"; + string halfHeight = $"{double.Parse(heightAndUnit.Value) / 2}{heightAndUnit.Unit}"; + + switch (pointingDirection) + { + case Side.Top: + return $"0 {halfWidth} {fullHeight} {halfWidth}"; + case Side.TopLeft: + return $"{fullWidth} {fullHeight} 0 0"; + case Side.Left: + return $"{halfHeight} {fullWidth} {halfHeight} 0"; + case Side.BottomLeft: + return $"{fullWidth} 0 0 {fullHeight}"; + case Side.Bottom: + return $"{fullHeight} {halfWidth} 0 {halfWidth}"; + case Side.BottomRight: + return $"0 0 {fullWidth} {fullHeight}"; + case Side.Right: + return $"{halfHeight} 0 {halfHeight} {fullWidth}"; + case Side.TopRight: + default: + return $"0 {fullWidth} {fullHeight} 0"; + } + } + + private string GetBorderColor(Side pointingDirection, string foregroundColor, string backgroundColor) + { + switch (pointingDirection) + { + case Side.Top: + case Side.BottomRight: + return $"{backgroundColor} {backgroundColor} {foregroundColor} {backgroundColor}"; + case Side.Right: + case Side.BottomLeft: + return $"{backgroundColor} {backgroundColor} {backgroundColor} {foregroundColor}"; + case Side.Bottom: + case Side.TopLeft: + return $"{foregroundColor} {backgroundColor} {backgroundColor} {backgroundColor}"; + case Side.Left: + case Side.TopRight: + default: + return $"{backgroundColor} {foregroundColor} {backgroundColor} {backgroundColor}"; + } + } + + private string RadialGradientFirstValue(string position, string shape, string extent) + { + StringBuilder sb = new StringBuilder(); + if (!string.IsNullOrWhiteSpace(position)) + { + sb.Append(position).Append(" "); + } + + if (!string.IsNullOrWhiteSpace(shape)) + { + sb.Append(shape).Append(" "); + } + + if (!string.IsNullOrWhiteSpace(extent)) + { + sb.Append(extent).Append(" "); + } + + string ret = sb.ToString(); + if (string.IsNullOrWhiteSpace(ret)) + { + return string.Empty; + } + else + { + return ret.Substring(0, ret.Length - 1) + ", "; + } + } + private string GenerateSources(string fontFilePath, List localFonts, List fileFormats, bool formatHint) { List fontReferences = new List(); diff --git a/src/Polished.net/Polished.net.csproj b/src/Polished.net/Polished.net.csproj index 07b9372..e33a9ad 100644 --- a/src/Polished.net/Polished.net.csproj +++ b/src/Polished.net/Polished.net.csproj @@ -5,7 +5,7 @@ Polished Polished - 1.0.0-preview-01 + 1.0.0-preview-02 Chanan Braunstein Polished.net A lightweight toolset for writing styles in C# diff --git a/src/Polished.net/RadialGradientConfiguration.cs b/src/Polished.net/RadialGradientConfiguration.cs new file mode 100644 index 0000000..84a1f39 --- /dev/null +++ b/src/Polished.net/RadialGradientConfiguration.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace Polished +{ + public class RadialGradientConfiguration + { + public List ColorStops { get; set; } + public string Extent { get; set; } + public string Fallback { get; set; } + public string Position { get; set; } + public string Shape { get; set; } + } +} diff --git a/src/Polished.net/Side.cs b/src/Polished.net/Side.cs index c1fa8fb..46789fc 100644 --- a/src/Polished.net/Side.cs +++ b/src/Polished.net/Side.cs @@ -3,8 +3,12 @@ public enum Side { Top, + TopRight, Right, + BottomRight, Bottom, - Left + BottomLeft, + Left, + TopLeft } } diff --git a/src/Polished.net/TimingFunction.cs b/src/Polished.net/TimingFunction.cs new file mode 100644 index 0000000..bd564e4 --- /dev/null +++ b/src/Polished.net/TimingFunction.cs @@ -0,0 +1,30 @@ +namespace Polished +{ + public enum TimingFunction + { + EaseInBack, + EaseInCirc, + EaseInCubic, + EaseInExpo, + EaseInQuad, + EaseInQuart, + EaseInQuint, + EaseInSine, + EaseOutBack, + EaseOutCubic, + EaseOutCirc, + EaseOutExpo, + EaseOutQuad, + EaseOutQuart, + EaseOutQuint, + EaseOutSine, + EaseInOutBack, + EaseInOutCirc, + EaseInOutCubic, + EaseInOutExpo, + EaseInOutQuad, + EaseInOutQuart, + EaseInOutQuint, + EaseInOutSine + } +} diff --git a/src/Polished.net/TriangleConfiguration.cs b/src/Polished.net/TriangleConfiguration.cs new file mode 100644 index 0000000..f1ece35 --- /dev/null +++ b/src/Polished.net/TriangleConfiguration.cs @@ -0,0 +1,11 @@ +namespace Polished +{ + public class TriangleConfiguration + { + public string BackgroundColor { get; set; } + public string ForegroundColor { get; set; } + public string Height { get; set; } + public string Width { get; set; } + public Side PointingDirection { get; set; } + } +}