Permalink
Browse files

First cracp at internal template definitions.

  • Loading branch information...
1 parent d9b6a16 commit 31a9ee810ae5b43dae6e9d4d08dd82b08fabbd10 @jdiamond jdiamond committed Oct 28, 2010
@@ -45,6 +45,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="TemplateDefinition.cs" />
<Compile Include="Render.cs" />
<Compile Include="RenderContext.cs" />
<Compile Include="EndSection.cs" />
@@ -8,7 +8,8 @@ namespace Nustache.Core
public class RenderContext
{
private const int IncludeLimit = 1024;
- private readonly Stack<object> _stack = new Stack<object>();
+ private readonly Stack<object> _dataStack = new Stack<object>();
+ private readonly Stack<Template> _templateStack = new Stack<Template>();
private object _data;
private readonly TextWriter _writer;
private readonly Func<string, Template> _templateLocator;
@@ -33,7 +34,7 @@ public object GetValue(string name)
return value;
}
- foreach (var data in _stack)
+ foreach (var data in _dataStack)
{
value = GetValue(name, data);
@@ -87,15 +88,25 @@ public IEnumerable<object> GetValues(string name)
}
}
- public void Push(object data)
+ public void PushData(object data)
{
- _stack.Push(_data);
+ _dataStack.Push(_data);
_data = data;
}
- public void Pop()
+ public void PopData()
{
- _data = _stack.Pop();
+ _data = _dataStack.Pop();
+ }
+
+ public void PushTemplate(Template template)
+ {
+ _templateStack.Push(template);
+ }
+
+ public void PopTemplate()
+ {
+ _templateStack.Pop();
}
public void Write(string text)
@@ -113,10 +124,21 @@ public void Include(string templateName)
_includeLevel++;
- // TODO: Check for null!
+ var currentTemplate = _templateStack.Peek();
+
+ var childTemplate = currentTemplate.GetTemplate(templateName);
+
+ if (childTemplate != null)
+ {
+ childTemplate.Render(this);
+ }
+ else if (_templateLocator != null)
+ {
+ var externalTemplate = _templateLocator(templateName);
+ externalTemplate.Render(this);
+ }
- var template = _templateLocator(templateName);
- template.Render(this);
+ _includeLevel--;
}
}
}
View
@@ -27,6 +27,10 @@ public IEnumerable<Part> Scan(string template)
{
yield return new StartSection(marker.Substring(1));
}
+ else if (marker[0] == '<')
+ {
+ yield return new TemplateDefinition(marker.Substring(1));
+ }
else if (marker[0] == '/')
{
yield return new EndSection(marker.Substring(1));
@@ -23,14 +23,14 @@ public override void Render(RenderContext context)
{
foreach (var value in context.GetValues(_name))
{
- context.Push(value);
+ context.PushData(value);
foreach (var child in _children)
{
child.Render(context);
}
- context.Pop();
+ context.PopData();
}
}
View
@@ -34,6 +34,11 @@ public void Load(TextReader reader)
// not during Render.
}
+ public void Load(IEnumerable<Part> parts)
+ {
+ _parts = parts;
+ }
+
/// <summary>
/// Renders the template.
/// </summary>
@@ -54,10 +59,27 @@ public void Render(object data, TextWriter writer, Func<string, Template> templa
public void Render(RenderContext context)
{
+ context.PushTemplate(this);
+
foreach (var part in _parts)
{
part.Render(context);
}
+
+ context.PopTemplate();
+ }
+
+ public Template GetTemplate(string templateName)
+ {
+ foreach (var part in _parts)
+ {
+ if (part is TemplateDefinition)
+ {
+ return ((TemplateDefinition)part).GetTemplate();
+ }
+ }
+
+ return null;
}
}
}
@@ -0,0 +1,47 @@
+namespace Nustache.Core
+{
+ public class TemplateDefinition : StartSection
+ {
+ public TemplateDefinition(string name)
+ : base(name)
+ {
+ }
+
+ public override void Render(RenderContext context)
+ {
+ }
+
+ public Template GetTemplate()
+ {
+ var template = new Template();
+ template.Load(Children);
+ return template;
+ }
+
+ #region Boring stuff
+
+ public bool Equals(TemplateDefinition other)
+ {
+ return base.Equals(other);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ return Equals(obj as TemplateDefinition);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return string.Format("TemplateDefinition(\"{0}\")", Name);
+ }
+
+ #endregion
+ }
+}
@@ -138,5 +138,14 @@ public void It_throws_to_prevent_infinite_template_recursion()
() => Render.StringToString(
"before{{>foo}}after", null, name => fooTemplate));
}
+
+ [Test]
+ public void It_can_include_templates_defined_in_templates()
+ {
+ var result = Render.StringToString(
+ "{{<foo}}FOO{{/foo}}before{{>foo}}after", null, null);
+
+ Assert.AreEqual("beforeFOOafter", result);
+ }
}
}
View
@@ -1,9 +1,7 @@
- Add tests for ValueGetter.
-- Add a syntax for defining templates.
- - {{<foo}}template definition goes here{{/foo}}
- - {{>foo}} looks for defined templates before hitting the disk.
- - Looks up context stack.
- - {{>}} invokes parent template with same name?
+- Make looking up internal templates use sections as scopes
+ instead of templates.
+- {{>}} invokes parent template with same name?
- Add magic variables like {{$i}} and {{$first}}.
- Need to work with sections, too, like {{#$first}}first stuff goes here{{/$first}}.
- Add some syntax to define "local" variables?

0 comments on commit 31a9ee8

Please sign in to comment.