public void MacroSyntaxParser_Matches_Macro_Params()
        {
            var parser = new MacroSyntaxParser();
            IEnumerable<MacroParserResult> results;
            var output = parser.Parse(@"<p>hello</p>
<div class=""umb-macro-holder"" data-macro-alias=""surface"" data-macro-params=""eyAiYmxhaCIgOiAiYXNkZmFzZGZhc2RmIiwgImVyd2Vyd2VyIiA6ICIyMzQyMzQyMzQiIH0="">
<!-- start macro --><!-- end macro -->
</div>
<p>asdf</p>
<p>&nbsp;</p>
<div class=""umb-macro-holder"" data-macro-alias=""partial"" data-macro-params=""eyAidGVzdCIgOiAiYXNkZmVlIiB9""><!-- start macro -->asdfasdfasdf<!-- end macro --></div>
<!--this is my comment-->",
                          (alias, parameters) =>
                          {
                              if (alias == "surface")
                              {
                                  Assert.AreEqual(2, parameters.Count);
                                  Assert.AreEqual("asdfasdfasdf", parameters["blah"]);
                                  Assert.AreEqual("234234234", parameters["erwerwer"]);
                              }
                              else
                              {
                                  Assert.AreEqual(1, parameters.Count);
                                  Assert.AreEqual("asdfee", parameters["test"]);
                              }
                              return "";
                          },
                          out results);

            Assert.AreEqual(2, results.Count());

        }
        public void MacroSyntaxParser_Returns_Callback_Data()
        {
            var parser = new MacroSyntaxParser();
            IEnumerable<MacroParserResult> results;
            var output = parser.Parse(@"<p>hello</p>
<div class=""umb-macro-holder"" data-macro-alias=""surface"" data-p-blah=""asdfasdfasdf"" data-p-erwerwer=""234234234"">
<!-- start macro --><!-- end macro -->
</div>
<p>asdf</p>
<p>&nbsp;</p>
<div class=""umb-macro-holder"" data-macro-alias=""partial"" data-p-test=""asdfee""><!-- start macro -->asdfasdfasdf<!-- end macro --></div>
<!--this is my comment-->",
                          (alias, parameters) =>
                          {
                              if (alias == "surface")
                              {
                                  return "macro 1 content";
                              }
                              return "macro 2 content";
                          },
                          out results);

            Assert.AreEqual(@"<p>hello</p>
macro 1 content
<p>asdf</p>
<p>&nbsp;</p>
macro 2 content
<!--this is my comment-->", output);

        }
        public void MacroSyntaxParser_Matches_Macro_Markers()
        {
            var parser = new MacroSyntaxParser();
            IEnumerable<MacroParserResult> results;
            var output = parser.Parse(@"<p>hello</p>
<div class=""umb-macro-holder"" data-macro-alias=""surface"" >
<!-- start macro --><!-- end macro -->
</div>
<p>asdf</p>
<p>&nbsp;</p>
<div class=""umb-macro-holder"" data-macro-alias=""partial""><!-- start macro -->asdfasdfasdf<!-- end macro --></div>
<!--this is my comment-->",
                          (alias, parameters) => "",
                          out results);

            Assert.AreEqual(2, results.Count());

        }
        public IHtmlString RenderField(IRoutableRequestContext routableRequestContext, ControllerContext controllerContext, Content item,
            string fieldAlias = "", string valueAlias = "", string altFieldAlias = "", string altValueAlias = "", string altText = "", string insertBefore = "", string insertAfter = "",
            bool recursive = false, bool convertLineBreaks = false, bool removeParagraphTags = false,
            UmbracoRenderItemCaseType casing = UmbracoRenderItemCaseType.Unchanged,
            UmbracoRenderItemEncodingType encoding = UmbracoRenderItemEncodingType.Unchanged)
        {
            var sb = new StringBuilder();

            // Handle hard coded "friendly" system keys
            if (fieldAlias == "Name" || fieldAlias == "UrlName")
            {
                valueAlias = fieldAlias;
                fieldAlias = NodeNameAttributeDefinition.AliasValue;
            }

            if (fieldAlias == "CurrentTemplateId")
            {
                fieldAlias = SelectedTemplateAttributeDefinition.AliasValue;
                valueAlias = "TemplateId";
            }

            if (altFieldAlias == "Name" || altFieldAlias == "UrlName")
            {
                altValueAlias = altFieldAlias;
                altFieldAlias = NodeNameAttributeDefinition.AliasValue;
            }

            if (altFieldAlias == "CurrentTemplateId")
            {
                altFieldAlias = SelectedTemplateAttributeDefinition.AliasValue;
                altValueAlias = "TemplateId";
            }

            var val = item.Field<string>(fieldAlias, valueAlias, recursive);

            if (val.IsNullOrWhiteSpace() && !altFieldAlias.IsNullOrWhiteSpace())
            {
                val = item.Field<string>(altFieldAlias, altValueAlias, recursive);
            }

            if (val.IsNullOrWhiteSpace() && !altText.IsNullOrWhiteSpace())
            {
                val = altText;
            }

            if(!val.IsNullOrWhiteSpace())
            {
                switch (casing)
                {
                    case UmbracoRenderItemCaseType.Upper:
                        val = val.ToUpper();
                        break;
                    case UmbracoRenderItemCaseType.Lower:
                        val = val.ToLower();
                        break;
                    case UmbracoRenderItemCaseType.Title:
                        val = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(val);
                        break;
                    default:
                        break;
                }

                switch (encoding)
                {
                    case UmbracoRenderItemEncodingType.Url:
                        val = HttpUtility.UrlEncode(val);
                        break;
                    case UmbracoRenderItemEncodingType.Html:
                        val = HttpUtility.HtmlEncode(val);
                        break;
                    default:
                        break;
                }

                if (convertLineBreaks)
                {
                    val = val.Replace(Environment.NewLine, "<br />");
                }

                if (removeParagraphTags)
                {
                    val = val.Trim().Trim("<p>").Trim("</p>");
                }

                sb.Append(HttpUtility.HtmlDecode(insertBefore));
                sb.Append(val);
                sb.Append(HttpUtility.HtmlDecode(insertAfter));
            }

            //now we need to parse the macro syntax out and replace it with the rendered macro content

            var macroRenderer = new MacroRenderer(routableRequestContext.RegisteredComponents, routableRequestContext);
            var macroParser = new MacroSyntaxParser();
            IEnumerable<MacroParserResult> parseResults;
            var parsed = macroParser.Parse(sb.ToString(),
                                           (macroAlias, macroParams)
                                           => macroRenderer.RenderMacroAsString(macroAlias,
                                                                                macroParams,
                                                                                controllerContext, false,
                                                                                () => item), out parseResults);

            //now we need to parse any internal links and replace with actual URLs
            var linkParse = new LinkSyntaxParser();
            parsed = linkParse.Parse(parsed, x => routableRequestContext.RoutingEngine.GetUrl(x));

            return new MvcHtmlString(parsed);
        }
        public IHtmlString RenderField(IRoutableRequestContext routableRequestContext, ControllerContext controllerContext, Content item,
            string fieldAlias = "", string valueAlias = "", string altFieldAlias = "", string altValueAlias = "", string altText = "", string insertBefore = "", string insertAfter = "",
            bool recursive = false, bool convertLineBreaks = false, bool removeParagraphTags = false,
            UmbracoRenderItemCaseType casing = UmbracoRenderItemCaseType.Unchanged,
            UmbracoRenderItemEncodingType encoding = UmbracoRenderItemEncodingType.Unchanged,
            string formatString = "")
        {
            var sb = new StringBuilder();

            var valObj = GetFieldValue(item, fieldAlias, valueAlias, recursive);

            if ((valObj == null || valObj.ToString().IsNullOrWhiteSpace()) && !altFieldAlias.IsNullOrWhiteSpace())
            {
                valObj = GetFieldValue(item, altFieldAlias, altValueAlias, recursive);
            }

            if ((valObj == null || valObj.ToString().IsNullOrWhiteSpace()) && !altText.IsNullOrWhiteSpace())
            {
                valObj = altText;
            }

            if(!formatString.IsNullOrWhiteSpace())
                formatString = "{0:" + formatString.Replace("\\", "\\\\").Replace("\"", "\\\"") + "}";
            else
                formatString = "{0}";

            var val = string.Format(formatString, valObj);

            if(!val.IsNullOrWhiteSpace())
            {
                switch (casing)
                {
                    case UmbracoRenderItemCaseType.Upper:
                        val = val.ToUpper();
                        break;
                    case UmbracoRenderItemCaseType.Lower:
                        val = val.ToLower();
                        break;
                    case UmbracoRenderItemCaseType.Title:
                        val = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(val);
                        break;
                    default:
                        break;
                }

                switch (encoding)
                {
                    case UmbracoRenderItemEncodingType.Url:
                        val = HttpUtility.UrlEncode(val);
                        break;
                    case UmbracoRenderItemEncodingType.Html:
                        val = HttpUtility.HtmlEncode(val);
                        break;
                    default:
                        break;
                }

                if (convertLineBreaks)
                {
                    val = val.Replace(Environment.NewLine, "<br />");
                }

                if (removeParagraphTags)
                {
                    val = val.Trim().Trim("<p>").Trim("</p>");
                }

                sb.Append(HttpUtility.HtmlDecode(insertBefore));
                sb.Append(val);
                sb.Append(HttpUtility.HtmlDecode(insertAfter));
            }

            //now we need to parse the macro syntax out and replace it with the rendered macro content

            var macroRenderer = new MacroRenderer(routableRequestContext.RegisteredComponents, routableRequestContext);
            var macroParser = new MacroSyntaxParser();
            IEnumerable<MacroParserResult> parseResults;
            var parsed = macroParser.Parse(sb.ToString(),
                                           (macroAlias, macroParams)
                                           => macroRenderer.RenderMacroAsString(macroAlias,
                                                                                macroParams,
                                                                                controllerContext, false,
                                                                                () => item), out parseResults);

            //now we need to parse any internal links and replace with actual URLs
            var linkParse = new LinkSyntaxParser();
            parsed = linkParse.Parse(parsed, x => routableRequestContext.RoutingEngine.GetUrl(x));

            return new MvcHtmlString(parsed);
        }