public void Should_combine_single_substitutions_and_each_substitutions() { var input = @"<html><head></head><body><ul>@Each.Users;<li>Hello @Current;, @Model.Name; says hello!</li>@EndEach;</ul></body></html>"; var model = new { Name = "Nancy", Users = new List <string>() { "Bob", "Jim", "Bill" } }; var output = Parse(input, model.GetType()); AssertSyntaxTree(output, SyntaxTree.WriteString("<html><head></head><body><ul>"), SyntaxTree.Iterate( SyntaxTreeExpression.Property(model.GetType(), "Users"), SyntaxTree.Block( SyntaxTree.WriteString("<li>Hello "), SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string), ExpressionScope.CurrentModelOnStack)), SyntaxTree.WriteString(", "), SyntaxTree.WriteExpression(SyntaxTreeExpression.Property(model.GetType(), "Name", ExpressionScope.RootModel)), SyntaxTree.WriteString(" says hello!</li>") ) ), SyntaxTree.WriteString("</ul></body></html>") ); }
public static ExpressionNode Parse(HandlebarsParserState state, HandlebarsBlockStack blockStack, SourceLocation location, string expression, IMemberLocator memberLocator = null) { int recursionLevel = 0; memberLocator = memberLocator ?? MemberLocator.Default; expression = expression.Trim(); if (expression == "this") { return(SyntaxTreeExpression.Self(blockStack.GetCurrentModelType(), location)); } if (expression.StartsWith("../")) { var blockNode = blockStack.FirstNode(); while (expression.StartsWith("../")) { var parentBlockNode = blockStack.GetParentNode(blockNode); if (parentBlockNode != null) { blockNode = parentBlockNode; expression = expression.Substring(3); location = location.MoveIndex(3); } recursionLevel++; } return(ParseAgainstModel(blockStack.GetCurrentModelType(blockNode), expression, ExpressionScope.ModelOfParentScope, recursionLevel, memberLocator, location)); } return(ParseAgainstModel(blockStack.GetCurrentModelType(), expression, ExpressionScope.CurrentModelOnStack, recursionLevel, memberLocator, location)); }
public void Should_parse_if_block_with_explicit_model_reference() { var input = @"<html><head></head><body>@If.Model.HasUsers;<ul>@Each.Users;<li>Hello @Current;, @Model.Name; says hello!</li>@EndEach;</ul>@EndIf;</body></html>"; var model = new FakeModel("Nancy", new List <string>() { "Bob", "Jim", "Bill" }); var output = Parse(input, model.GetType()); AssertSyntaxTree(output, SyntaxTree.WriteString("<html><head></head><body>"), SyntaxTree.Conditional( SyntaxTreeExpression.Property(model.GetType(), "HasUsers", ExpressionScope.RootModel), SyntaxTree.Block( SyntaxTree.WriteString("<ul>"), SyntaxTree.Iterate( SyntaxTreeExpression.Property(model.GetType(), "Users"), SyntaxTree.Block( SyntaxTree.WriteString("<li>Hello "), SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string))), SyntaxTree.WriteString(", "), SyntaxTree.WriteExpression(SyntaxTreeExpression.Property(model.GetType(), "Name", ExpressionScope.RootModel)), SyntaxTree.WriteString(" says hello!</li>") ) ), SyntaxTree.WriteString("</ul>") ) ), SyntaxTree.WriteString("</body></html>") ); }
private static void HandlePartial(HandlebarsParserState state) { var partialTemplateName = state.CurrentToken.Content.Substring(1).Trim(); var self = SyntaxTreeExpression.Self(state.BlockStack.GetCurrentModelType()); state.AddNodeToCurrentBlock(SyntaxTree.Include(partialTemplateName, self)); }
public void Should_return_true_for_ifhascollection_when_if_model_has_a_collection_with_items_but_no_bool() { var input = @"<html><head></head><body>@If.HasUsers;<ul>@Each.Users;<li>Hello @Current;, @Model.Name; says hello!</li>@EndEach;</ul>@EndIf;</body></html>"; var model = new { Users = new List <string>() { "Bob", "Jim", "Bill" }, Name = "Nancy" }; var output = Parse(input, model.GetType()); AssertSyntaxTree( output, SyntaxTree.WriteString("<html><head></head><body>"), SyntaxTree.Conditional( SyntaxTreeExpression.HasItems(SyntaxTreeExpression.Property(model.GetType(), "Users")), SyntaxTree.Block( SyntaxTree.WriteString("<ul>"), SyntaxTree.Iterate( SyntaxTreeExpression.Property(model.GetType(), "Users"), SyntaxTree.Block( SyntaxTree.WriteString("<li>Hello "), SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string))), SyntaxTree.WriteString(", "), SyntaxTree.WriteExpression(SyntaxTreeExpression.Property(model.GetType(), "Name", ExpressionScope.RootModel)), SyntaxTree.WriteString(" says hello!</li>") ) ), SyntaxTree.WriteString("</ul>") ) ), SyntaxTree.WriteString("</body></html>") ); }
public void Should_not_render_block_when_ifnot_statements_returns_true() { var input = @"<html><head></head><body>@IfNot.HasUsers;<p>No users found!</p>@EndIf;<ul>@Each.Users;<li>Hello @Current;, @Model.Name; says hello!</li>@EndEach;</ul></body></html>"; var model = new FakeModel("Nancy", new List <string>() { "Bob", "Jim", "Bill" }); var output = Parse(input, model.GetType()); AssertSyntaxTree(output, SyntaxTree.WriteString("<html><head></head><body>"), SyntaxTree.Conditional( SyntaxTreeExpression.Property(model.GetType(), "HasUsers"), SyntaxTree.Block(), SyntaxTree.Block( SyntaxTree.WriteString("<p>No users found!</p>") ) ), SyntaxTree.WriteString("<ul>"), SyntaxTree.Iterate( SyntaxTreeExpression.Property(model.GetType(), "Users"), SyntaxTree.Block( SyntaxTree.WriteString("<li>Hello "), SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string))), SyntaxTree.WriteString(", "), SyntaxTree.WriteExpression(SyntaxTreeExpression.Property(model.GetType(), "Name", ExpressionScope.RootModel)), SyntaxTree.WriteString(" says hello!</li>") ) ), SyntaxTree.WriteString("</ul></body></html>") ); }
public void Should_parse_current_keyword_as_self_expression() { var model = new { }; var result = SuperSimpleExpressionParser.Parse(CreateScopes(model.GetType()), "Current"); result.ShouldDeepEqual(SyntaxTreeExpression.Self(model.GetType())); }
public void Should_parse_model_keywords_as_self_expression_scoped_to_root() { var model = new { }; var result = SuperSimpleExpressionParser.Parse(CreateScopes(model.GetType()), "Model"); result.ShouldDeepEqual(SyntaxTreeExpression.Self(model.GetType(), ExpressionScope.RootModel)); }
public static ExpressionNode Parse(LinkedList <SuperSimpleTemplateParserScope> scopes, string originalExpression) { var expression = originalExpression.Trim(); if (expression == "Model") { return(SyntaxTreeExpression.Self(scopes.Last.Value.ModelType, ExpressionScope.RootModel)); } if (expression == "Current") { return(SyntaxTreeExpression.Self(scopes.First.Value.ModelType, ExpressionScope.CurrentModelOnStack)); } var chosenScope = scopes.First.Value; var expressionScope = ExpressionScope.CurrentModelOnStack; if (expression.StartsWith("Current.")) { expression = expression.Substring(8); } else if (expression.StartsWith("Model.")) { expression = expression.Substring(6); chosenScope = scopes.Last.Value; expressionScope = ExpressionScope.RootModel; } return(ParseAgainstModel(originalExpression, expression, chosenScope, expressionScope)); }
public void Should_be_able_to_write_from_parent_scope_model() { var model = new Model <string> { Name = "Root", SubModels = new[] { new SubModel <string> { Name = "1", Strings = new [] { "A", "B" } }, new SubModel <string> { Name = "2", Strings = new [] { "C", "D" } } } }; var template = SyntaxTree.Block( SyntaxTree.Iterate( SyntaxTreeExpression.Property(model.GetType(), "SubModels", ExpressionScope.RootModel), SyntaxTree.Block( SyntaxTree.Iterate( SyntaxTreeExpression.Property(model.Sub.GetType(), "Strings", ExpressionScope.CurrentModelOnStack), SyntaxTree.Block( SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string), ExpressionScope.CurrentModelOnStack)), SyntaxTree.WriteExpression(SyntaxTreeExpression.Property(model.Sub.GetType(), "Name", ExpressionScope.ModelOfParentScope)), SyntaxTree.WriteExpression(SyntaxTreeExpression.Property(model.GetType(), "Name", ExpressionScope.RootModel)) ) ) ) ) ); var result = ExecuteTemplate(template, model); Assert.That(result, Is.EqualTo("A1RootB1RootC2RootD2Root")); }
public void Should_trim_whitespace_from_previous_literal() { var template = Parse("Hello \r\n{{~this}}", typeof(string)); AssertSyntaxTree( template, SyntaxTree.WriteString("Hello"), SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string)), true) ); }
private static void HandleEachOverSelf(SuperSimpleTemplateParserState state) { var each = SyntaxTree.Iterate( SyntaxTreeExpression.Self(state.CurrentTypeInScope()), SyntaxTree.Block() ); state.AddNodeToCurrentBlock(each); state.PushNewScope(each.Body, each.ItemType); }
public void Should_trim_whitespace_from_next_literal() { var template = Parse("Hello {{this~}}\r\n!", typeof(string)); AssertSyntaxTree( template, SyntaxTree.WriteString("Hello "), SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string)), true), SyntaxTree.WriteString("!") ); }
public void Should_parse_partial_syntax() { var model = new { }; var template = Parse("Hello {{> person }}", model.GetType()); AssertSyntaxTree( template, SyntaxTree.WriteString("Hello "), SyntaxTree.Include("person", SyntaxTreeExpression.Self(model.GetType())) ); }
private static void HandlePartial(SuperSimpleTemplateParserState state) { var details = state.ParseCurrentTokenNameAndModelExpression(); ExpressionNode expression = SyntaxTreeExpression.Self(state.CurrentTypeInScope()); if (!String.IsNullOrEmpty(details.Model)) { expression = state.ParseExpression(details.Model); } state.AddNodeToCurrentBlock(SyntaxTree.Include(details.Name, expression)); }
public void Should_replace_primitive_model_with_value() { var input = @"<html><head></head><body>Hello there @Model;</body></html>"; var output = Parse(input, typeof(string)); AssertSyntaxTree(output, SyntaxTree.WriteString("<html><head></head><body>Hello there "), SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string), ExpressionScope.RootModel)), SyntaxTree.WriteString("</body></html>") ); }
public void Should_parse_basic_partials() { var input = @"<html><head></head><body>@Partial['testing'];</body></html>"; var result = Parse(input, typeof(object)); AssertSyntaxTree( result, SyntaxTree.WriteString("<html><head></head><body>"), SyntaxTree.Include("testing", SyntaxTreeExpression.Self(typeof(object))), SyntaxTree.WriteString("</body></html>") ); }
public void Should_parse_each_block() { var result = Parse("{{#each Items }}{{ this }}{{/each}}", typeof(TestModel)); AssertSyntaxTree(result, SyntaxTree.Iterate( SyntaxTreeExpression.Property(typeof(TestModel), "Items"), SyntaxTree.Block( SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string)), true) ) ) ); }
public void Should_throw_if_unable_to_load_template() { var model = new { Name = "Joe" }; var template = SyntaxTree.Block( SyntaxTree.WriteString("Hello "), SyntaxTree.Include("person", SyntaxTreeExpression.Self(model.GetType())) ); Assert.Throws <VeilCompilerException>(() => { ExecuteTemplate(template, model); }); }
public void Should_be_able_to_output_value_types_from_collections() { var model = new { Items = new[] { "1", "2", "3", "4" } }; var template = SyntaxTree.Block(SyntaxTree.Iterate( SyntaxTreeExpression.Property(model.GetType(), "Items"), SyntaxTree.Block( SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string))) ) )); var result = ExecuteTemplate(template, model); Assert.Equal("1234", result); }
public void Should_be_able_to_reference_parent_scope_from_within_each_block() { var result = Parse("{{#each Items }}{{ ../Prefix }}{{ this }}{{/each}}", typeof(TestModel)); AssertSyntaxTree(result, SyntaxTree.Iterate( SyntaxTreeExpression.Property(typeof(TestModel), "Items"), SyntaxTree.Block( SyntaxTree.WriteExpression(SyntaxTreeExpression.Property(typeof(TestModel), "Prefix", ExpressionScope.ModelOfParentScope), true), SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string)), true) ) ) ); }
public static ExpressionNode Parse(HandlebarsBlockStack blockStack, string expression) { expression = expression.Trim(); if (expression == "this") { return(SyntaxTreeExpression.Self(blockStack.GetCurrentModelType(), ExpressionScope.CurrentModelOnStack)); } if (expression.StartsWith("../")) { return(ParseAgainstModel(blockStack.GetParentModelType(), expression.Substring(3), ExpressionScope.ModelOfParentScope)); } return(ParseAgainstModel(blockStack.GetCurrentModelType(), expression, ExpressionScope.CurrentModelOnStack)); }
public void Should_be_able_to_iterate_items_from_an_untyped_model() { var model = new Dictionary <string, object>(); model.Add("Items", new string[] { "1", "2" }); var template = SyntaxTree.Block(SyntaxTree.Iterate( SyntaxTreeExpression.LateBound("Items"), SyntaxTree.Block( SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(object))) ) )); var result = ExecuteTemplate(template, model); Assert.Equal("12", result); }
public void Should_render_include_with_same_model() { var model = new { Name = "Joe" }; RegisterTemplate("person", SyntaxTree.Block( SyntaxTree.WriteExpression(SyntaxTreeExpression.Property(model.GetType(), "Name")) )); var template = SyntaxTree.Block( SyntaxTree.WriteString("Hello "), SyntaxTree.Include("person", SyntaxTreeExpression.Self(model.GetType())) ); var result = ExecuteTemplate(template, model); Assert.That(result, Is.EqualTo("Hello Joe")); }
public void Should_support_this_inside_with_block() { var model = new { User = "" }; var template = Parse("Hello {{#with User}}{{this}}{{/with}}", model.GetType()); AssertSyntaxTree( template, SyntaxTree.WriteString("Hello "), SyntaxTree.ScopeNode( SyntaxTreeExpression.Property(model.GetType(), "User"), SyntaxTree.Block( SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(model.User.GetType()), true) ) ) ); }
public void Should_render_include_with_untyped_model() { var model = new Dictionary <string, object>(); model.Add("Name", "Joe"); RegisterTemplate("person", SyntaxTree.Block( SyntaxTree.WriteExpression(SyntaxTreeExpression.LateBound("Name")) )); var template = SyntaxTree.Block( SyntaxTree.WriteString("Hello "), SyntaxTree.Include("person", SyntaxTreeExpression.Self(model.GetType())) ); var result = ExecuteTemplate(template, model); Assert.That(result, Is.EqualTo("Hello Joe")); }
public void Should_handle_conditional_on_root_scope() { var model = new { RootConditional = true, Values = new[] { 1, 2, 3 } }; var template = SyntaxTree.Block( SyntaxTree.Iterate( SyntaxTreeExpression.Property(model.GetType(), "Values"), SyntaxTree.Block( SyntaxTree.Conditional( SyntaxTreeExpression.Property(model.GetType(), "RootConditional", ExpressionScope.RootModel), SyntaxTree.Block(SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(int)))) ) ) ) ); var result = this.ExecuteTemplate(template, model); Assert.Equal("123", result); }
public void Should_allow_each_without_a_variable_and_iterate_over_the_model_if_it_is_enumerable(string input) { var model = new List <string>() { "Bob", "Jim", "Bill" }; var output = Parse(input, model.GetType()); AssertSyntaxTree( output, SyntaxTree.WriteString("<html><head></head><body><ul>"), SyntaxTree.Iterate( SyntaxTreeExpression.Self(model.GetType()), SyntaxTree.Block( SyntaxTree.WriteString("<li>Hello "), SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string))), SyntaxTree.WriteString("</li>") ) ), SyntaxTree.WriteString("</ul></body></html>") ); }
public void Should_allow_each_statements_to_work_over_multiple_lines() { var input = "<html>\n\t<head>\n\t</head>\n\t<body>\n\t\t<ul>@Each.Users;\n\t\t\t<li>@Current;</li>@EndEach;\n\t\t</ul>\n\t</body>\n</html>"; var model = new { Users = new List <string>() { "Bob", "Jim", "Bill" } }; var output = Parse(input, model.GetType()); AssertSyntaxTree(output, SyntaxTree.WriteString("<html>\n\t<head>\n\t</head>\n\t<body>\n\t\t<ul>"), SyntaxTree.Iterate( SyntaxTreeExpression.Property(model.GetType(), "Users"), SyntaxTree.Block( SyntaxTree.WriteString("\n\t\t\t<li>"), SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string))), SyntaxTree.WriteString("</li>") ) ), SyntaxTree.WriteString("\n\t\t</ul>\n\t</body>\n</html>") ); }
public void Should_support_implicit_model_reference_for_each_block() { var input = @"<html><head></head><body><ul>@Each.Users;<li>@Current;</li>@EndEach;</ul></body></html>"; var model = new { Users = new List <string>() { "Bob", "Jim", "Bill" } }; var output = Parse(input, model.GetType()); AssertSyntaxTree(output, SyntaxTree.WriteString("<html><head></head><body><ul>"), SyntaxTree.Iterate( SyntaxTreeExpression.Property(model.GetType(), "Users"), SyntaxTree.Block( SyntaxTree.WriteString("<li>"), SyntaxTree.WriteExpression(SyntaxTreeExpression.Self(typeof(string), ExpressionScope.CurrentModelOnStack)), SyntaxTree.WriteString("</li>") ) ), SyntaxTree.WriteString("</ul></body></html>") ); }