diff --git a/ZenCoding.Test/Html/LoremPixel.cs b/ZenCoding.Test/Html/LoremPixel.cs index 8f6c7c8..c0cc9ec 100644 --- a/ZenCoding.Test/Html/LoremPixel.cs +++ b/ZenCoding.Test/Html/LoremPixel.cs @@ -14,7 +14,7 @@ public void Initialize() } [TestMethod] - public void LoremPixel1() + public void LoremPixelBasic() { string result = _parser.Parse("pix", ZenType.HTML); string expected = "\"\""; @@ -23,7 +23,7 @@ public void LoremPixel1() } [TestMethod] - public void LoremPixel2() + public void LoremPixelGrayScale() { string result = _parser.Parse("pix-g", ZenType.HTML); string expected = "\"\""; @@ -32,7 +32,16 @@ public void LoremPixel2() } [TestMethod] - public void LoremPixel3() + public void LoremPixelSingleDimension() + { + string result = _parser.Parse("pix-40", ZenType.HTML); + string expected = "\"\""; + + Assert.AreEqual(expected, result); + } + + [TestMethod] + public void LoremPixelCategory() { string result = _parser.Parse("pix-120x1879-sports-SomeRandomText", ZenType.HTML); string expectedStart = "http://lorempixel.com/120/1879/sports/"; @@ -43,7 +52,7 @@ public void LoremPixel3() } [TestMethod] - public void LoremPixel4() + public void LoremPixelText() { string result = _parser.Parse("pix-g-999x1920-animals-SomeRandomText", ZenType.HTML); @@ -55,7 +64,7 @@ public void LoremPixel4() } [TestMethod] - public void LoremPixel5() + public void LoremPixelOverflowedDimensions() { string result = _parser.Parse("pix-20000x3599-SomeRandomText", ZenType.HTML); string expected = "\"\""; // the allowed bound is 0-1920 @@ -64,13 +73,12 @@ public void LoremPixel5() } [TestMethod] - public void LoremPixelWithAttributes() + public void LoremPixelWithAttributesWithMarkup() { string result = _parser.Parse("pix[alt=\"tag's here\" title=\"picture title\" data-foo=\"bar\"]", ZenType.HTML); string expected = "\"tag's"; Assert.AreEqual(expected, result); } - } } diff --git a/ZenCoding.Test/Html/Placehold.cs b/ZenCoding.Test/Html/Placehold.cs index b074795..8f15e38 100644 --- a/ZenCoding.Test/Html/Placehold.cs +++ b/ZenCoding.Test/Html/Placehold.cs @@ -14,7 +14,7 @@ public void Initialize() } [TestMethod] - public void PlaceHold1() + public void PlaceHoldBasic() { string result = _parser.Parse("place", ZenType.HTML); string expected = "\"\""; @@ -23,7 +23,7 @@ public void PlaceHold1() } [TestMethod] - public void PlaceHold2() + public void PlaceHoldFormat() { string result = _parser.Parse("place-30-png", ZenType.HTML); string expected = "\"\""; @@ -32,26 +32,26 @@ public void PlaceHold2() } [TestMethod] - public void PlaceHold3() + public void PlaceHoldText() { - string result = _parser.Parse("place-120x1879-jpeg-t=SomeRandomText", ZenType.HTML); - string expected = "http://placehold.it/120x1879/jpeg/&text=SomeRandomText"; + string result = _parser.Parse("place-120x1879-jpeg-t=Some%20Random%20Text=", ZenType.HTML); + string expected = "http://placehold.it/120x1879/jpeg/&text=Some%20Random%20Text="; // Text is: "Some Random Text=" StringAssert.Contains(result, expected); } [TestMethod] - public void PlaceHold4() + public void PlaceHoldColors() { - string result = _parser.Parse("place-999x1920-EEE-FFFFFF-t=Some%20Random%20Text", ZenType.HTML); + string result = _parser.Parse("place-999x1920-EEE-FFFFFF-t=Some%20Random%20Text!", ZenType.HTML); - string expected = "http://placehold.it/999x1920/EEE/FFFFFF/&text=Some%20Random%20Text"; + string expected = "http://placehold.it/999x1920/EEE/FFFFFF/&text=Some%20Random%20Text!"; StringAssert.Contains(result, expected); } [TestMethod] - public void PlaceHold5() + public void PlaceHoldOverflowedDimensions() { string result = _parser.Parse("place-20000x3599-t=SomeRandomText", ZenType.HTML); string expected = "\"\""; // the allowed bound is 0-1920 diff --git a/ZenCoding/Commons/IParser.cs b/ZenCoding/Commons/IParser.cs new file mode 100644 index 0000000..531ce16 --- /dev/null +++ b/ZenCoding/Commons/IParser.cs @@ -0,0 +1,7 @@ +namespace ZenCoding +{ + interface IZenParser + { + string Parse(string zenSyntax); + } +} \ No newline at end of file diff --git a/ZenCoding/Css/CssParser.cs b/ZenCoding/Css/CssParser.cs index c8f5dae..0d6dde8 100644 --- a/ZenCoding/Css/CssParser.cs +++ b/ZenCoding/Css/CssParser.cs @@ -2,7 +2,7 @@ namespace ZenCoding { - public class CssParser + public class CssParser : IZenParser { public string Parse(string zenSyntax) { diff --git a/ZenCoding/Helpers/Extensions.cs b/ZenCoding/Helpers/Extensions.cs index 87a6b13..3a13dbb 100644 --- a/ZenCoding/Helpers/Extensions.cs +++ b/ZenCoding/Helpers/Extensions.cs @@ -1,5 +1,4 @@ - -namespace ZenCoding +namespace ZenCoding { public static class Extensions { @@ -10,4 +9,4 @@ public static bool IsHex(this char value) (value >= 'A' && value <= 'F'); } } -} +} \ No newline at end of file diff --git a/ZenCoding/Html/CustomHtmlAnchor.cs b/ZenCoding/Html/CustomHtmlAnchor.cs index 3518a6a..257cb31 100644 --- a/ZenCoding/Html/CustomHtmlAnchor.cs +++ b/ZenCoding/Html/CustomHtmlAnchor.cs @@ -2,7 +2,7 @@ using System.Web.UI; using System.Web.UI.HtmlControls; -namespace ZenCoding.Html +namespace ZenCoding { public class CustomHtmlAnchor : HtmlAnchor { diff --git a/ZenCoding/Html/CustomHtmlImage.cs b/ZenCoding/Html/CustomHtmlImage.cs index 16e34ce..f4d92fe 100644 --- a/ZenCoding/Html/CustomHtmlImage.cs +++ b/ZenCoding/Html/CustomHtmlImage.cs @@ -2,7 +2,7 @@ using System.Web.UI; using System.Web.UI.HtmlControls; -namespace ZenCoding.Html +namespace ZenCoding { public class CustomHtmlImage : HtmlImage { diff --git a/ZenCoding/Html/CustomHtmlTextArea.cs b/ZenCoding/Html/CustomHtmlTextArea.cs index 41b2ec4..d752849 100644 --- a/ZenCoding/Html/CustomHtmlTextArea.cs +++ b/ZenCoding/Html/CustomHtmlTextArea.cs @@ -2,7 +2,7 @@ using System.Web.UI; using System.Web.UI.HtmlControls; -namespace ZenCoding.Html +namespace ZenCoding { class CustomHtmlTextArea : HtmlTextArea { diff --git a/ZenCoding/Html/HtmlElementFactory.cs b/ZenCoding/Html/HtmlElementFactory.cs index e2a1dc7..76973ae 100644 --- a/ZenCoding/Html/HtmlElementFactory.cs +++ b/ZenCoding/Html/HtmlElementFactory.cs @@ -5,7 +5,6 @@ using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; -using ZenCoding.Html; namespace ZenCoding { @@ -84,6 +83,16 @@ public static HtmlControl Create(string tagName, Type type, bool isClone) if (tagName == null) return null; + HtmlControl control = TryCreateSepcialControl(tagName, type, isClone); + + if (control != null) + return control; + + return new BlockHtmlControl(tagName); + } + + private static HtmlControl TryCreateSepcialControl(string tagName, Type type, bool isClone) + { if (tagName.StartsWith("lorem", System.StringComparison.Ordinal) || (type == typeof(LoremControl) && isClone)) { @@ -98,6 +107,11 @@ public static HtmlControl Create(string tagName, Type type, bool isClone) return new PlaceHold(tagName); } + return TryCreateFromStateMachine(tagName); + } + + private static HtmlControl TryCreateFromStateMachine(string tagName) + { switch (tagName) { case "": @@ -267,10 +281,10 @@ public static HtmlControl Create(string tagName, Type type, bool isClone) return new HtmlGenericSelfClosing(tagName); } - return new BlockHtmlControl(tagName); + return null; } - public static Control CreateDoctypes(string part, ref List current) + public static Control CreateDoctypes(string part, ref IEnumerable current) { if (part == null) return null; @@ -306,7 +320,7 @@ public static Control CreateDoctypes(string part, ref List current) using (HtmlControl body = HtmlElementFactory.Create("body")) { html.Controls.Add(body); - current = new List() { body }; + current = new Control[] { body }; } return root; } diff --git a/ZenCoding/Html/HtmlParser.cs b/ZenCoding/Html/HtmlParser.cs index ded1cf5..ed8af20 100644 --- a/ZenCoding/Html/HtmlParser.cs +++ b/ZenCoding/Html/HtmlParser.cs @@ -10,7 +10,7 @@ namespace ZenCoding { - public class HtmlParser + public class HtmlParser : IZenParser { private static char[] _attr = new[] { '#', '.', '[', '{' }; private static char[] _elem = new[] { '>', '+', '^' }; @@ -20,25 +20,27 @@ public class HtmlParser public static bool IsValid(string zenSyntax) { - if (zenSyntax == null || zenSyntax.Length == 0 || zenSyntax.StartsWith("asp:", StringComparison.OrdinalIgnoreCase)) + if (string.IsNullOrEmpty(zenSyntax) || zenSyntax.StartsWith("asp:", StringComparison.OrdinalIgnoreCase)) return false; int indexSpace = zenSyntax.IndexOf(' '); + if (indexSpace > -1 && (indexSpace < zenSyntax.IndexOfAny(new[] { '[', '{', '"' }) || indexSpace > zenSyntax.LastIndexOfAny(new[] { ']', '}', '"' }))) return false; - if (zenSyntax.Contains("{") || zenSyntax.Contains("}")) - { - if (zenSyntax.Count(c => c == '{') != zenSyntax.Count(c => c == '}')) - return false; - } + if ((zenSyntax.Contains("{") || zenSyntax.Contains("}")) && (zenSyntax.Count(c => c == '{') != zenSyntax.Count(c => c == '}'))) + return false; if (zenSyntax.Contains("<") || zenSyntax.Contains("|") || zenSyntax.Contains("@")) return false; - char last = zenSyntax.Last(); - if (!char.IsLetterOrDigit(last) && last != ']' && last != '}' && last != '+' && !char.IsWhiteSpace(last)) - return false; + if (!zenSyntax.StartsWith("place", StringComparison.CurrentCultureIgnoreCase)) + { + char last = zenSyntax.Last(); + + if (!char.IsLetterOrDigit(last) && last != ']' && last != '}' && last != '+' && !char.IsWhiteSpace(last)) + return false; + } if (zenSyntax.Count(z => z == ']') != zenSyntax.Count(z => z == '[')) return false; @@ -114,13 +116,13 @@ public static string ParseGroup(string zenSyntax) if (!IsValidHtmlElements(parts)) return string.Empty; - List current = new List() { root }; + IEnumerable current = new Control[] { root }; HandleDoctypes(ref root, parts, ref current); if (root == null) return null; - BuildControlTree(CloneStack(parts), current[0], -1); + BuildControlTree(CloneStack(parts), current.First(), -1); return RenderControl(root); } @@ -133,7 +135,7 @@ public static string ParseGroup(string zenSyntax) } } - private static void HandleDoctypes(ref Control root, List parts, ref List current) + private static void HandleDoctypes(ref Control root, List parts, ref IEnumerable current) { if (parts[0] == "html:4t" || parts[0] == "html:4s" || parts[0] == "html:xt" || parts[0] == "html:xs" || parts[0] == "html:xxs" || parts[0] == "html:5") { @@ -154,7 +156,7 @@ private static void AdjustImplicitTagNames(List parts) currentDefault = "span"; else if (i != 0 && parts[i - 1] == "table" && parts[i][0] == '>') currentDefault = "tr"; - else if (i != 0 && (parts[i - 1] == "tr" || parts[i - 1].StartsWith(">tr")) && parts[i][0] == '>') + else if (i != 0 && (parts[i - 1] == "tr" || parts[i - 1].StartsWith(">tr", StringComparison.CurrentCultureIgnoreCase)) && parts[i][0] == '>') currentDefault = "td"; else if ((parts[i][0] == '>' && currentDefault == "td") || (currentDefault != "div" && parts[i][0] == '^')) currentDefault = "div"; @@ -415,7 +417,7 @@ private static int GetCountAndName(string part, out string cleanPart, char[] sym int index = part.IndexOf('*'); int count = 1; - if (index > -1 && part.Length > index && !char.IsNumber(part[index + 1])) + if (index > -1 && part.Length > index + 1 && !char.IsNumber(part[index + 1])) index = -1; if (index > -1 && int.TryParse(part.Substring(index + 1), out count)) diff --git a/ZenCoding/Html/LoremPixel.cs b/ZenCoding/Html/LoremPixel.cs index b562f98..1e301ae 100644 --- a/ZenCoding/Html/LoremPixel.cs +++ b/ZenCoding/Html/LoremPixel.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Text; -using ZenCoding.Html; namespace ZenCoding { @@ -26,50 +25,47 @@ public override void Generate(string pixText) parts = pixText == null ? new string[] { } : pixText.Split('-'); - try + if (parts.Length > 1) { - if (parts.Length > 1) + if (parts[1].Equals("g")) { - if (parts[1].Equals("g")) - { - this.IsGray = true; + this.IsGray = true; + + if (parts.Length > 2) dimensions = parts[2]; - } - else - { - dimensions = parts[1]; - } + } + else + { + dimensions = parts[1]; + } - SetDimensions(dimensions); + SetDimensions(dimensions); - if (parts.Length > 2) + if (parts.Length > 2) + { + if (this.IsGray) { - if (this.IsGray) + category = parts[3]; + if (parts.Length > 4) { - category = parts[3]; - if (parts.Length > 4) - { - text = parts[4]; - } + text = parts[4]; } - else - { - category = parts[2]; - if (parts.Length > 3) - { - text = parts[3]; - } - } - if (_categories.Contains(category)) + } + else + { + category = parts[2]; + if (parts.Length > 3) { - this.Category = category; - this.Text = text; + text = parts[3]; } } + if (_categories.Contains(category)) + { + this.Category = category; + this.Text = text; + } } } - catch - { } this.AssetWidth = this.AssetWidth % 1921; this.AssetHeight = this.AssetHeight % 1921; diff --git a/ZenCoding/Html/PixelBase.cs b/ZenCoding/Html/PixelBase.cs index b9763cc..7409264 100644 --- a/ZenCoding/Html/PixelBase.cs +++ b/ZenCoding/Html/PixelBase.cs @@ -2,7 +2,7 @@ using System.Globalization; using System.Text.RegularExpressions; -namespace ZenCoding.Html +namespace ZenCoding { public abstract class PixelBase : CustomHtmlImage { @@ -11,7 +11,7 @@ public abstract class PixelBase : CustomHtmlImage public int AssetWidth { get; set; } public int AssetHeight { get; set; } - public PixelBase() + protected PixelBase() { Initialize(); } @@ -22,6 +22,9 @@ public PixelBase() protected void SetDimensions(string slug) { + if (string.IsNullOrEmpty(slug)) + return; + var dimensions = _numberExtractor.Split(slug); if (ValidateIntegers(dimensions)) @@ -43,7 +46,7 @@ private static bool ValidateIntegers(params string[] values) { Convert.ToInt32(value, CultureInfo.CurrentCulture); } - catch + catch (AggregateException) { return false; } diff --git a/ZenCoding/Html/Placehold.cs b/ZenCoding/Html/Placehold.cs index 0de40f1..a15e22b 100644 --- a/ZenCoding/Html/Placehold.cs +++ b/ZenCoding/Html/Placehold.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using System.Text; -using ZenCoding.Html; namespace ZenCoding { @@ -34,33 +33,30 @@ public override void Generate(string pixText) string dimensions = ""; string[] parts; - parts = pixText == null ? new string[] { } : pixText.Split('-'); + parts = pixText == null ? new string[] { } : pixText.Trim('-').Split('-'); - try + if (parts.Length > 1) { - if (parts.Length > 1) - { - dimensions = parts[1]; - - SetDimensions(dimensions); - - if (parts.Length > 2) - { - if (_formats.Contains(parts[2])) - this.Format = parts[2]; - else - SetTextAndColors(parts[2]); + dimensions = parts[1]; - if (parts.Length > 3) - SetTextAndColors(parts[3]); + SetDimensions(dimensions); - if (parts.Length > 4) - SetTextAndColors(parts[4]); - } + if (parts.Length > 2) + { + if (_formats.Contains(parts[2])) + this.Format = parts[2]; + else + SetTextAndColors(parts[2]); + + if (parts.Length > 3) + SetTextAndColors(parts[3]); + if (parts.Length > 4) + SetTextAndColors(parts[4]); } } - catch - { } + + if (pixText.Last() == '-') + this.Text += '-'; this.AssetWidth = this.AssetWidth % 1921; this.AssetHeight = this.AssetHeight % 1921; @@ -71,7 +67,7 @@ public override void Generate(string pixText) private void SetTextAndColors(string slug) { if (string.IsNullOrEmpty(this.Text) && slug.Contains("=")) - this.Text = slug.Split('=')[1]; + this.Text = string.Join("=", slug.Split('=').Skip(1)); else if ((slug.Length == 3 || slug.Length == 6) && slug.All(c => c.IsHex())) if (string.IsNullOrEmpty(this.Background)) this.Background = slug; diff --git a/ZenCoding/Parser.cs b/ZenCoding/Parser.cs index 108ba09..b77efbc 100644 --- a/ZenCoding/Parser.cs +++ b/ZenCoding/Parser.cs @@ -1,8 +1,9 @@ - -namespace ZenCoding +namespace ZenCoding { public class Parser { + IZenParser _parser; + public string Parse(string zenSyntax, ZenType type) { if (zenSyntax == null) @@ -11,12 +12,11 @@ public string Parse(string zenSyntax, ZenType type) switch (type) { case ZenType.HTML: - HtmlParser htmlParser = new HtmlParser(); - return htmlParser.Parse(zenSyntax.Trim()); - + this._parser = new HtmlParser(); + return this._parser.Parse(zenSyntax.Trim()); case ZenType.CSS: - CssParser cssParser = new CssParser(); - return cssParser.Parse(zenSyntax.Trim()); + this._parser = new CssParser(); + return this._parser.Parse(zenSyntax.Trim()); } return null; diff --git a/ZenCoding/ZenCoding.csproj b/ZenCoding/ZenCoding.csproj index 524ed52..12c8225 100644 --- a/ZenCoding/ZenCoding.csproj +++ b/ZenCoding/ZenCoding.csproj @@ -54,6 +54,7 @@ +