Begin implementation of context scopes.
Instead of context data being a single object, it now supports the same scoping rules as keys. Now the #index tag is always available.
This commit is contained in:
parent
eb7e909f95
commit
f136dd61a5
|
@ -1093,7 +1093,7 @@ Item Number: foo<br />
|
|||
return new TagParameter[] { new TagParameter("param") { IsRequired = false, DefaultValue = 123 } };
|
||||
}
|
||||
|
||||
public override void GetText(TextWriter writer, Dictionary<string, object> arguments, object contextData)
|
||||
public override void GetText(TextWriter writer, Dictionary<string, object> arguments, Scope contextScope)
|
||||
{
|
||||
writer.Write(arguments["param"]);
|
||||
}
|
||||
|
@ -1168,5 +1168,23 @@ Your order total was: $7.50";
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Context Variables
|
||||
|
||||
/// <summary>
|
||||
/// We will use the index variable to determine whether or not to print out a line.
|
||||
/// </summary>
|
||||
[TestMethod]
|
||||
public void TestCompile_CanUseContextVariablesToMakeDecisions()
|
||||
{
|
||||
FormatCompiler compiler = new FormatCompiler();
|
||||
const string format = @"{{#each this}}{{#if @index}}{{#index}}{{/if}}{{/each}}";
|
||||
Generator generator = compiler.Compile(format);
|
||||
string actual = generator.Render(new int[] { 1, 1, 1, 1, });
|
||||
string expected = "123";
|
||||
Assert.AreEqual(expected, actual, "The numbers were not valid.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,9 +50,10 @@ namespace Mustache
|
|||
/// <summary>
|
||||
/// Substitutes the key placeholders with their respective values.
|
||||
/// </summary>
|
||||
/// <param name="scope">The current lexical scope.</param>
|
||||
/// <param name="keyScope">The key/value pairs in the current lexical scope.</param>
|
||||
/// <param name="contextScope">The key/value pairs in current context.</param>
|
||||
/// <returns>A dictionary associating the parameter name to the associated value.</returns>
|
||||
public Dictionary<string, object> GetArguments(KeyScope scope)
|
||||
public Dictionary<string, object> GetArguments(Scope keyScope, Scope contextScope)
|
||||
{
|
||||
Dictionary<string, object> arguments = new Dictionary<string,object>();
|
||||
foreach (KeyValuePair<TagParameter, string> pair in _argumentLookup)
|
||||
|
@ -62,13 +63,27 @@ namespace Mustache
|
|||
{
|
||||
value = pair.Key.DefaultValue;
|
||||
}
|
||||
else if (pair.Value.StartsWith("@"))
|
||||
{
|
||||
value = contextScope.Find(pair.Value.Substring(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
value = scope.Find(pair.Value);
|
||||
value = keyScope.Find(pair.Value);
|
||||
}
|
||||
arguments.Add(pair.Key.Name, value);
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public Dictionary<string, object> GetArguments()
|
||||
{
|
||||
Dictionary<string, object> arguments = new Dictionary<string, object>();
|
||||
foreach (KeyValuePair<TagParameter, string> pair in _argumentLookup)
|
||||
{
|
||||
arguments.Add(pair.Key.Name, pair.Value);
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,10 +59,10 @@ namespace Mustache
|
|||
}
|
||||
}
|
||||
|
||||
void IGenerator.GetText(KeyScope scope, TextWriter writer, object contextData)
|
||||
void IGenerator.GetText(Scope keyScope, TextWriter writer, Scope contextScope)
|
||||
{
|
||||
Dictionary<string, object> arguments = _arguments.GetArguments(scope);
|
||||
IEnumerable<NestedContext> contexts = _definition.GetChildContext(writer, scope, arguments);
|
||||
Dictionary<string, object> arguments = _arguments.GetArguments(keyScope, contextScope);
|
||||
IEnumerable<NestedContext> contexts = _definition.GetChildContext(writer, keyScope, arguments, contextScope);
|
||||
List<IGenerator> generators;
|
||||
if (_definition.ShouldGeneratePrimaryGroup(arguments))
|
||||
{
|
||||
|
@ -80,7 +80,7 @@ namespace Mustache
|
|||
{
|
||||
foreach (IGenerator generator in generators)
|
||||
{
|
||||
generator.GetText(context.KeyScope ?? scope, context.Writer ?? writer, context.Data);
|
||||
generator.GetText(context.KeyScope ?? keyScope, context.Writer ?? writer, context.ContextScope);
|
||||
if (context.WriterNeedsConsidated)
|
||||
{
|
||||
writer.Write(_definition.ConsolidateWriter(context.Writer ?? writer, arguments));
|
||||
|
|
|
@ -43,10 +43,14 @@ namespace Mustache
|
|||
/// Gets the context to use when building the inner text of the tag.
|
||||
/// </summary>
|
||||
/// <param name="writer">The text writer passed</param>
|
||||
/// <param name="scope">The current scope.</param>
|
||||
/// <param name="keyScope">The current scope.</param>
|
||||
/// <param name="arguments">The arguments passed to the tag.</param>
|
||||
/// <returns>The scope to use when building the inner text of the tag.</returns>
|
||||
public override IEnumerable<NestedContext> GetChildContext(TextWriter writer, KeyScope scope, Dictionary<string, object> arguments)
|
||||
public override IEnumerable<NestedContext> GetChildContext(
|
||||
TextWriter writer,
|
||||
Scope keyScope,
|
||||
Dictionary<string, object> arguments,
|
||||
Scope contextScope)
|
||||
{
|
||||
object value = arguments[collectionParameter];
|
||||
IEnumerable enumerable = value as IEnumerable;
|
||||
|
@ -57,7 +61,14 @@ namespace Mustache
|
|||
int index = 0;
|
||||
foreach (object item in enumerable)
|
||||
{
|
||||
yield return new NestedContext() { KeyScope = scope.CreateChildScope(item), Writer = writer, Data = index };
|
||||
NestedContext childContext = new NestedContext()
|
||||
{
|
||||
KeyScope = keyScope.CreateChildScope(item),
|
||||
Writer = writer,
|
||||
ContextScope = contextScope.CreateChildScope(),
|
||||
};
|
||||
childContext.ContextScope.Set("index", index);
|
||||
yield return childContext;
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ namespace Mustache
|
|||
_tagLookup.Add(withDefinition.Name, withDefinition);
|
||||
NewlineTagDefinition newlineDefinition = new NewlineTagDefinition();
|
||||
_tagLookup.Add(newlineDefinition.Name, newlineDefinition);
|
||||
SetTagDefinition setDefinition = new SetTagDefinition();
|
||||
_tagLookup.Add(setDefinition.Name, setDefinition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -150,9 +152,11 @@ namespace Mustache
|
|||
foreach (TagParameter parameter in definition.Parameters)
|
||||
{
|
||||
regexBuilder.Append(@"(\s+?");
|
||||
regexBuilder.Append(@"(?<argument>");
|
||||
regexBuilder.Append(@"(?<argument>(");
|
||||
regexBuilder.Append(RegexHelper.CompoundKey);
|
||||
regexBuilder.Append(@"))");
|
||||
regexBuilder.Append("|@");
|
||||
regexBuilder.Append(RegexHelper.Key);
|
||||
regexBuilder.Append(@")))");
|
||||
if (!parameter.IsRequired)
|
||||
{
|
||||
regexBuilder.Append("?");
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace Mustache
|
|||
|
||||
private string render(IFormatProvider provider, object source)
|
||||
{
|
||||
KeyScope scope = new KeyScope(source);
|
||||
Scope scope = new Scope(source);
|
||||
foreach (EventHandler<KeyFoundEventArgs> handler in _foundHandlers)
|
||||
{
|
||||
scope.KeyFound += handler;
|
||||
|
@ -80,7 +80,8 @@ namespace Mustache
|
|||
scope.KeyNotFound += handler;
|
||||
}
|
||||
StringWriter writer = new StringWriter(provider);
|
||||
_generator.GetText(scope, writer, null);
|
||||
Scope contextScope = new Scope(new Dictionary<string, object>());
|
||||
_generator.GetText(scope, writer, contextScope);
|
||||
return writer.ToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@ namespace Mustache
|
|||
/// <summary>
|
||||
/// Generates the text when applying the format plan.
|
||||
/// </summary>
|
||||
/// <param name="scope">The current lexical scope of the keys.</param>
|
||||
/// <param name="keyScope">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>
|
||||
/// <param name="contextScope">The data associated to the context.</param>
|
||||
/// <returns>The generated text.</returns>
|
||||
void GetText(KeyScope scope, TextWriter writer, object contextData);
|
||||
void GetText(Scope keyScope, TextWriter writer, Scope contextScope);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,28 +13,23 @@ namespace Mustache
|
|||
/// Initializes a new instance of an IndexTagDefinition.
|
||||
/// </summary>
|
||||
public IndexTagDefinition()
|
||||
: base("index")
|
||||
: base("index", true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <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)
|
||||
/// <param name="contextScope">Extra data passed along with the context.</param>
|
||||
public override void GetText(TextWriter writer, Dictionary<string, object> arguments, Scope contextScope)
|
||||
{
|
||||
object index;
|
||||
if (contextScope.TryFind("index", out index))
|
||||
{
|
||||
int index = (int)contextData;
|
||||
writer.Write(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ using System.IO;
|
|||
namespace Mustache
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates the text for a tag that only exists on a single line.
|
||||
/// Generates the text for a tag that is replaced with its generated text.
|
||||
/// </summary>
|
||||
internal sealed class InlineGenerator : IGenerator
|
||||
{
|
||||
|
@ -23,10 +23,18 @@ namespace Mustache
|
|||
_arguments = arguments;
|
||||
}
|
||||
|
||||
void IGenerator.GetText(KeyScope scope, TextWriter writer, object contextData)
|
||||
void IGenerator.GetText(Scope scope, TextWriter writer, Scope context)
|
||||
{
|
||||
Dictionary<string, object> arguments = _arguments.GetArguments(scope);
|
||||
_definition.GetText(writer, arguments, contextData);
|
||||
Dictionary<string, object> arguments;
|
||||
if (_definition.IsSetter)
|
||||
{
|
||||
arguments = _arguments.GetArguments();
|
||||
}
|
||||
else
|
||||
{
|
||||
arguments = _arguments.GetArguments(scope, context);
|
||||
}
|
||||
_definition.GetText(writer, arguments, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace Mustache
|
|||
return formatBuilder.ToString();
|
||||
}
|
||||
|
||||
void IGenerator.GetText(KeyScope scope, TextWriter writer, object contextData)
|
||||
void IGenerator.GetText(Scope scope, TextWriter writer, Scope context)
|
||||
{
|
||||
object value = scope.Find(_key);
|
||||
writer.Write(_format, value);
|
||||
|
|
|
@ -19,36 +19,24 @@ namespace Mustache
|
|||
/// Gets or sets the writer to use when generating the child context.
|
||||
/// </summary>
|
||||
/// <remarks>Setting the writer to null will indicate that the tag's writer should be used.</remarks>
|
||||
public TextWriter Writer
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public TextWriter Writer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the text sent to the returned writer needs to be added
|
||||
/// to the parent tag's writer. This should be false if the parent writer is
|
||||
/// being returned or is being wrapped.
|
||||
/// </summary>
|
||||
public bool WriterNeedsConsidated
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public bool WriterNeedsConsidated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the scope to use when generating the child context.
|
||||
/// Gets or sets the key scope to use when generating the child context.
|
||||
/// </summary>
|
||||
/// <remarks>Setting the scope to null will indicate that the current scope should be used.</remarks>
|
||||
public KeyScope KeyScope
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public Scope KeyScope { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets data associated with the context.
|
||||
/// </summary>
|
||||
public object Data { get; set; }
|
||||
public Scope ContextScope { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ namespace Mustache
|
|||
/// </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)
|
||||
/// <param name="context">Extra data passed along with the context.</param>
|
||||
public override void GetText(TextWriter writer, Dictionary<string, object> arguments, Scope context)
|
||||
{
|
||||
writer.Write(Environment.NewLine);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace Mustache
|
|||
/// </summary>
|
||||
public static class RegexHelper
|
||||
{
|
||||
private const string Key = @"[_\w][_\w\d]*";
|
||||
internal const string Key = @"[_\w][_\w\d]*";
|
||||
internal const string CompoundKey = Key + @"(\." + Key + ")*";
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -9,16 +9,16 @@ namespace Mustache
|
|||
/// <summary>
|
||||
/// Represents a scope of keys.
|
||||
/// </summary>
|
||||
public sealed class KeyScope
|
||||
public sealed class Scope
|
||||
{
|
||||
private readonly object _source;
|
||||
private readonly KeyScope _parent;
|
||||
private readonly Scope _parent;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of a KeyScope.
|
||||
/// </summary>
|
||||
/// <param name="source">The object to search for keys in.</param>
|
||||
internal KeyScope(object source)
|
||||
internal Scope(object source)
|
||||
: this(source, null)
|
||||
{
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ namespace Mustache
|
|||
/// </summary>
|
||||
/// <param name="source">The object to search for keys in.</param>
|
||||
/// <param name="parent">The parent scope to search in if the value is not found.</param>
|
||||
internal KeyScope(object source, KeyScope parent)
|
||||
internal Scope(object source, Scope parent)
|
||||
{
|
||||
_parent = parent;
|
||||
_source = source;
|
||||
|
@ -44,14 +44,23 @@ namespace Mustache
|
|||
/// </summary>
|
||||
public event EventHandler<KeyNotFoundEventArgs> KeyNotFound;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a child scope that searches for keys in a default dictionary of key/value pairs.
|
||||
/// </summary>
|
||||
/// <returns>The new child scope.</returns>
|
||||
public Scope CreateChildScope()
|
||||
{
|
||||
return CreateChildScope(new Dictionary<string, object>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a child scope that searches for keys in the given object.
|
||||
/// </summary>
|
||||
/// <param name="source">The object to search for keys in.</param>
|
||||
/// <returns>The new child scope.</returns>
|
||||
public KeyScope CreateChildScope(object source)
|
||||
public Scope CreateChildScope(object source)
|
||||
{
|
||||
KeyScope scope = new KeyScope(source, this);
|
||||
Scope scope = new Scope(source, this);
|
||||
scope.KeyFound = KeyFound;
|
||||
scope.KeyNotFound = KeyNotFound;
|
||||
return scope;
|
||||
|
@ -65,58 +74,45 @@ namespace Mustache
|
|||
/// <exception cref="System.Collections.Generic.KeyNotFoundException">A key with the given name could not be found.</exception>
|
||||
internal object Find(string name)
|
||||
{
|
||||
string[] names = name.Split('.');
|
||||
string member = names[0];
|
||||
object nextLevel = _source;
|
||||
if (member != "this")
|
||||
string member = null;
|
||||
object value = null;
|
||||
if (tryFind(name, ref member, ref value))
|
||||
{
|
||||
nextLevel = find(name, member);
|
||||
onKeyFound(name, ref value);
|
||||
return value;
|
||||
}
|
||||
for (int index = 1; index < names.Length; ++index)
|
||||
if (onKeyNotFound(name, member, ref value))
|
||||
{
|
||||
IDictionary<string, object> context = toLookup(nextLevel);
|
||||
member = names[index];
|
||||
if (!context.TryGetValue(member, out nextLevel))
|
||||
return value;
|
||||
}
|
||||
string message = String.Format(CultureInfo.CurrentCulture, Resources.KeyNotFound, member);
|
||||
throw new KeyNotFoundException(message);
|
||||
}
|
||||
|
||||
private void onKeyFound(string name, ref object value)
|
||||
{
|
||||
nextLevel = handleKeyNotFound(name, member);
|
||||
}
|
||||
}
|
||||
if (KeyFound != null)
|
||||
{
|
||||
KeyFoundEventArgs args = new KeyFoundEventArgs(name, nextLevel);
|
||||
KeyFoundEventArgs args = new KeyFoundEventArgs(name, value);
|
||||
KeyFound(this, args);
|
||||
nextLevel = args.Substitute;
|
||||
value = args.Substitute;
|
||||
}
|
||||
return nextLevel;
|
||||
}
|
||||
|
||||
private object find(string fullName, string memberName)
|
||||
private bool onKeyNotFound(string name, string member, ref object value)
|
||||
{
|
||||
IDictionary<string, object> lookup = toLookup(_source);
|
||||
if (lookup.ContainsKey(memberName))
|
||||
if (KeyNotFound == null)
|
||||
{
|
||||
return lookup[memberName];
|
||||
return false;
|
||||
}
|
||||
if (_parent == null)
|
||||
{
|
||||
return handleKeyNotFound(fullName, memberName);
|
||||
}
|
||||
return _parent.find(fullName, memberName);
|
||||
}
|
||||
|
||||
private object handleKeyNotFound(string fullName, string memberName)
|
||||
{
|
||||
KeyNotFoundEventArgs args = new KeyNotFoundEventArgs(fullName, memberName);
|
||||
if (KeyNotFound != null)
|
||||
{
|
||||
KeyNotFoundEventArgs args = new KeyNotFoundEventArgs(name, member);
|
||||
KeyNotFound(this, args);
|
||||
}
|
||||
if (args.Handled)
|
||||
if (!args.Handled)
|
||||
{
|
||||
return args.Substitute;
|
||||
return false;
|
||||
}
|
||||
string message = String.Format(CultureInfo.CurrentCulture, Resources.KeyNotFound, memberName);
|
||||
throw new KeyNotFoundException(message);
|
||||
value = args.Substitute;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static IDictionary<string, object> toLookup(object value)
|
||||
|
@ -128,5 +124,59 @@ namespace Mustache
|
|||
}
|
||||
return lookup;
|
||||
}
|
||||
|
||||
internal void Set(string key, object value)
|
||||
{
|
||||
IDictionary<string, object> lookup = toLookup(_source);
|
||||
lookup[key] = value;
|
||||
}
|
||||
|
||||
public bool TryFind(string name, out object value)
|
||||
{
|
||||
string member = null;
|
||||
value = null;
|
||||
return tryFind(name, ref member, ref value);
|
||||
}
|
||||
|
||||
private bool tryFind(string name, ref string member, ref object value)
|
||||
{
|
||||
string[] names = name.Split('.');
|
||||
member = names[0];
|
||||
value = _source;
|
||||
if (member != "this")
|
||||
{
|
||||
if (!tryFindFirst(member, ref value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int index = 1; index < names.Length; ++index)
|
||||
{
|
||||
IDictionary<string, object> context = toLookup(value);
|
||||
member = names[index];
|
||||
if (!context.TryGetValue(member, out value))
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool tryFindFirst(string member, ref object value)
|
||||
{
|
||||
IDictionary<string, object> lookup = toLookup(_source);
|
||||
if (lookup.ContainsKey(member))
|
||||
{
|
||||
value = lookup[member];
|
||||
return true;
|
||||
}
|
||||
if (_parent == null)
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
return _parent.tryFindFirst(member, ref value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Mustache
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a tag that declares a named value in the current context.
|
||||
/// </summary>
|
||||
internal sealed class SetTagDefinition : InlineTagDefinition
|
||||
{
|
||||
private const string nameParameter = "name";
|
||||
private static readonly TagParameter name = new TagParameter(nameParameter) { IsRequired = true };
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of an SetTagDefinition.
|
||||
/// </summary>
|
||||
public SetTagDefinition()
|
||||
: base("set", true)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool GetIsSetter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override IEnumerable<TagParameter> GetParameters()
|
||||
{
|
||||
return new TagParameter[] { name };
|
||||
}
|
||||
|
||||
/// <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="contextScope">Extra data passed along with the context.</param>
|
||||
public override void GetText(TextWriter writer, Dictionary<string, object> arguments, Scope contextScope)
|
||||
{
|
||||
string name = (string)arguments[nameParameter];
|
||||
// TODO - get the value for the variable
|
||||
object value = null;
|
||||
contextScope.Set(name, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ namespace Mustache
|
|||
get { return value; }
|
||||
}
|
||||
|
||||
void IGenerator.GetText(KeyScope scope, TextWriter writer, object contextData)
|
||||
void IGenerator.GetText(Scope scope, TextWriter writer, Scope context)
|
||||
{
|
||||
writer.Write(Value);
|
||||
}
|
||||
|
|
|
@ -44,6 +44,16 @@ namespace Mustache
|
|||
get { return _tagName; }
|
||||
}
|
||||
|
||||
internal bool IsSetter
|
||||
{
|
||||
get { return GetIsSetter(); }
|
||||
}
|
||||
|
||||
protected virtual bool GetIsSetter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the tag is limited to the parent tag's context.
|
||||
/// </summary>
|
||||
|
@ -139,12 +149,22 @@ namespace Mustache
|
|||
/// Gets the context to use when building the inner text of the tag.
|
||||
/// </summary>
|
||||
/// <param name="writer">The text writer passed</param>
|
||||
/// <param name="scope">The current scope.</param>
|
||||
/// <param name="keyScope">The current key scope.</param>
|
||||
/// <param name="arguments">The arguments passed to the tag.</param>
|
||||
/// <returns>The scope to use when building the inner text of the tag.</returns>
|
||||
public virtual IEnumerable<NestedContext> GetChildContext(TextWriter writer, KeyScope scope, Dictionary<string, object> arguments)
|
||||
public virtual IEnumerable<NestedContext> GetChildContext(
|
||||
TextWriter writer,
|
||||
Scope keyScope,
|
||||
Dictionary<string, object> arguments,
|
||||
Scope contextScope)
|
||||
{
|
||||
yield return new NestedContext() { KeyScope = scope, Writer = writer };
|
||||
NestedContext context = new NestedContext()
|
||||
{
|
||||
KeyScope = keyScope,
|
||||
Writer = writer,
|
||||
ContextScope = contextScope.CreateChildScope()
|
||||
};
|
||||
yield return context;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -152,8 +172,8 @@ namespace Mustache
|
|||
/// </summary>
|
||||
/// <param name="writer">The text writer to write to.</param>
|
||||
/// <param name="arguments">The arguments passed to the tag.</param>
|
||||
/// <param name="contextData">The data associated to the context.</param>
|
||||
public virtual void GetText(TextWriter writer, Dictionary<string, object> arguments, object contextData)
|
||||
/// <param name="context">The data associated to the context.</param>
|
||||
public virtual void GetText(TextWriter writer, Dictionary<string, object> arguments, Scope context)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -50,13 +50,23 @@ namespace Mustache
|
|||
/// Gets the context to use when building the inner text of the tag.
|
||||
/// </summary>
|
||||
/// <param name="writer">The text writer passed</param>
|
||||
/// <param name="scope">The current scope.</param>
|
||||
/// <param name="keyScope">The current key scope.</param>
|
||||
/// <param name="arguments">The arguments passed to the tag.</param>
|
||||
/// <returns>The scope to use when building the inner text of the tag.</returns>
|
||||
public override IEnumerable<NestedContext> GetChildContext(TextWriter writer, KeyScope scope, Dictionary<string, object> arguments)
|
||||
public override IEnumerable<NestedContext> GetChildContext(
|
||||
TextWriter writer,
|
||||
Scope keyScope,
|
||||
Dictionary<string, object> arguments,
|
||||
Scope contextScope)
|
||||
{
|
||||
object context = arguments[contextParameter];
|
||||
yield return new NestedContext() { KeyScope = scope.CreateChildScope(context), Writer = writer };
|
||||
object contextSource = arguments[contextParameter];
|
||||
NestedContext context = new NestedContext()
|
||||
{
|
||||
KeyScope = keyScope.CreateChildScope(contextSource),
|
||||
Writer = writer,
|
||||
ContextScope = contextScope.CreateChildScope()
|
||||
};
|
||||
yield return context;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,6 +40,7 @@
|
|||
<Compile Include="ContentTagDefinition.cs" />
|
||||
<Compile Include="Context.cs" />
|
||||
<Compile Include="ContextParameter.cs" />
|
||||
<Compile Include="SetTagDefinition.cs" />
|
||||
<Compile Include="NewlineTagDefinition.cs" />
|
||||
<Compile Include="IndexTagDefinition.cs" />
|
||||
<Compile Include="KeyFoundEventArgs.cs" />
|
||||
|
@ -68,8 +69,8 @@
|
|||
<Compile Include="StaticGenerator.cs" />
|
||||
<Compile Include="TagDefinition.cs" />
|
||||
<Compile Include="TagParameter.cs" />
|
||||
<Compile Include="KeyScope.cs" />
|
||||
<Compile Include="WithGenerator.cs" />
|
||||
<Compile Include="Scope.cs" />
|
||||
<Compile Include="WithTagDefinition.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
|
|
Loading…
Reference in New Issue