Skip to content

Commit

Permalink
Merge pull request #83 from jdiamond/dev
Browse files Browse the repository at this point in the history
Release 1.14.0
  • Loading branch information
Romanx committed Apr 15, 2015
2 parents 646343e + b1e6c99 commit 459c798
Show file tree
Hide file tree
Showing 20 changed files with 297 additions and 21 deletions.
3 changes: 3 additions & 0 deletions Nustache.Compilation.Tests/Nustache.Compilation.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@
<Name>Nustache.Core</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
2 changes: 1 addition & 1 deletion Nustache.Compilation/Nustache.Compilation.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<description>$description$</description>
<tags>Template Mustache</tags>
<dependencies>
<dependency id="Nustache" version="1.12.2.12" />
<dependency id="Nustache" version="$version$" />
<dependency id="Newtonsoft.Json" version="5.0.6" />
</dependencies>
</metadata>
Expand Down
4 changes: 2 additions & 2 deletions Nustache.Compilation/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.13.8.22")]
[assembly: AssemblyFileVersion("1.13.8.22")]
[assembly: AssemblyVersion("1.14.0.0")]
[assembly: AssemblyFileVersion("1.14.0.0")]
18 changes: 18 additions & 0 deletions Nustache.Core.Tests/Describe_Block.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,24 @@ public void It_does_not_treat_dictionaries_as_lists()
Assert.AreEqual("x", writer.GetStringBuilder().ToString());
}

[Test]
public void It_Nested_Fully_Qualified_Statements_Are_Evaluated()
{
var a = new Block("a.b",
new Block("a.c", new LiteralText("I should render."), new EndSection("a.c")),
new EndSection("a.b"));
var writer = new StringWriter();
var context = new RenderContext(
null,
new Dictionary<string, object> { { "a", new Dictionary<string, object> { { "b", 3 }, { "c", true } } } },
writer,
null);

a.Render(context);

Assert.AreEqual("I should render.", writer.GetStringBuilder().ToString());
}

[Test]
public void It_has_a_useful_ToString_method()
{
Expand Down
13 changes: 12 additions & 1 deletion Nustache.Core.Tests/Describe_Lambda.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,20 @@ public void The_text_passed_is_the_literal_block_unrendered()
{
var result = Render.StringToString("{{#wrapped}}{{name}} is awesome.{{/wrapped}}", new
{
wrapped = (Lambda)((s) => string.Format("<b>{0}</b>", s))
wrapped = (Lambda)((body, context, render) => string.Format("<b>{0}</b>", body))
});
Assert.AreEqual("<b>{{name}} is awesome.</b>", result);
}

[Test]
public void It_can_use_context_and_render_delegate_inside_lambda()
{
var result = Render.StringToString("{{#wrapped}}{{name}} is awesome.{{/wrapped}}", new
{
wrapped = (Lambda)((body, context, render) => string.Format("<b>{0}</b>", render(context))),
name = "Lukasz"
});
Assert.AreEqual("<b>Lukasz is awesome.</b>", result);
}
}
}
38 changes: 38 additions & 0 deletions Nustache.Core.Tests/Describe_Template_Render.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
using System.Collections.Generic;
using System;

namespace Nustache.Core.Tests
{
Expand Down Expand Up @@ -214,6 +216,42 @@ public void It_can_include_templates_defined_in_outer_templates()
Assert.AreEqual("beforeOUTSIDEafter", result);
}

[Test]
public void It_can_include_templates_over_three_levels()
{
var result = Render.StringToString("{{<t1}}One{{/t1}}{{<t2}}{{>t1}}Two{{/t2}}{{<t3}}{{>t2}}Three{{/t3}}{{>t3}}", null);

Assert.AreEqual("OneTwoThree", result);
}


[Test]
public void It_can_include_templates_over_three_levels_with_external_includes()
{
var baseTemplate = new Template("Base");
baseTemplate.Load(new StringReader("Base{{>BaseContent}}"));

var masterTemplate = new Template("Master");
masterTemplate.Load(new StringReader("{{<BaseContent}}Master{{>MasterContent}}{{/BaseContent}}{{>Base}}"));

var templates = new Dictionary<string, Template>();
templates.Add("Base", baseTemplate);
templates.Add("Master", masterTemplate);

TemplateLocator locateTemplate =
name =>
{
Template ret;
templates.TryGetValue(name, out ret);
if (ret == null) throw new KeyNotFoundException(string.Format("The view '{0}' could not be found.", name));
return ret;
};

var result = Render.StringToString("{{<MasterContent}}Hello{{/MasterContent}}{{>Master}}", null, locateTemplate);

Assert.AreEqual("BaseMasterHello", result);
}

[Test]
public void It_allows_templates_to_be_overridden_in_sections()
{
Expand Down
29 changes: 29 additions & 0 deletions Nustache.Core.Tests/Describe_ValueGetter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Xml;
using Moq;
using NUnit.Framework;
using System.Collections.Specialized;

namespace Nustache.Core.Tests
{
Expand Down Expand Up @@ -173,6 +174,34 @@ public void It_fails_ListValueByIndex_values_from_List()
Assert.AreEqual(ValueGetter.NoValue, ValueGetter.GetValue(target, "2"));
}

[Test]
public void It_gets_DataRow_Values()
{
DataTable dt = new DataTable();
dt.Columns.Add("IntColumn", typeof(int));
dt.Rows.Add(new object[] { 123 });
var target = dt.Rows[0];
Assert.AreEqual(123, ValueGetter.GetValue(target, "IntColumn"));
}

[Test]
public void It_gets_case_insensitive_DataRow_Values()
{
DataTable dt = new DataTable();
dt.Columns.Add("IntColumn", typeof(int));
dt.Rows.Add(new object[] { 123 });
var target = dt.Rows[0];
Assert.AreEqual(123, ValueGetter.GetValue(target, "intcolumn"));
}

[Test]
public void It_gets_NameValueCollection_values()
{
NameValueCollection target = new NameValueCollection();
target["IntKey"] = "123";
Assert.AreEqual("123", ValueGetter.GetValue(target, "IntKey"));
}

public class ReadWriteInts
{
public int IntField = -1;
Expand Down
40 changes: 40 additions & 0 deletions Nustache.Core.Tests/Example_DataTable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;

namespace Nustache.Core.Tests
{
[TestFixture]
public class Example_DataTable
{
[Test]
public void It_can_Render_Datatables()
{
var dt = new System.Data.DataTable();
dt.Columns.Add("IntColumn", typeof(int));
dt.Rows.Add(new object[] { 1 });
dt.Rows.Add(new object[] { 2 });
dt.Rows.Add(new object[] { 3 });

var result = Render.StringToString("{{#Item}}{{IntColumn}}{{/Item}}", new { Item = dt });

Assert.AreEqual("123", result);
}

[Test]
public void It_can_Render_Datatables_Case_Insensitive()
{
var dt = new System.Data.DataTable();
dt.Columns.Add("IntColumn", typeof(int));
dt.Rows.Add(new object[] { 1 });
dt.Rows.Add(new object[] { 2 });
dt.Rows.Add(new object[] { 3 });

var result = Render.StringToString("{{#Item}}{{intcolumn}}{{/Item}}", new { Item = dt });

Assert.AreEqual("123", result);
}
}
}
4 changes: 4 additions & 0 deletions Nustache.Core.Tests/Nustache.Core.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Describe_Helpers.cs" />
<Compile Include="Example_DataTable.cs" />
<Compile Include="Example_Trees.cs" />
<Compile Include="Describe_Encoders.cs" />
<Compile Include="Describe_Lambda.cs" />
Expand Down Expand Up @@ -114,6 +115,9 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
13 changes: 12 additions & 1 deletion Nustache.Core/Block.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@

using System;
using System.IO;

namespace Nustache.Core
{
public class Block : Section
Expand All @@ -17,7 +20,15 @@ public override void Render(RenderContext context)

if (lambda != null)
{
context.Write(lambda(InnerSource()).ToString());
RenderFunc render = c =>
{
var textWriter = new StringWriter();
var lambdaContext = new RenderContext(context, textWriter);
RenderParts(lambdaContext);
return textWriter.GetStringBuilder().ToString();
};

context.Write(lambda(InnerSource(), context, render).ToString());

return;
}
Expand Down
11 changes: 9 additions & 2 deletions Nustache.Core/Encoders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,17 @@ public static string DefaultHtmlEncode(string text)
sb.Append("&amp;");
break;
default:
if (text[i] > 159)
var ch = text[i];
if (ch > 159)
{
sb.Append("&#");
sb.Append(((int)text[i]).ToString(CultureInfo.InvariantCulture));
if (char.IsHighSurrogate(ch) && (i + 1) < len) {
// convert surrogates to their decimal value
sb.Append(char.ConvertToUtf32(ch, text[i+1]));
i++;
} else {
sb.Append(((int)ch).ToString(CultureInfo.InvariantCulture));
}
sb.Append(";");
}
else
Expand Down
1 change: 1 addition & 0 deletions Nustache.Core/Nustache.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions Nustache.Core/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.13.8.22")]
[assembly: AssemblyFileVersion("1.13.8.22")]
[assembly: AssemblyVersion("1.14.0.0")]
[assembly: AssemblyFileVersion("1.14.0.0")]
38 changes: 34 additions & 4 deletions Nustache.Core/RenderContext.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml;
Expand All @@ -9,7 +10,9 @@ namespace Nustache.Core
{
public delegate Template TemplateLocator(string name);

public delegate Object Lambda(string text);
public delegate Object Lambda(string text, RenderContext context, RenderFunc render);

public delegate string RenderFunc(RenderContext context);

public class RenderContext
{
Expand All @@ -36,6 +39,18 @@ public RenderContext(Section section, object data, TextWriter writer, TemplateLo
RenderContextBehaviour.GetDefaultRenderContextBehaviour();
}

public RenderContext(RenderContext baseContext, TextWriter writer)
{
_sectionStack = baseContext._sectionStack;
_dataStack = baseContext._dataStack;
_writer = writer;
_templateLocator = baseContext._templateLocator;
_renderContextBehaviour = baseContext._renderContextBehaviour;
_includeLevel = baseContext._includeLevel;
_indent = baseContext._indent;
_lineEnded = baseContext._lineEnded;
}

public object GetValue(string path)
{
if (path == ".")
Expand Down Expand Up @@ -109,13 +124,17 @@ private static object GetValueFromPath(object data, string path, out bool partia

if (names.Length > 1)
{
foreach (var name in names)
for (int i = 0; i < names.Length; i++ )
{
data = ValueGetter.GetValue(data, name);
data = ValueGetter.GetValue(data, names[i]);

if (data == null || ReferenceEquals(data, ValueGetter.NoValue))
{
partialMatch = true;
if (i > 0)
{
partialMatch = true;
}

break;
}
}
Expand Down Expand Up @@ -174,6 +193,13 @@ public IEnumerable<object> GetValues(string path)
yield return item;
}
}
else if (value is DataTable)
{
foreach (var item in ((DataTable)value).Rows)
{
yield return item;
}
}
else
{
yield return value;
Expand Down Expand Up @@ -259,7 +285,11 @@ public void Include(string templateName, string indent)

if (template != null)
{
// push the included template on the stack so that internally defined templates can be resolved properly later.
// designed to pass test Describe_Template_Render.It_can_include_templates_over_three_levels_with_external_includes()
this.Enter(template);
template.Render(this);
this.Exit();
}
}

Expand Down
Loading

0 comments on commit 459c798

Please sign in to comment.