diff --git a/README.md b/README.md
index 78667a7..b4f59e0 100644
--- a/README.md
+++ b/README.md
@@ -86,6 +86,16 @@ If you need to print out a block of text for each item in a collection, use the
{{/each}}
Within the context of the **each** block, the scope changes to the current item. So, in the example above, `Name` would refer to a property in the `Customer` class.
+
+Additionally, you can access the current index into the collection being enumerated using the **index** tag.
+
+
+ {{#each Items}}
+ - {{Description}}
+ {{/each}}
+
+
+This will build an HTML list, building a list of items with `Description` and `Value` properties. Additionally, the `index` tag is used to create a CSS class with increasing numbers.
## The 'with' tag
Within a block of text, you may refer to a same top-level placeholder over and over. You can cut down the amount of text by using the **with** tag.
diff --git a/mustache-sharp.test/FormatCompilerTester.cs b/mustache-sharp.test/FormatCompilerTester.cs
index 30cec2a..e035525 100644
--- a/mustache-sharp.test/FormatCompilerTester.cs
+++ b/mustache-sharp.test/FormatCompilerTester.cs
@@ -990,6 +990,20 @@ Last";
Assert.AreEqual("Before123After", result, "The wrong text was generated.");
}
+ ///
+ /// We can use the index tag to get the current iteration.
+ ///
+ [TestMethod]
+ public void TestCompile_Each_Index_PrintsIndexOfItem()
+ {
+ FormatCompiler parser = new FormatCompiler();
+ const string format = "{{#each this}}- Item {{#index}}
{{/each}}
";
+ Generator generator = parser.Compile(format);
+ string result = generator.Render(new int[] { 1, 2, 3 });
+ const string expected = @"";
+ Assert.AreEqual(expected, result, "The wrong text was generated.");
+ }
+
#endregion
#region With
@@ -1038,7 +1052,7 @@ Last";
return new TagParameter[] { new TagParameter("param") { IsRequired = false, DefaultValue = 123 } };
}
- public override void GetText(TextWriter writer, Dictionary arguments)
+ public override void GetText(TextWriter writer, Dictionary arguments, object contextData)
{
writer.Write(arguments["param"]);
}
diff --git a/mustache-sharp.test/Properties/AssemblyInfo.cs b/mustache-sharp.test/Properties/AssemblyInfo.cs
index 0fdb5f2..7ccaa92 100644
--- a/mustache-sharp.test/Properties/AssemblyInfo.cs
+++ b/mustache-sharp.test/Properties/AssemblyInfo.cs
@@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("0.1.1.0")]
-[assembly: AssemblyFileVersion("0.1.1.0")]
+[assembly: AssemblyVersion("0.1.2.0")]
+[assembly: AssemblyFileVersion("0.1.2.0")]
diff --git a/mustache-sharp/CompoundGenerator.cs b/mustache-sharp/CompoundGenerator.cs
index aa7227f..6e8934c 100644
--- a/mustache-sharp/CompoundGenerator.cs
+++ b/mustache-sharp/CompoundGenerator.cs
@@ -72,7 +72,7 @@ namespace Mustache
}
}
- void IGenerator.GetText(KeyScope scope, TextWriter writer)
+ void IGenerator.GetText(KeyScope scope, TextWriter writer, object contextData)
{
Dictionary arguments = _arguments.GetArguments(scope);
IEnumerable contexts = _definition.GetChildContext(writer, scope, arguments);
@@ -93,7 +93,7 @@ namespace Mustache
{
foreach (IGenerator generator in generators)
{
- generator.GetText(context.KeyScope ?? scope, context.Writer ?? writer);
+ generator.GetText(context.KeyScope ?? scope, context.Writer ?? writer, context.Data);
if (context.WriterNeedsConsidated)
{
writer.Write(_definition.ConsolidateWriter(context.Writer ?? writer, arguments));
diff --git a/mustache-sharp/EachTagDefinition.cs b/mustache-sharp/EachTagDefinition.cs
index 54ca2b6..30c8e2f 100644
--- a/mustache-sharp/EachTagDefinition.cs
+++ b/mustache-sharp/EachTagDefinition.cs
@@ -54,9 +54,11 @@ namespace Mustache
{
yield break;
}
+ int index = 0;
foreach (object item in enumerable)
{
- yield return new NestedContext() { KeyScope = scope.CreateChildScope(item), Writer = writer };
+ yield return new NestedContext() { KeyScope = scope.CreateChildScope(item), Writer = writer, Data = index };
+ ++index;
}
}
@@ -66,7 +68,7 @@ namespace Mustache
/// The name of the tags that are in scope.
protected override IEnumerable GetChildTags()
{
- return new string[] { };
+ return new string[] { "index" };
}
///
diff --git a/mustache-sharp/FormatCompiler.cs b/mustache-sharp/FormatCompiler.cs
index 040e738..27a6738 100644
--- a/mustache-sharp/FormatCompiler.cs
+++ b/mustache-sharp/FormatCompiler.cs
@@ -33,6 +33,8 @@ namespace Mustache
_tagLookup.Add(elseDefinition.Name, elseDefinition);
EachTagDefinition eachDefinition = new EachTagDefinition();
_tagLookup.Add(eachDefinition.Name, eachDefinition);
+ IndexTagDefinition indexDefinition = new IndexTagDefinition();
+ _tagLookup.Add(indexDefinition.Name, indexDefinition);
WithTagDefinition withDefinition = new WithTagDefinition();
_tagLookup.Add(withDefinition.Name, withDefinition);
}
diff --git a/mustache-sharp/Generator.cs b/mustache-sharp/Generator.cs
index f0b51b8..0553e12 100644
--- a/mustache-sharp/Generator.cs
+++ b/mustache-sharp/Generator.cs
@@ -80,7 +80,7 @@ namespace Mustache
scope.KeyNotFound += handler;
}
StringWriter writer = new StringWriter(provider);
- _generator.GetText(scope, writer);
+ _generator.GetText(scope, writer, null);
return writer.ToString();
}
}
diff --git a/mustache-sharp/IGenerator.cs b/mustache-sharp/IGenerator.cs
index 5f16d18..4ddb7ce 100644
--- a/mustache-sharp/IGenerator.cs
+++ b/mustache-sharp/IGenerator.cs
@@ -13,7 +13,8 @@ namespace Mustache
///
/// The current lexical scope of the keys.
/// The text writer to send all text to.
+ /// The data associated to the context.
/// The generated text.
- void GetText(KeyScope scope, TextWriter writer);
+ void GetText(KeyScope scope, TextWriter writer, object contextData);
}
}
diff --git a/mustache-sharp/IndexTagDefinition.cs b/mustache-sharp/IndexTagDefinition.cs
new file mode 100644
index 0000000..86d1759
--- /dev/null
+++ b/mustache-sharp/IndexTagDefinition.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Mustache
+{
+ ///
+ /// Defines a tag that outputs the current index within an each loop.
+ ///
+ internal sealed class IndexTagDefinition : InlineTagDefinition
+ {
+ ///
+ /// Initializes a new instance of an IndexTagDefinition.
+ ///
+ public IndexTagDefinition()
+ : base("index")
+ {
+ }
+
+ ///
+ /// Gets whether the tag only exists within the scope of its parent.
+ ///
+ protected override bool GetIsContextSensitive()
+ {
+ return true;
+ }
+
+ ///
+ /// Gets the text to output.
+ ///
+ /// The writer to write the output to.
+ /// The arguments passed to the tag.
+ /// Extra data passed along with the context.
+ public override void GetText(TextWriter writer, Dictionary arguments, object contextData)
+ {
+ int index = (int)contextData;
+ writer.Write(index);
+ }
+ }
+}
diff --git a/mustache-sharp/InlineGenerator.cs b/mustache-sharp/InlineGenerator.cs
index c1fb2c7..cf07ea7 100644
--- a/mustache-sharp/InlineGenerator.cs
+++ b/mustache-sharp/InlineGenerator.cs
@@ -23,10 +23,10 @@ namespace Mustache
_arguments = arguments;
}
- void IGenerator.GetText(KeyScope scope, TextWriter writer)
+ void IGenerator.GetText(KeyScope scope, TextWriter writer, object contextData)
{
Dictionary arguments = _arguments.GetArguments(scope);
- _definition.GetText(writer, arguments);
+ _definition.GetText(writer, arguments, contextData);
}
}
}
diff --git a/mustache-sharp/KeyGenerator.cs b/mustache-sharp/KeyGenerator.cs
index 6dbe146..599ff2a 100644
--- a/mustache-sharp/KeyGenerator.cs
+++ b/mustache-sharp/KeyGenerator.cs
@@ -42,7 +42,7 @@ namespace Mustache
return formatBuilder.ToString();
}
- void IGenerator.GetText(KeyScope scope, TextWriter writer)
+ void IGenerator.GetText(KeyScope scope, TextWriter writer, object contextData)
{
object value = scope.Find(_key);
writer.Write(_format, value);
diff --git a/mustache-sharp/NestedContext.cs b/mustache-sharp/NestedContext.cs
index 090706a..1a0cacb 100644
--- a/mustache-sharp/NestedContext.cs
+++ b/mustache-sharp/NestedContext.cs
@@ -45,5 +45,10 @@ namespace Mustache
get;
set;
}
+
+ ///
+ /// Gets or sets data associated with the context.
+ ///
+ public object Data { get; set; }
}
}
diff --git a/mustache-sharp/Properties/AssemblyInfo.cs b/mustache-sharp/Properties/AssemblyInfo.cs
index f37dd73..f08da59 100644
--- a/mustache-sharp/Properties/AssemblyInfo.cs
+++ b/mustache-sharp/Properties/AssemblyInfo.cs
@@ -34,6 +34,6 @@ using System.Runtime.CompilerServices;
// 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("0.1.1.0")]
-[assembly: AssemblyFileVersion("0.1.1.0")]
+[assembly: AssemblyVersion("0.1.2.0")]
+[assembly: AssemblyFileVersion("0.1.2.0")]
[assembly: InternalsVisibleTo("mustache-sharp.test")]
\ No newline at end of file
diff --git a/mustache-sharp/StaticGenerator.cs b/mustache-sharp/StaticGenerator.cs
index 7ed6b4d..f03fd4a 100644
--- a/mustache-sharp/StaticGenerator.cs
+++ b/mustache-sharp/StaticGenerator.cs
@@ -46,7 +46,7 @@ namespace Mustache
}
}
- void IGenerator.GetText(KeyScope scope, TextWriter writer)
+ void IGenerator.GetText(KeyScope scope, TextWriter writer, object contextData)
{
writer.Write(Value);
}
diff --git a/mustache-sharp/TagDefinition.cs b/mustache-sharp/TagDefinition.cs
index 2d3ce02..dec179f 100644
--- a/mustache-sharp/TagDefinition.cs
+++ b/mustache-sharp/TagDefinition.cs
@@ -152,7 +152,8 @@ namespace Mustache
///
/// The text writer to write to.
/// The arguments passed to the tag.
- public virtual void GetText(TextWriter writer, Dictionary arguments)
+ /// The data associated to the context.
+ public virtual void GetText(TextWriter writer, Dictionary arguments, object contextData)
{
}
diff --git a/mustache-sharp/mustache-sharp.csproj b/mustache-sharp/mustache-sharp.csproj
index d7ecc04..0d5d7b4 100644
--- a/mustache-sharp/mustache-sharp.csproj
+++ b/mustache-sharp/mustache-sharp.csproj
@@ -40,6 +40,7 @@
+