mirror of
				https://github.com/art-ist/mustache-sharp.git
				synced 2024-06-16 21:05:32 +00:00 
			
		
		
		
	Add support for index in each tags
It was requested that the current index could be accessed in the each tag.
This commit is contained in:
		
							parent
							
								
									3795a77354
								
							
						
					
					
						commit
						d7a0ab3b38
					
				
							
								
								
									
										10
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								README.md
									
									
									
									
									
								
							@ -87,6 +87,16 @@ If you need to print out a block of text for each item in a collection, use the
 | 
			
		||||
    
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
    <ul>
 | 
			
		||||
    {{#each Items}}
 | 
			
		||||
        <li class="list-item{{#index}}" value="{{Value}}">{{Description}}</li>
 | 
			
		||||
    {{/each}}
 | 
			
		||||
    </ul>
 | 
			
		||||
    
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -990,6 +990,20 @@ Last";
 | 
			
		||||
            Assert.AreEqual("Before123After", result, "The wrong text was generated.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// We can use the index tag to get the current iteration.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        [TestMethod]
 | 
			
		||||
        public void TestCompile_Each_Index_PrintsIndexOfItem()
 | 
			
		||||
        {
 | 
			
		||||
            FormatCompiler parser = new FormatCompiler();
 | 
			
		||||
            const string format = "<ul>{{#each this}}<li value=\"{{this}}\">Item {{#index}}</li>{{/each}}</ul>";
 | 
			
		||||
            Generator generator = parser.Compile(format);
 | 
			
		||||
            string result = generator.Render(new int[] { 1, 2, 3 });
 | 
			
		||||
            const string expected = @"<ul><li value=""1"">Item 0</li><li value=""2"">Item 1</li><li value=""3"">Item 2</li></ul>";
 | 
			
		||||
            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<string, object> arguments)
 | 
			
		||||
            public override void GetText(TextWriter writer, Dictionary<string, object> arguments, object contextData)
 | 
			
		||||
            {
 | 
			
		||||
                writer.Write(arguments["param"]);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -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")]
 | 
			
		||||
 | 
			
		||||
@ -72,7 +72,7 @@ namespace Mustache
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void IGenerator.GetText(KeyScope scope, TextWriter writer)
 | 
			
		||||
        void IGenerator.GetText(KeyScope scope, TextWriter writer, object contextData)
 | 
			
		||||
        {
 | 
			
		||||
            Dictionary<string, object> arguments = _arguments.GetArguments(scope);
 | 
			
		||||
            IEnumerable<NestedContext> 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));
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
        /// <returns>The name of the tags that are in scope.</returns>
 | 
			
		||||
        protected override IEnumerable<string> GetChildTags()
 | 
			
		||||
        {
 | 
			
		||||
            return new string[] { };
 | 
			
		||||
            return new string[] { "index" };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,8 @@ namespace Mustache
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="scope">The current lexical scope of the keys.</param>
 | 
			
		||||
        /// <param name="writer">The text writer to send all text to.</param>
 | 
			
		||||
        /// <param name="contextData">The data associated to the context.</param>
 | 
			
		||||
        /// <returns>The generated text.</returns>
 | 
			
		||||
        void GetText(KeyScope scope, TextWriter writer);
 | 
			
		||||
        void GetText(KeyScope scope, TextWriter writer, object contextData);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										40
									
								
								mustache-sharp/IndexTagDefinition.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								mustache-sharp/IndexTagDefinition.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
 | 
			
		||||
namespace Mustache
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Defines a tag that outputs the current index within an each loop.
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    internal sealed class IndexTagDefinition : InlineTagDefinition
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initializes a new instance of an IndexTagDefinition.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IndexTagDefinition()
 | 
			
		||||
            : base("index")
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets whether the tag only exists within the scope of its parent.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected override bool GetIsContextSensitive()
 | 
			
		||||
        {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets the text to output.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="writer">The writer to write the output to.</param>
 | 
			
		||||
        /// <param name="arguments">The arguments passed to the tag.</param>
 | 
			
		||||
        /// <param name="contextData">Extra data passed along with the context.</param>
 | 
			
		||||
        public override void GetText(TextWriter writer, Dictionary<string, object> arguments, object contextData)
 | 
			
		||||
        {
 | 
			
		||||
            int index = (int)contextData;
 | 
			
		||||
            writer.Write(index);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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<string, object> arguments = _arguments.GetArguments(scope);
 | 
			
		||||
            _definition.GetText(writer, arguments);
 | 
			
		||||
            _definition.GetText(writer, arguments, contextData);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -45,5 +45,10 @@ namespace Mustache
 | 
			
		||||
            get;
 | 
			
		||||
            set;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets or sets data associated with the context.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public object Data { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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")]
 | 
			
		||||
@ -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);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -152,7 +152,8 @@ namespace Mustache
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="writer">The text writer to write to.</param>
 | 
			
		||||
        /// <param name="arguments">The arguments passed to the tag.</param>
 | 
			
		||||
        public virtual void GetText(TextWriter writer, Dictionary<string, object> arguments)
 | 
			
		||||
        /// <param name="contextData">The data associated to the context.</param>
 | 
			
		||||
        public virtual void GetText(TextWriter writer, Dictionary<string, object> arguments, object contextData)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,7 @@
 | 
			
		||||
    <Compile Include="ContentTagDefinition.cs" />
 | 
			
		||||
    <Compile Include="Context.cs" />
 | 
			
		||||
    <Compile Include="ContextParameter.cs" />
 | 
			
		||||
    <Compile Include="IndexTagDefinition.cs" />
 | 
			
		||||
    <Compile Include="KeyFoundEventArgs.cs" />
 | 
			
		||||
    <Compile Include="InlineTagDefinition.cs" />
 | 
			
		||||
    <Compile Include="EachTagDefinition.cs" />
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user