diff --git a/mustache-sharp.test/FormatCompilerTester.cs b/mustache-sharp.test/FormatCompilerTester.cs
index ad563e5..b57d1fc 100644
--- a/mustache-sharp.test/FormatCompilerTester.cs
+++ b/mustache-sharp.test/FormatCompilerTester.cs
@@ -1387,5 +1387,69 @@ Odd
}
#endregion
+
+ #region Strings
+
+ ///
+ /// We will use a string variable to determine whether or not to print out a line.
+ ///
+ [TestMethod]
+ public void TestCompile_StringArgument_PassedToTag()
+ {
+ FormatCompiler compiler = new FormatCompiler();
+ const string format = @"{{#if 'hello'}}Hello{{/if}}";
+ Generator generator = compiler.Compile(format);
+ string actual = generator.Render(null);
+ string expected = "Hello";
+ Assert.AreEqual(expected, actual, "The string was not passed to the formatter.");
+ }
+
+ ///
+ /// We will use a string variable to determine whether or not to print out a line.
+ ///
+ [TestMethod]
+ public void TestCompile_EmptyStringArgument_PassedToTag()
+ {
+ FormatCompiler compiler = new FormatCompiler();
+ const string format = @"{{#if ''}}Hello{{/if}}";
+ Generator generator = compiler.Compile(format);
+ string actual = generator.Render(null);
+ string expected = "";
+ Assert.AreEqual(expected, actual, "The string was not passed to the formatter.");
+ }
+
+ #endregion
+
+ #region Numbers
+
+ ///
+ /// We will use a number variable to determine whether or not to print out a line.
+ ///
+ [TestMethod]
+ public void TestCompile_NumberArgument_PassedToTag()
+ {
+ FormatCompiler compiler = new FormatCompiler();
+ const string format = @"{{#if 4}}Hello{{/if}}";
+ Generator generator = compiler.Compile(format);
+ string actual = generator.Render(null);
+ string expected = "Hello";
+ Assert.AreEqual(expected, actual, "The number was not passed to the formatter.");
+ }
+
+ ///
+ /// We will use a string variable to determine whether or not to print out a line.
+ ///
+ [TestMethod]
+ public void TestCompile_ZeroNumberArgument_PassedToTag()
+ {
+ FormatCompiler compiler = new FormatCompiler();
+ const string format = @"{{#if 00.0000}}Hello{{/if}}";
+ Generator generator = compiler.Compile(format);
+ string actual = generator.Render(null);
+ string expected = "";
+ Assert.AreEqual(expected, actual, "The number was not passed to the formatter.");
+ }
+
+ #endregion
}
}
diff --git a/mustache-sharp/ArgumentCollection.cs b/mustache-sharp/ArgumentCollection.cs
index 97d41f8..07c23af 100644
--- a/mustache-sharp/ArgumentCollection.cs
+++ b/mustache-sharp/ArgumentCollection.cs
@@ -9,25 +9,25 @@ namespace Mustache
///
internal sealed class ArgumentCollection
{
- private readonly Dictionary _argumentLookup;
+ private readonly Dictionary _argumentLookup;
///
/// Initializes a new instance of an ArgumentCollection.
///
public ArgumentCollection()
{
- _argumentLookup = new Dictionary();
+ _argumentLookup = new Dictionary();
}
///
/// Associates the given parameter to the key placeholder.
///
/// The parameter to associate the key with.
- /// The key placeholder used as the argument.
+ /// The argument.
/// If the key is null, the default value of the parameter will be used.
- public void AddArgument(TagParameter parameter, string key)
+ public void AddArgument(TagParameter parameter, IArgument argument)
{
- _argumentLookup.Add(parameter, key);
+ _argumentLookup.Add(parameter, argument);
}
///
@@ -36,10 +36,10 @@ namespace Mustache
/// The name of the parameter.
public string GetKey(TagParameter parameter)
{
- string key;
- if (_argumentLookup.TryGetValue(parameter, out key))
+ IArgument argument;
+ if (_argumentLookup.TryGetValue(parameter, out argument) && argument != null)
{
- return key;
+ return argument.GetKey();
}
else
{
@@ -56,20 +56,16 @@ namespace Mustache
public Dictionary GetArguments(Scope keyScope, Scope contextScope)
{
Dictionary arguments = new Dictionary();
- foreach (KeyValuePair pair in _argumentLookup)
+ foreach (KeyValuePair pair in _argumentLookup)
{
object value;
if (pair.Value == null)
{
value = pair.Key.DefaultValue;
}
- else if (pair.Value.StartsWith("@"))
- {
- value = contextScope.Find(pair.Value.Substring(1));
- }
else
{
- value = keyScope.Find(pair.Value);
+ value = pair.Value.GetValue(keyScope, contextScope);
}
arguments.Add(pair.Key.Name, value);
}
@@ -78,7 +74,7 @@ namespace Mustache
public Dictionary GetArgumentKeyNames()
{
- return _argumentLookup.ToDictionary(p => p.Key.Name, p => (object)p.Value);
+ return _argumentLookup.ToDictionary(p => p.Key.Name, p => (object)GetKey(p.Key));
}
}
}
diff --git a/mustache-sharp/FormatCompiler.cs b/mustache-sharp/FormatCompiler.cs
index f9dfea1..530eb92 100644
--- a/mustache-sharp/FormatCompiler.cs
+++ b/mustache-sharp/FormatCompiler.cs
@@ -152,7 +152,7 @@ namespace Mustache
private static string getKeyRegex()
{
- return @"((?@?" + RegexHelper.CompoundKey + @")(,(?(\+|-)?[\d]+))?(:(?.*?))?)";
+ return @"((?" + RegexHelper.CompoundKey + @")(,(?(\+|-)?[\d]+))?(:(?.*?))?)";
}
private static string getTagRegex(TagDefinition definition)
@@ -164,8 +164,8 @@ namespace Mustache
foreach (TagParameter parameter in definition.Parameters)
{
regexBuilder.Append(@"(\s+?");
- regexBuilder.Append(@"(?(@?");
- regexBuilder.Append(RegexHelper.CompoundKey);
+ regexBuilder.Append(@"(?(");
+ regexBuilder.Append(RegexHelper.Argument);
regexBuilder.Append(@")))");
if (!parameter.IsRequired)
{
@@ -341,28 +341,46 @@ namespace Mustache
foreach (var pair in arguments)
{
string placeholder = pair.Value;
+ IArgument argument = null;
if (placeholder != null)
{
if (placeholder.StartsWith("@"))
{
+ string variableName = placeholder.Substring(1);
VariableFoundEventArgs args = new VariableFoundEventArgs(placeholder.Substring(1), String.Empty, String.Empty, context.ToArray());
if (VariableFound != null)
{
VariableFound(this, args);
- placeholder = "@" + args.Name;
+ variableName = args.Name;
+ }
+ argument = new VariableArgument(variableName);
+ }
+ else if (RegexHelper.IsString(placeholder))
+ {
+ string value = placeholder.Trim('\'');
+ argument = new StringArgument(value);
+ }
+ else if (RegexHelper.IsNumber(placeholder))
+ {
+ decimal number;
+ if (Decimal.TryParse(placeholder, out number))
+ {
+ argument = new NumberArgument(number);
}
}
else
{
+ string placeholderName = placeholder;
PlaceholderFoundEventArgs args = new PlaceholderFoundEventArgs(placeholder, String.Empty, String.Empty, context.ToArray());
if (PlaceholderFound != null)
{
PlaceholderFound(this, args);
- placeholder = args.Key;
+ placeholderName = args.Key;
}
+ argument = new PlaceholderArgument(placeholderName);
}
}
- collection.AddArgument(pair.Key, placeholder);
+ collection.AddArgument(pair.Key, argument);
}
return collection;
}
diff --git a/mustache-sharp/IArgument.cs b/mustache-sharp/IArgument.cs
new file mode 100644
index 0000000..4877cc2
--- /dev/null
+++ b/mustache-sharp/IArgument.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Mustache
+{
+ public interface IArgument
+ {
+ string GetKey();
+
+ object GetValue(Scope keyScope, Scope contextScope);
+ }
+}
diff --git a/mustache-sharp/NumberArgument.cs b/mustache-sharp/NumberArgument.cs
new file mode 100644
index 0000000..ec40ae4
--- /dev/null
+++ b/mustache-sharp/NumberArgument.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Mustache
+{
+ public class NumberArgument : IArgument
+ {
+ private readonly decimal value;
+
+ public NumberArgument(decimal value)
+ {
+ this.value = value;
+ }
+
+ public string GetKey()
+ {
+ return null;
+ }
+
+ public object GetValue(Scope keyScope, Scope contextScope)
+ {
+ return value;
+ }
+ }
+}
diff --git a/mustache-sharp/PlaceholderArgument.cs b/mustache-sharp/PlaceholderArgument.cs
new file mode 100644
index 0000000..39047f3
--- /dev/null
+++ b/mustache-sharp/PlaceholderArgument.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Mustache
+{
+ public class PlaceholderArgument : IArgument
+ {
+ private readonly string name;
+
+ public PlaceholderArgument(string name)
+ {
+ this.name = name;
+ }
+
+ public string GetKey()
+ {
+ return name;
+ }
+
+ public object GetValue(Scope keyScope, Scope contextScope)
+ {
+ return keyScope.Find(name);
+ }
+ }
+}
diff --git a/mustache-sharp/RegexHelper.cs b/mustache-sharp/RegexHelper.cs
index c6738cb..c3bbc1a 100644
--- a/mustache-sharp/RegexHelper.cs
+++ b/mustache-sharp/RegexHelper.cs
@@ -6,10 +6,13 @@ namespace Mustache
///
/// Provides utility methods that require regular expressions.
///
- public static class RegexHelper
+ internal static class RegexHelper
{
- internal const string Key = @"[_\w][_\w\d]*";
- internal const string CompoundKey = Key + @"(\." + Key + ")*";
+ public const string Key = @"[_\w][_\w\d]*";
+ public const string String = @"'.*?'";
+ public const string Number = @"[-+]?\d*\.?\d+";
+ public const string CompoundKey = "@?" + Key + @"(?:\." + Key + ")*";
+ public const string Argument = @"(?:(?" + CompoundKey + @")|(?" + String + @")|(?" + Number + @"))";
///
/// Determines whether the given name is a legal identifier.
@@ -25,5 +28,25 @@ namespace Mustache
Regex regex = new Regex("^" + Key + "$");
return regex.IsMatch(name);
}
+
+ public static bool IsString(string value)
+ {
+ if (value == null)
+ {
+ return false;
+ }
+ Regex regex = new Regex("^" + String + "$");
+ return regex.IsMatch(value);
+ }
+
+ public static bool IsNumber(string value)
+ {
+ if (value == null)
+ {
+ return false;
+ }
+ Regex regex = new Regex("^" + Number + "$");
+ return regex.IsMatch(value);
+ }
}
}
diff --git a/mustache-sharp/StringArgument.cs b/mustache-sharp/StringArgument.cs
new file mode 100644
index 0000000..36aeec6
--- /dev/null
+++ b/mustache-sharp/StringArgument.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Mustache
+{
+ public class StringArgument : IArgument
+ {
+ private readonly string value;
+
+ public StringArgument(string value)
+ {
+ this.value = value;
+ }
+
+ public string GetKey()
+ {
+ return null;
+ }
+
+ public object GetValue(Scope keyScope, Scope contextScope)
+ {
+ return value;
+ }
+ }
+}
diff --git a/mustache-sharp/VariableArgument.cs b/mustache-sharp/VariableArgument.cs
new file mode 100644
index 0000000..c59e128
--- /dev/null
+++ b/mustache-sharp/VariableArgument.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Mustache
+{
+ public class VariableArgument : IArgument
+ {
+ private readonly string name;
+
+ public VariableArgument(string name)
+ {
+ this.name = name;
+ }
+
+ public string GetKey()
+ {
+ return null;
+ }
+
+ public object GetValue(Scope keyScope, Scope contextScope)
+ {
+ return contextScope.Find(name);
+ }
+ }
+}
diff --git a/mustache-sharp/mustache-sharp.csproj b/mustache-sharp/mustache-sharp.csproj
index 7e35b1b..22eecdc 100644
--- a/mustache-sharp/mustache-sharp.csproj
+++ b/mustache-sharp/mustache-sharp.csproj
@@ -40,7 +40,12 @@
+
+
+
+
+