diff --git a/Nustache.Compilation.Tests/Compiled_Templates_Support.cs b/Nustache.Compilation.Tests/Compiled_Templates_Support.cs index 80286c2..066d965 100644 --- a/Nustache.Compilation.Tests/Compiled_Templates_Support.cs +++ b/Nustache.Compilation.Tests/Compiled_Templates_Support.cs @@ -169,7 +169,7 @@ public void Multiple_Levels_of_Enumerable_Sections() new SubObject { SubText = "c" }, } }); - Assert.AreEqual("A template witha TrueBlahThirdc ", result.Replace("\r\n", "")); + Assert.AreEqual("A template witha TrueBlahThirdc ", result.Replace("\r\n", "").Replace("\n", "").Replace("\r", "")); } [Test] @@ -231,7 +231,7 @@ public void Internal_Templates_AKA_Inline_Partials() var compiled = template.Compile(null); var result = compiled(new TestObject { Sub = new SubObject { SubText = "Byaaah" } }); - Assert.AreEqual("in partial Byaaah after partial", result.Replace("\r\n", "")); + Assert.AreEqual("in partial Byaaah after partial", result.Replace("\r\n", "").Replace("\n", "").Replace("\r", "")); } [Test] diff --git a/Nustache.Compilation.Tests/Mustache_Spec/MustacheSpec.cs b/Nustache.Compilation.Tests/Mustache_Spec/MustacheSpec.cs index 0183db1..97fe294 100644 --- a/Nustache.Compilation.Tests/Mustache_Spec/MustacheSpec.cs +++ b/Nustache.Compilation.Tests/Mustache_Spec/MustacheSpec.cs @@ -48,8 +48,8 @@ public static JObject GetSpecs(JToken[] specDefinition) private static string StripReservedWords(string s) { - s = new Regex(@"\{\s*[#\/\^]?string\s*\}\}").Replace(s, eval => eval.Value.Replace("string", "string1")); - s = new Regex(@"\{\s*[#\/\^]?bool\s*\}\}").Replace(s, eval => eval.Value.Replace("bool", "bool1")); + s = new Regex(@"\{\{\s*[#\/\^&]?\s*string\s*\}\}").Replace(s, eval => eval.Value.Replace("string", "string1")); + s = new Regex(@"\{\{\s*[#\/\^&]?\s*bool\s*\}\}").Replace(s, eval => eval.Value.Replace("bool", "bool1")); return s.Replace("\"string\"", "\"string1\"") .Replace("\"bool\"", "\"bool1\""); diff --git a/Nustache.Compilation.Tests/Mustache_Spec/Official_Specs.cs b/Nustache.Compilation.Tests/Mustache_Spec/Official_Specs.cs index 10e9f1f..9f3d703 100644 --- a/Nustache.Compilation.Tests/Mustache_Spec/Official_Specs.cs +++ b/Nustache.Compilation.Tests/Mustache_Spec/Official_Specs.cs @@ -72,11 +72,21 @@ private static void RunMustacheSpecs(MustacheSpec.MustacheTest test) !test.Name.ToLower().Contains("broken chain") && !(test.SpecName == "inverted" && (test.Name == "List" || test.Name == "Context"))) { - var compiledTemplate = templ.Compile( + try + { + var compiledTemplate = templ.Compile( test.StronglyTypedExample != null ? test.StronglyTypedExample.GetType() : typeof(object), testDataTemplateLocator); - rendered = compiledTemplate(test.StronglyTypedExample); - Assert.AreEqual(test.Expected, rendered, "Compiled Template rendering failed for " + test.Description); + rendered = compiledTemplate(test.StronglyTypedExample); + Assert.AreEqual(test.Expected, rendered, "Compiled Template rendering failed for " + test.Description); + } + catch (Nustache.Core.NustacheException ex) + { + if (ex.Message.StartsWith("Unsupported:")) + { + Assert.Inconclusive(ex.Message); + } + } } else { diff --git a/Nustache.Compilation/CompileContext.cs b/Nustache.Compilation/CompileContext.cs index 3bc35e6..267527b 100644 --- a/Nustache.Compilation/CompileContext.cs +++ b/Nustache.Compilation/CompileContext.cs @@ -5,6 +5,7 @@ using System.Linq.Expressions; using System.Collections; using Nustache.Core; +using System.Text.RegularExpressions; namespace Nustache.Compilation { @@ -12,6 +13,9 @@ public class CompileContext { private int IncludeLimit = 255; private int _includeLevel = 0; + public string _indent; + public readonly Regex _indenter = new Regex("\n(?!$)"); + public bool _lineEnded; private readonly Type targetType; private readonly RenderContext renderContext; @@ -174,7 +178,7 @@ internal void Pop() _targetObjectStack.Pop(); } - internal Expression Include(string templateName) + internal Expression Include(string templateName, string indent) { if (_includeLevel >= IncludeLimit) { @@ -184,12 +188,15 @@ internal Expression Include(string templateName) _includeLevel++; + var oldIndent = _indent; + _indent = (_indent ?? "") + (indent ?? ""); + Expression compiled = null; TemplateDefinition templateDefinition = GetTemplateDefinition(templateName); if (_includedTemplates.Contains(templateName)) - throw new NustacheException("Compiled recursive templates will be supported in a later release"); + throw new NustacheException("Unsupported: Compiled recursive templates will be supported in a later release"); _includedTemplates.Add(templateName); if (templateDefinition != null) @@ -205,6 +212,7 @@ internal Expression Include(string templateName) compiled = template.Compile(this); } } + _indent = oldIndent; _includeLevel--; diff --git a/Nustache.Compilation/CompilePartVisitor.cs b/Nustache.Compilation/CompilePartVisitor.cs index 30bbc11..ff41351 100644 --- a/Nustache.Compilation/CompilePartVisitor.cs +++ b/Nustache.Compilation/CompilePartVisitor.cs @@ -75,12 +75,15 @@ public void Visit(Block block) return expression; })); - } public void Visit(LiteralText literal) { - parts.Add(Expression.Constant(literal.Text, typeof(string))); + var text = literal.Text; + + parts.Add(CompoundExpression.IndentCheck(Expression.Constant(text, typeof(string)), context)); + + context._lineEnded = text.Length > 0 && text[text.Length - 1] == '\n'; } public void Visit(EndSection endSections) @@ -105,7 +108,7 @@ public void Visit(InvertedBlock invertedBlock) public void Visit(TemplateInclude include) { - parts.Add(context.Include(include.Name)); + parts.Add(context.Include(include.Name, include.Indent)); } public void Visit(VariableReference variable) @@ -116,11 +119,11 @@ public void Visit(VariableReference variable) if (variable.Escaped) { - parts.Add(Expression.Call(null, typeof(Encoders).GetMethod("DefaultHtmlEncode"), getter)); + parts.Add(CompoundExpression.IndentOnLineEnd(Expression.Call(null, typeof(Encoders).GetMethod("DefaultHtmlEncode"), getter), context)); } else { - parts.Add(getter); + parts.Add(CompoundExpression.IndentOnLineEnd(getter, context)); } } } diff --git a/Nustache.Compilation/CompoundExpression.cs b/Nustache.Compilation/CompoundExpression.cs index 1e0b2ab..33f3582 100644 --- a/Nustache.Compilation/CompoundExpression.cs +++ b/Nustache.Compilation/CompoundExpression.cs @@ -4,6 +4,7 @@ using System.Text; using System.Linq.Expressions; using System.Collections; +using System.Text.RegularExpressions; namespace Nustache.Compilation { @@ -56,6 +57,38 @@ public static Expression Enumerator(Func itemCallback, E return block; } + public static Expression IndentCheck(Expression expression, CompileContext context) + { + if (context._indent == null) return expression; + + var regex = Expression.Variable(typeof(Regex)); + + return Expression.Block( + new[] { regex }, + Expression.Assign(regex, Expression.New(typeof(Regex).GetConstructor(new[] { typeof(String) }), new List() { Expression.Constant("\n(?!$)", typeof(String)) })), + Expression.Call(regex, typeof(Regex).GetMethod("Replace", new[] { typeof(String), typeof(String) }), new List() + { + IndentOnLineEnd(expression, context), + Expression.Constant("\n" + context._indent) + }) + ); + } + + public static Expression IndentOnLineEnd(Expression expression, CompileContext context) + { + if (context._indent != null && context._lineEnded) + { + var expr = Expression.Call(typeof(String).GetMethod("Concat", new [] { typeof(String), typeof(String) }), new List { + Expression.Constant(context._indent, typeof(String)), + expression + }); + context._lineEnded = false; + return expr; + } + + return expression; + } + internal static Expression NullCheck(Expression expression, string nullValue = "", Expression returnIfNotNull = null) { if (returnIfNotNull == null) returnIfNotNull = expression; diff --git a/Nustache.Compilation/Nustache.Compilation.csproj b/Nustache.Compilation/Nustache.Compilation.csproj index 4eb3022..a7cb275 100644 --- a/Nustache.Compilation/Nustache.Compilation.csproj +++ b/Nustache.Compilation/Nustache.Compilation.csproj @@ -51,6 +51,7 @@ + diff --git a/Nustache.Compilation/Nustache.Compilation.nuspec b/Nustache.Compilation/Nustache.Compilation.nuspec new file mode 100644 index 0000000..32e491e --- /dev/null +++ b/Nustache.Compilation/Nustache.Compilation.nuspec @@ -0,0 +1,18 @@ + + + + Nustache.Compilation + $version$ + Jason Diamond + Jason Diamond + https://raw.github.com/jdiamond/Nustache/master/LICENSE.txt + https://github.com/jdiamond/Nustache + false + $description$ + Template Mustache + + + + + + \ No newline at end of file diff --git a/Nustache.Compilation/Properties/AssemblyInfo.cs b/Nustache.Compilation/Properties/AssemblyInfo.cs index 1da2cd1..d1e03a0 100644 --- a/Nustache.Compilation/Properties/AssemblyInfo.cs +++ b/Nustache.Compilation/Properties/AssemblyInfo.cs @@ -6,11 +6,11 @@ // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Nustache.Compilation")] -[assembly: AssemblyDescription("")] +[assembly: AssemblyDescription("Compliation for Logic-less templates for .NET")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyCompany("Jason Diamond")] [assembly: AssemblyProduct("Nustache.Compilation")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2013")] +[assembly: AssemblyCopyright("Copyright © 2010-2013")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("1.13.8.22")] +[assembly: AssemblyFileVersion("1.13.8.22")] diff --git a/Nustache.Mvc3.Example/Nustache.Mvc3.Example.csproj b/Nustache.Mvc3.Example/Nustache.Mvc3.Example.csproj index 3d54b6c..4f6bfda 100644 --- a/Nustache.Mvc3.Example/Nustache.Mvc3.Example.csproj +++ b/Nustache.Mvc3.Example/Nustache.Mvc3.Example.csproj @@ -21,6 +21,7 @@ 4.0 + true true diff --git a/Nustache.Mvc3/Nustache.Mvc3.csproj b/Nustache.Mvc3/Nustache.Mvc3.csproj index 86d7488..62f3051 100644 --- a/Nustache.Mvc3/Nustache.Mvc3.csproj +++ b/Nustache.Mvc3/Nustache.Mvc3.csproj @@ -31,11 +31,38 @@ 4 + + True + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + - + + True + ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.Helpers.dll + + + True + ..\packages\Microsoft.AspNet.Mvc.3.0.50813.1\lib\net40\System.Web.Mvc.dll + + + True + ..\packages\Microsoft.AspNet.Razor.1.0.20105.408\lib\net40\System.Web.Razor.dll + + + True + ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.dll + + + True + ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Deployment.dll + + + True + ..\packages\Microsoft.AspNet.WebPages.1.0.20105.408\lib\net40\System.Web.WebPages.Razor.dll + @@ -52,6 +79,7 @@ Designer +